aboutsummaryrefslogtreecommitdiffstats
path: root/src/tests/unit_x509.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/tests/unit_x509.cpp')
-rw-r--r--src/tests/unit_x509.cpp333
1 files changed, 205 insertions, 128 deletions
diff --git a/src/tests/unit_x509.cpp b/src/tests/unit_x509.cpp
index 0d3946012..08ed5b578 100644
--- a/src/tests/unit_x509.cpp
+++ b/src/tests/unit_x509.cpp
@@ -8,8 +8,6 @@
#if defined(BOTAN_HAS_X509_CERTIFICATES)
-#if defined(BOTAN_HAS_RSA) && defined(BOTAN_HAS_DSA)
-
#include <botan/calendar.h>
#include <botan/pkcs8.h>
#include <botan/hash.h>
@@ -30,34 +28,24 @@
#include <botan/ecdsa.h>
#endif
-#include <iostream>
-#include <memory>
+#endif
-using namespace Botan;
+namespace Botan_Tests {
namespace {
-X509_Time from_date(const int y, const int m, const int d)
- {
- auto t = calendar_point(y, m, d, 0, 0, 0);
- return X509_Time(t.to_std_timepoint());
- }
+#if defined(BOTAN_HAS_X509_CERTIFICATES)
-u64bit key_id(const Public_Key* key)
+Botan::X509_Time from_date(const int y, const int m, const int d)
{
- std::unique_ptr<HashFunction> hash(HashFunction::create("SHA-1"));
- hash->update(key->algo_name());
- hash->update(key->algorithm_identifier().parameters);
- hash->update(key->x509_subject_public_key());
- secure_vector<byte> output = hash->final();
- return load_be<u64bit>(output.data(), 0);
+ Botan::calendar_point t(y, m, d, 0, 0, 0);
+ return Botan::X509_Time(t.to_std_timepoint());
}
-
/* Return some option sets */
-X509_Cert_Options ca_opts()
+Botan::X509_Cert_Options ca_opts()
{
- X509_Cert_Options opts("Test CA/US/Botan Project/Testing");
+ Botan::X509_Cert_Options opts("Test CA/US/Botan Project/Testing");
opts.uri = "http://botan.randombit.net";
opts.dns = "botan.randombit.net";
@@ -68,9 +56,9 @@ X509_Cert_Options ca_opts()
return opts;
}
-X509_Cert_Options req_opts1()
+Botan::X509_Cert_Options req_opts1()
{
- X509_Cert_Options opts("Test User 1/US/Botan Project/Testing");
+ Botan::X509_Cert_Options opts("Test User 1/US/Botan Project/Testing");
opts.uri = "http://botan.randombit.net";
opts.dns = "botan.randombit.net";
@@ -79,9 +67,9 @@ X509_Cert_Options req_opts1()
return opts;
}
-X509_Cert_Options req_opts2()
+Botan::X509_Cert_Options req_opts2()
{
- X509_Cert_Options opts("Test User 2/US/Botan Project/Testing");
+ Botan::X509_Cert_Options opts("Test User 2/US/Botan Project/Testing");
opts.uri = "http://botan.randombit.net";
opts.dns = "botan.randombit.net";
@@ -92,164 +80,253 @@ X509_Cert_Options req_opts2()
return opts;
}
-u32bit check_against_copy(const Private_Key& orig,
- RandomNumberGenerator& rng)
+std::unique_ptr<Botan::Private_Key> make_a_private_key()
{
- Private_Key* copy_priv = PKCS8::copy_key(orig, rng);
- Public_Key* copy_pub = X509::copy_key(orig);
-
- const std::string passphrase= "I need work! -Mr. T";
- DataSource_Memory enc_source(PKCS8::PEM_encode(orig, rng, passphrase));
- Private_Key* copy_priv_enc = PKCS8::load_key(enc_source, rng,
- passphrase);
-
- u64bit orig_id = key_id(&orig);
- u64bit pub_id = key_id(copy_pub);
- u64bit priv_id = key_id(copy_priv);
- u64bit priv_enc_id = key_id(copy_priv_enc);
-
- delete copy_pub;
- delete copy_priv;
- delete copy_priv_enc;
+#if defined(BOTAN_HAS_DSA)
+ if(Test::rng().next_byte() < 32)
+ {
+ Botan::DL_Group grp("dsa/botan/2048");
+ return std::unique_ptr<Botan::Private_Key>(new Botan::DSA_PrivateKey(Test::rng(), grp));
+ }
+#endif
- if(orig_id != pub_id || orig_id != priv_id || orig_id != priv_enc_id)
+#if defined(BOTAN_HAS_RSA)
+ if(Test::rng().next_byte() < 32)
{
- std::cout << "Failed copy check for " << orig.algo_name() << std::endl;
- return 1;
+ return std::unique_ptr<Botan::Private_Key>(new Botan::RSA_PrivateKey(Test::rng(), 1536));
}
- return 0;
- }
+#endif
-}
+#if defined(BOTAN_HAS_ECDSA)
+ Botan::EC_Group grp("secp256r1");
+ return std::unique_ptr<Botan::Private_Key>(new Botan::ECDSA_PrivateKey(Test::rng(), grp));
+#endif
-size_t test_x509()
+ throw std::runtime_error("Skipping X.509 cert test due to missing algos");
+ }
+
+class X509_Cert_Unit_Tests : public Test
{
- auto& rng = test_rng();
- const std::string hash_fn = "SHA-256";
+ public:
+ std::vector<Test::Result> run() override;
+
+ private:
+ Test::Result test_x509_dates()
+ {
+ Test::Result result("X509_Time");
+
+ Botan::X509_Time time;
+ result.confirm("unset time not set", !time.time_is_set());
+ time = Botan::X509_Time("0802011822Z", Botan::ASN1_Tag::UTC_TIME);
+ result.confirm("time set after construction", time.time_is_set());
+ result.test_eq("time readable_string", time.readable_string(), "2008/02/01 18:22:00 UTC");
+
+ const std::vector<std::string> valid = {
+ "0802010000Z",
+ "0802011724Z",
+ "0406142334Z",
+ "9906142334Z",
+ "0006142334Z",
+
+ "080201000000Z",
+ "080201172412Z",
+ "040614233433Z",
+ "990614233444Z",
+ "000614233455Z",
+ };
+
+ // Dates that are valid per X.500 but rejected as unsupported
+ const std::vector<std::string> valid_but_unsup = {
+ "0802010000-0000",
+ "0802011724+0000",
+ "0406142334-0500",
+ "9906142334+0500",
+ "0006142334-0530",
+ "0006142334+0530",
+
+ "080201000000-0000",
+ "080201172412+0000",
+ "040614233433-0500",
+ "990614233444+0500",
+ "000614233455-0530",
+ "000614233455+0530",
+ };
+
+ const std::vector<std::string> invalid = {
+ "",
+ " ",
+ "2008`02-01",
+ "9999-02-01",
+ "2000-02-01 17",
+ "999921",
+
+ // valid length 13 -> range check
+ "080201000061Z", // seconds too big (61)
+ "080201000060Z", // seconds too big (60, leap seconds not covered by the standard)
+ "0802010000-1Z", // seconds too small (-1)
+ "080201006000Z", // minutes too big (60)
+ "080201240000Z", // hours too big (24:00)
+
+ // valid length 13 -> invalid numbers
+ "08020123112 Z",
+ "08020123112!Z",
+ "08020123112,Z",
+ "08020123112\nZ",
+ "080201232 33Z",
+ "080201232!33Z",
+ "080201232,33Z",
+ "080201232\n33Z",
+ "0802012 3344Z",
+ "0802012!3344Z",
+ "0802012,3344Z",
+ "08022\n334455Z",
+ "08022 334455Z",
+ "08022!334455Z",
+ "08022,334455Z",
+ "08022\n334455Z",
+ "082 33445511Z",
+ "082!33445511Z",
+ "082,33445511Z",
+ "082\n33445511Z",
+ "2 2211221122Z",
+ "2!2211221122Z",
+ "2,2211221122Z",
+ "2\n2211221122Z",
+
+ // wrong time zone
+ "0802010000",
+ "0802010000z"
+ };
+
+ for(auto&& v : valid)
+ {
+ Botan::X509_Time t(v, Botan::ASN1_Tag::UTC_TIME);
+ }
+
+ for(auto&& v : valid_but_unsup)
+ {
+ result.test_throws("valid but unsupported", [v]() { Botan::X509_Time t(v, Botan::ASN1_Tag::UTC_TIME); });
+ }
+
+ for(auto&& v : invalid)
+ {
+ result.test_throws("invalid", [v]() { Botan::X509_Time t(v, Botan::ASN1_Tag::UTC_TIME); });
+ }
+
+ return result;
+ }
+ };
+
+std::vector<Test::Result> X509_Cert_Unit_Tests::run()
+ {
+ std::vector<Test::Result> results;
+ Test::Result result("X509 Unit");
- size_t fails = 0;
+ const std::string hash_fn = "SHA-256";
/* Create the CA's key and self-signed cert */
- RSA_PrivateKey ca_key(rng, 2048);
+ std::unique_ptr<Botan::Private_Key> ca_key(make_a_private_key());
+
+ Botan::X509_Certificate ca_cert =
+ Botan::X509::create_self_signed_cert(ca_opts(),
+ *ca_key,
+ hash_fn,
+ Test::rng());
- X509_Certificate ca_cert = X509::create_self_signed_cert(ca_opts(),
- ca_key,
- hash_fn,
- rng);
/* Create user #1's key and cert request */
- DSA_PrivateKey user1_key(rng, DL_Group("dsa/botan/2048"));
+ std::unique_ptr<Botan::Private_Key> user1_key(make_a_private_key());
- PKCS10_Request user1_req = X509::create_cert_req(req_opts1(),
- user1_key,
- "SHA-1",
- rng);
+ Botan::PKCS10_Request user1_req =
+ Botan::X509::create_cert_req(req_opts1(),
+ *user1_key,
+ hash_fn,
+ Test::rng());
/* Create user #2's key and cert request */
-#if defined(BOTAN_HAS_ECDSA)
- EC_Group ecc_domain(OID("1.2.840.10045.3.1.7"));
- ECDSA_PrivateKey user2_key(rng, ecc_domain);
-#else
- RSA_PrivateKey user2_key(rng, 1536);
-#endif
+ std::unique_ptr<Botan::Private_Key> user2_key(make_a_private_key());
- PKCS10_Request user2_req = X509::create_cert_req(req_opts2(),
- user2_key,
- hash_fn,
- rng);
+ Botan::PKCS10_Request user2_req =
+ Botan::X509::create_cert_req(req_opts2(),
+ *user2_key,
+ hash_fn,
+ Test::rng());
/* Create the CA object */
- X509_CA ca(ca_cert, ca_key, hash_fn);
+ Botan::X509_CA ca(ca_cert, *ca_key, hash_fn);
/* Sign the requests to create the certs */
- X509_Certificate user1_cert =
- ca.sign_request(user1_req, rng,
- from_date(2008, 01, 01), from_date(2033, 01, 01));
+ Botan::X509_Certificate user1_cert =
+ ca.sign_request(user1_req, Test::rng(),
+ from_date(2008, 01, 01),
+ from_date(2033, 01, 01));
- X509_Certificate user2_cert = ca.sign_request(user2_req, rng,
+ Botan::X509_Certificate user2_cert = ca.sign_request(user2_req, Test::rng(),
from_date(2008, 01, 01),
from_date(2033, 01, 01));
- X509_CRL crl1 = ca.new_crl(rng);
+ Botan::X509_CRL crl1 = ca.new_crl(Test::rng());
/* Verify the certs */
- Certificate_Store_In_Memory store;
+ Botan::Certificate_Store_In_Memory store;
store.add_certificate(ca_cert);
- Path_Validation_Restrictions restrictions(false);
+ Botan::Path_Validation_Restrictions restrictions(false);
- Path_Validation_Result result_u1 = x509_path_validate(user1_cert, restrictions, store);
- if(!result_u1.successful_validation())
+ Botan::Path_Validation_Result result_u1 = Botan::x509_path_validate(user1_cert, restrictions, store);
+ if(!result.confirm("user 1 validates", result_u1.successful_validation()))
{
- std::cout << "FAILED: User cert #1 did not validate - "
- << result_u1.result_string() << std::endl;
- ++fails;
+ result.test_note("user 1 validation result was " + result_u1.result_string());
}
- Path_Validation_Result result_u2 = x509_path_validate(user2_cert, restrictions, store);
- if(!result_u2.successful_validation())
+ Botan::Path_Validation_Result result_u2 = Botan::x509_path_validate(user2_cert, restrictions, store);
+ if(!result.confirm("user 2 validates", result_u2.successful_validation()))
{
- std::cout << "FAILED: User cert #2 did not validate - "
- << result_u2.result_string() << std::endl;
- ++fails;
+ result.test_note("user 2 validation result was " + result_u2.result_string());
}
store.add_crl(crl1);
- std::vector<CRL_Entry> revoked;
- revoked.push_back(CRL_Entry(user1_cert, CESSATION_OF_OPERATION));
+ std::vector<Botan::CRL_Entry> revoked;
+ revoked.push_back(Botan::CRL_Entry(user1_cert, Botan::CESSATION_OF_OPERATION));
revoked.push_back(user2_cert);
- X509_CRL crl2 = ca.update_crl(crl1, revoked, rng);
+ Botan::X509_CRL crl2 = ca.update_crl(crl1, revoked, Test::rng());
store.add_crl(crl2);
- result_u1 = x509_path_validate(user1_cert, restrictions, store);
- if(result_u1.result() != Certificate_Status_Code::CERT_IS_REVOKED)
- {
- std::cout << "FAILED: User cert #1 was not revoked - "
- << result_u1.result_string() << std::endl;
- ++fails;
- }
+ const std::string revoked_str =
+ Botan::Path_Validation_Result::status_string(Botan::Certificate_Status_Code::CERT_IS_REVOKED);
- result_u2 = x509_path_validate(user2_cert, restrictions, store);
- if(result_u2.result() != Certificate_Status_Code::CERT_IS_REVOKED)
- {
- std::cout << "FAILED: User cert #2 was not revoked - "
- << result_u2.result_string() << std::endl;
- ++fails;
- }
+ result_u1 = Botan::x509_path_validate(user1_cert, restrictions, store);
+ result.test_eq("user 1 revoked", result_u1.result_string(), revoked_str);
+
+ result_u2 = Botan::x509_path_validate(user2_cert, restrictions, store);
+ result.test_eq("user 1 revoked", result_u2.result_string(), revoked_str);
revoked.clear();
- revoked.push_back(CRL_Entry(user1_cert, REMOVE_FROM_CRL));
- X509_CRL crl3 = ca.update_crl(crl2, revoked, rng);
+ revoked.push_back(Botan::CRL_Entry(user1_cert, Botan::REMOVE_FROM_CRL));
+ Botan::X509_CRL crl3 = ca.update_crl(crl2, revoked, Test::rng());
store.add_crl(crl3);
- result_u1 = x509_path_validate(user1_cert, restrictions, store);
- if(!result_u1.successful_validation())
+ result_u1 = Botan::x509_path_validate(user1_cert, restrictions, store);
+ if(!result.confirm("user 1 validates", result_u1.successful_validation()))
{
- std::cout << "FAILED: User cert #1 was not un-revoked - "
- << result_u1.result_string() << std::endl;
- ++fails;
+ result.test_note("user 1 validation result was " + result_u1.result_string());
}
- check_against_copy(ca_key, rng);
- check_against_copy(user1_key, rng);
- check_against_copy(user2_key, rng);
+ result_u2 = Botan::x509_path_validate(user2_cert, restrictions, store);
+ result.test_eq("user 2 still revoked", result_u2.result_string(), revoked_str);
- test_report("X509", 0, fails);
-
- return fails;
+ results.push_back(result);
+ results.push_back(test_x509_dates());
+ return results;
}
-#else
-
-UNTESTED_WARNING(x509);
+BOTAN_REGISTER_TEST("unit_x509", X509_Cert_Unit_Tests);
-#endif // BOTAN_HAS_RSA && BOTAN_HAS_DSA
-
-#else
+#endif
-SKIP_TEST(x509);
+}
-#endif // BOTAN_HAS_X509_CERTIFICATES
+}