diff options
Diffstat (limited to 'src/tests/unit_x509.cpp')
-rw-r--r-- | src/tests/unit_x509.cpp | 255 |
1 files changed, 255 insertions, 0 deletions
diff --git a/src/tests/unit_x509.cpp b/src/tests/unit_x509.cpp new file mode 100644 index 000000000..cd0beec5b --- /dev/null +++ b/src/tests/unit_x509.cpp @@ -0,0 +1,255 @@ +/* +* (C) 2009 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include "tests.h" + +#include <botan/filters.h> +#include <botan/auto_rng.h> + +#if defined(BOTAN_HAS_RSA) + #include <botan/rsa.h> +#endif + +#if defined(BOTAN_HAS_DSA) + #include <botan/dsa.h> +#endif + +#if defined(BOTAN_HAS_ECDSA) + #include <botan/ecdsa.h> +#endif + +#if defined(BOTAN_HAS_X509_CERTIFICATES) + #include <botan/x509self.h> + #include <botan/x509path.h> + #include <botan/x509_ca.h> + #include <botan/pkcs10.h> +#endif + +using namespace Botan; + +#include <iostream> +#include <memory> + + +#if defined(BOTAN_HAS_X509_CERTIFICATES) && \ + defined(BOTAN_HAS_RSA) && \ + defined(BOTAN_HAS_DSA) + +namespace { + +u64bit key_id(const Public_Key* key) + { + Pipe pipe(new Hash_Filter("SHA-1", 8)); + pipe.start_msg(); + pipe.write(key->algo_name()); + pipe.write(key->algorithm_identifier().parameters); + pipe.write(key->x509_subject_public_key()); + pipe.end_msg(); + + secure_vector<byte> output = pipe.read_all(); + + if(output.size() != 8) + throw Internal_Error("Public_Key::key_id: Incorrect output size"); + + u64bit id = 0; + for(u32bit j = 0; j != 8; ++j) + id = (id << 8) | output[j]; + return id; + } + + +/* Return some option sets */ +X509_Cert_Options ca_opts() + { + X509_Cert_Options opts("Test CA/US/Botan Project/Testing"); + + opts.uri = "http://botan.randombit.net"; + opts.dns = "botan.randombit.net"; + opts.email = "[email protected]"; + + opts.CA_key(1); + + return opts; + } + +X509_Cert_Options req_opts1() + { + X509_Cert_Options opts("Test User 1/US/Botan Project/Testing"); + + opts.uri = "http://botan.randombit.net"; + opts.dns = "botan.randombit.net"; + opts.email = "[email protected]"; + + return opts; + } + +X509_Cert_Options req_opts2() + { + X509_Cert_Options opts("Test User 2/US/Botan Project/Testing"); + + opts.uri = "http://botan.randombit.net"; + opts.dns = "botan.randombit.net"; + opts.email = "[email protected]"; + + opts.add_ex_constraint("PKIX.EmailProtection"); + + return opts; + } + +u32bit check_against_copy(const Private_Key& orig, + RandomNumberGenerator& rng) + { + 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(orig_id != pub_id || orig_id != priv_id || orig_id != priv_enc_id) + { + std::cout << "Failed copy check for " << orig.algo_name() << "\n"; + return 1; + } + return 0; + } + +} + +size_t test_x509() + { + AutoSeeded_RNG rng; + const std::string hash_fn = "SHA-256"; + + size_t fails = 0; + + /* Create the CA's key and self-signed cert */ + RSA_PrivateKey ca_key(rng, 2048); + + 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")); + + PKCS10_Request user1_req = X509::create_cert_req(req_opts1(), + user1_key, + "SHA-1", + 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 + + PKCS10_Request user2_req = X509::create_cert_req(req_opts2(), + user2_key, + hash_fn, + rng); + + /* Create the CA object */ + 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, + X509_Time("2008-01-01"), X509_Time("2100-01-01")); + + X509_Certificate user2_cert = ca.sign_request(user2_req, rng, + X509_Time("2008-01-01"), + X509_Time("2100-01-01")); + X509_CRL crl1 = ca.new_crl(rng); + + /* Verify the certs */ + Certificate_Store_In_Memory store; + + store.add_certificate(ca_cert); + + Path_Validation_Restrictions restrictions; + + Path_Validation_Result result_u1 = x509_path_validate(user1_cert, restrictions, store); + if(!result_u1.successful_validation()) + { + std::cout << "FAILED: User cert #1 did not validate - " + << result_u1.result_string() << std::endl; + ++fails; + } + + Path_Validation_Result result_u2 = x509_path_validate(user2_cert, restrictions, store); + if(!result_u2.successful_validation()) + { + std::cout << "FAILED: User cert #2 did not validate - " + << result_u2.result_string() << std::endl; + ++fails; + } + + store.add_crl(crl1); + + std::vector<CRL_Entry> revoked; + revoked.push_back(CRL_Entry(user1_cert, CESSATION_OF_OPERATION)); + revoked.push_back(user2_cert); + + X509_CRL crl2 = ca.update_crl(crl1, revoked, 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; + } + + 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; + } + + revoked.clear(); + revoked.push_back(CRL_Entry(user1_cert, REMOVE_FROM_CRL)); + X509_CRL crl3 = ca.update_crl(crl2, revoked, rng); + + store.add_crl(crl3); + + result_u1 = x509_path_validate(user1_cert, restrictions, store); + if(!result_u1.successful_validation()) + { + std::cout << "FAILED: User cert #1 was not un-revoked - " + << result_u1.result_string() << std::endl; + ++fails; + } + + check_against_copy(ca_key, rng); + check_against_copy(user1_key, rng); + check_against_copy(user2_key, rng); + + return fails; + } + +#else + +size_t test_x590() { return 0; } + +#endif + |