diff options
594 files changed, 15802 insertions, 10114 deletions
diff --git a/botan_version.py b/botan_version.py index a44619e71..eada52c86 100644 --- a/botan_version.py +++ b/botan_version.py @@ -1,6 +1,6 @@ release_major = 1 -release_minor = 10 +release_minor = 99 release_patch = 2 release_vc_rev = None diff --git a/checks/bench.cpp b/checks/bench.cpp index e9eb92199..5faba00db 100644 --- a/checks/bench.cpp +++ b/checks/bench.cpp @@ -14,9 +14,12 @@ #include <botan/engine.h> #include <botan/parsing.h> #include <botan/symkey.h> -#include <botan/time.h> #include <botan/hex.h> +#include <chrono> + +typedef std::chrono::high_resolution_clock benchmark_clock; + #include "common.h" #include "bench.h" @@ -150,18 +153,6 @@ void report_results(const std::string& algo, std::cout << algo; -#if defined(__SUNPRO_CC) - #define REVERSE_ITERATOR_BUG 1 -#elif defined(__GNUC__) && __GNUC__ <= 3 - #define REVERSE_ITERATOR_BUG 1 -#elif defined(__GNUC__) && (__GNUC__ == 4 && __GNUC_MINOR__ == 0) - #define REVERSE_ITERATOR_BUG 1 -#endif - -#ifndef REVERSE_ITERATOR_BUG - #define REVERSE_ITERATOR_BUG 0 -#endif - #if (defined(__GNUC__) && __GNUC__ <= 3) || defined(__SUNPRO_CC) // Work around GCC 3.x bug, reverse iterators don't work for(std::map<double, std::string>::const_iterator i = results.begin(); i != results.end(); ++i) @@ -184,10 +175,11 @@ bool bench_algo(const std::string& algo, { Botan::Algorithm_Factory& af = Botan::global_state().algorithm_factory(); - u32bit milliseconds = static_cast<u32bit>(seconds * 1000); + std::chrono::milliseconds ms( + static_cast<std::chrono::milliseconds::rep>(seconds * 1000)); std::map<std::string, double> speeds = - algorithm_benchmark(algo, af, rng, milliseconds, buf_size); + algorithm_benchmark(algo, af, rng, ms, buf_size); if(speeds.empty()) // maybe a cipher mode, then? { @@ -236,17 +228,23 @@ bool bench_algo(const std::string& algo, Botan::Pipe pipe(filt, new Botan::BitBucket); pipe.start_msg(); - const u64bit start = Botan::get_nanoseconds_clock(); - u64bit nanoseconds_used = 0; + std::chrono::nanoseconds max_time(nanoseconds_max); + std::chrono::nanoseconds time_used(0); + + auto start = benchmark_clock::now(); + u64bit reps = 0; - while(nanoseconds_used < nanoseconds_max) + while(time_used < max_time) { pipe.write(&buf[0], buf.size()); ++reps; - nanoseconds_used = Botan::get_nanoseconds_clock() - start; + time_used = benchmark_clock::now() - start; } + u64bit nanoseconds_used = + std::chrono::duration_cast<std::chrono::nanoseconds>(time_used).count(); + double mbytes_per_second = (953.67 * (buf.size() * reps)) / nanoseconds_used; diff --git a/checks/common.h b/checks/common.h index 33499a99d..05a6fb974 100644 --- a/checks/common.h +++ b/checks/common.h @@ -55,13 +55,13 @@ class Fixed_Output_RNG : public Botan::RandomNumberGenerator void clear() throw() {} - Fixed_Output_RNG(const Botan::SecureVector<byte>& in) + Fixed_Output_RNG(const Botan::secure_vector<byte>& in) { buf.insert(buf.end(), in.begin(), in.end()); } Fixed_Output_RNG(const std::string& in_str) { - Botan::SecureVector<byte> in = Botan::hex_decode(in_str); + Botan::secure_vector<byte> in = Botan::hex_decode(in_str); buf.insert(buf.end(), in.begin(), in.end()); } diff --git a/checks/cvc_tests.cpp b/checks/cvc_tests.cpp index 334fb8581..9dc56610c 100644 --- a/checks/cvc_tests.cpp +++ b/checks/cvc_tests.cpp @@ -27,7 +27,6 @@ #include <botan/cvc_self.h> #include <botan/cvc_cert.h> #include <botan/cvc_ado.h> -#include <botan/time.h> #define TEST_DATA_DIR "checks/ecc_testdata" @@ -41,7 +40,7 @@ namespace { // helper functions void helper_write_file(EAC_Signed_Object const& to_write, std::string const& file_path) { - SecureVector<byte> sv = to_write.BER_encode(); + std::vector<byte> sv = to_write.BER_encode(); std::ofstream cert_file(file_path.c_str(), std::ios::binary); cert_file.write((char*)&sv[0], sv.size()); cert_file.close(); @@ -51,8 +50,8 @@ bool helper_files_equal(std::string const& file_path1, std::string const& file_p { std::ifstream cert_1_in(file_path1.c_str()); std::ifstream cert_2_in(file_path2.c_str()); - SecureVector<byte> sv1; - SecureVector<byte> sv2; + std::vector<byte> sv1; + std::vector<byte> sv2; if (!cert_1_in || !cert_2_in) { return false; @@ -95,7 +94,7 @@ void test_enc_gen_selfsigned(RandomNumberGenerator& rng) key.set_parameter_encoding(EC_DOMPAR_ENC_IMPLICITCA); EAC1_1_CVC cert = CVC_EAC::create_self_signed_cert(key, opts, rng); - SecureVector<byte> der(cert.BER_encode()); + std::vector<byte> der(cert.BER_encode()); std::ofstream cert_file; cert_file.open(TEST_DATA_DIR "/my_cv_cert.ber", std::ios::binary); //cert_file << der; // this is bad !!! @@ -105,15 +104,15 @@ void test_enc_gen_selfsigned(RandomNumberGenerator& rng) EAC1_1_CVC cert_in(TEST_DATA_DIR "/my_cv_cert.ber"); CHECK(cert == cert_in); // encoding it again while it has no dp - SecureVector<byte> der2(cert_in.BER_encode()); + std::vector<byte> der2(cert_in.BER_encode()); std::ofstream cert_file2(TEST_DATA_DIR "/my_cv_cert2.ber", std::ios::binary); cert_file2.write((char*)&der2[0], der2.size()); cert_file2.close(); // read both and compare them std::ifstream cert_1_in(TEST_DATA_DIR "/my_cv_cert.ber"); std::ifstream cert_2_in(TEST_DATA_DIR "/my_cv_cert2.ber"); - SecureVector<byte> sv1; - SecureVector<byte> sv2; + std::vector<byte> sv1; + std::vector<byte> sv2; if (!cert_1_in || !cert_2_in) { CHECK_MESSAGE(false, "could not read certificate files"); @@ -162,12 +161,12 @@ void test_enc_gen_selfsigned(RandomNumberGenerator& rng) } CHECK(ill_date_exc2); //cout << "readable = '" << cert_in.get_ced().readable_string() << "'\n"; - std::auto_ptr<Public_Key> p_pk(cert_in.subject_public_key()); - //auto_ptr<ECDSA_PublicKey> ecdsa_pk(dynamic_cast<auto_ptr<ECDSA_PublicKey> >(p_pk)); + std::unique_ptr<Public_Key> p_pk(cert_in.subject_public_key()); ECDSA_PublicKey* p_ecdsa_pk = dynamic_cast<ECDSA_PublicKey*>(p_pk.get()); + // let´s see if encoding is truely implicitca, because this is what the key should have // been set to when decoding (see above)(because it has no domain params): - //cout << "encoding = " << p_ecdsa_pk->get_parameter_encoding() << std::endl; + CHECK(p_ecdsa_pk->domain_format() == EC_DOMPAR_ENC_IMPLICITCA); bool exc = false; try @@ -181,7 +180,7 @@ void test_enc_gen_selfsigned(RandomNumberGenerator& rng) CHECK(exc); // set them and try again //cert_in.set_domain_parameters(dom_pars); - std::auto_ptr<Public_Key> p_pk2(cert_in.subject_public_key()); + std::unique_ptr<Public_Key> p_pk2(cert_in.subject_public_key()); ECDSA_PublicKey* p_ecdsa_pk2 = dynamic_cast<ECDSA_PublicKey*>(p_pk2.get()); //p_ecdsa_pk2->set_domain_parameters(dom_pars); CHECK(p_ecdsa_pk2->domain().get_order() == dom_pars.get_order()); @@ -204,7 +203,7 @@ void test_enc_gen_req(RandomNumberGenerator& rng) ECDSA_PrivateKey key(rng, dom_pars); key.set_parameter_encoding(EC_DOMPAR_ENC_IMPLICITCA); EAC1_1_Req req = CVC_EAC::create_cvc_req(key, opts.chr, opts.hash_alg, rng); - SecureVector<byte> der(req.BER_encode()); + std::vector<byte> der(req.BER_encode()); std::ofstream req_file(TEST_DATA_DIR "/my_cv_req.ber", std::ios::binary); req_file.write((char*)&der[0], der.size()); req_file.close(); @@ -212,7 +211,7 @@ void test_enc_gen_req(RandomNumberGenerator& rng) // read and check signature... EAC1_1_Req req_in(TEST_DATA_DIR "/my_cv_req.ber"); //req_in.set_domain_parameters(dom_pars); - std::auto_ptr<Public_Key> p_pk(req_in.subject_public_key()); + std::unique_ptr<Public_Key> p_pk(req_in.subject_public_key()); ECDSA_PublicKey* p_ecdsa_pk = dynamic_cast<ECDSA_PublicKey*>(p_pk.get()); //p_ecdsa_pk->set_domain_parameters(dom_pars); CHECK(p_ecdsa_pk->domain().get_order() == dom_pars.get_order()); @@ -227,7 +226,7 @@ void test_cvc_req_ext(RandomNumberGenerator&) EAC1_1_Req req_in(TEST_DATA_DIR "/DE1_flen_chars_cvcRequest_ECDSA.der"); EC_Group dom_pars(OID("1.3.36.3.3.2.8.1.1.5")); // "german curve" //req_in.set_domain_parameters(dom_pars); - std::auto_ptr<Public_Key> p_pk(req_in.subject_public_key()); + std::unique_ptr<Public_Key> p_pk(req_in.subject_public_key()); ECDSA_PublicKey* p_ecdsa_pk = dynamic_cast<ECDSA_PublicKey*>(p_pk.get()); //p_ecdsa_pk->set_domain_parameters(dom_pars); CHECK(p_ecdsa_pk->domain().get_order() == dom_pars.get_order()); @@ -261,7 +260,7 @@ void test_cvc_ado_creation(RandomNumberGenerator& rng) req_key.set_parameter_encoding(EC_DOMPAR_ENC_IMPLICITCA); //EAC1_1_Req req = CVC_EAC::create_cvc_req(req_key, opts); EAC1_1_Req req = CVC_EAC::create_cvc_req(req_key, opts.chr, opts.hash_alg, rng); - SecureVector<byte> der(req.BER_encode()); + std::vector<byte> der(req.BER_encode()); std::ofstream req_file(TEST_DATA_DIR "/my_cv_req.ber", std::ios::binary); req_file.write((char*)&der[0], der.size()); req_file.close(); @@ -277,7 +276,7 @@ void test_cvc_ado_creation(RandomNumberGenerator& rng) CHECK_MESSAGE(ado.check_signature(ado_key), "failure of ado verification after creation"); std::ofstream ado_file(TEST_DATA_DIR "/ado", std::ios::binary); - SecureVector<byte> ado_der(ado.BER_encode()); + std::vector<byte> ado_der(ado.BER_encode()); ado_file.write((char*)&ado_der[0], ado_der.size()); ado_file.close(); // read it again and check the signature @@ -333,7 +332,7 @@ void test_cvc_ado_comparison(RandomNumberGenerator& rng) CHECK_MESSAGE(ado != ado2, "ado's found to be equal where they are not"); // std::ofstream ado_file(TEST_DATA_DIR "/ado"); - // SecureVector<byte> ado_der(ado.BER_encode()); + // std::vector<byte> ado_der(ado.BER_encode()); // ado_file.write((char*)&ado_der[0], ado_der.size()); // ado_file.close(); // read it again and check the signature @@ -349,8 +348,7 @@ void test_eac_time(RandomNumberGenerator&) { std::cout << "." << std::flush; - const u64bit current_time = system_time(); - EAC_Time time(current_time); + EAC_Time time(std::chrono::system_clock::now()); // std::cout << "time as std::string = " << time.as_string() << std::endl; EAC_Time sooner("", ASN1_Tag(99)); //X509_Time sooner("", ASN1_Tag(99)); @@ -389,11 +387,9 @@ void test_ver_cvca(RandomNumberGenerator&) EAC1_1_CVC req_in(TEST_DATA_DIR "/cvca01.cv.crt"); - //auto_ptr<ECDSA_PublicKey> ecdsa_pk(dynamic_cast<auto_ptr<ECDSA_PublicKey> >(p_pk)); - //ECDSA_PublicKey* p_ecdsa_pk = dynamic_cast<ECDSA_PublicKey*>(p_pk.get()); bool exc = false; - std::auto_ptr<Public_Key> p_pk2(req_in.subject_public_key()); + std::unique_ptr<Public_Key> p_pk2(req_in.subject_public_key()); ECDSA_PublicKey* p_ecdsa_pk2 = dynamic_cast<ECDSA_PublicKey*>(p_pk2.get()); bool ver_ec = req_in.check_signature(*p_pk2); CHECK_MESSAGE(ver_ec, "could not positively verify correct selfsigned cvca certificate"); @@ -494,7 +490,7 @@ void test_cvc_chain(RandomNumberGenerator& rng) ASN1_Car car("DECVCA00001"); EAC1_1_CVC cvca_cert = DE_EAC::create_cvca(cvca_privk, hash, car, true, true, 12, rng); std::ofstream cvca_file(TEST_DATA_DIR "/cvc_chain_cvca.cer", std::ios::binary); - SecureVector<byte> cvca_sv = cvca_cert.BER_encode(); + std::vector<byte> cvca_sv = cvca_cert.BER_encode(); cvca_file.write((char*)&cvca_sv[0], cvca_sv.size()); cvca_file.close(); @@ -502,7 +498,7 @@ void test_cvc_chain(RandomNumberGenerator& rng) ASN1_Car car2("DECVCA00002"); EAC1_1_CVC cvca_cert2 = DE_EAC::create_cvca(cvca_privk2, hash, car2, true, true, 12, rng); EAC1_1_CVC link12 = DE_EAC::link_cvca(cvca_cert, cvca_privk, cvca_cert2, rng); - SecureVector<byte> link12_sv = link12.BER_encode(); + std::vector<byte> link12_sv = link12.BER_encode(); std::ofstream link12_file(TEST_DATA_DIR "/cvc_chain_link12.cer", std::ios::binary); link12_file.write((char*)&link12_sv[0], link12_sv.size()); link12_file.close(); @@ -511,14 +507,14 @@ void test_cvc_chain(RandomNumberGenerator& rng) CHECK(link12.check_signature(cvca_privk)); EAC1_1_CVC link12_reloaded(TEST_DATA_DIR "/cvc_chain_link12.cer"); EAC1_1_CVC cvca1_reloaded(TEST_DATA_DIR "/cvc_chain_cvca.cer"); - std::auto_ptr<Public_Key> cvca1_rel_pk(cvca1_reloaded.subject_public_key()); + std::unique_ptr<Public_Key> cvca1_rel_pk(cvca1_reloaded.subject_public_key()); CHECK(link12_reloaded.check_signature(*cvca1_rel_pk)); // create first round dvca-req ECDSA_PrivateKey dvca_priv_key(rng, dom_pars); EAC1_1_Req dvca_req = DE_EAC::create_cvc_req(dvca_priv_key, ASN1_Chr("DEDVCAEPASS"), hash, rng); std::ofstream dvca_file(TEST_DATA_DIR "/cvc_chain_dvca_req.cer", std::ios::binary); - SecureVector<byte> dvca_sv = dvca_req.BER_encode(); + std::vector<byte> dvca_sv = dvca_req.BER_encode(); dvca_file.write((char*)&dvca_sv[0], dvca_sv.size()); dvca_file.close(); @@ -532,7 +528,7 @@ void test_cvc_chain(RandomNumberGenerator& rng) ECDSA_PrivateKey dvca_priv_key2(rng, dom_pars); EAC1_1_Req dvca_req2 = DE_EAC::create_cvc_req(dvca_priv_key2, ASN1_Chr("DEDVCAEPASS"), hash, rng); std::ofstream dvca_file2(TEST_DATA_DIR "/cvc_chain_dvca_req2.cer", std::ios::binary); - SecureVector<byte> dvca_sv2 = dvca_req2.BER_encode(); + std::vector<byte> dvca_sv2 = dvca_req2.BER_encode(); dvca_file2.write((char*)&dvca_sv2[0], dvca_sv2.size()); dvca_file2.close(); EAC1_1_ADO dvca_ado2 = CVC_EAC::create_ado_req(dvca_priv_key, dvca_req2, @@ -541,7 +537,7 @@ void test_cvc_chain(RandomNumberGenerator& rng) // verify the ado and sign the request too - std::auto_ptr<Public_Key> ap_pk(dvca_cert1.subject_public_key()); + std::unique_ptr<Public_Key> ap_pk(dvca_cert1.subject_public_key()); ECDSA_PublicKey* cert_pk = dynamic_cast<ECDSA_PublicKey*>(ap_pk.get()); //cert_pk->set_domain_parameters(dom_pars); diff --git a/checks/dolook.cpp b/checks/dolook.cpp index a8e08a96b..364a3f8c3 100644 --- a/checks/dolook.cpp +++ b/checks/dolook.cpp @@ -83,14 +83,14 @@ class PBKDF_Filter : public Filter pbkdf = algo; outlen = o; iterations = i; - salt = s.bits_of(); + salt = unlock(s.bits_of()); } ~PBKDF_Filter() { delete pbkdf; } private: std::string passphrase; PBKDF* pbkdf; - SecureVector<byte> salt; + std::vector<byte> salt; u32bit outlen, iterations; }; @@ -126,12 +126,12 @@ class KDF_Filter : public Filter { kdf = algo; outlen = o; - salt = s.bits_of(); + salt = unlock(s.bits_of()); } ~KDF_Filter() { delete kdf; } private: - SecureVector<byte> secret; - SecureVector<byte> salt; + std::vector<byte> secret; + std::vector<byte> salt; KDF* kdf; u32bit outlen; }; @@ -139,7 +139,7 @@ class KDF_Filter : public Filter Filter* lookup_pbkdf(const std::string& algname, const std::vector<std::string>& params) { - PBKDF* pbkdf = 0; + PBKDF* pbkdf = nullptr; try { pbkdf = get_pbkdf(algname); @@ -149,7 +149,7 @@ Filter* lookup_pbkdf(const std::string& algname, if(pbkdf) return new PBKDF_Filter(pbkdf, params[0], to_u32bit(params[1]), to_u32bit(params[2])); - return 0; + return nullptr; } void RNG_Filter::write(const byte[], size_t length) @@ -163,7 +163,7 @@ void RNG_Filter::write(const byte[], size_t length) Filter* lookup_rng(const std::string& algname, const std::string& key) { - RandomNumberGenerator* prng = 0; + RandomNumberGenerator* prng = nullptr; #if defined(BOTAN_HAS_AUTO_SEEDING_RNG) if(algname == "AutoSeeded") @@ -233,21 +233,21 @@ Filter* lookup_rng(const std::string& algname, return new RNG_Filter(prng); } - return 0; + return nullptr; } Filter* lookup_kdf(const std::string& algname, const std::string& salt, const std::string& params) { - KDF* kdf = 0; + KDF* kdf = nullptr; try { kdf = get_kdf(algname); } - catch(...) { return 0; } + catch(...) { return nullptr; } if(kdf) return new KDF_Filter(kdf, salt, to_u32bit(params)); - return 0; + return nullptr; } Filter* lookup_encoder(const std::string& algname) @@ -278,7 +278,7 @@ Filter* lookup_encoder(const std::string& algname) return new Zlib_Decompression; #endif - return 0; + return nullptr; } } @@ -288,7 +288,7 @@ Filter* lookup(const std::string& algname, { std::string key = params[0]; std::string iv = params[1]; - Filter* filter = 0; + Filter* filter = nullptr; // The order of the lookup has to change based on how the names are // formatted and parsed. @@ -304,6 +304,6 @@ Filter* lookup(const std::string& algname, filter = lookup_pbkdf(algname, params); if(filter) return filter; - return 0; + return nullptr; } diff --git a/checks/ec_tests.cpp b/checks/ec_tests.cpp index 8ed975603..39c32de37 100644 --- a/checks/ec_tests.cpp +++ b/checks/ec_tests.cpp @@ -76,10 +76,10 @@ void test_point_turn_on_sp_red_mul() std::string a_secp = "ffffffffffffffffffffffffffffffff7ffffffc"; std::string b_secp = "1c97befc54bd7a8b65acf89f81d4d4adc565fa45"; std::string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82"; - SecureVector<byte> sv_p_secp = hex_decode(p_secp); - SecureVector<byte> sv_a_secp = hex_decode(a_secp); - SecureVector<byte> sv_b_secp = hex_decode(b_secp); - SecureVector<byte> sv_G_secp_comp = hex_decode(G_secp_comp); + secure_vector<byte> sv_p_secp = hex_decode(p_secp); + secure_vector<byte> sv_a_secp = hex_decode(a_secp); + secure_vector<byte> sv_b_secp = hex_decode(b_secp); + secure_vector<byte> sv_G_secp_comp = hex_decode(G_secp_comp); BigInt bi_p_secp = BigInt::decode(&sv_p_secp[0], sv_p_secp.size()); BigInt bi_a_secp = BigInt::decode(&sv_a_secp[0], sv_a_secp.size()); BigInt bi_b_secp = BigInt::decode(&sv_b_secp[0], sv_b_secp.size()); @@ -139,10 +139,10 @@ void test_coordinates() std::string a_secp = "ffffffffffffffffffffffffffffffff7ffffffc"; std::string b_secp = "1c97befc54bd7a8b65acf89f81d4d4adc565fa45"; std::string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82"; - SecureVector<byte> sv_p_secp = hex_decode ( p_secp ); - SecureVector<byte> sv_a_secp = hex_decode ( a_secp ); - SecureVector<byte> sv_b_secp = hex_decode ( b_secp ); - SecureVector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp ); + secure_vector<byte> sv_p_secp = hex_decode ( p_secp ); + secure_vector<byte> sv_a_secp = hex_decode ( a_secp ); + secure_vector<byte> sv_b_secp = hex_decode ( b_secp ); + secure_vector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp ); BigInt bi_p_secp = BigInt::decode ( &sv_p_secp[0], sv_p_secp.size() ); BigInt bi_a_secp = BigInt::decode ( &sv_a_secp[0], sv_a_secp.size() ); @@ -196,7 +196,7 @@ void test_point_mult () const CurveGFp& curve = secp160r1.get_curve(); std::string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82"; - SecureVector<byte> sv_G_secp_comp = hex_decode(G_secp_comp); + secure_vector<byte> sv_G_secp_comp = hex_decode(G_secp_comp); PointGFp p_G = OS2ECP(sv_G_secp_comp, curve); BigInt d_U("0xaa374ffc3ce144e6b073307972cb6d57b2a4e982"); @@ -215,10 +215,10 @@ void test_point_negative() std::string a_secp = "ffffffffffffffffffffffffffffffff7ffffffc"; std::string b_secp = "1c97befc54bd7a8b65acf89f81d4d4adc565fa45"; std::string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82"; - SecureVector<byte> sv_p_secp = hex_decode ( p_secp ); - SecureVector<byte> sv_a_secp = hex_decode ( a_secp ); - SecureVector<byte> sv_b_secp = hex_decode ( b_secp ); - SecureVector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp ); + secure_vector<byte> sv_p_secp = hex_decode ( p_secp ); + secure_vector<byte> sv_a_secp = hex_decode ( a_secp ); + secure_vector<byte> sv_b_secp = hex_decode ( b_secp ); + secure_vector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp ); BigInt bi_p_secp = BigInt::decode ( &sv_p_secp[0], sv_p_secp.size() ); BigInt bi_a_secp = BigInt::decode ( &sv_a_secp[0], sv_a_secp.size() ); BigInt bi_b_secp = BigInt::decode ( &sv_b_secp[0], sv_b_secp.size() ); @@ -242,7 +242,7 @@ void test_zeropoint() std::string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82"; - SecureVector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp ); + secure_vector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp ); BigInt bi_p_secp("0xffffffffffffffffffffffffffffffff7fffffff"); BigInt bi_a_secp("0xffffffffffffffffffffffffffffffff7ffffffc"); BigInt bi_b_secp("0x1c97befc54bd7a8b65acf89f81d4d4adc565fa45"); @@ -273,7 +273,7 @@ void test_zeropoint_enc_dec() CHECK_MESSAGE( p.is_zero(), "by constructor created zeropoint is no zeropoint!"); - SecureVector<byte> sv_p = EC2OSP(p, PointGFp::UNCOMPRESSED); + secure_vector<byte> sv_p = EC2OSP(p, PointGFp::UNCOMPRESSED); PointGFp p_encdec = OS2ECP(sv_p, curve); CHECK_MESSAGE( p == p_encdec, "encoded-decoded (uncompressed) point is not equal the original!"); @@ -291,7 +291,7 @@ void test_calc_with_zeropoint() std::cout << "." << std::flush; std::string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82"; - SecureVector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp ); + secure_vector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp ); BigInt bi_p_secp("0xffffffffffffffffffffffffffffffff7fffffff"); BigInt bi_a_secp("0xffffffffffffffffffffffffffffffff7ffffffc"); BigInt bi_b_secp("0x1c97befc54bd7a8b65acf89f81d4d4adc565fa45"); @@ -327,10 +327,10 @@ void test_add_point() std::string a_secp = "ffffffffffffffffffffffffffffffff7ffffffc"; std::string b_secp = "1c97befc54bd7a8b65acf89f81d4d4adc565fa45"; std::string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82"; - SecureVector<byte> sv_p_secp = hex_decode ( p_secp ); - SecureVector<byte> sv_a_secp = hex_decode ( a_secp ); - SecureVector<byte> sv_b_secp = hex_decode ( b_secp ); - SecureVector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp ); + secure_vector<byte> sv_p_secp = hex_decode ( p_secp ); + secure_vector<byte> sv_a_secp = hex_decode ( a_secp ); + secure_vector<byte> sv_b_secp = hex_decode ( b_secp ); + secure_vector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp ); BigInt bi_p_secp = BigInt::decode ( &sv_p_secp[0], sv_p_secp.size() ); BigInt bi_a_secp = BigInt::decode ( &sv_a_secp[0], sv_a_secp.size() ); BigInt bi_b_secp = BigInt::decode ( &sv_b_secp[0], sv_b_secp.size() ); @@ -363,10 +363,10 @@ void test_sub_point() std::string a_secp = "ffffffffffffffffffffffffffffffff7ffffffc"; std::string b_secp = "1c97befc54bd7a8b65acf89f81d4d4adc565fa45"; std::string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82"; - SecureVector<byte> sv_p_secp = hex_decode ( p_secp ); - SecureVector<byte> sv_a_secp = hex_decode ( a_secp ); - SecureVector<byte> sv_b_secp = hex_decode ( b_secp ); - SecureVector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp ); + secure_vector<byte> sv_p_secp = hex_decode ( p_secp ); + secure_vector<byte> sv_a_secp = hex_decode ( a_secp ); + secure_vector<byte> sv_b_secp = hex_decode ( b_secp ); + secure_vector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp ); BigInt bi_p_secp = BigInt::decode ( &sv_p_secp[0], sv_p_secp.size() ); BigInt bi_a_secp = BigInt::decode ( &sv_a_secp[0], sv_a_secp.size() ); BigInt bi_b_secp = BigInt::decode ( &sv_b_secp[0], sv_b_secp.size() ); @@ -398,10 +398,10 @@ void test_mult_point() std::string a_secp = "ffffffffffffffffffffffffffffffff7ffffffc"; std::string b_secp = "1c97befc54bd7a8b65acf89f81d4d4adc565fa45"; std::string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82"; - SecureVector<byte> sv_p_secp = hex_decode ( p_secp ); - SecureVector<byte> sv_a_secp = hex_decode ( a_secp ); - SecureVector<byte> sv_b_secp = hex_decode ( b_secp ); - SecureVector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp ); + secure_vector<byte> sv_p_secp = hex_decode ( p_secp ); + secure_vector<byte> sv_a_secp = hex_decode ( a_secp ); + secure_vector<byte> sv_b_secp = hex_decode ( b_secp ); + secure_vector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp ); BigInt bi_p_secp = BigInt::decode ( &sv_p_secp[0], sv_p_secp.size() ); BigInt bi_a_secp = BigInt::decode ( &sv_a_secp[0], sv_a_secp.size() ); BigInt bi_b_secp = BigInt::decode ( &sv_b_secp[0], sv_b_secp.size() ); @@ -427,10 +427,10 @@ void test_basic_operations() std::string a_secp = "ffffffffffffffffffffffffffffffff7ffffffc"; std::string b_secp = "1c97befc54bd7a8b65acf89f81d4d4adc565fa45"; std::string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82"; - SecureVector<byte> sv_p_secp = hex_decode ( p_secp ); - SecureVector<byte> sv_a_secp = hex_decode ( a_secp ); - SecureVector<byte> sv_b_secp = hex_decode ( b_secp ); - SecureVector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp ); + secure_vector<byte> sv_p_secp = hex_decode ( p_secp ); + secure_vector<byte> sv_a_secp = hex_decode ( a_secp ); + secure_vector<byte> sv_b_secp = hex_decode ( b_secp ); + secure_vector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp ); BigInt bi_p_secp = BigInt::decode ( &sv_p_secp[0], sv_p_secp.size() ); BigInt bi_a_secp = BigInt::decode ( &sv_a_secp[0], sv_a_secp.size() ); BigInt bi_b_secp = BigInt::decode ( &sv_b_secp[0], sv_b_secp.size() ); @@ -490,10 +490,10 @@ void test_enc_dec_compressed_160() std::string G_secp_comp = "024A96B5688EF573284664698968C38BB913CBFC82"; std::string G_order_secp_comp = "0100000000000000000001F4C8F927AED3CA752257"; - SecureVector<byte> sv_p_secp = hex_decode ( p_secp ); - SecureVector<byte> sv_a_secp = hex_decode ( a_secp ); - SecureVector<byte> sv_b_secp = hex_decode ( b_secp ); - SecureVector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp ); + secure_vector<byte> sv_p_secp = hex_decode ( p_secp ); + secure_vector<byte> sv_a_secp = hex_decode ( a_secp ); + secure_vector<byte> sv_b_secp = hex_decode ( b_secp ); + secure_vector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp ); BigInt bi_p_secp = BigInt::decode ( &sv_p_secp[0], sv_p_secp.size() ); BigInt bi_a_secp = BigInt::decode ( &sv_a_secp[0], sv_a_secp.size() ); @@ -502,7 +502,7 @@ void test_enc_dec_compressed_160() CurveGFp secp160r1(bi_p_secp, bi_a_secp, bi_b_secp); PointGFp p_G = OS2ECP ( sv_G_secp_comp, secp160r1 ); - SecureVector<byte> sv_result = EC2OSP(p_G, PointGFp::COMPRESSED); + secure_vector<byte> sv_result = EC2OSP(p_G, PointGFp::COMPRESSED); CHECK( sv_result == sv_G_secp_comp); } @@ -519,10 +519,10 @@ void test_enc_dec_compressed_256() std::string G_secp_comp = "036B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296"; std::string G_order_secp_comp = "ffffffff00000000ffffffffffffffffBCE6FAADA7179E84F3B9CAC2FC632551"; - SecureVector<byte> sv_p_secp = hex_decode ( p_secp ); - SecureVector<byte> sv_a_secp = hex_decode ( a_secp ); - SecureVector<byte> sv_b_secp = hex_decode ( b_secp ); - SecureVector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp ); + secure_vector<byte> sv_p_secp = hex_decode ( p_secp ); + secure_vector<byte> sv_a_secp = hex_decode ( a_secp ); + secure_vector<byte> sv_b_secp = hex_decode ( b_secp ); + secure_vector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp ); BigInt bi_p_secp = BigInt::decode ( &sv_p_secp[0], sv_p_secp.size() ); BigInt bi_a_secp = BigInt::decode ( &sv_a_secp[0], sv_a_secp.size() ); @@ -531,7 +531,7 @@ void test_enc_dec_compressed_256() CurveGFp secp160r1(bi_p_secp, bi_a_secp, bi_b_secp); PointGFp p_G = OS2ECP ( sv_G_secp_comp, secp160r1 ); - SecureVector<byte> sv_result = EC2OSP(p_G, PointGFp::COMPRESSED); + secure_vector<byte> sv_result = EC2OSP(p_G, PointGFp::COMPRESSED); CHECK( sv_result == sv_G_secp_comp); } @@ -550,10 +550,10 @@ void test_enc_dec_uncompressed_112() std::string G_secp_uncomp = "044BA30AB5E892B4E1649DD0928643ADCD46F5882E3747DEF36E956E97"; std::string G_order_secp_uncomp = "36DF0AAFD8B8D7597CA10520D04B"; - SecureVector<byte> sv_p_secp = hex_decode ( p_secp ); - SecureVector<byte> sv_a_secp = hex_decode ( a_secp ); - SecureVector<byte> sv_b_secp = hex_decode ( b_secp ); - SecureVector<byte> sv_G_secp_uncomp = hex_decode ( G_secp_uncomp ); + secure_vector<byte> sv_p_secp = hex_decode ( p_secp ); + secure_vector<byte> sv_a_secp = hex_decode ( a_secp ); + secure_vector<byte> sv_b_secp = hex_decode ( b_secp ); + secure_vector<byte> sv_G_secp_uncomp = hex_decode ( G_secp_uncomp ); BigInt bi_p_secp = BigInt::decode ( &sv_p_secp[0], sv_p_secp.size() ); BigInt bi_a_secp = BigInt::decode ( &sv_a_secp[0], sv_a_secp.size() ); @@ -562,7 +562,7 @@ void test_enc_dec_uncompressed_112() CurveGFp secp160r1(bi_p_secp, bi_a_secp, bi_b_secp); PointGFp p_G = OS2ECP ( sv_G_secp_uncomp, secp160r1 ); - SecureVector<byte> sv_result = EC2OSP(p_G, PointGFp::UNCOMPRESSED); + secure_vector<byte> sv_result = EC2OSP(p_G, PointGFp::UNCOMPRESSED); CHECK( sv_result == sv_G_secp_uncomp); } @@ -579,10 +579,10 @@ void test_enc_dec_uncompressed_521() std::string G_secp_uncomp = "0400C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2ffA8DE3348B3C1856A429BF97E7E31C2E5BD66011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650"; std::string G_order_secp_uncomp = "01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409"; - SecureVector<byte> sv_p_secp = hex_decode ( p_secp ); - SecureVector<byte> sv_a_secp = hex_decode ( a_secp ); - SecureVector<byte> sv_b_secp = hex_decode ( b_secp ); - SecureVector<byte> sv_G_secp_uncomp = hex_decode ( G_secp_uncomp ); + secure_vector<byte> sv_p_secp = hex_decode ( p_secp ); + secure_vector<byte> sv_a_secp = hex_decode ( a_secp ); + secure_vector<byte> sv_b_secp = hex_decode ( b_secp ); + secure_vector<byte> sv_G_secp_uncomp = hex_decode ( G_secp_uncomp ); BigInt bi_p_secp = BigInt::decode ( &sv_p_secp[0], sv_p_secp.size() ); BigInt bi_a_secp = BigInt::decode ( &sv_a_secp[0], sv_a_secp.size() ); @@ -592,7 +592,7 @@ void test_enc_dec_uncompressed_521() PointGFp p_G = OS2ECP ( sv_G_secp_uncomp, secp160r1 ); - SecureVector<byte> sv_result = EC2OSP(p_G, PointGFp::UNCOMPRESSED); + secure_vector<byte> sv_result = EC2OSP(p_G, PointGFp::UNCOMPRESSED); std::string result = hex_encode(&sv_result[0], sv_result.size()); std::string exp_result = hex_encode(&sv_G_secp_uncomp[0], sv_G_secp_uncomp.size()); @@ -611,21 +611,21 @@ void test_enc_dec_uncompressed_521_prime_too_large() std::string G_secp_uncomp = "0400C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2ffA8DE3348B3C1856A429BF97E7E31C2E5BD66011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650"; std::string G_order_secp_uncomp = "01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409"; - SecureVector<byte> sv_p_secp = hex_decode ( p_secp ); - SecureVector<byte> sv_a_secp = hex_decode ( a_secp ); - SecureVector<byte> sv_b_secp = hex_decode ( b_secp ); - SecureVector<byte> sv_G_secp_uncomp = hex_decode ( G_secp_uncomp ); + secure_vector<byte> sv_p_secp = hex_decode ( p_secp ); + secure_vector<byte> sv_a_secp = hex_decode ( a_secp ); + secure_vector<byte> sv_b_secp = hex_decode ( b_secp ); + secure_vector<byte> sv_G_secp_uncomp = hex_decode ( G_secp_uncomp ); BigInt bi_p_secp = BigInt::decode ( &sv_p_secp[0], sv_p_secp.size() ); BigInt bi_a_secp = BigInt::decode ( &sv_a_secp[0], sv_a_secp.size() ); BigInt bi_b_secp = BigInt::decode ( &sv_b_secp[0], sv_b_secp.size() ); CurveGFp secp521r1 (bi_p_secp, bi_a_secp, bi_b_secp); - std::auto_ptr<PointGFp> p_G; + std::unique_ptr<PointGFp> p_G; bool exc = false; try { - p_G = std::auto_ptr<PointGFp>(new PointGFp(OS2ECP ( sv_G_secp_uncomp, secp521r1))); + p_G = std::unique_ptr<PointGFp>(new PointGFp(OS2ECP ( sv_G_secp_uncomp, secp521r1))); if(!p_G->on_the_curve()) throw Internal_Error("Point not on the curve"); } @@ -648,7 +648,7 @@ void test_gfp_store_restore() PointGFp p = dom_pars.get_base_point(); //store point (to std::string) - SecureVector<byte> sv_mes = EC2OSP(p, PointGFp::COMPRESSED); + secure_vector<byte> sv_mes = EC2OSP(p, PointGFp::COMPRESSED); PointGFp new_p = OS2ECP(sv_mes, dom_pars.get_curve()); CHECK_MESSAGE( p == new_p, "original and restored point are different!"); @@ -662,7 +662,7 @@ void test_cdc_curve_33() std::string G_secp_uncomp = "04081523d03d4f12cd02879dea4bf6a4f3a7df26ed888f10c5b2235a1274c386a2f218300dee6ed217841164533bcdc903f07a096f9fbf4ee95bac098a111f296f5830fe5c35b3e344d5df3a2256985f64fbe6d0edcc4c61d18bef681dd399df3d0194c5a4315e012e0245ecea56365baa9e8be1f7"; - SecureVector<byte> sv_G_uncomp = hex_decode ( G_secp_uncomp ); + secure_vector<byte> sv_G_uncomp = hex_decode ( G_secp_uncomp ); BigInt bi_p_secp = BigInt("2117607112719756483104013348936480976596328609518055062007450442679169492999007105354629105748524349829824407773719892437896937279095106809"); BigInt bi_a_secp("0xa377dede6b523333d36c78e9b0eaa3bf48ce93041f6d4fc34014d08f6833807498deedd4290101c5866e8dfb589485d13357b9e78c2d7fbe9fe"); @@ -689,7 +689,7 @@ void test_more_zeropoint() // by Falko std::string G = "024a96b5688ef573284664698968c38bb913cbfc82"; - SecureVector<byte> sv_G_secp_comp = hex_decode ( G ); + secure_vector<byte> sv_G_secp_comp = hex_decode ( G ); BigInt bi_p("0xffffffffffffffffffffffffffffffff7fffffff"); BigInt bi_a("0xffffffffffffffffffffffffffffffff7ffffffc"); BigInt bi_b("0x1c97befc54bd7a8b65acf89f81d4d4adc565fa45"); diff --git a/checks/ecdh.cpp b/checks/ecdh.cpp index c641796d6..841bce55b 100644 --- a/checks/ecdh.cpp +++ b/checks/ecdh.cpp @@ -96,8 +96,8 @@ void test_ecdh_der_derivation(RandomNumberGenerator& rng) ECDH_PrivateKey private_a(rng, dom_pars); ECDH_PrivateKey private_b(rng, dom_pars); - MemoryVector<byte> key_a = private_a.public_value(); - MemoryVector<byte> key_b = private_b.public_value(); + std::vector<byte> key_a = private_a.public_value(); + std::vector<byte> key_b = private_b.public_value(); PK_Key_Agreement ka(private_a, "KDF2(SHA-1)"); PK_Key_Agreement kb(private_b, "KDF2(SHA-1)"); diff --git a/checks/ecdsa.cpp b/checks/ecdsa.cpp index 5cf353e58..554f72dd7 100644 --- a/checks/ecdsa.cpp +++ b/checks/ecdsa.cpp @@ -32,7 +32,7 @@ using namespace Botan; namespace { -std::string to_hex(const SecureVector<byte>& bin) +std::string to_hex(const std::vector<byte>& bin) { return hex_encode(&bin[0], bin.size()); } @@ -54,7 +54,7 @@ void test_hash_larger_than_n(RandomNumberGenerator& rng) ECDSA_PrivateKey priv_key(rng, dom_pars); - SecureVector<byte> message(20); + std::vector<byte> message(20); for(size_t i = 0; i != message.size(); ++i) message[i] = i; @@ -64,14 +64,14 @@ void test_hash_larger_than_n(RandomNumberGenerator& rng) PK_Signer pk_signer_224(priv_key, "EMSA1_BSI(SHA-224)"); // Verify we can sign and verify with SHA-160 - SecureVector<byte> signature_160 = pk_signer_160.sign_message(message, rng); + std::vector<byte> signature_160 = pk_signer_160.sign_message(message, rng); CHECK(pk_verifier_160.verify_message(message, signature_160)); bool signature_failed = false; try { - SecureVector<byte> signature_224 = pk_signer_224.sign_message(message, rng); + std::vector<byte> signature_224 = pk_signer_224.sign_message(message, rng); } catch(Encoding_Error) { @@ -84,7 +84,7 @@ void test_hash_larger_than_n(RandomNumberGenerator& rng) // sign it with the normal EMSA1 PK_Signer pk_signer(priv_key, "EMSA1(SHA-224)"); - SecureVector<byte> signature = pk_signer.sign_message(message, rng); + std::vector<byte> signature = pk_signer.sign_message(message, rng); PK_Verifier pk_verifier(priv_key, "EMSA1_BSI(SHA-224)"); @@ -104,7 +104,7 @@ void test_decode_ecdsa_X509() CHECK_MESSAGE(to_hex(cert.authority_key_id()) == "0096452DE588F966C4CCDF161DD1F3F5341B71E7", "error reading authority key id from x509 ecdsa certificate"); CHECK_MESSAGE(to_hex(cert.subject_key_id()) == "0096452DE588F966C4CCDF161DD1F3F5341B71E7", "error reading Subject key id from x509 ecdsa certificate"); - std::auto_ptr<X509_PublicKey> pubkey(cert.subject_public_key()); + std::unique_ptr<X509_PublicKey> pubkey(cert.subject_public_key()); bool ver_ec = cert.check_signature(*pubkey); CHECK_MESSAGE(ver_ec, "could not positively verify correct selfsigned x509-ecdsa certificate"); } @@ -116,7 +116,7 @@ void test_decode_ver_link_SHA256() X509_Certificate root_cert(TEST_DATA_DIR "/root2_SHA256.cer"); X509_Certificate link_cert(TEST_DATA_DIR "/link_SHA256.cer"); - std::auto_ptr<X509_PublicKey> pubkey(root_cert.subject_public_key()); + std::unique_ptr<X509_PublicKey> pubkey(root_cert.subject_public_key()); bool ver_ec = link_cert.check_signature(*pubkey); CHECK_MESSAGE(ver_ec, "could not positively verify correct SHA256 link x509-ecdsa certificate"); @@ -128,7 +128,7 @@ void test_decode_ver_link_SHA1() X509_Certificate root_cert(TEST_DATA_DIR "/root_SHA1.163.crt"); X509_Certificate link_cert(TEST_DATA_DIR "/link_SHA1.166.crt"); - std::auto_ptr<X509_PublicKey> pubkey(root_cert.subject_public_key()); + std::unique_ptr<X509_PublicKey> pubkey(root_cert.subject_public_key()); bool ver_ec = link_cert.check_signature(*pubkey); CHECK_MESSAGE(ver_ec, "could not positively verify correct SHA1 link x509-ecdsa certificate"); } @@ -142,8 +142,8 @@ void test_sign_then_ver(RandomNumberGenerator& rng) PK_Signer signer(ecdsa, "EMSA1(SHA-1)"); - SecureVector<byte> msg = hex_decode("12345678901234567890abcdef12"); - SecureVector<byte> sig = signer.sign_message(msg, rng); + secure_vector<byte> msg = hex_decode("12345678901234567890abcdef12"); + std::vector<byte> sig = signer.sign_message(msg, rng); PK_Verifier verifier(ecdsa, "EMSA1(SHA-1)"); @@ -174,7 +174,7 @@ bool test_ec_sign(RandomNumberGenerator& rng) for(size_t i = 0; i != 256; ++i) signer.update(static_cast<byte>(i)); - SecureVector<byte> sig = signer.signature(rng); + std::vector<byte> sig = signer.signature(rng); for(u32bit i = 0; i != 256; ++i) verifier.update(static_cast<byte>(i)); @@ -251,11 +251,11 @@ void test_create_and_verify(RandomNumberGenerator& rng) std::ofstream priv_key(TEST_DATA_DIR "/dompar_private.pkcs8.pem"); priv_key << PKCS8::PEM_encode(key); - std::auto_ptr<PKCS8_PrivateKey> loaded_key(PKCS8::load_key(TEST_DATA_DIR "/wo_dompar_private.pkcs8.pem", rng)); + std::unique_ptr<PKCS8_PrivateKey> loaded_key(PKCS8::load_key(TEST_DATA_DIR "/wo_dompar_private.pkcs8.pem", rng)); ECDSA_PrivateKey* loaded_ec_key = dynamic_cast<ECDSA_PrivateKey*>(loaded_key.get()); CHECK_MESSAGE(loaded_ec_key, "the loaded key could not be converted into an ECDSA_PrivateKey"); - std::auto_ptr<PKCS8_PrivateKey> loaded_key_1(PKCS8::load_key(TEST_DATA_DIR "/rsa_private.pkcs8.pem", rng)); + std::unique_ptr<PKCS8_PrivateKey> loaded_key_1(PKCS8::load_key(TEST_DATA_DIR "/rsa_private.pkcs8.pem", rng)); ECDSA_PrivateKey* loaded_rsa_key = dynamic_cast<ECDSA_PrivateKey*>(loaded_key_1.get()); CHECK_MESSAGE(!loaded_rsa_key, "the loaded key is ECDSA_PrivateKey -> shouldn't be, is a RSA-Key"); @@ -267,11 +267,11 @@ void test_create_and_verify(RandomNumberGenerator& rng) std::string G_secp_comp = "04081523d03d4f12cd02879dea4bf6a4f3a7df26ed888f10c5b2235a1274c386a2f218300dee6ed217841164533bcdc903f07a096f9fbf4ee95bac098a111f296f5830fe5c35b3e344d5df3a2256985f64fbe6d0edcc4c61d18bef681dd399df3d0194c5a4315e012e0245ecea56365baa9e8be1f7"; std::string order_g = "0e1a16196e6000000000bc7f1618d867b15bb86474418f"; - // ::SecureVector<byte> sv_p_secp = hex_decode ( p_secp ); - SecureVector<byte> sv_a_secp = hex_decode ( a_secp ); - SecureVector<byte> sv_b_secp = hex_decode ( b_secp ); - SecureVector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp ); - SecureVector<byte> sv_order_g = hex_decode ( order_g ); + // ::std::vector<byte> sv_p_secp = hex_decode ( p_secp ); + secure_vector<byte> sv_a_secp = hex_decode ( a_secp ); + secure_vector<byte> sv_b_secp = hex_decode ( b_secp ); + secure_vector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp ); + secure_vector<byte> sv_order_g = hex_decode ( order_g ); // BigInt bi_p_secp = BigInt::decode ( &sv_p_secp[0], sv_p_secp.size() ); BigInt bi_p_secp("2117607112719756483104013348936480976596328609518055062007450442679169492999007105354629105748524349829824407773719892437896937279095106809"); @@ -289,7 +289,7 @@ void test_create_and_verify(RandomNumberGenerator& rng) std::string key_odd_oid_str = PKCS8::PEM_encode(key_odd_oid); DataSource_Memory key_data_src(key_odd_oid_str); - std::auto_ptr<PKCS8_PrivateKey> loaded_key2(PKCS8::load_key(key_data_src, rng)); + std::unique_ptr<PKCS8_PrivateKey> loaded_key2(PKCS8::load_key(key_data_src, rng)); if(!dynamic_cast<ECDSA_PrivateKey*>(loaded_key.get())) { @@ -343,8 +343,8 @@ void test_curve_registry(RandomNumberGenerator& rng) PK_Signer signer(ecdsa, "EMSA1(SHA-1)"); PK_Verifier verifier(ecdsa, "EMSA1(SHA-1)"); - SecureVector<byte> msg = hex_decode("12345678901234567890abcdef12"); - SecureVector<byte> sig = signer.sign_message(msg, rng); + secure_vector<byte> msg = hex_decode("12345678901234567890abcdef12"); + std::vector<byte> sig = signer.sign_message(msg, rng); if(!verifier.verify_message(msg, sig)) std::cout << "Failed testing ECDSA sig for curve " << oids[i] << "\n"; @@ -361,17 +361,17 @@ void test_read_pkcs8(RandomNumberGenerator& rng) { std::cout << "." << std::flush; - SecureVector<byte> msg = hex_decode("12345678901234567890abcdef12"); + secure_vector<byte> msg = hex_decode("12345678901234567890abcdef12"); try { - std::auto_ptr<PKCS8_PrivateKey> loaded_key(PKCS8::load_key(TEST_DATA_DIR "/wo_dompar_private.pkcs8.pem", rng)); + std::unique_ptr<PKCS8_PrivateKey> loaded_key(PKCS8::load_key(TEST_DATA_DIR "/wo_dompar_private.pkcs8.pem", rng)); ECDSA_PrivateKey* ecdsa = dynamic_cast<ECDSA_PrivateKey*>(loaded_key.get()); CHECK_MESSAGE(ecdsa, "the loaded key could not be converted into an ECDSA_PrivateKey"); PK_Signer signer(*ecdsa, "EMSA1(SHA-1)"); - SecureVector<byte> sig = signer.sign_message(msg, rng); + std::vector<byte> sig = signer.sign_message(msg, rng); PK_Verifier verifier(*ecdsa, "EMSA1(SHA-1)"); @@ -385,7 +385,7 @@ void test_read_pkcs8(RandomNumberGenerator& rng) try { - std::auto_ptr<PKCS8_PrivateKey> loaded_key_nodp(PKCS8::load_key(TEST_DATA_DIR "/nodompar_private.pkcs8.pem", rng)); + std::unique_ptr<PKCS8_PrivateKey> loaded_key_nodp(PKCS8::load_key(TEST_DATA_DIR "/nodompar_private.pkcs8.pem", rng)); // anew in each test with unregistered domain-parameters ECDSA_PrivateKey* ecdsa_nodp = dynamic_cast<ECDSA_PrivateKey*>(loaded_key_nodp.get()); CHECK_MESSAGE(ecdsa_nodp, "the loaded key could not be converted into an ECDSA_PrivateKey"); @@ -393,14 +393,14 @@ void test_read_pkcs8(RandomNumberGenerator& rng) PK_Signer signer(*ecdsa_nodp, "EMSA1(SHA-1)"); PK_Verifier verifier(*ecdsa_nodp, "EMSA1(SHA-1)"); - SecureVector<byte> signature_nodp = signer.sign_message(msg, rng); + std::vector<byte> signature_nodp = signer.sign_message(msg, rng); CHECK_MESSAGE(verifier.verify_message(msg, signature_nodp), "generated signature could not be verified positively (no_dom)"); try { - std::auto_ptr<PKCS8_PrivateKey> loaded_key_withdp( + std::unique_ptr<PKCS8_PrivateKey> loaded_key_withdp( PKCS8::load_key(TEST_DATA_DIR "/withdompar_private.pkcs8.pem", rng)); std::cout << "Unexpected success: loaded key with unknown OID\n"; diff --git a/checks/pk.cpp b/checks/pk.cpp index 6291b1566..5ef5df94b 100644 --- a/checks/pk.cpp +++ b/checks/pk.cpp @@ -14,6 +14,12 @@ #include <botan/botan.h> #include <botan/oids.h> +#if defined(BOTAN_HAS_PUBLIC_KEY_CRYPTO) + #include <botan/x509_key.h> + #include <botan/pkcs8.h> + #include <botan/pubkey.h> +#endif + #if defined(BOTAN_HAS_RSA) #include <botan/rsa.h> #endif @@ -79,8 +85,8 @@ BigInt to_bigint(std::string input) input.length(), BigInt::Hexadecimal); } -void dump_data(const SecureVector<byte>& out, - const SecureVector<byte>& expected) +void dump_data(const std::vector<byte>& out, + const std::vector<byte>& expected) { Pipe pipe(new Hex_Encoder); @@ -102,7 +108,7 @@ void validate_save_and_load(const Private_Key* priv_key, DataSource_Memory input_pub(pub_pem); std::auto_ptr<Public_Key> restored_pub(X509::load_key(input_pub)); - if(restored_pub.get() == 0) + if(!restored_pub.get()) std::cout << "Could not recover " << name << " public key\n"; else if(restored_pub->check_key(rng, true) == false) std::cout << "Restored pubkey failed self tests " << name << "\n"; @@ -122,7 +128,7 @@ void validate_save_and_load(const Private_Key* priv_key, std::auto_ptr<Private_Key> restored_priv( PKCS8::load_key(input_priv, rng)); - if(restored_priv.get() == 0) + if(!restored_priv.get()) std::cout << "Could not recover " << name << " privlic key\n"; else if(restored_priv->check_key(rng, true) == false) std::cout << "Restored privkey failed self tests " << name << "\n"; @@ -136,11 +142,11 @@ void validate_save_and_load(const Private_Key* priv_key, } void validate_decryption(PK_Decryptor& d, const std::string& algo, - const SecureVector<byte> ctext, - const SecureVector<byte> ptext, + const std::vector<byte> ctext, + const std::vector<byte> ptext, bool& failure) { - SecureVector<byte> decrypted = d.decrypt(ctext); + std::vector<byte> decrypted = unlock(d.decrypt(ctext)); if(decrypted != ptext) { std::cout << "FAILED (decrypt): " << algo << std::endl; @@ -154,11 +160,11 @@ void validate_encryption(PK_Encryptor& e, PK_Decryptor& d, const std::string& random, const std::string& exp, bool& failure) { - SecureVector<byte> message = hex_decode(input); - SecureVector<byte> expected = hex_decode(exp); + std::vector<byte> message = unlock(hex_decode(input)); + std::vector<byte> expected = unlock(hex_decode(exp)); Fixed_Output_RNG rng(hex_decode(random)); - SecureVector<byte> out = e.encrypt(message, rng); + std::vector<byte> out = e.encrypt(message, rng); if(out != expected) { std::cout << "FAILED (encrypt): " << algo << std::endl; @@ -174,11 +180,11 @@ void validate_signature(PK_Verifier& v, PK_Signer& s, const std::string& algo, RandomNumberGenerator& rng, const std::string& exp, bool& failure) { - SecureVector<byte> message = hex_decode(input); + std::vector<byte> message = unlock(hex_decode(input)); - SecureVector<byte> expected = hex_decode(exp); + std::vector<byte> expected = unlock(hex_decode(exp)); - SecureVector<byte> sig = s.sign_message(message, rng); + std::vector<byte> sig = s.sign_message(message, rng); if(sig != expected) { @@ -214,18 +220,18 @@ void validate_signature(PK_Verifier& v, PK_Signer& s, const std::string& algo, } void validate_kas(PK_Key_Agreement& kas, const std::string& algo, - const SecureVector<byte>& pubkey, const std::string& output, + const std::vector<byte>& pubkey, const std::string& output, u32bit keylen, bool& failure) { - SecureVector<byte> expected = hex_decode(output); + secure_vector<byte> expected = hex_decode(output); - SecureVector<byte> got = kas.derive_key(keylen, - pubkey).bits_of(); + secure_vector<byte> got = kas.derive_key(keylen, + pubkey).bits_of(); if(got != expected) { std::cout << "FAILED: " << algo << std::endl; - dump_data(got, expected); + dump_data(unlock(got), unlock(expected)); failure = true; } } @@ -247,7 +253,7 @@ u32bit validate_rsa_enc_pkcs8(const std::string& algo, DataSource_Memory keysource(reinterpret_cast<const byte*>(str[0].c_str()), str[0].length()); - std::auto_ptr<Private_Key> privkey(PKCS8::load_key(keysource, rng, pass)); + std::unique_ptr<Private_Key> privkey(PKCS8::load_key(keysource, rng, pass)); RSA_PrivateKey* rsapriv = dynamic_cast<RSA_PrivateKey*>(privkey.get()); if(!rsapriv) @@ -319,8 +325,8 @@ u32bit validate_elg_enc(const std::string& algo, validate_encryption(e, d, algo, str[4], str[5], str[6], failure); } else - validate_decryption(d, algo, hex_decode(str[5]), - hex_decode(str[4]), failure); + validate_decryption(d, algo, unlock(hex_decode(str[5])), + unlock(hex_decode(str[4])), failure); return (failure ? 1 : 0); #endif @@ -367,8 +373,8 @@ u32bit validate_rsa_ver(const std::string& algo, PK_Verifier v(key, emsa); - SecureVector<byte> msg = hex_decode(str[2]); - SecureVector<byte> sig = hex_decode(str[3]); + std::vector<byte> msg = unlock(hex_decode(str[2])); + std::vector<byte> sig = unlock(hex_decode(str[3])); bool passed = true; passed = v.verify_message(msg, sig); @@ -388,7 +394,7 @@ u32bit validate_rsa_ver_x509(const std::string& algo, DataSource_Memory keysource(reinterpret_cast<const byte*>(str[0].c_str()), str[0].length()); - std::auto_ptr<Public_Key> key(X509::load_key(keysource)); + std::unique_ptr<Public_Key> key(X509::load_key(keysource)); RSA_PublicKey* rsakey = dynamic_cast<RSA_PublicKey*>(key.get()); @@ -399,8 +405,8 @@ u32bit validate_rsa_ver_x509(const std::string& algo, PK_Verifier v(*rsakey, emsa); - SecureVector<byte> msg = hex_decode(str[1]); - SecureVector<byte> sig = hex_decode(str[2]); + std::vector<byte> msg = unlock(hex_decode(str[1])); + std::vector<byte> sig = unlock(hex_decode(str[2])); bool passed = v.verify_message(msg, sig); return (passed ? 0 : 1); @@ -423,8 +429,8 @@ u32bit validate_rw_ver(const std::string& algo, PK_Verifier v(key, emsa); - SecureVector<byte> msg = hex_decode(str[2]); - SecureVector<byte> sig = hex_decode(str[3]); + std::vector<byte> msg = unlock(hex_decode(str[2])); + std::vector<byte> sig = unlock(hex_decode(str[3])); bool passed = true; passed = v.verify_message(msg, sig); @@ -476,7 +482,7 @@ u32bit validate_dsa_sig(const std::string& algo, DataSource_Memory keysource(reinterpret_cast<const byte*>(str[0].c_str()), str[0].length()); - std::auto_ptr<Private_Key> privkey(PKCS8::load_key(keysource, rng, pass)); + std::unique_ptr<Private_Key> privkey(PKCS8::load_key(keysource, rng, pass)); DSA_PrivateKey* dsapriv = dynamic_cast<DSA_PrivateKey*>(privkey.get()); if(!dsapriv) @@ -532,7 +538,7 @@ u32bit validate_gost_ver(const std::string& algo, EC_Group group(OIDS::lookup(str[0])); - PointGFp public_point = OS2ECP(hex_decode(str[1]), group.get_curve()); + PointGFp public_point = OS2ECP(unlock(hex_decode(str[1])), group.get_curve()); GOST_3410_PublicKey gost(group, public_point); @@ -540,8 +546,8 @@ u32bit validate_gost_ver(const std::string& algo, PK_Verifier v(gost, emsa); - SecureVector<byte> msg = hex_decode(str[2]); - SecureVector<byte> sig = hex_decode(str[3]); + std::vector<byte> msg = unlock(hex_decode(str[2])); + std::vector<byte> sig = unlock(hex_decode(str[3])); bool passed = v.verify_message(msg, sig); return (passed ? 0 : 1); @@ -561,7 +567,7 @@ u32bit validate_dsa_ver(const std::string& algo, #if defined(BOTAN_HAS_DSA) - std::auto_ptr<Public_Key> key(X509::load_key(keysource)); + std::unique_ptr<Public_Key> key(X509::load_key(keysource)); DSA_PublicKey* dsakey = dynamic_cast<DSA_PublicKey*>(key.get()); @@ -572,8 +578,8 @@ u32bit validate_dsa_ver(const std::string& algo, PK_Verifier v(*dsakey, emsa); - SecureVector<byte> msg = hex_decode(str[1]); - SecureVector<byte> sig = hex_decode(str[2]); + std::vector<byte> msg = unlock(hex_decode(str[1])); + std::vector<byte> sig = unlock(hex_decode(str[2])); v.set_input_format(DER_SEQUENCE); bool passed = v.verify_message(msg, sig); diff --git a/checks/pk_bench.cpp b/checks/pk_bench.cpp index de8ad0730..da2221b90 100644 --- a/checks/pk_bench.cpp +++ b/checks/pk_bench.cpp @@ -10,6 +10,12 @@ #include <botan/oids.h> #include <map> +#if defined(BOTAN_HAS_PUBLIC_KEY_CRYPTO) + #include <botan/x509_key.h> + #include <botan/pkcs8.h> + #include <botan/pubkey.h> +#endif + #if defined(BOTAN_HAS_RSA) #include <botan/rsa.h> #endif @@ -77,7 +83,7 @@ const char* ec_domains[] = { "secp256r1", "secp384r1", "secp521r1", - 0 + nullptr }; class Benchmark_Report @@ -98,7 +104,7 @@ void benchmark_enc_dec(PK_Encryptor& enc, PK_Decryptor& dec, RandomNumberGenerator& rng, u32bit runs, double seconds) { - SecureVector<byte> plaintext, ciphertext; + std::vector<byte> plaintext, ciphertext; for(u32bit i = 0; i != runs; ++i) { @@ -121,7 +127,7 @@ void benchmark_enc_dec(PK_Encryptor& enc, PK_Decryptor& dec, if(dec_timer.seconds() < seconds) { dec_timer.start(); - SecureVector<byte> plaintext_out = dec.decrypt(ciphertext); + std::vector<byte> plaintext_out = unlock(dec.decrypt(ciphertext)); dec_timer.stop(); if(plaintext_out != plaintext) @@ -137,7 +143,7 @@ void benchmark_sig_ver(PK_Verifier& ver, PK_Signer& sig, RandomNumberGenerator& rng, u32bit runs, double seconds) { - SecureVector<byte> message, signature, sig_random; + std::vector<byte> message, signature, sig_random; for(u32bit i = 0; i != runs; ++i) { @@ -165,7 +171,7 @@ void benchmark_sig_ver(PK_Verifier& ver, PK_Signer& sig, if((i % 100) == 0) { - sig_random = rng.random_vec(signature.size()); + sig_random = unlock(rng.random_vec(signature.size())); verify_timer.start(); const bool verified_bad = ver.verify_message(message, sig_random); @@ -240,7 +246,7 @@ void benchmark_rsa(RandomNumberGenerator& rng, sig_timer, rng, 10000, seconds); } - const std::string rsa_keylen = "RSA-" + to_string(keylen); + const std::string rsa_keylen = "RSA-" + std::to_string(keylen); report.report(rsa_keylen, keygen_timer); report.report(rsa_keylen, verify_timer); @@ -292,7 +298,7 @@ void benchmark_rw(RandomNumberGenerator& rng, rng, 10000, seconds); } - const std::string nm = "RW-" + to_string(keylen); + const std::string nm = "RW-" + std::to_string(keylen); report.report(nm, keygen_timer); report.report(nm, verify_timer); report.report(nm, sig_timer); @@ -319,7 +325,7 @@ void benchmark_ecdsa(RandomNumberGenerator& rng, if(hashbits == 521) hashbits = 512; - const std::string padding = "EMSA1(SHA-" + to_string(hashbits) + ")"; + const std::string padding = "EMSA1(SHA-" + std::to_string(hashbits) + ")"; Timer keygen_timer("keygen"); Timer verify_timer(padding + " verify"); @@ -339,7 +345,7 @@ void benchmark_ecdsa(RandomNumberGenerator& rng, sig_timer, rng, 1000, seconds); } - const std::string nm = "ECDSA-" + to_string(pbits); + const std::string nm = "ECDSA-" + std::to_string(pbits); report.report(nm, keygen_timer); report.report(nm, verify_timer); @@ -381,7 +387,7 @@ void benchmark_gost_3410(RandomNumberGenerator& rng, sig_timer, rng, 1000, seconds); } - const std::string nm = "GOST-34.10-" + to_string(pbits); + const std::string nm = "GOST-34.10-" + std::to_string(pbits); report.report(nm, keygen_timer); report.report(nm, verify_timer); @@ -439,7 +445,7 @@ void benchmark_ecdh(RandomNumberGenerator& rng, } } - const std::string nm = "ECDH-" + to_string(pbits); + const std::string nm = "ECDH-" + std::to_string(pbits); report.report(nm, keygen_timer); report.report(nm, kex_timer); } @@ -456,7 +462,7 @@ void benchmark_dsa_nr(RandomNumberGenerator& rng, const char* domains[] = { "dsa/jce/1024", "dsa/botan/2048", "dsa/botan/3072", - NULL }; + nullptr }; std::string algo_name; @@ -465,7 +471,7 @@ void benchmark_dsa_nr(RandomNumberGenerator& rng, size_t pbits = to_u32bit(split_on(domains[j], '/')[2]); size_t qbits = (pbits <= 1024) ? 160 : 256; - const std::string padding = "EMSA1(SHA-" + to_string(qbits) + ")"; + const std::string padding = "EMSA1(SHA-" + std::to_string(qbits) + ")"; Timer keygen_timer("keygen"); Timer verify_timer(padding + " verify"); @@ -488,7 +494,7 @@ void benchmark_dsa_nr(RandomNumberGenerator& rng, sig_timer, rng, 1000, seconds); } - const std::string nm = algo_name + "-" + to_string(pbits); + const std::string nm = algo_name + "-" + std::to_string(pbits); report.report(nm, keygen_timer); report.report(nm, verify_timer); report.report(nm, sig_timer); @@ -507,7 +513,7 @@ void benchmark_dh(RandomNumberGenerator& rng, "modp/ietf/4096", "modp/ietf/6144", "modp/ietf/8192", - NULL }; + nullptr }; for(size_t j = 0; domains[j]; j++) { @@ -568,7 +574,7 @@ void benchmark_dlies(RandomNumberGenerator& rng, "modp/ietf/4096", "modp/ietf/6144", "modp/ietf/8192", - NULL }; + nullptr }; for(size_t j = 0; domains[j]; j++) { @@ -627,7 +633,7 @@ void benchmark_elg(RandomNumberGenerator& rng, "modp/ietf/4096", "modp/ietf/6144", "modp/ietf/8192", - NULL }; + nullptr }; const std::string algo_name = "ElGamal"; @@ -657,7 +663,7 @@ void benchmark_elg(RandomNumberGenerator& rng, rng, 1000, seconds); } - const std::string nm = algo_name + "-" + to_string(pbits); + const std::string nm = algo_name + "-" + std::to_string(pbits); report.report(nm, keygen_timer); report.report(nm, enc_timer); report.report(nm, dec_timer); diff --git a/checks/timer.cpp b/checks/timer.cpp index 3736a4779..9f3d34607 100644 --- a/checks/timer.cpp +++ b/checks/timer.cpp @@ -5,7 +5,7 @@ */ #include "timer.h" -#include <botan/time.h> +#include <chrono> #include <iomanip> Timer::Timer(const std::string& n, u32bit e_mul) : @@ -38,7 +38,8 @@ void Timer::stop() u64bit Timer::get_clock() { - return Botan::get_nanoseconds_clock(); + auto now = std::chrono::high_resolution_clock::now().time_since_epoch(); + return std::chrono::duration_cast<std::chrono::nanoseconds>(now).count(); } std::ostream& operator<<(std::ostream& out, Timer& timer) diff --git a/checks/validate.cpp b/checks/validate.cpp index 65317604e..bae5e857f 100644 --- a/checks/validate.cpp +++ b/checks/validate.cpp @@ -110,6 +110,7 @@ bool keywrap_test(const char* key_str, bool ok = true; +#if defined(BOTAN_HAS_RFC3394_KEYWRAP) try { SymmetricKey key(key_str); @@ -118,7 +119,7 @@ bool keywrap_test(const char* key_str, Algorithm_Factory& af = global_state().algorithm_factory(); - SecureVector<byte> enc = rfc3394_keywrap(key.bits_of(), kek, af); + secure_vector<byte> enc = rfc3394_keywrap(key.bits_of(), kek, af); if(enc != expected.bits_of()) { @@ -127,7 +128,7 @@ bool keywrap_test(const char* key_str, ok = false; } - SecureVector<byte> dec = rfc3394_keyunwrap(expected.bits_of(), kek, af); + secure_vector<byte> dec = rfc3394_keyunwrap(expected.bits_of(), kek, af); if(dec != key.bits_of()) { @@ -140,6 +141,7 @@ bool keywrap_test(const char* key_str, { std::cout << e.what() << "\n"; } +#endif return ok; } @@ -339,7 +341,7 @@ u32bit do_validation_tests(const std::string& filename, if(should_pass) std::cout << "Testing " << algorithm << "..." << std::endl; else - std::cout << "Testing (expecing failure) " + std::cout << "Testing (expecting failure) " << algorithm << "..." << std::endl; #endif alg_count = 0; @@ -472,8 +474,10 @@ bool failed_test(const std::string& algo, try { Botan::Filter* test = lookup(algo, params); - if(test == 0 && is_extension) return !exp_pass; - if(test == 0) + + if(!test && is_extension) return !exp_pass; + + if(!test) { if(algo != last_missing) { @@ -488,7 +492,7 @@ bool failed_test(const std::string& algo, pipe.append(test); pipe.append(new Botan::Hex_Encoder); - Botan::SecureVector<byte> data = Botan::hex_decode(in); + secure_vector<byte> data = Botan::hex_decode(in); const byte* data_ptr = &data[0]; // this can help catch errors with buffering, etc @@ -536,7 +540,7 @@ bool failed_test(const std::string& algo, size_t offset = random_word(rng, pipe.remaining() - 1); size_t length = random_word(rng, pipe.remaining() - offset); - Botan::SecureVector<byte> peekbuf(length); + std::vector<byte> peekbuf(length); pipe.peek(&peekbuf[0], peekbuf.size(), offset); output = pipe.read_all_as_string(); diff --git a/checks/validate.dat b/checks/validate.dat index 6b9a49e52..7b221db49 100644 --- a/checks/validate.dat +++ b/checks/validate.dat @@ -4123,25 +4123,64 @@ F0E1D2C3B4A5968778695A4B3C2D1E0F00112233445566 FEDCBA9876543210:05044B62FA52D080:\ F0E1D2C3B4A5968778695A4B3C2D1E0F0011223344556677 -[Camellia] +[Camellia-128] # From RFC 3713 - 0123456789ABCDEFFEDCBA9876543210:67673138549669730857065648EABE43:\ 0123456789ABCDEFFEDCBA9876543210 +# Nessie +00000000000000000000000000000000:6C227F749319A3AA7DA235A9BBA05A2C:\ +80000000000000000000000000000000 + +00000000000000000000000000000000:F04D51E45E70FB6DEE0D16A204FBBA16:\ +40000000000000000000000000000000 + +00000000000000000000000000000000:ED44242E619F8C32EAA2D3641DA47EA4:\ +20000000000000000000000000000000 + +EFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEF:5CA8B8A4B8AF15A6184259831B18BBB5:\ +EFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEF + +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:25DD9EB9DD67FBC6E8431F56F4FBE651:\ +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + + +[Camellia-192] +# From RFC 3713 0123456789ABCDEFFEDCBA9876543210:B4993401B3E996F84EE5CEE7D79B09B9:\ 0123456789ABCDEFFEDCBA98765432100011223344556677 +# Nessie + +00000000000000000000000000000000:1B6220D365C2176C1D41A5826520FCA1:\ +800000000000000000000000000000000000000000000000 + +FEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFE:A2F5A98929658AF4A9700B9923DAF014:\ +FEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFE + +[Camellia-256] +# From RFC 3713 0123456789ABCDEFFEDCBA9876543210:9ACC237DFF16D76C20EF7C919E3A7509:\ 0123456789ABCDEFFEDCBA987654321000112233445566778899AABBCCDDEEFF -# From NESSIE +00000000000000000000000000000000:2136FABDA091DFB5171B94B8EFBB5D08:\ +8000000000000000000000000000000000000000000000000000000000000000 -00000000000000000000000000000000:6C227F749319A3AA7DA235A9BBA05A2C:\ -80000000000000000000000000000000 +00000000000000000000000000000000:E18B0CB1980124504B46A46A6F4273F3:\ +0000000000000200000000000000000000000000000000000000000000000000 -FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:25DD9EB9DD67FBC6E8431F56F4FBE651:\ -FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +00000000000000000000000000000001:9CDB269B5D293BC5DB9C55B057D9B591:\ +0000000000000000000000000000000000000000000000000000000000000000 + +0000000000000000000000000000000000000000000000000000000000000001\ +0000000000000000000000000000000200000000000000000000000000000004\ +0000000000000000000000000000000800000000000000000000000000000010\ +0000000000000000000000000000002000000000000000000000000000000040:\ +396154111ADEFC500CF6E5C99038BC179CDB269B5D293BC5DB9C55B057D9B591\ +3D4B2CDE666761BA5DFB305178E667FB6A3F25AAB7E92D9CF378E5D9C040F26B\ +7C92854D801A1648F65CA81813DDBF83BA664AC39855518DFDEE10D1B3111FAE\ +7A6985778D3A66E97F23E01F0D0E45E78B1F247802E47C91BEE2AA34ECFD7A01:\ +0000000000000000000000000000000000000000000000000000000000000000 # First one is from RFC 2144. The rest were done with OpenSSL and bits taken # from /dev/urandom @@ -67685,6 +67724,8 @@ DC37E008CF9EE69BF11F00ED9ABA26901DD7C28CDEC066CC6AF42E40F82F3A1E\ [Parallel(MD5,SHA-1)] :D41D8CD98F00B204E9800998ECF8427EDA39A3EE5E6B4B0D3255BFEF95601890AFD80709 +61:0CC175B9C0F1B6A831C399E26977266186F7E437FAA5A7FCE15D1DDCB9EAEAEA377667B8 + [Parallel(SHA-160,Tiger(24,3))] :DA39A3EE5E6B4B0D3255BFEF95601890AFD807093293AC630\ C13F0245F92BBB1766E16167A4E58492DDE73F3 diff --git a/checks/x509.cpp b/checks/x509.cpp index 138d1b346..46b748da6 100644 --- a/checks/x509.cpp +++ b/checks/x509.cpp @@ -49,7 +49,7 @@ u64bit key_id(const Public_Key* key) pipe.write(key->x509_subject_public_key()); pipe.end_msg(); - SecureVector<byte> output = pipe.read_all(); + secure_vector<byte> output = pipe.read_all(); if(output.size() != 8) throw Internal_Error("Public_Key::key_id: Incorrect output size"); @@ -147,7 +147,6 @@ void do_x509_tests(RandomNumberGenerator& rng) std::cout << '.' << std::flush; /* Create user #1's key and cert request */ - std::cout << '.' << std::flush; DSA_PrivateKey user1_key(rng, DL_Group("dsa/botan/2048")); std::cout << '.' << std::flush; diff --git a/configure.py b/configure.py index 71d2a3d39..31b55756d 100755 --- a/configure.py +++ b/configure.py @@ -2,7 +2,7 @@ """ Configuration program for botan (http://botan.randombit.net/) - (C) 2009-2011 Jack Lloyd + (C) 2009,2010,2011,2012 Jack Lloyd Distributed under the terms of the Botan license Tested with CPython 2.6, 2.7, 3.1 and PyPy 1.5 @@ -267,10 +267,6 @@ def process_command_line(args): default=False, action='store_true', help='build via amalgamation') - build_group.add_option('--with-tr1-implementation', metavar='WHICH', - dest='with_tr1', default=None, - help='enable TR1 (choices: none, system, boost)') - build_group.add_option('--with-build-dir', metavar='DIR', default='', help='setup the build in DIR') @@ -306,10 +302,6 @@ def process_command_line(args): build_group.add_option('--without-doxygen', action='store_false', dest='with_doxygen', help=optparse.SUPPRESS_HELP) - build_group.add_option('--dumb-gcc', dest='dumb_gcc', - action='store_true', default=False, - help=optparse.SUPPRESS_HELP) - build_group.add_option('--maintainer-mode', dest='maintainer_mode', action='store_true', default=False, help=optparse.SUPPRESS_HELP) @@ -548,7 +540,6 @@ class ModuleInfo(object): { 'load_on': 'auto', 'define': [], - 'uses_tr1': 'false', 'need_isa': None, 'mp_bits': 0 }) @@ -597,8 +588,6 @@ class ModuleInfo(object): self.mp_bits = int(self.mp_bits) - self.uses_tr1 = (True if self.uses_tr1 == 'yes' else False) - if self.comment != []: self.comment = ' '.join(self.comment) else: @@ -643,12 +632,6 @@ class ModuleInfo(object): def compatible_compiler(self, cc): return self.cc == [] or cc in self.cc - def tr1_ok(self, with_tr1): - if self.uses_tr1: - return with_tr1 in ['boost', 'system'] - else: - return True - def dependencies(self): # utils is an implicit dep (contains types, etc) deps = self.requires + ['utils'] @@ -776,8 +759,7 @@ class CompilerInfo(object): 'visibility_build_flags': '', 'visibility_attribute': '', 'ar_command': None, - 'makefile_style': '', - 'has_tr1': False, + 'makefile_style': '' }) self.so_link_flags = force_to_dict(self.so_link_flags) @@ -884,19 +866,8 @@ class CompilerInfo(object): """ Return defines for build.h """ - def defines(self, with_tr1): - - def tr1_macro(): - if with_tr1: - if with_tr1 == 'boost': - return ['USE_BOOST_TR1'] - elif with_tr1 == 'system': - return ['USE_STD_TR1'] - elif self.has_tr1: - return ['USE_STD_TR1'] - return [] - - return ['BUILD_COMPILER_IS_' + self.macro_name] + tr1_macro() + def defines(self): + return ['BUILD_COMPILER_IS_' + self.macro_name] class OsInfo(object): def __init__(self, infofile): @@ -1035,10 +1006,15 @@ def create_template_vars(build_config, options, modules, cc, arch, osinfo): if dir.startswith('src'): parts = dir.split(os.sep)[1:] + + # Handle src/X/X.cpp -> X.o if file == parts[-1] + '.cpp': name = '_'.join(dir.split(os.sep)[1:]) + '.cpp' else: name = '_'.join(dir.split(os.sep)[1:]) + '_' + file + + # Special case hack cause I'm lazy + name = name.replace('tls_tls_', 'tls_') else: name = file @@ -1137,7 +1113,7 @@ def create_template_vars(build_config, options, modules, cc, arch, osinfo): 'lib_opt': cc.library_opt_flags(options), 'mach_opt': cc.mach_opts(options.arch, options.cpu), 'check_opt': '' if options.no_optimizations else cc.check_opt_flags, - 'lang_flags': cc.lang_flags + options.extra_flags, + 'lang_flags': cc.lang_flags, 'warn_flags': warning_flags(cc.warning_flags, cc.maintainer_warning_flags, options.maintainer_mode), @@ -1153,8 +1129,7 @@ def create_template_vars(build_config, options, modules, cc, arch, osinfo): 'target_os_defines': make_cpp_macros(osinfo.defines()), - 'target_compiler_defines': make_cpp_macros( - cc.defines(options.with_tr1)), + 'target_compiler_defines': make_cpp_macros(cc.defines()), 'target_cpu_defines': make_cpp_macros(arch.defines(options)), @@ -1245,8 +1220,6 @@ def choose_modules_to_use(modules, archinfo, options): cannot_use_because(modname, 'incompatible compiler') elif not module.compatible_cpu(archinfo, options): cannot_use_because(modname, 'incompatible CPU') - elif not module.tr1_ok(options.with_tr1): - cannot_use_because(modname, 'missing TR1') else: if module.load_on == 'never': @@ -1760,7 +1733,6 @@ def main(argv = None): cc = ccinfo[options.compiler] # Kind of a hack... - options.extra_flags = '' if options.compiler == 'gcc': def get_gcc_version(gcc_bin): @@ -1785,49 +1757,17 @@ def main(argv = None): logging.warning('Could not execute %s for version check' % (gcc_bin)) return None - def is_64bit_arch(arch): - if arch.endswith('64') or arch in ['alpha', 's390x']: - return True - return False - gcc_version = get_gcc_version(options.compiler_binary or cc.binary_name) if gcc_version: + versions_without_cpp0x = '(4\.[01234]\.)|(3\.[0-4]\.)|(2\.95\.[0-4])' - if not is_64bit_arch(options.arch) and not options.dumb_gcc: - matching_version = '(4\.[01234]\.)|(3\.[34]\.)|(2\.95\.[0-4])' - - if re.search(matching_version, gcc_version): - options.dumb_gcc = True - - versions_without_tr1 = '(4\.0\.)|(3\.[0-4]\.)|(2\.95\.[0-4])' - - if options.with_tr1 == None and \ - re.search(versions_without_tr1, gcc_version): - logging.info('Disabling TR1 support for this gcc, too old') - options.with_tr1 = 'none' - - versions_without_visibility = '(3\.[0-4]\.)|(2\.95\.[0-4])' - if options.with_visibility == None and \ - re.search(versions_without_visibility, gcc_version): - logging.info('Disabling DSO visibility support for this gcc, too old') - options.with_visibility = False - - if options.dumb_gcc is True: - logging.info('Setting -fpermissive to work around gcc bug') - options.extra_flags = ' -fpermissive' + if re.search(versions_without_cpp0x, gcc_version): + logging.info('This GCC is too old to compile C++0x') if options.with_visibility is None: options.with_visibility = True - if options.with_tr1 == None: - if cc.has_tr1: - logging.info('Assuming %s has TR1 (use --with-tr1=none to disable)' % ( - options.compiler)) - options.with_tr1 = 'system' - else: - options.with_tr1 = 'none' - if options.with_sphinx is None: if have_program('sphinx-build'): logging.info('Found sphinx-build, will use it ' + diff --git a/doc/contents.txt b/doc/contents.txt index dd600d587..141c9188f 100644 --- a/doc/contents.txt +++ b/doc/contents.txt @@ -12,7 +12,8 @@ Contents filters pubkey x509 - ssl + tls + credentials_manager bigint lowlevel secmem diff --git a/doc/examples/GNUmakefile b/doc/examples/GNUmakefile index a5da47a7c..b034cac78 100644 --- a/doc/examples/GNUmakefile +++ b/doc/examples/GNUmakefile @@ -1,9 +1,9 @@ BOTAN_CONFIG = botan-config -CXX = g++ -CFLAGS = -O2 -ansi -W -Wall -I../../build/include -LIBS = -L../.. -lbotan-1.10 +CXX = g++-4.8.0-r187608 +CFLAGS = -O2 -ansi -std=c++0x -W -Wall -I../../build/include +LIBS = -L../.. -lbotan-1.99 SRCS=$(wildcard *.cpp) @@ -19,3 +19,6 @@ clean: eax_test: eax_test.cpp $(CXX) $(CFLAGS) $? $(LIBS) -lboost_regex -o $@ + +asio_tls_server: asio_tls_server.cpp credentials.h + $(CXX) $(CFLAGS) $< $(LIBS) -lboost_thread -lboost_system -o $@ diff --git a/doc/examples/asio_tls_server.cpp b/doc/examples/asio_tls_server.cpp new file mode 100644 index 000000000..0cf499e0a --- /dev/null +++ b/doc/examples/asio_tls_server.cpp @@ -0,0 +1,295 @@ +#include <iostream> +#include <string> +#include <vector> +#define _GLIBCXX_HAVE_GTHR_DEFAULT +#include <boost/asio.hpp> +#include <boost/bind.hpp> +#include <boost/thread.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/enable_shared_from_this.hpp> + +#include <botan/tls_server.h> +#include <botan/x509cert.h> +#include <botan/pkcs8.h> +#include <botan/auto_rng.h> +#include <botan/init.h> + +#include "credentials.h" + +using Botan::byte; +using boost::asio::ip::tcp; + +class tls_server_session : public boost::enable_shared_from_this<tls_server_session> + { + public: + typedef boost::shared_ptr<tls_server_session> pointer; + + static pointer create(boost::asio::io_service& io_service, + Botan::TLS::Session_Manager& session_manager, + Botan::Credentials_Manager& credentials, + Botan::TLS::Policy& policy, + Botan::RandomNumberGenerator& rng) + { + return pointer( + new tls_server_session( + io_service, + session_manager, + credentials, + policy, + rng) + ); + } + + tcp::socket& socket() { return m_socket; } + + void start() + { + m_socket.async_read_some( + boost::asio::buffer(m_read_buf, sizeof(m_read_buf)), + m_strand.wrap( + boost::bind(&tls_server_session::handle_read, shared_from_this(), + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred))); + } + + void stop() { m_socket.close(); } + + private: + tls_server_session(boost::asio::io_service& io_service, + Botan::TLS::Session_Manager& session_manager, + Botan::Credentials_Manager& credentials, + Botan::TLS::Policy& policy, + Botan::RandomNumberGenerator& rng) : + m_strand(io_service), + m_socket(io_service), + m_tls(boost::bind(&tls_server_session::tls_output_wanted, this, _1, _2), + boost::bind(&tls_server_session::tls_data_recv, this, _1, _2, _3), + boost::bind(&tls_server_session::tls_handshake_complete, this, _1), + session_manager, + credentials, + policy, + rng) + { + } + + void handle_read(const boost::system::error_code& error, + size_t bytes_transferred) + { + if(!error) + { + try + { + m_tls.received_data(m_read_buf, bytes_transferred); + } + catch(std::exception& e) + { + std::cout << "Read failed " << e.what() << "\n"; + stop(); + return; + } + + m_socket.async_read_some( + boost::asio::buffer(m_read_buf, sizeof(m_read_buf)), + m_strand.wrap(boost::bind(&tls_server_session::handle_read, shared_from_this(), + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred))); + } + else + { + stop(); + } + } + + void handle_write(const boost::system::error_code& error) + { + if(!error) + { + m_write_buf.clear(); + + // initiate another write if needed + tls_output_wanted(NULL, 0); + } + else + { + stop(); + } + } + + void tls_output_wanted(const byte buf[], size_t buf_len) + { + if(buf_len > 0) + m_outbox.insert(m_outbox.end(), buf, buf + buf_len); + + // no write pending and have output pending + if(m_write_buf.empty() && !m_outbox.empty()) + { + std::swap(m_outbox, m_write_buf); + + boost::asio::async_write(m_socket, + boost::asio::buffer(&m_write_buf[0], m_write_buf.size()), + m_strand.wrap( + boost::bind(&tls_server_session::handle_write, + shared_from_this(), + boost::asio::placeholders::error))); + } + } + + void tls_data_recv(const byte buf[], size_t buf_len, Botan::TLS::Alert alert) + { + if(alert.is_valid()) + { + if(alert.type() == Botan::TLS::Alert::CLOSE_NOTIFY) + { + m_tls.close(); + return; + } + } + + if(buf_len > 4) // FIXME: ghetto + { + std::string out; + out += "\r\n"; + out += "HTTP/1.0 200 OK\r\n"; + out += "Server: Botan ASIO test server\r\n"; + if(m_hostname != "") + out += "Host: " + m_hostname + "\r\n"; + out += "Content-Type: text/html\r\n"; + out += "\r\n"; + out += "<html><body>Greets. You said: "; + out += std::string((const char*)buf, buf_len); + out += "</body></html>\r\n\r\n"; + + m_tls.send(reinterpret_cast<const byte*>(&out[0]), + out.size()); + m_tls.close(); + } + } + + bool tls_handshake_complete(const Botan::TLS::Session& session) + { + m_hostname = session.sni_hostname(); + return true; + } + + boost::asio::io_service::strand m_strand; // serialization + + tcp::socket m_socket; + Botan::TLS::Server m_tls; + std::string m_hostname; + + unsigned char m_read_buf[Botan::TLS::MAX_TLS_RECORD_SIZE]; + + // used to hold the data currently being written by the system + std::vector<byte> m_write_buf; + + // used to hold data queued for writing + std::vector<byte> m_outbox; + }; + +class tls_server + { + public: + typedef tls_server_session session; + + tls_server(boost::asio::io_service& io_service, unsigned short port) : + m_acceptor(io_service, tcp::endpoint(tcp::v4(), port)), + m_creds(m_rng) + { + session::pointer new_session = make_session(); + + m_acceptor.async_accept( + new_session->socket(), + boost::bind( + &tls_server::handle_accept, + this, + new_session, + boost::asio::placeholders::error) + ); + } + + private: + session::pointer make_session() + { + return session::create( + m_acceptor.get_io_service(), + m_session_manager, + m_creds, + m_policy, + m_rng + ); + } + + void handle_accept(session::pointer new_session, + const boost::system::error_code& error) + { + if (!error) + { + new_session->start(); + + new_session = make_session(); + + m_acceptor.async_accept( + new_session->socket(), + boost::bind( + &tls_server::handle_accept, + this, + new_session, + boost::asio::placeholders::error) + ); + } + } + + tcp::acceptor m_acceptor; + + Botan::AutoSeeded_RNG m_rng; + Botan::TLS::Session_Manager_In_Memory m_session_manager; + Botan::TLS::Policy m_policy; + Credentials_Manager_Simple m_creds; + }; + +size_t choose_thread_count() + { + size_t result = boost::thread::hardware_concurrency(); + + if(result) + return result; + + return 2; + } + +int main() + { + try + { + Botan::LibraryInitializer init("thread_safe=true"); + boost::asio::io_service io_service; + + unsigned short port = 4434; + tls_server server(io_service, port); + + const size_t num_threads = choose_thread_count(); + + std::cout << "Using " << num_threads << " threads\n"; + + std::vector<boost::shared_ptr<boost::thread> > threads; + + for(size_t i = 0; i != num_threads; ++i) + { + boost::shared_ptr<boost::thread> thread( + new boost::thread( + boost::bind(&boost::asio::io_service::run, &io_service))); + threads.push_back(thread); + } + + // Wait for all threads in the pool to exit. + for (size_t i = 0; i < threads.size(); ++i) + threads[i]->join(); + } + catch (std::exception& e) + { + std::cerr << e.what() << std::endl; + } + + return 0; + } + diff --git a/doc/examples/asn1.cpp b/doc/examples/asn1.cpp index 95e5b2627..d12ee1eec 100644 --- a/doc/examples/asn1.cpp +++ b/doc/examples/asn1.cpp @@ -72,8 +72,8 @@ void decode(BER_Decoder& decoder, size_t level) /* hack to insert the tag+length back in front of the stuff now that we've gotten the type info */ DER_Encoder encoder; - encoder.add_object(type_tag, class_tag, obj.value, obj.value.size()); - SecureVector<byte> bits = encoder.get_contents(); + encoder.add_object(type_tag, class_tag, obj.value); + secure_vector<byte> bits = encoder.get_contents(); BER_Decoder data(bits); @@ -97,7 +97,7 @@ void decode(BER_Decoder& decoder, size_t level) if((class_tag & APPLICATION) || (class_tag & CONTEXT_SPECIFIC) || (class_tag & PRIVATE)) { - name = "cons [" + to_string(type_tag) + "]"; + name = "cons [" + std::to_string(type_tag) + "]"; if(class_tag & APPLICATION) name += " appl"; @@ -124,7 +124,7 @@ void decode(BER_Decoder& decoder, size_t level) Pipe pipe(((not_text) ? new Hex_Encoder : 0)); pipe.process_msg(bits); - emit("[" + to_string(type_tag) + "]", level, length, + emit("[" + std::to_string(type_tag) + "]", level, length, pipe.read_all_as_string()); } else if(type_tag == OBJECT_ID) @@ -143,7 +143,7 @@ void decode(BER_Decoder& decoder, size_t level) BigInt number; data.decode(number); - SecureVector<byte> rep; + std::vector<byte> rep; /* If it's small, it's probably a number, not a hash */ if(number.bits() <= 16) @@ -170,7 +170,7 @@ void decode(BER_Decoder& decoder, size_t level) } else if(type_tag == OCTET_STRING) { - SecureVector<byte> bits; + secure_vector<byte> bits; data.decode(bits, type_tag); bool not_text = false; @@ -184,7 +184,7 @@ void decode(BER_Decoder& decoder, size_t level) } else if(type_tag == BIT_STRING) { - SecureVector<byte> bits; + secure_vector<byte> bits; data.decode(bits, type_tag); std::vector<bool> bit_set; diff --git a/doc/examples/bench.cpp b/doc/examples/bench.cpp index 6cfd9205f..5378b3e6a 100644 --- a/doc/examples/bench.cpp +++ b/doc/examples/bench.cpp @@ -67,22 +67,19 @@ const std::string algos[] = { "", }; + void benchmark_algo(const std::string& algo, RandomNumberGenerator& rng) { - u32bit milliseconds = 1000; + std::chrono::milliseconds ms(1000); Algorithm_Factory& af = global_state().algorithm_factory(); - std::map<std::string, double> speeds = - algorithm_benchmark(algo, af, rng, milliseconds, 16); + auto speeds = algorithm_benchmark(algo, af, rng, ms, 16); std::cout << algo << ":"; - for(std::map<std::string, double>::const_iterator i = speeds.begin(); - i != speeds.end(); ++i) - { - std::cout << " " << i->second << " [" << i->first << "]"; - } + for(auto s: speeds) + std::cout << " " << s.second << " [" << s.first << "]"; std::cout << "\n"; } @@ -96,12 +93,12 @@ int main(int argc, char* argv[]) if(argc == 1) // no args, benchmark everything { - for(u32bit i = 0; algos[i] != ""; ++i) + for(size_t i = 0; algos[i] != ""; ++i) benchmark_algo(algos[i], rng); } else { - for(int i = 1; argv[i]; ++i) + for(size_t i = 1; argv[i]; ++i) benchmark_algo(argv[i], rng); } } diff --git a/doc/examples/benchmark.cpp b/doc/examples/benchmark.cpp index b5adb3d4f..a11054c0c 100644 --- a/doc/examples/benchmark.cpp +++ b/doc/examples/benchmark.cpp @@ -26,14 +26,13 @@ int main(int argc, char* argv[]) Botan::Algorithm_Factory& af = Botan::global_state().algorithm_factory(); - double ms = 1000 * std::atof(argv[1]); + std::chrono::milliseconds ms(static_cast<std::chrono::milliseconds::rep>(1000 * std::atof(argv[1]))); for(size_t i = 2; argv[i]; ++i) { std::string algo = argv[i]; - std::map<std::string, double> results = - algorithm_benchmark(algo, af, rng, ms, 16); + auto results = algorithm_benchmark(algo, af, rng, ms, 16); std::cout << algo << ":\n"; for(std::map<std::string, double>::iterator r = results.begin(); diff --git a/doc/examples/bzip.cpp b/doc/examples/bzip.cpp index 6137bb6af..74ba431ed 100644 --- a/doc/examples/bzip.cpp +++ b/doc/examples/bzip.cpp @@ -37,6 +37,7 @@ int main(int argc, char* argv[]) Botan::LibraryInitializer init; +#ifdef BOTAN_HAS_COMPRESSOR_BZIP2 std::vector<std::string> files; bool decompress = false, small = false; int level = 9; @@ -60,18 +61,10 @@ int main(int argc, char* argv[]) try { Botan::Filter* bzip = 0; -#ifdef BOTAN_HAS_COMPRESSOR_BZIP2 if(decompress) bzip = new Botan::Bzip_Decompression(small); else bzip = new Botan::Bzip_Compression(level); -#endif - - if(!bzip) - { - std::cout << "Sorry, support for bzip2 not compiled into Botan\n"; - return 1; - } Botan::Pipe pipe(bzip); @@ -112,5 +105,11 @@ int main(int argc, char* argv[]) std::cout << "Exception caught: " << e.what() << std::endl; return 1; } +#else + + std::cout << "Sorry, support for bzip2 not compiled into Botan\n"; + +#endif + return 0; } diff --git a/doc/examples/ca.cpp b/doc/examples/ca.cpp index 7a3e6daf9..6fd2eb15b 100644 --- a/doc/examples/ca.cpp +++ b/doc/examples/ca.cpp @@ -1,10 +1,10 @@ #include <botan/botan.h> #include <botan/x509_ca.h> -#include <botan/time.h> using namespace Botan; #include <iostream> #include <memory> +#include <chrono> int main(int argc, char* argv[]) { @@ -41,8 +41,13 @@ int main(int argc, char* argv[]) // (this example should be extended to show how) // now sign the request - X509_Time start_time(system_time()); - X509_Time end_time(system_time() + 365 * 60 * 60 * 24); + auto now = std::chrono::system_clock::now(); + + X509_Time start_time(now); + + typedef std::chrono::duration<int, std::ratio<31556926>> years; + + X509_Time end_time(now + years(1)); X509_Certificate new_cert = ca.sign_request(req, rng, start_time, end_time); diff --git a/doc/examples/cms_dec.cpp b/doc/examples/cms_dec.cpp deleted file mode 100644 index 84355fb4a..000000000 --- a/doc/examples/cms_dec.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/* -* (C) 2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/botan.h> -#include <botan/pkcs8.h> -#include <botan/cms_dec.h> -using namespace Botan; - -#include <iostream> -#include <memory> - -int main(int argc, char* argv[]) - { - if(argc != 2) - { - std::cout << "Usage: " << argv[0] << " <filename>\n"; - return 1; - } - - Botan::LibraryInitializer init; - - try { - AutoSeeded_RNG rng; - - X509_Certificate mycert("mycert.pem"); - PKCS8_PrivateKey* mykey = PKCS8::load_key("mykey.pem", rng, "cut"); - - X509_Certificate yourcert("yourcert.pem"); - X509_Certificate cacert("cacert.pem"); - X509_Certificate int_ca("int_ca.pem"); - - X509_Store store; - store.add_cert(mycert); - store.add_cert(yourcert); - store.add_cert(cacert, true); - store.add_cert(int_ca); - - DataSource_Stream message(argv[1]); - - CMS_Decoder decoder(message, store, mykey); - - while(decoder.layer_type() != CMS_Decoder::DATA) - { - CMS_Decoder::Status status = decoder.layer_status(); - CMS_Decoder::Content_Type content = decoder.layer_type(); - - if(status == CMS_Decoder::FAILURE) - { - std::cout << "Failure reading CMS data" << std::endl; - break; - } - - if(content == CMS_Decoder::DIGESTED) - { - std::cout << "Digested data, hash = " << decoder.layer_info() - << std::endl; - std::cout << "Hash is " - << ((status == CMS_Decoder::GOOD) ? "good" : "bad") - << std::endl; - } - - if(content == CMS_Decoder::SIGNED) - { - // how to handle multiple signers? they can all exist within a - // single level... - - std::cout << "Signed by " << decoder.layer_info() << std::endl; - //std::cout << "Sign time: " << decoder.xxx() << std::endl; - std::cout << "Signature is "; - if(status == CMS_Decoder::GOOD) - std::cout << "valid"; - else if(status == CMS_Decoder::BAD) - std::cout << "bad"; - else if(status == CMS_Decoder::NO_KEY) - std::cout << "(cannot check, no known cert)"; - std::cout << std::endl; - } - if(content == CMS_Decoder::ENVELOPED || - content == CMS_Decoder::COMPRESSED || - content == CMS_Decoder::AUTHENTICATED) - { - if(content == CMS_Decoder::ENVELOPED) - std::cout << "Enveloped"; - if(content == CMS_Decoder::COMPRESSED) - std::cout << "Compressed"; - if(content == CMS_Decoder::AUTHENTICATED) - std::cout << "MACed"; - - std::cout << ", algo = " << decoder.layer_info() << std::endl; - - if(content == CMS_Decoder::AUTHENTICATED) - { - std::cout << "MAC status is "; - if(status == CMS_Decoder::GOOD) - std::cout << "valid"; - else if(status == CMS_Decoder::BAD) - std::cout << "bad"; - else if(status == CMS_Decoder::NO_KEY) - std::cout << "(cannot check, no key)"; - std::cout << std::endl; - } - } - decoder.next_layer(); - } - - if(decoder.layer_type() == CMS_Decoder::DATA) - std::cout << "Message is \"" << decoder.get_data() - << '"' << std::endl; - else - std::cout << "No data anywhere?" << std::endl; - } - catch(std::exception& e) - { - std::cerr << e.what() << std::endl; - } - return 0; - } diff --git a/doc/examples/cms_enc.cpp b/doc/examples/cms_enc.cpp deleted file mode 100644 index 2cf813987..000000000 --- a/doc/examples/cms_enc.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/* -* (C) 2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/botan.h> -#include <botan/cms_enc.h> -using namespace Botan; - -#include <iostream> -#include <fstream> -#include <memory> - -int main() - { - Botan::LibraryInitializer init; - - try { - - X509_Certificate mycert("mycert.pem"); - X509_Certificate mycert2("mycert2.pem"); - X509_Certificate yourcert("yourcert.pem"); - X509_Certificate cacert("cacert.pem"); - X509_Certificate int_ca("int_ca.pem"); - - AutoSeeded_RNG rng; - - X509_Store store; - store.add_cert(mycert); - store.add_cert(mycert2); - store.add_cert(yourcert); - store.add_cert(int_ca); - store.add_cert(cacert, true); - - const std::string msg = "prioncorp: we don't toy\n"; - - CMS_Encoder encoder(msg); - - encoder.compress("Zlib"); - encoder.digest(); - encoder.encrypt(rng, mycert); - - /* - PKCS8_PrivateKey* mykey = PKCS8::load_key("mykey.pem", rng, "cut"); - encoder.sign(store, *mykey); - */ - - SecureVector<byte> raw = encoder.get_contents(); - std::ofstream out("out.der"); - - out.write((const char*)raw.begin(), raw.size()); - } - catch(std::exception& e) - { - std::cerr << e.what() << std::endl; - } - return 0; - } diff --git a/doc/examples/credentials.h b/doc/examples/credentials.h new file mode 100644 index 000000000..2734b1649 --- /dev/null +++ b/doc/examples/credentials.h @@ -0,0 +1,284 @@ + +#ifndef EXAMPLE_CREDENTIALS_MANAGER_H__ +#define EXAMPLE_CREDENTIALS_MANAGER_H__ + +#include <botan/credentials_manager.h> +#include <botan/x509self.h> +#include <botan/rsa.h> +#include <botan/dsa.h> +#include <botan/srp6.h> +#include <botan/srp6_files.h> +#include <botan/ecdsa.h> +#include <iostream> +#include <fstream> +#include <memory> + +bool value_exists(const std::vector<std::string>& vec, + const std::string& val) + { + for(size_t i = 0; i != vec.size(); ++i) + if(vec[i] == val) + return true; + return false; + } + +class Credentials_Manager_Simple : public Botan::Credentials_Manager + { + public: + Credentials_Manager_Simple(Botan::RandomNumberGenerator& rng) : rng(rng) {} + + std::string srp_identifier(const std::string& type, + const std::string& hostname) + { + if(type == "tls-client" && hostname == "srp-host") + return "user"; + return ""; + } + + bool attempt_srp(const std::string& type, + const std::string& hostname) + { + if(hostname == "srp-host") + return true; + return false; + } + + std::vector<Botan::X509_Certificate> + trusted_certificate_authorities(const std::string& type, + const std::string& hostname) + { + + std::vector<Botan::X509_Certificate> certs; + + if(type == "tls-server" && hostname == "localhost") + { + Botan::X509_Certificate testca("testCA.crt"); + certs.push_back(testca); + } + + if(type == "tls-client" && hostname == "twitter.com") + { + Botan::X509_Certificate verisign("/usr/share/ca-certificates/mozilla/VeriSign_Class_3_Public_Primary_Certification_Authority_-_G5.crt"); + certs.push_back(verisign); + } + + return certs; + } + + void verify_certificate_chain( + const std::string& type, + const std::string& purported_hostname, + const std::vector<Botan::X509_Certificate>& cert_chain) + { + try + { + Botan::Credentials_Manager::verify_certificate_chain(type, + purported_hostname, + cert_chain); + } + catch(std::exception& e) + { + std::cout << "Certificate verification failed - " << e.what() << " - but will ignore\n"; + } + } + + std::string srp_password(const std::string& type, + const std::string& hostname, + const std::string& identifier) + { + if(type == "tls-client" && hostname == "localhost" && identifier == "user") + return "password"; + + return ""; + } + + bool srp_verifier(const std::string& type, + const std::string& context, + const std::string& identifier, + std::string& group_id, + Botan::BigInt& verifier, + std::vector<Botan::byte>& salt, + bool generate_fake_on_unknown) + { + + std::string pass = srp_password("tls-client", context, identifier); + if(pass == "") + { + if(!generate_fake_on_unknown) + return false; + + pass.resize(16); + Botan::global_state().global_rng().randomize((Botan::byte*)&pass[0], pass.size()); + } + + group_id = "modp/srp/2048"; + + salt.resize(16); + Botan::global_state().global_rng().randomize(&salt[0], salt.size()); + + verifier = Botan::generate_srp6_verifier(identifier, + pass, + salt, + group_id, + "SHA-1"); + + return true; + } + + std::string psk_identity_hint(const std::string&, + const std::string&) + { + return ""; + } + + std::string psk_identity(const std::string&, const std::string&, + const std::string& identity_hint) + { + //return "lloyd"; + return "Client_identity"; + } + + Botan::SymmetricKey psk(const std::string& type, const std::string& context, + const std::string& identity) + { + if(type == "tls-server" && context == "session-ticket") + { + if(session_ticket_key.length() == 0) + session_ticket_key = Botan::SymmetricKey(rng, 32); + return session_ticket_key; + } + + if(identity == "Client_identity") + return Botan::SymmetricKey("b5a72e1387552e6dc10766dc0eda12961f5b21e17f98ef4c41e6572e53bd7527"); + if(identity == "lloyd") + return Botan::SymmetricKey("85b3c1b7dc62b507636ac767999c9630"); + + throw Botan::Internal_Error("No PSK set for " + identity); + } + + std::pair<Botan::X509_Certificate,Botan::Private_Key*> + load_or_make_cert(const std::string& hostname, + const std::string& key_type, + Botan::RandomNumberGenerator& rng) + { + using namespace Botan; + + const std::string key_fsname_prefix = hostname + "." + key_type + "."; + const std::string key_file_name = key_fsname_prefix + "key"; + const std::string cert_file_name = key_fsname_prefix + "crt"; + + try + { + X509_Certificate cert(cert_file_name); + Private_Key* key = PKCS8::load_key(key_file_name, rng); + + //std::cout << "Loaded existing key/cert from " << cert_file_name << " and " << key_file_name << "\n"; + + return std::make_pair(cert, key); + } + catch(...) {} + + // Failed. Instead, make a new one + + std::cout << "Creating new certificate for identifier '" << hostname << "'\n"; + + X509_Cert_Options opts; + + opts.common_name = hostname; + opts.country = "US"; + opts.email = "root@" + hostname; + opts.dns = hostname; + + std::auto_ptr<Private_Key> key; + if(key_type == "rsa") + key.reset(new RSA_PrivateKey(rng, 1024)); + else if(key_type == "dsa") + key.reset(new DSA_PrivateKey(rng, DL_Group("dsa/jce/1024"))); + else if(key_type == "ecdsa") + key.reset(new ECDSA_PrivateKey(rng, EC_Group("secp256r1"))); + else + throw std::runtime_error("Don't know what to do about key type '" + key_type + "'"); + + X509_Certificate cert = + X509::create_self_signed_cert(opts, *key, "SHA-1", rng); + + // Now save both + + std::cout << "Saving new " << key_type << " key to " << key_file_name << "\n"; + std::ofstream key_file(key_file_name.c_str()); + key_file << PKCS8::PEM_encode(*key, rng, ""); + key_file.close(); + + std::cout << "Saving new " << key_type << " cert to " << key_file_name << "\n"; + std::ofstream cert_file(cert_file_name.c_str()); + cert_file << cert.PEM_encode() << "\n"; + cert_file.close(); + + return std::make_pair(cert, key.release()); + } + + std::vector<Botan::X509_Certificate> cert_chain( + const std::vector<std::string>& cert_key_types, + const std::string& type, + const std::string& context) + { + using namespace Botan; + + std::vector<X509_Certificate> certs; + + try + { + if(type == "tls-server") + { + const std::string hostname = (context == "" ? "localhost" : context); + + if(hostname == "nosuchname") + return std::vector<Botan::X509_Certificate>(); + + std::string key_name = ""; + + if(value_exists(cert_key_types, "RSA")) + key_name = "rsa"; + else if(value_exists(cert_key_types, "DSA")) + key_name = "dsa"; + else if(value_exists(cert_key_types, "ECDSA")) + key_name = "ecdsa"; + + std::pair<X509_Certificate, Private_Key*> cert_and_key = + load_or_make_cert(hostname, key_name, rng); + + certs_and_keys[cert_and_key.first] = cert_and_key.second; + certs.push_back(cert_and_key.first); + } + else if(type == "tls-client") + { + X509_Certificate cert("user-rsa.crt"); + Private_Key* key = PKCS8::load_key("user-rsa.key", rng); + + certs_and_keys[cert] = key; + certs.push_back(cert); + } + } + catch(std::exception& e) + { + std::cout << e.what() << "\n"; + } + + return certs; + } + + Botan::Private_Key* private_key_for(const Botan::X509_Certificate& cert, + const std::string& type, + const std::string& context) + { + return certs_and_keys[cert]; + } + + private: + Botan::RandomNumberGenerator& rng; + + Botan::SymmetricKey session_ticket_key; + std::map<Botan::X509_Certificate, Botan::Private_Key*> certs_and_keys; + }; + +#endif diff --git a/doc/examples/decrypt.cpp b/doc/examples/decrypt.cpp index ea510c5e9..42c4071c7 100644 --- a/doc/examples/decrypt.cpp +++ b/doc/examples/decrypt.cpp @@ -27,7 +27,7 @@ stderr so there is no confusion. using namespace Botan; -SecureVector<byte> b64_decode(const std::string&); +secure_vector<byte> b64_decode(const std::string&); int main(int argc, char* argv[]) { @@ -111,7 +111,7 @@ int main(int argc, char* argv[]) const u32bit PBKDF2_ITERATIONS = 8192; - SecureVector<byte> salt = b64_decode(salt_str); + secure_vector<byte> salt = b64_decode(salt_str); SymmetricKey bc_key = pbkdf->derive_key(key_len, "BLK" + passphrase, &salt[0], salt.size(), @@ -165,7 +165,7 @@ int main(int argc, char* argv[]) return 0; } -SecureVector<byte> b64_decode(const std::string& in) +secure_vector<byte> b64_decode(const std::string& in) { Pipe pipe(new Base64_Decoder); pipe.process_msg(in); diff --git a/doc/examples/dh.cpp b/doc/examples/dh.cpp index 8d163303a..d62d49f65 100644 --- a/doc/examples/dh.cpp +++ b/doc/examples/dh.cpp @@ -24,12 +24,12 @@ int main() DH_PrivateKey private_b(rng, shared_domain); // Alice sends to Bob her public key and a session parameter - MemoryVector<byte> public_a = private_a.public_value(); + std::vector<byte> public_a = private_a.public_value(); const std::string session_param = "Alice and Bob's shared session parameter"; // Bob sends his public key to Alice - MemoryVector<byte> public_b = private_b.public_value(); + std::vector<byte> public_b = private_b.public_value(); // Now Alice performs the key agreement operation PK_Key_Agreement ka_alice(private_a, "KDF2(SHA-256)"); diff --git a/doc/examples/dsa_ver.cpp b/doc/examples/dsa_ver.cpp index 9cb85740e..e6910a4e1 100644 --- a/doc/examples/dsa_ver.cpp +++ b/doc/examples/dsa_ver.cpp @@ -12,7 +12,7 @@ using namespace Botan; namespace { -SecureVector<byte> b64_decode(const std::string& in) +secure_vector<byte> b64_decode(const std::string& in) { Pipe pipe(new Base64_Decoder); pipe.process_msg(in); @@ -60,7 +60,7 @@ int main(int argc, char* argv[]) return 1; } - SecureVector<byte> sig = b64_decode(sigstr); + secure_vector<byte> sig = b64_decode(sigstr); PK_Verifier ver(*dsakey, "EMSA1(SHA-1)"); diff --git a/doc/examples/ecdsa.cpp b/doc/examples/ecdsa.cpp index 1607107eb..b0a66a888 100644 --- a/doc/examples/ecdsa.cpp +++ b/doc/examples/ecdsa.cpp @@ -40,7 +40,7 @@ int main() signer.update((const byte*)message, strlen(message)); - SecureVector<byte> sig = signer.signature(rng); + std::vector<byte> sig = signer.signature(rng); std::cout << sig.size() << "\n"; diff --git a/doc/examples/encrypt.cpp b/doc/examples/encrypt.cpp index 28017d875..158806936 100644 --- a/doc/examples/encrypt.cpp +++ b/doc/examples/encrypt.cpp @@ -33,7 +33,7 @@ you're encrypting is 1 Gb... you better have a lot of RAM. using namespace Botan; -std::string b64_encode(const SecureVector<byte>&); +std::string b64_encode(const secure_vector<byte>&); int main(int argc, char* argv[]) { @@ -128,7 +128,7 @@ int main(int argc, char* argv[]) std::auto_ptr<PBKDF> pbkdf(get_pbkdf("PBKDF2(SHA-1)")); - SecureVector<byte> salt(8); + secure_vector<byte> salt(8); rng.randomize(&salt[0], salt.size()); const u32bit PBKDF2_ITERATIONS = 8192; @@ -185,7 +185,7 @@ int main(int argc, char* argv[]) return 0; } -std::string b64_encode(const SecureVector<byte>& in) +std::string b64_encode(const secure_vector<byte>& in) { Pipe pipe(new Base64_Encoder); pipe.process_msg(in); diff --git a/doc/examples/encrypt2.cpp b/doc/examples/encrypt2.cpp index 41f4fb478..c6c735af9 100644 --- a/doc/examples/encrypt2.cpp +++ b/doc/examples/encrypt2.cpp @@ -28,10 +28,10 @@ int main() const u32bit PBKDF2_ITERATIONS = 8192; - SecureVector<byte> salt(8); + secure_vector<byte> salt(8); rng.randomize(&salt[0], salt.size()); - SecureVector<byte> master_key = pbkdf2.derive_key(48, passphrase, + secure_vector<byte> master_key = pbkdf2.derive_key(48, passphrase, &salt[0], salt.size(), PBKDF2_ITERATIONS).bits_of(); @@ -55,12 +55,12 @@ int main() ) ); - outfile.write((const char*)salt.begin(), salt.size()); + outfile.write((const char*)&salt[0], salt.size()); pipe.start_msg(); infile >> pipe; pipe.end_msg(); - SecureVector<byte> hmac = pipe.read_all(1); - outfile.write((const char*)hmac.begin(), hmac.size()); + secure_vector<byte> hmac = pipe.read_all(1); + outfile.write((const char*)&hmac[0], hmac.size()); } diff --git a/doc/examples/fpe.cpp b/doc/examples/fpe.cpp index 029a761e7..8f5eaca9f 100644 --- a/doc/examples/fpe.cpp +++ b/doc/examples/fpe.cpp @@ -55,11 +55,11 @@ u64bit cc_derank(u64bit cc_number) /* * Use the SHA-1 hash of the account name or ID as a tweak */ -SecureVector<byte> sha1(const std::string& acct_name) +std::vector<byte> sha1(const std::string& acct_name) { SHA_160 hash; hash.update(acct_name); - return hash.final(); + return unlock(hash.final()); } u64bit encrypt_cc_number(u64bit cc_number, @@ -123,7 +123,7 @@ int main(int argc, char* argv[]) * In practice something like PBKDF2 with a salt and high iteration * count would be a good idea. */ - SymmetricKey key = sha1(passwd); + SymmetricKey key(sha1(passwd)); u64bit enc_cc = encrypt_cc_number(cc_number, key, acct_name); diff --git a/doc/examples/gen_certs.cpp b/doc/examples/gen_certs.cpp index f8c9fe124..14ae5a0a9 100644 --- a/doc/examples/gen_certs.cpp +++ b/doc/examples/gen_certs.cpp @@ -11,9 +11,9 @@ #include <botan/botan.h> #include <botan/rsa.h> -#include <botan/time.h> #include <botan/x509self.h> #include <botan/x509_ca.h> +#include <chrono> using namespace Botan; @@ -81,14 +81,14 @@ void save_pair(const std::string& name, } +typedef std::chrono::duration<int, std::ratio<31556926>> years; + int main() { - const u32bit seconds_in_a_year = 31556926; - - const u32bit current_time = system_time(); + auto current_time = std::chrono::system_clock::now(); X509_Time now = X509_Time(current_time); - X509_Time later = X509_Time(current_time + 4*seconds_in_a_year); + X509_Time later = X509_Time(current_time + years(4)); LibraryInitializer init; diff --git a/doc/examples/hash_quickly.cpp b/doc/examples/hash_quickly.cpp index a18ab4fa6..87937efff 100644 --- a/doc/examples/hash_quickly.cpp +++ b/doc/examples/hash_quickly.cpp @@ -29,7 +29,7 @@ namespace { void set_fastest_implementation(const std::string& algo, Botan::RandomNumberGenerator& rng, - double ms = 30) + std::chrono::milliseconds ms = std::chrono::milliseconds(30)) { Botan::Algorithm_Factory& af = Botan::global_state().algorithm_factory(); diff --git a/doc/examples/keywrap.cpp b/doc/examples/keywrap.cpp index 730bcb6c9..93cdbfb84 100644 --- a/doc/examples/keywrap.cpp +++ b/doc/examples/keywrap.cpp @@ -28,11 +28,11 @@ int main() Algorithm_Factory& af = global_state().algorithm_factory(); - SecureVector<byte> enc = rfc3394_keywrap(key.bits_of(), kek, af); + secure_vector<byte> enc = rfc3394_keywrap(key.bits_of(), kek, af); std::cout << "Encrypted: " << hex_encode(enc) << "\n"; - SecureVector<byte> dec = rfc3394_keyunwrap(enc, kek, af); + secure_vector<byte> dec = rfc3394_keyunwrap(enc, kek, af); std::cout << "Decrypted: " << hex_encode(dec) << "\n"; } diff --git a/doc/examples/new_engine.cpp b/doc/examples/new_engine.cpp index 42e5dbe33..7e51df2e2 100644 --- a/doc/examples/new_engine.cpp +++ b/doc/examples/new_engine.cpp @@ -43,7 +43,7 @@ class XOR_Cipher : public StreamCipher copy_mem(&mask[0], key, length); } - SecureVector<byte> mask; + secure_vector<byte> mask; u32bit mask_pos; }; diff --git a/doc/examples/pqg_gen.cpp b/doc/examples/pqg_gen.cpp index c033dac3b..b24c30844 100644 --- a/doc/examples/pqg_gen.cpp +++ b/doc/examples/pqg_gen.cpp @@ -13,7 +13,7 @@ #include <botan/botan.h> #include <botan/auto_rng.h> -#include <botan/dsa.h> +#include <botan/hex.h> #include <botan/numthry.h> #include <botan/dl_group.h> using namespace Botan; @@ -94,9 +94,7 @@ bool check(RandomNumberGenerator& rng, //u32bit c = to_u32bit(inputs["c"]); - Pipe pipe(new Hex_Decoder); - pipe.process_msg(inputs["Seed"]); - SecureVector<byte> seed = pipe.read_all(); + std::vector<byte> seed = unlock(hex_decode(inputs["Seed"])); BigInt our_p, our_q; diff --git a/doc/examples/read_ssh.cpp b/doc/examples/read_ssh.cpp index f6299a29d..0392786a5 100644 --- a/doc/examples/read_ssh.cpp +++ b/doc/examples/read_ssh.cpp @@ -42,7 +42,7 @@ BigInt read_bigint(Pipe& pipe) { u32bit len = read_u32bit(pipe); - SecureVector<byte> buf(len); + secure_vector<byte> buf(len); pipe.read(&buf[0], len); return BigInt::decode(buf); } diff --git a/doc/examples/rng_test.cpp b/doc/examples/rng_test.cpp index c0d24fd80..385ac57f3 100644 --- a/doc/examples/rng_test.cpp +++ b/doc/examples/rng_test.cpp @@ -68,11 +68,11 @@ void x931_tests(std::vector<std::pair<std::string, std::string> > vecs, ANSI_X931_RNG prng(get_block_cipher(cipher), new Fixed_Output_RNG); - SecureVector<byte> x = hex_decode(input); - prng.add_entropy(x.begin(), x.size()); + secure_vector<byte> x = hex_decode(input); + prng.add_entropy(&x[0], x.size()); - SecureVector<byte> output(result.size() / 2); - prng.randomize(output, output.size()); + secure_vector<byte> output(result.size() / 2); + prng.randomize(&output[0], output.size()); if(hex_decode(result) != output) std::cout << "FAIL"; diff --git a/doc/examples/row_encryptor.cpp b/doc/examples/row_encryptor.cpp index 685850945..b512025b6 100644 --- a/doc/examples/row_encryptor.cpp +++ b/doc/examples/row_encryptor.cpp @@ -26,22 +26,22 @@ class Row_Encryptor RandomNumberGenerator& rng); Row_Encryptor(const std::string& passphrase, - const MemoryRegion<byte>& salt); + const std::vector<byte>& salt); std::string encrypt(const std::string& input, - const MemoryRegion<byte>& salt); + const std::vector<byte>& salt); std::string decrypt(const std::string& input, - const MemoryRegion<byte>& salt); + const std::vector<byte>& salt); - SecureVector<byte> get_pbkdf_salt() const { return pbkdf_salt; } + std::vector<byte> get_pbkdf_salt() const { return pbkdf_salt; } private: void init(const std::string& passphrase); Row_Encryptor(const Row_Encryptor&) {} Row_Encryptor& operator=(const Row_Encryptor&) { return (*this); } - SecureVector<byte> pbkdf_salt; + std::vector<byte> pbkdf_salt; Pipe enc_pipe, dec_pipe; EAX_Encryption* eax_enc; // owned by enc_pipe EAX_Decryption* eax_dec; // owned by dec_pipe; @@ -56,7 +56,7 @@ Row_Encryptor::Row_Encryptor(const std::string& passphrase, } Row_Encryptor::Row_Encryptor(const std::string& passphrase, - const MemoryRegion<byte>& salt) + const std::vector<byte>& salt) { pbkdf_salt = salt; init(passphrase); @@ -66,7 +66,7 @@ void Row_Encryptor::init(const std::string& passphrase) { std::auto_ptr<PBKDF> pbkdf(get_pbkdf("PBKDF2(SHA-160)")); - SecureVector<byte> key = pbkdf->derive_key(32, passphrase, + secure_vector<byte> key = pbkdf->derive_key(32, passphrase, &pbkdf_salt[0], pbkdf_salt.size(), 10000).bits_of(); @@ -89,7 +89,7 @@ void Row_Encryptor::init(const std::string& passphrase) } std::string Row_Encryptor::encrypt(const std::string& input, - const MemoryRegion<byte>& salt) + const std::vector<byte>& salt) { eax_enc->set_iv(salt); enc_pipe.process_msg(input); @@ -97,7 +97,7 @@ std::string Row_Encryptor::encrypt(const std::string& input, } std::string Row_Encryptor::decrypt(const std::string& input, - const MemoryRegion<byte>& salt) + const std::vector<byte>& salt) { eax_dec->set_iv(salt); dec_pipe.process_msg(input); @@ -133,7 +133,7 @@ int main() } std::vector<std::string> encrypted_values; - MemoryVector<byte> salt(4); // keep out of loop to avoid excessive dynamic allocation + std::vector<byte> salt(4); for(u32bit i = 0; i != original_inputs.size(); ++i) { diff --git a/doc/examples/rsa_dec.cpp b/doc/examples/rsa_dec.cpp index 81592328c..98768cda7 100644 --- a/doc/examples/rsa_dec.cpp +++ b/doc/examples/rsa_dec.cpp @@ -20,7 +20,7 @@ same key format as that generated by rsa_kgen. #include <botan/rsa.h> using namespace Botan; -SecureVector<byte> b64_decode(const std::string&); +secure_vector<byte> b64_decode(const std::string&); SymmetricKey derive_key(const std::string&, const SymmetricKey&, u32bit); const std::string SUFFIX = ".enc"; @@ -41,7 +41,7 @@ int main(int argc, char* argv[]) AutoSeeded_RNG rng; std::auto_ptr<PKCS8_PrivateKey> key( - PKCS8::load_key(argv[1], rng, argv[3])); + PKCS8::load_key(std::string(argv[1]), rng, std::string(argv[3]))); RSA_PrivateKey* rsakey = dynamic_cast<RSA_PrivateKey*>(key.get()); if(!rsakey) @@ -73,11 +73,11 @@ int main(int argc, char* argv[]) std::string mac_str; std::getline(message, mac_str); - SecureVector<byte> enc_masterkey = b64_decode(enc_masterkey_str); + secure_vector<byte> enc_masterkey = b64_decode(enc_masterkey_str); PK_Decryptor_EME decryptor(*rsakey, "EME1(SHA-1)"); - SecureVector<byte> masterkey = decryptor.decrypt(enc_masterkey); + secure_vector<byte> masterkey = decryptor.decrypt(enc_masterkey); SymmetricKey cast_key = derive_key("CAST", masterkey, 16); InitializationVector iv = derive_key("IV", masterkey, 8); @@ -113,7 +113,7 @@ int main(int argc, char* argv[]) return 0; } -SecureVector<byte> b64_decode(const std::string& in) +secure_vector<byte> b64_decode(const std::string& in) { Pipe pipe(new Base64_Decoder); pipe.process_msg(in); diff --git a/doc/examples/rsa_enc.cpp b/doc/examples/rsa_enc.cpp index ac609c4b3..b8e5d874b 100644 --- a/doc/examples/rsa_enc.cpp +++ b/doc/examples/rsa_enc.cpp @@ -34,9 +34,10 @@ #include <botan/botan.h> #include <botan/pubkey.h> #include <botan/rsa.h> +#include <botan/base64.h> + using namespace Botan; -std::string b64_encode(const SecureVector<byte>&); SymmetricKey derive_key(const std::string&, const SymmetricKey&, u32bit); int main(int argc, char* argv[]) @@ -98,10 +99,10 @@ int main(int argc, char* argv[]) SymmetricKey mac_key = derive_key("MAC", masterkey, 16); SymmetricKey iv = derive_key("IV", masterkey, 8); - SecureVector<byte> encrypted_key = + std::vector<byte> encrypted_key = encryptor.encrypt(masterkey.bits_of(), rng); - ciphertext << b64_encode(encrypted_key) << std::endl; + ciphertext << base64_encode(encrypted_key) << std::endl; Pipe pipe(new Fork( new Chain( @@ -135,13 +136,6 @@ int main(int argc, char* argv[]) return 0; } -std::string b64_encode(const SecureVector<byte>& in) - { - Pipe pipe(new Base64_Encoder); - pipe.process_msg(in); - return pipe.read_all_as_string(); - } - SymmetricKey derive_key(const std::string& param, const SymmetricKey& masterkey, u32bit outputlength) diff --git a/doc/examples/rsa_manykey.cpp b/doc/examples/rsa_manykey.cpp index e6a511753..c282e7882 100644 --- a/doc/examples/rsa_manykey.cpp +++ b/doc/examples/rsa_manykey.cpp @@ -31,7 +31,7 @@ int main() RSA_PrivateKey key(rng, j); - std::ofstream priv(("rsa/" + to_string(j) + ".pem").c_str()); + std::ofstream priv(("rsa/" + std::to_string(j) + ".pem").c_str()); priv << PKCS8::PEM_encode(key); priv.close(); diff --git a/doc/examples/self_sig.cpp b/doc/examples/self_sig.cpp index 64b778b71..7cb159db9 100644 --- a/doc/examples/self_sig.cpp +++ b/doc/examples/self_sig.cpp @@ -36,6 +36,9 @@ int main(int argc, char* argv[]) AutoSeeded_RNG rng; RSA_PrivateKey key(rng, 2048); + //DL_Group group(rng, DL_Group::DSA_Kosherizer, 2048, 256); + + //DSA_PrivateKey key(rng, group); std::ofstream priv_key("private.pem"); priv_key << PKCS8::PEM_encode(key, rng, argv[1]); diff --git a/doc/examples/socket.h b/doc/examples/socket.h index f7ce98fea..9e16ab36a 100644 --- a/doc/examples/socket.h +++ b/doc/examples/socket.h @@ -48,6 +48,7 @@ #include <netdb.h> #include <unistd.h> #include <errno.h> + #include <fcntl.h> typedef int socket_t; const socket_t invalid_socket = -1; @@ -66,7 +67,7 @@ class Socket { public: - size_t read(unsigned char[], size_t); + size_t read(unsigned char[], size_t, bool dont_block = false); void write(const unsigned char[], size_t); std::string peer_id() const { return peer; } @@ -158,23 +159,28 @@ Socket::Socket(const std::string& host, unsigned short port) : peer(host) throw std::runtime_error("Socket: connect failed"); } + //fcntl(fd, F_SETFL, O_NONBLOCK); + sockfd = fd; } /** * Read from a Unix socket */ -size_t Socket::read(unsigned char buf[], size_t length) +size_t Socket::read(unsigned char buf[], size_t length, bool partial) { if(sockfd == invalid_socket) throw std::runtime_error("Socket::read: Socket not connected"); size_t got = 0; + int flags = MSG_NOSIGNAL; + while(length) { - ssize_t this_time = ::recv(sockfd, (char*)buf + got, - length, MSG_NOSIGNAL); + ssize_t this_time = ::recv(sockfd, (char*)buf + got, length, flags); + + const bool full_ret = (this_time == (ssize_t)length); if(this_time == 0) break; @@ -183,13 +189,19 @@ size_t Socket::read(unsigned char buf[], size_t length) { if(socket_error_code == EINTR) this_time = 0; + else if(socket_error_code == EAGAIN) + break; else throw std::runtime_error("Socket::read: Socket read failed"); } got += this_time; length -= this_time; + + if(partial && !full_ret) + break; } + return got; } diff --git a/doc/examples/tls_client.cpp b/doc/examples/tls_client.cpp index cedfe1ca8..deb0ff460 100644 --- a/doc/examples/tls_client.cpp +++ b/doc/examples/tls_client.cpp @@ -1,91 +1,242 @@ #include <botan/botan.h> #include <botan/tls_client.h> -#include "socket.h" - -using namespace Botan; - +#include <botan/pkcs8.h> +#include <botan/hex.h> #include <stdio.h> #include <string> #include <iostream> #include <memory> -class Client_TLS_Policy : public TLS_Policy +#include <sys/types.h> +#include <sys/time.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netdb.h> +#include <unistd.h> +#include <errno.h> +#include <fcntl.h> + +#if defined(BOTAN_HAS_TLS_SQLITE_SESSION_MANAGER) + #include <botan/tls_sqlite_sess_mgr.h> +#endif + +#include "credentials.h" + +using namespace Botan; + +using namespace std::placeholders; + +int connect_to_host(const std::string& host, u16bit port) { - public: - bool check_cert(const std::vector<X509_Certificate>& certs) const - { - for(size_t i = 0; i != certs.size(); ++i) - { - std::cout << certs[i].to_string(); - } + hostent* host_addr = ::gethostbyname(host.c_str()); + + if(host_addr == 0) + throw std::runtime_error("gethostbyname failed for " + host); + + if(host_addr->h_addrtype != AF_INET) // FIXME + throw std::runtime_error(host + " has IPv6 address"); + + int fd = ::socket(PF_INET, SOCK_STREAM, 0); + if(fd == -1) + throw std::runtime_error("Unable to acquire socket"); + + sockaddr_in socket_info; + ::memset(&socket_info, 0, sizeof(socket_info)); + socket_info.sin_family = AF_INET; + socket_info.sin_port = htons(port); + + ::memcpy(&socket_info.sin_addr, + host_addr->h_addr, + host_addr->h_length); + + socket_info.sin_addr = *(struct in_addr*)host_addr->h_addr; // FIXME + + if(::connect(fd, (sockaddr*)&socket_info, sizeof(struct sockaddr)) != 0) + { + ::close(fd); + throw std::runtime_error("connect failed"); + } + + return fd; + } + +bool handshake_complete(const TLS::Session& session) + { + std::cout << "Handshake complete!\n"; + std::cout << "Protocol version " << session.version().to_string() << "\n"; + std::cout << "Ciphersuite " << std::hex << session.ciphersuite().to_string() << "\n"; + std::cout << "Session ID " << hex_encode(session.session_id()) << "\n"; + std::cout << "Session ticket " << hex_encode(session.session_ticket()) << "\n"; - std::cout << "Warning: not checking cert signatures\n"; + return true; + } + +void socket_write(int sockfd, const byte buf[], size_t length) + { + size_t offset = 0; - return true; + while(length) + { + ssize_t sent = ::send(sockfd, (const char*)buf + offset, + length, MSG_NOSIGNAL); + + if(sent == -1) + { + if(errno == EINTR) + sent = 0; + else + throw std::runtime_error("Socket::write: Socket write failed"); } - }; -int main(int argc, char* argv[]) + offset += sent; + length -= sent; + } + } + +bool got_alert = false; + +void process_data(const byte buf[], size_t buf_size, TLS::Alert alert) { - if(argc != 2 && argc != 3) + if(alert.is_valid()) { - printf("Usage: %s host [port]\n", argv[0]); - return 1; + std::cout << "Alert: " << alert.type_string() << "\n"; + got_alert = true; } - try + for(size_t i = 0; i != buf_size; ++i) { - LibraryInitializer botan_init; + std::cout << buf[i]; + } + } - std::string host = argv[1]; - u32bit port = argc == 3 ? Botan::to_u32bit(argv[2]) : 443; +std::string protocol_chooser(const std::vector<std::string>& protocols) + { + for(size_t i = 0; i != protocols.size(); ++i) + std::cout << "Protocol " << i << " = " << protocols[i] << "\n"; + return "http/1.1"; + } - printf("Connecting to %s:%d...\n", host.c_str(), port); +void doit(RandomNumberGenerator& rng, + TLS::Policy& policy, + TLS::Session_Manager& session_manager, + Credentials_Manager& creds, + const std::string& host, + u16bit port) + { + int sockfd = connect_to_host(host, port); - SocketInitializer socket_init; + TLS::Client client(std::bind(socket_write, sockfd, _1, _2), + process_data, + handshake_complete, + session_manager, + creds, + policy, + rng, + host); - Socket sock(argv[1], port); + fd_set readfds; - AutoSeeded_RNG rng; + while(true) + { + FD_ZERO(&readfds); + FD_SET(sockfd, &readfds); + FD_SET(STDIN_FILENO, &readfds); - Client_TLS_Policy policy; + ::select(sockfd + 1, &readfds, NULL, NULL, NULL); - TLS_Client tls(std::tr1::bind(&Socket::read, std::tr1::ref(sock), _1, _2), - std::tr1::bind(&Socket::write, std::tr1::ref(sock), _1, _2), - policy, rng); + if(client.is_closed()) + break; - printf("Handshake extablished...\n"); + if(FD_ISSET(sockfd, &readfds)) + { + byte buf[64] = { 0 }; -#if 0 - std::string http_command = "GET / HTTP/1.1\r\n" - "Server: " + host + ':' + to_string(port) + "\r\n\r\n"; -#else - std::string http_command = "GET / HTTP/1.0\r\n\r\n"; -#endif + size_t to_read = rand() % sizeof(buf); + if(to_read == 0) + to_read = 1; - tls.write((const Botan::byte*)http_command.c_str(), - http_command.length()); + ssize_t got = read(sockfd, buf, to_read); - size_t total_got = 0; + if(got == 0) + { + std::cout << "EOF on socket\n"; + break; + } + else if(got == -1) + { + std::cout << "Socket error: " << errno << " " << strerror(errno) << "\n"; + continue; + } - while(true) + client.received_data(buf, got); + //std::cout << "Socket - got " << got << " bytes, need " << needed << "\n"; + } + else if(FD_ISSET(STDIN_FILENO, &readfds)) { - if(tls.is_closed()) - break; + byte buf[1024] = { 0 }; + ssize_t got = read(STDIN_FILENO, buf, sizeof(buf)); - Botan::byte buf[128+1] = { 0 }; - size_t got = tls.read(buf, sizeof(buf)-1); - printf("%s", buf); - fflush(0); + if(got == 0) + { + std::cout << "EOF on stdin\n"; + client.close(); + break; + } + else if(got == -1) + { + std::cout << "Stdin error: " << errno << " " << strerror(errno) << "\n"; + continue; + } - total_got += got; + if(got == 2 && (buf[0] == 'R' || buf[0] == 'r') && buf[1] == '\n') + { + std::cout << "Client initiated renegotiation\n"; + client.renegotiate((buf[0] == 'R')); + } + + if(buf[0] == 'H') + client.heartbeat(&buf[1], got-1); + else + client.send(buf, got); } + } + + ::close(sockfd); + } + +int main(int argc, char* argv[]) + { + if(argc != 2 && argc != 3) + { + std::cout << "Usage " << argv[0] << " host [port]\n"; + return 1; + } + + try + { + LibraryInitializer botan_init; + AutoSeeded_RNG rng; + TLS::Policy policy; + +#if defined(BOTAN_HAS_TLS_SQLITE_SESSION_MANAGER) + TLS::Session_Manager_SQLite session_manager("my secret passphrase", rng, + "sessions.db"); +#else + TLS::Session_Manager_In_Memory session_manager; +#endif + + Credentials_Manager_Simple creds(rng); + + std::string host = argv[1]; + u32bit port = argc == 3 ? Botan::to_u32bit(argv[2]) : 443; + + //while(true) + doit(rng, policy, session_manager, creds, host, port); - printf("\nRetrieved %d bytes total\n", total_got); } catch(std::exception& e) { - printf("%s\n", e.what()); + std::cout << "Exception: " << e.what() << "\n"; return 1; } return 0; diff --git a/doc/examples/tls_server.cpp b/doc/examples/tls_server.cpp index 153b26d04..727f4c333 100644 --- a/doc/examples/tls_server.cpp +++ b/doc/examples/tls_server.cpp @@ -1,33 +1,140 @@ #include <botan/botan.h> #include <botan/tls_server.h> +#include <botan/hex.h> #include <botan/rsa.h> #include <botan/dsa.h> #include <botan/x509self.h> +#include <botan/secqueue.h> #include "socket.h" +#include "credentials.h" using namespace Botan; +using namespace std::placeholders; + #include <stdio.h> #include <string> #include <iostream> #include <memory> -class Server_TLS_Policy : public TLS_Policy +class Blocking_TLS_Server { public: - bool check_cert(const std::vector<X509_Certificate>& certs) const + Blocking_TLS_Server(std::function<void (const byte[], size_t)> output_fn, + std::function<size_t (byte[], size_t)> input_fn, + std::vector<std::string>& protocols, + TLS::Session_Manager& sessions, + Credentials_Manager& creds, + TLS::Policy& policy, + RandomNumberGenerator& rng) : + input_fn(input_fn), + server( + output_fn, + std::bind(&Blocking_TLS_Server::reader_fn, std::ref(*this), _1, _2, _3), + std::bind(&Blocking_TLS_Server::handshake_complete, std::ref(*this), _1), + sessions, + creds, + policy, + rng, + protocols), + exit(false) + { + read_loop(); + } + + bool handshake_complete(const TLS::Session& session) + { + std::cout << "Handshake complete: " + << session.version().to_string() << " " + << session.ciphersuite().to_string() << " " + << "SessionID: " << hex_encode(session.session_id()) << "\n"; + + if(session.srp_identifier() != "") + std::cout << "SRP identifier: " << session.srp_identifier() << "\n"; + + if(server.next_protocol() != "") + std::cout << "Next protocol: " << server.next_protocol() << "\n"; + + /* + std::vector<X509_Certificate> peer_certs = session.peer_certs(); + if(peer_certs.size()) + std::cout << peer_certs[0].to_string(); + */ + + return true; + } + + size_t read(byte buf[], size_t buf_len) { - for(size_t i = 0; i != certs.size(); ++i) + size_t got = read_queue.read(buf, buf_len); + + while(!exit && !got) { - std::cout << certs[i].to_string(); + read_loop(TLS::TLS_HEADER_SIZE); + got = read_queue.read(buf, buf_len); } - std::cout << "Warning: not checking cert signatures\n"; + return got; + } - return true; + void write(const byte buf[], size_t buf_len) + { + server.send(buf, buf_len); + } + + void close() { server.close(); } + + bool is_active() const { return server.is_active(); } + + TLS::Server& underlying() { return server; } + private: + void read_loop(size_t init_desired = 0) + { + size_t desired = init_desired; + + byte buf[4096]; + while(!exit && (!server.is_active() || desired)) + { + const size_t asking = std::max(sizeof(buf), std::min(desired, static_cast<size_t>(1))); + + const size_t socket_got = input_fn(&buf[0], asking); + + if(socket_got == 0) // eof? + { + close(); + printf("got eof on socket\n"); + exit = true; + } + + desired = server.received_data(&buf[0], socket_got); + } + } + + void reader_fn(const byte buf[], size_t buf_len, TLS::Alert alert) + { + if(alert.is_valid()) + { + printf("Alert %s\n", alert.type_string().c_str()); + //exit = true; + } + + printf("Got %d bytes: ", (int)buf_len); + for(size_t i = 0; i != buf_len; ++i) + { + if(isprint(buf[i])) + printf("%c", buf[i]); + } + printf("\n"); + + read_queue.write(buf, buf_len); } + + std::function<size_t (byte[], size_t)> input_fn; + TLS::Server server; + SecureQueue read_queue; + bool exit; }; int main(int argc, char* argv[]) @@ -40,59 +147,82 @@ int main(int argc, char* argv[]) try { LibraryInitializer botan_init; - SocketInitializer socket_init; + //SocketInitializer socket_init; AutoSeeded_RNG rng; - //RSA_PrivateKey key(rng, 1024); - DSA_PrivateKey key(rng, DL_Group("dsa/jce/1024")); + Server_Socket listener(port); - X509_Cert_Options options( - "localhost/US/Syn Ack Labs/Mathematical Munitions Dept"); + TLS::Policy policy; - X509_Certificate cert = - X509::create_self_signed_cert(options, key, "SHA-1", rng); + TLS::Session_Manager_In_Memory sessions; - Server_Socket listener(port); + Credentials_Manager_Simple creds(rng); - Server_TLS_Policy policy; + std::vector<std::string> protocols; + + /* + * These are the protocols we advertise to the client, but the + * client will send back whatever it actually plans on talking, + * which may or may not take into account what we advertise. + */ + protocols.push_back("echo/1.0"); + protocols.push_back("echo/1.1"); while(true) { try { printf("Listening for new connection on port %d\n", port); - Socket* sock = listener.accept(); + std::auto_ptr<Socket> sock(listener.accept()); printf("Got new connection\n"); - TLS_Server tls( - std::tr1::bind(&Socket::read, std::tr1::ref(sock), _1, _2), - std::tr1::bind(&Socket::write, std::tr1::ref(sock), _1, _2), - policy, - rng, - cert, - key); + Blocking_TLS_Server tls( + std::bind(&Socket::write, std::ref(sock), _1, _2), + std::bind(&Socket::read, std::ref(sock), _1, _2, true), + protocols, + sessions, + creds, + policy, + rng); - std::string hostname = tls.requested_hostname(); + const char* msg = "Welcome to the best echo server evar\n"; + tls.write((const Botan::byte*)msg, strlen(msg)); - if(hostname != "") - printf("Client requested host '%s'\n", hostname.c_str()); + std::string line; - printf("Writing some text\n"); + while(tls.is_active()) + { + byte b; + size_t got = tls.read(&b, 1); - char msg[] = "Foo\nBar\nBaz\nQuux\n"; - tls.write((const Botan::byte*)msg, strlen(msg)); + if(got == 0) + break; + + line += (char)b; + if(b == '\n') + { + //std::cout << line; + + tls.write(reinterpret_cast<const byte*>(line.data()), line.size()); - printf("Now trying a read...\n"); + if(line == "quit\n") + { + tls.close(); + break; + } - char buf[1024] = { 0 }; - u32bit got = tls.read((Botan::byte*)buf, sizeof(buf)-1); - printf("%d: '%s'\n", got, buf); + if(line == "reneg\n") + tls.underlying().renegotiate(false); + else if(line == "RENEG\n") + tls.underlying().renegotiate(true); - tls.close(); + line.clear(); + } + } } - catch(std::exception& e) { printf("%s\n", e.what()); } + catch(std::exception& e) { printf("Connection problem: %s\n", e.what()); } } } catch(std::exception& e) diff --git a/doc/examples/tss.cpp b/doc/examples/tss.cpp index 03d7699bf..aecf95796 100644 --- a/doc/examples/tss.cpp +++ b/doc/examples/tss.cpp @@ -11,7 +11,7 @@ namespace { -void print(const Botan::SecureVector<Botan::byte>& r) +void print(const Botan::secure_vector<Botan::byte>& r) { for(Botan::u32bit i = 0; i != r.size(); ++i) printf("%02X", r[i]); diff --git a/doc/index.txt b/doc/index.txt index 75e2ca434..33de06f55 100644 --- a/doc/index.txt +++ b/doc/index.txt @@ -4,7 +4,7 @@ Welcome Botan is a :doc:`BSD-licensed <license>` crypto library for C++. It provides applications with most any :doc:`cryptographic algorithm -<algos>` you might be looking for, along with :doc:`SSL/TLS <ssl>`, +<algos>` you might be looking for, along with :doc:`SSL/TLS <tls>`, :doc:`X.509 certificates and CRLs <x509>`, a :doc:`pipeline-style message processing system <filters>`, and a wide variety of other features. A third party open source implementation of `SSHv2 diff --git a/doc/log.txt b/doc/log.txt index 478b27a94..180a50340 100644 --- a/doc/log.txt +++ b/doc/log.txt @@ -10,10 +10,21 @@ Series 1.10 Version 1.10.2, Not Yet Released ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +* Pipe::reset no longer requires that message processing be completed, + a requirement that caused problems when a Filter's end_msg call + threw an exception, after which point the Pipe object was no longer + usable. + * The SSL/TLS code is disabled by default in this release. A new version is being developed and the current iteration should not be used unless needed for existing code. +* Add support for the rdrand instruction introduced in Intel's Ivy + Bridge processors. + +* CPUID::has_rdrand was checking the wrong cpuid bit, and would false + positive on AMD Bulldozer processors. + * Add the Camellia block cipher * An implementation of SRP-6a compatible with the specification in @@ -34,6 +45,9 @@ Version 1.10.2, Not Yet Released * Add Google's Native Client as an compile target +* The Qt mutex wrapper was broken and would not compile with any recent + version of Qt. It has been removed. + * If targetting GCC on a Windows system, configure.py will warn that likely you wanted to configure for either MinGW or Cygwin, not the generic Windows target which is oriented to Win32 plus the Visual diff --git a/doc/ssl.txt b/doc/ssl.txt deleted file mode 100644 index f536b7198..000000000 --- a/doc/ssl.txt +++ /dev/null @@ -1,58 +0,0 @@ - -.. _ssl_api: - -SSL and TLS -======================================== - -.. versionadded:: 1.9.4 - -Botan supports both client and server implementations of the SSL/TLS -protocols, including SSL v3, TLS v1.0, and TLS v1.1. The insecure and -obsolete SSL v2 is not supported. - -The implementation uses ``std::tr1::function``, so it may not have -been compiled into the version you are using; you can test for the -feature macro ``BOTAN_HAS_SSL_TLS`` to check. - -TLS Clients ----------------------------------------- - -.. cpp:class:: TLS_Client - - .. cpp:function:: TLS_Client( \ - std::tr1::function<size_t, byte*, size_t> input_fn, \ - std::tr1::function<void, const byte*, size_t> output_fn, \ - const TLS_Policy& policy, RandomNumberGenerator& rng) - - Creates a TLS client. It will call *input_fn* to read bytes from - the network and call *output_fn* when bytes need to be written to - the network. - - .. cpp:function:: size_t read(byte* buf, size_t buf_len) - - Reads up to *buf_len* bytes from the open connection into *buf*, - returning the number of bytes actually written. - - .. cpp:function:: void write(const byte* buf, size_t buf_len) - - Writes *buf_len* bytes in *buf* to the remote side - - .. cpp:function:: void close() - - Closes the connection - - .. cpp:function:: std::vector<X509_Certificate> peer_cert_chain() - - Returns the certificate chain of the server - -A simple TLS client example: - -.. literalinclude:: examples/tls_client.cpp - - -TLS Servers ----------------------------------------- - -A simple TLS server - -.. literalinclude:: examples/tls_server.cpp diff --git a/doc/tls.txt b/doc/tls.txt new file mode 100644 index 000000000..267fb6e62 --- /dev/null +++ b/doc/tls.txt @@ -0,0 +1,151 @@ + +.. _tls_api: + +SSL and TLS +======================================== + +.. versionadded:: 1.10.2 + +Botan supports both client and server implementations of the SSL/TLS +protocols, including SSL v3, TLS v1.0, TLS v1.1, and TLS v1.2 (the +insecure and obsolete SSL v2 protocol is not supported, beyond +processing SSL v2 client hellos which some clients still send for +backwards compatability with ancient servers). + +The implementation uses ``std::tr1::function`` for callbacks, so it +may not have been compiled into the version you are using; you can +test for the feature macro ``BOTAN_HAS_TLS`` to check. + +General TLS Interface +---------------------------------------- + +TLS servers and clients share most of an interface, called +`TLS_Channel`. The primary difference is in terms of how the objects +are constructed. A TLS channel (either client or server object) has +these methods available: + +.. cpp:class:: TLS_Channel + + .. cpp:function size_t received_data(const byte buf[], size_t buf_size) + + This function is used to provide data sent by the counterparty (eg + data that you read off the socket layer). Depending on the current + protocol state and the amount of data provided this may result in one + or more callback functions that were provided to the constructor being + called. + + .. cpp:function void send(const byte buf[], size_t buf_size) + + If the connection has completed the initial handshake process, the + data provided is sent to the counterparty as TLS + traffic. Otherwise, an exception is thrown. + + .. cpp:function:: void close() + + A close notification is sent to the counterparty, and the internal + state is cleared. + + .. cpp:function:: bool is_active() + + Returns true if and only if a handshake has been completed on this + connection. + + .. cpp:function:: bool is_closed() + + Returns true if and only if a close notification has been sent or + received, or if a fatal alert of any kind was received from the + counterparty. + + .. cpp:function:: void renegotiate() + + Initiates a renegotiation. The counterparty is allowed by the + protocol to ignore this request. If a successful renegotiation + occurs, the *handshake_complete* callback will be called again. + + .. cpp:function:: std::vector<X509_Certificate> peer_cert_chain() + + Returns the certificate chain of the server + + + +TLS Clients +---------------------------------------- + +.. cpp:class:: TLS_Client + + .. cpp:function:: TLS_Client( \ + std::tr1::function<void, const byte*, size_t> socket_output_fn, \ + std::tr1::function<void, const byte*, size_t, u16bit> proc_fn, \ + std::tr1::function<bool, const TLS_Session&> handshake_complete, \ + TLS_Session_Manager& session_manager, \ + Credentials_Manager& credendials_manager, \ + const TLS_Policy& policy, \ + RandomNumberGenerator& rng, \ + const std::string& servername = "", \ + std::tr1::function<std::string, std::vector<std::string> > next_protocol) + + Initialize a new TLS client. The constructor will immediately + initiate a new session. The *socket_output_fn* callback will be + called with output that should be sent to the counterparty. + + The *proc_fn* will be called with data sent by the counterparty + after it has been processed. The byte array and size_t represent + the plaintext; the u16bit value provides notification if the + counterparty sent an alert via the TLS alert system. Possible values + of alert data are included in the Alert_Type enum. Particularly + relevant is the CLOSE_NOTIFY value. + + The *handshake_complete* function is called when a handshake + (either initial or renegotiation) is completed. The return value of + the callback specifies if the session should be cached for later + resumption. If the function for some reason desires to prevent the + connection from completing, it should throw an exception + (preferably a TLS_Exception, which can provide more specific alert + information to the counterparty). + + The *session_manager* is an interface for storing TLS sessions, + which allows for session resumption upon reconnecting to a server. + In the absence of a need for persistent sessions, use + `TLS_Session_Manager_In_Memory` which caches connections for the + lifetime of a single process. + + The *credentials_manager* is an interface that will be called to + retrieve any certificates, secret keys, pre-shared keys, or SRP + intformation; see :doc:`credentials <credentials_manager>` for more + information. + + Use *servername* to specify the DNS name of the server you are + attempting to connect to, if you know it. + + The optional *next_protocol* callback is called if the server + indicates it supports the next protocol notification extension. + The callback wlil be called with a list of protocol names that the + server advertises, and the client can select from them or return an + unadvertised protocol. + +A simple TLS client example: + +.. literalinclude:: examples/tls_client.cpp + + +TLS Servers +---------------------------------------- + +.. cpp:class:: TLS_Server + + .. cpp:function:: TLS_Server(std::tr1::function<void, const byte*, size_t> socket_output_fn, \ + std::tr1::function<void, const byte*, size_t, u16bit> proc_fn, \ + std::tr1::function<bool, const TLS_Session&> handshake_complete, \ + TLS_Session_Manager& session_manager, \ + Credentials_Manager& creds, \ + const TLS_Policy& policy, \ + RandomNumberGenerator& rng, \ + const std::vector<std::string>& protocols) + +The first 7 arguments are treated similiarly to `TLS_Client`. The +final (optional) argument, protocols, specifies the protocols the +server is willing to advertise it supports. + +A TLS server that can handle concurrent connections using asio: + +.. literalinclude:: examples/asio_tls_server.cpp diff --git a/src/algo_base/algo_base.h b/src/algo_base/algo_base.h index 813216a36..f757a9a83 100644 --- a/src/algo_base/algo_base.h +++ b/src/algo_base/algo_base.h @@ -19,7 +19,6 @@ namespace Botan { class BOTAN_DLL Algorithm { public: - /** * Zeroize internal state */ @@ -31,10 +30,10 @@ class BOTAN_DLL Algorithm virtual std::string name() const = 0; Algorithm() {} + Algorithm(const Algorithm&) = delete; + Algorithm& operator=(const Algorithm&) = delete; + virtual ~Algorithm() {} - private: - Algorithm(const Algorithm&) {} - Algorithm& operator=(const Algorithm&) { return (*this); } }; } diff --git a/src/algo_base/buf_comp.h b/src/algo_base/buf_comp.h index 7838571e9..1dd8be992 100644 --- a/src/algo_base/buf_comp.h +++ b/src/algo_base/buf_comp.h @@ -10,6 +10,7 @@ #include <botan/secmem.h> #include <botan/get_byte.h> +#include <string> namespace Botan { @@ -34,9 +35,18 @@ class BOTAN_DLL Buffered_Computation /** * Add new input to process. - * @param in the input to process as a MemoryRegion + * @param in the input to process as a secure_vector */ - void update(const MemoryRegion<byte>& in) + void update(const secure_vector<byte>& in) + { + add_data(&in[0], in.size()); + } + + /** + * Add new input to process. + * @param in the input to process as a std::vector + */ + void update(const std::vector<byte>& in) { add_data(&in[0], in.size()); } @@ -82,11 +92,11 @@ class BOTAN_DLL Buffered_Computation /** * Complete the computation and retrieve the * final result. - * @return SecureVector holding the result + * @return secure_vector holding the result */ - SecureVector<byte> final() + secure_vector<byte> final() { - SecureVector<byte> output(output_length()); + secure_vector<byte> output(output_length()); final_result(&output[0]); return output; } @@ -98,7 +108,7 @@ class BOTAN_DLL Buffered_Computation * @param length the length of the byte array * @result the result of the call to final() */ - SecureVector<byte> process(const byte in[], size_t length) + secure_vector<byte> process(const byte in[], size_t length) { add_data(in, length); return final(); @@ -110,7 +120,13 @@ class BOTAN_DLL Buffered_Computation * @param in the input to process * @result the result of the call to final() */ - SecureVector<byte> process(const MemoryRegion<byte>& in) + secure_vector<byte> process(const secure_vector<byte>& in) + { + add_data(&in[0], in.size()); + return final(); + } + + secure_vector<byte> process(const std::vector<byte>& in) { add_data(&in[0], in.size()); return final(); @@ -122,7 +138,7 @@ class BOTAN_DLL Buffered_Computation * @param in the input to process as a string * @result the result of the call to final() */ - SecureVector<byte> process(const std::string& in) + secure_vector<byte> process(const std::string& in) { update(in); return final(); diff --git a/src/algo_base/symkey.cpp b/src/algo_base/symkey.cpp index 56648d9c5..52b216361 100644 --- a/src/algo_base/symkey.cpp +++ b/src/algo_base/symkey.cpp @@ -26,7 +26,7 @@ OctetString::OctetString(RandomNumberGenerator& rng, /* * Create an OctetString from a hex string */ -void OctetString::change(const std::string& hex_string) +OctetString::OctetString(const std::string& hex_string) { bits.resize(1 + hex_string.length() / 2); bits.resize(hex_decode(&bits[0], hex_string)); @@ -35,10 +35,9 @@ void OctetString::change(const std::string& hex_string) /* * Create an OctetString from a byte string */ -void OctetString::change(const byte in[], size_t n) +OctetString::OctetString(const byte in[], size_t n) { - bits.resize(n); - bits.copy(in, n); + bits.assign(in, in + n); } /* @@ -113,7 +112,7 @@ bool operator!=(const OctetString& s1, const OctetString& s2) */ OctetString operator+(const OctetString& k1, const OctetString& k2) { - SecureVector<byte> out; + secure_vector<byte> out; out += k1.bits_of(); out += k2.bits_of(); return OctetString(out); @@ -124,9 +123,10 @@ OctetString operator+(const OctetString& k1, const OctetString& k2) */ OctetString operator^(const OctetString& k1, const OctetString& k2) { - SecureVector<byte> ret(std::max(k1.length(), k2.length())); - ret.copy(k1.begin(), k1.length()); - xor_buf(ret, k2.begin(), k2.length()); + secure_vector<byte> ret(std::max(k1.length(), k2.length())); + + copy_mem(&ret[0], k1.begin(), k1.length()); + xor_buf(&ret[0], k2.begin(), k2.length()); return OctetString(ret); } diff --git a/src/algo_base/symkey.h b/src/algo_base/symkey.h index 6735b2b87..b47da8a69 100644 --- a/src/algo_base/symkey.h +++ b/src/algo_base/symkey.h @@ -25,9 +25,9 @@ class BOTAN_DLL OctetString size_t length() const { return bits.size(); } /** - * @return this object as a SecureVector<byte> + * @return this object as a secure_vector<byte> */ - SecureVector<byte> bits_of() const { return bits; } + secure_vector<byte> bits_of() const { return bits; } /** * @return start of this string @@ -57,23 +57,10 @@ class BOTAN_DLL OctetString void set_odd_parity(); /** - * Change the contents of this octet string - * @param hex_string a hex encoded bytestring - */ - void change(const std::string& hex_string); - - /** - * Change the contents of this octet string - * @param in the input - * @param length of in in bytes - */ - void change(const byte in[], size_t length); - - /** - * Change the contents of this octet string - * @param in the input + * Create a new OctetString + * @param str is a hex encoded string */ - void change(const MemoryRegion<byte>& in) { bits = in; } + OctetString(const std::string& str = ""); /** * Create a new random OctetString @@ -84,24 +71,24 @@ class BOTAN_DLL OctetString /** * Create a new OctetString - * @param str is a hex encoded string + * @param in is an array + * @param len is the length of in in bytes */ - OctetString(const std::string& str = "") { change(str); } + OctetString(const byte in[], size_t len); /** * Create a new OctetString - * @param in is an array - * @param len is the length of in in bytes + * @param in a bytestring */ - OctetString(const byte in[], size_t len) { change(in, len); } + OctetString(const secure_vector<byte>& in) : bits(in) {} /** * Create a new OctetString * @param in a bytestring */ - OctetString(const MemoryRegion<byte>& in) { change(in); } + OctetString(const std::vector<byte>& in) : bits(&in[0], &in[in.size()]) {} private: - SecureVector<byte> bits; + secure_vector<byte> bits; }; /** diff --git a/src/algo_factory/algo_cache.h b/src/algo_factory/algo_cache.h index 25f2db023..11a5580fb 100644 --- a/src/algo_factory/algo_cache.h +++ b/src/algo_factory/algo_cache.h @@ -8,8 +8,9 @@ #ifndef BOTAN_ALGORITHM_CACHE_TEMPLATE_H__ #define BOTAN_ALGORITHM_CACHE_TEMPLATE_H__ -#include <botan/internal/mutex.h> +#include <botan/types.h> #include <botan/internal/stl_util.h> +#include <mutex> #include <string> #include <vector> #include <map> @@ -67,21 +68,12 @@ class Algorithm_Cache */ void clear_cache(); - /** - * Constructor - * @param m a mutex to serialize internal access - */ - Algorithm_Cache(Mutex* m) : mutex(m) {} - ~Algorithm_Cache() { clear_cache(); delete mutex; } + ~Algorithm_Cache() { clear_cache(); } private: - typedef typename std::map<std::string, std::map<std::string, T*> >::iterator - algorithms_iterator; - - typedef typename std::map<std::string, T*>::iterator provider_iterator; + typename std::map<std::string, std::map<std::string, T*> >::const_iterator + find_algorithm(const std::string& algo_spec); - algorithms_iterator find_algorithm(const std::string& algo_spec); - - Mutex* mutex; + std::mutex mutex; std::map<std::string, std::string> aliases; std::map<std::string, std::string> pref_providers; std::map<std::string, std::map<std::string, T*> > algorithms; @@ -92,16 +84,15 @@ class Algorithm_Cache * Assumes object lock is held */ template<typename T> -typename Algorithm_Cache<T>::algorithms_iterator +typename std::map<std::string, std::map<std::string, T*> >::const_iterator Algorithm_Cache<T>::find_algorithm(const std::string& algo_spec) { - algorithms_iterator algo = algorithms.find(algo_spec); + auto algo = algorithms.find(algo_spec); // Not found? Check if a known alias if(algo == algorithms.end()) { - std::map<std::string, std::string>::const_iterator alias = - aliases.find(algo_spec); + auto alias = aliases.find(algo_spec); if(alias != aliases.end()) algo = algorithms.find(alias->second); @@ -117,28 +108,28 @@ template<typename T> const T* Algorithm_Cache<T>::get(const std::string& algo_spec, const std::string& requested_provider) { - Mutex_Holder lock(mutex); + std::lock_guard<std::mutex> lock(mutex); - algorithms_iterator algo = find_algorithm(algo_spec); + auto algo = find_algorithm(algo_spec); if(algo == algorithms.end()) // algo not found at all (no providers) - return 0; + return nullptr; // If a provider is requested specifically, return it or fail entirely if(requested_provider != "") { - provider_iterator prov = algo->second.find(requested_provider); + auto prov = algo->second.find(requested_provider); if(prov != algo->second.end()) return prov->second; - return 0; + return nullptr; } - const T* prototype = 0; + const T* prototype = nullptr; std::string prototype_provider; size_t prototype_prov_weight = 0; const std::string pref_provider = search_map(pref_providers, algo_spec); - for(provider_iterator i = algo->second.begin(); i != algo->second.end(); ++i) + for(auto i = algo->second.begin(); i != algo->second.end(); ++i) { const std::string prov_name = i->first; const size_t prov_weight = static_provider_weight(prov_name); @@ -147,7 +138,7 @@ const T* Algorithm_Cache<T>::get(const std::string& algo_spec, if(prov_name == pref_provider) return i->second; - if(prototype == 0 || prov_weight > prototype_prov_weight) + if(prototype == nullptr || prov_weight > prototype_prov_weight) { prototype = i->second; prototype_provider = i->first; @@ -169,7 +160,7 @@ void Algorithm_Cache<T>::add(T* algo, if(!algo) return; - Mutex_Holder lock(mutex); + std::lock_guard<std::mutex> lock(mutex); if(algo->name() != requested_name && aliases.find(requested_name) == aliases.end()) @@ -189,15 +180,14 @@ void Algorithm_Cache<T>::add(T* algo, template<typename T> std::vector<std::string> Algorithm_Cache<T>::providers_of(const std::string& algo_name) { - Mutex_Holder lock(mutex); + std::lock_guard<std::mutex> lock(mutex); std::vector<std::string> providers; - algorithms_iterator algo = find_algorithm(algo_name); - + auto algo = find_algorithm(algo_name); if(algo != algorithms.end()) { - provider_iterator provider = algo->second.begin(); + auto provider = algo->second.begin(); while(provider != algo->second.end()) { @@ -216,7 +206,7 @@ template<typename T> void Algorithm_Cache<T>::set_preferred_provider(const std::string& algo_spec, const std::string& provider) { - Mutex_Holder lock(mutex); + std::lock_guard<std::mutex> lock(mutex); pref_providers[algo_spec] = provider; } @@ -227,11 +217,11 @@ void Algorithm_Cache<T>::set_preferred_provider(const std::string& algo_spec, template<typename T> void Algorithm_Cache<T>::clear_cache() { - algorithms_iterator algo = algorithms.begin(); + auto algo = algorithms.begin(); while(algo != algorithms.end()) { - provider_iterator provider = algo->second.begin(); + auto provider = algo->second.begin(); while(provider != algo->second.end()) { diff --git a/src/algo_factory/algo_factory.cpp b/src/algo_factory/algo_factory.cpp index 3d640ab8a..1683648bd 100644 --- a/src/algo_factory/algo_factory.cpp +++ b/src/algo_factory/algo_factory.cpp @@ -30,7 +30,7 @@ template<typename T> T* engine_get_algo(Engine*, const SCAN_Name&, Algorithm_Factory&) - { return 0; } + { return nullptr; } template<> BlockCipher* engine_get_algo(Engine* engine, @@ -75,7 +75,7 @@ const T* factory_prototype(const std::string& algo_spec, SCAN_Name scan_name(algo_spec); if(scan_name.cipher_mode() != "") - return 0; + return nullptr; for(size_t i = 0; i != engines.size(); ++i) { @@ -94,13 +94,13 @@ const T* factory_prototype(const std::string& algo_spec, /* * Setup caches */ -Algorithm_Factory::Algorithm_Factory(Mutex_Factory& mf) +Algorithm_Factory::Algorithm_Factory() { - block_cipher_cache = new Algorithm_Cache<BlockCipher>(mf.make()); - stream_cipher_cache = new Algorithm_Cache<StreamCipher>(mf.make()); - hash_cache = new Algorithm_Cache<HashFunction>(mf.make()); - mac_cache = new Algorithm_Cache<MessageAuthenticationCode>(mf.make()); - pbkdf_cache = new Algorithm_Cache<PBKDF>(mf.make()); + block_cipher_cache = new Algorithm_Cache<BlockCipher>(); + stream_cipher_cache = new Algorithm_Cache<StreamCipher>(); + hash_cache = new Algorithm_Cache<HashFunction>(); + mac_cache = new Algorithm_Cache<MessageAuthenticationCode>(); + pbkdf_cache = new Algorithm_Cache<PBKDF>(); } /* @@ -114,7 +114,8 @@ Algorithm_Factory::~Algorithm_Factory() delete mac_cache; delete pbkdf_cache; - std::for_each(engines.begin(), engines.end(), del_fun<Engine>()); + for(auto i = engines.begin(); i != engines.end(); ++i) + delete *i; } void Algorithm_Factory::clear_caches() @@ -156,7 +157,7 @@ void Algorithm_Factory::set_preferred_provider(const std::string& algo_spec, Engine* Algorithm_Factory::get_engine_n(size_t n) const { if(n >= engines.size()) - return 0; + return nullptr; return engines[n]; } diff --git a/src/algo_factory/algo_factory.h b/src/algo_factory/algo_factory.h index b9f15757d..1bec2adf7 100644 --- a/src/algo_factory/algo_factory.h +++ b/src/algo_factory/algo_factory.h @@ -26,7 +26,6 @@ class PBKDF; template<typename T> class Algorithm_Cache; class Engine; -class Mutex_Factory; /** * Algorithm Factory @@ -38,7 +37,7 @@ class BOTAN_DLL Algorithm_Factory * Constructor * @param mf a mutex factory */ - Algorithm_Factory(Mutex_Factory& mf); + Algorithm_Factory(); /** * Destructor diff --git a/src/algo_factory/info.txt b/src/algo_factory/info.txt index eae4b3934..236fdda0e 100644 --- a/src/algo_factory/info.txt +++ b/src/algo_factory/info.txt @@ -20,6 +20,5 @@ block engine hash mac -mutex stream </requires> diff --git a/src/alloc/alloc_mmap/info.txt b/src/alloc/alloc_mmap/info.txt deleted file mode 100644 index 562277a37..000000000 --- a/src/alloc/alloc_mmap/info.txt +++ /dev/null @@ -1,28 +0,0 @@ -define ALLOC_MMAP - -<source> -mmap_mem.cpp -</source> - -<header:internal> -mmap_mem.h -</header:internal> - -<os> -linux -freebsd -dragonfly -openbsd -netbsd -solaris -qnx -darwin -tru64 - -# Only without -ansi, otherwise can't get mkstemp -#cygwin -</os> - -<requires> -mem_pool -</requires> diff --git a/src/alloc/alloc_mmap/mmap_mem.cpp b/src/alloc/alloc_mmap/mmap_mem.cpp deleted file mode 100644 index e4b602764..000000000 --- a/src/alloc/alloc_mmap/mmap_mem.cpp +++ /dev/null @@ -1,143 +0,0 @@ -/* -* Memory Mapping Allocator -* (C) 1999-2010 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/internal/mmap_mem.h> -#include <vector> -#include <cstring> - -#include <sys/types.h> -#include <sys/mman.h> -#include <sys/stat.h> -#include <unistd.h> -#include <stdlib.h> -#include <fcntl.h> -#include <errno.h> - -#ifndef MAP_FAILED - #define MAP_FAILED -1 -#endif - -namespace Botan { - -namespace { - -/* -* MemoryMapping_Allocator Exception -*/ -class BOTAN_DLL MemoryMapping_Failed : public Exception - { - public: - MemoryMapping_Failed(const std::string& msg) : - Exception("MemoryMapping_Allocator: " + msg) {} - }; - -} - -/* -* Memory Map a File into Memory -*/ -void* MemoryMapping_Allocator::alloc_block(size_t n) - { - class TemporaryFile - { - public: - int get_fd() const { return fd; } - - TemporaryFile(const std::string& base) - { - const std::string mkstemp_template = base + "XXXXXX"; - - std::vector<char> filepath(mkstemp_template.begin(), - mkstemp_template.end()); - filepath.push_back(0); // add terminating NULL - - mode_t old_umask = ::umask(077); - fd = ::mkstemp(&filepath[0]); - ::umask(old_umask); - - if(fd == -1) - throw MemoryMapping_Failed("Temporary file allocation failed"); - - if(::unlink(&filepath[0]) != 0) - throw MemoryMapping_Failed("Could not unlink temporary file"); - } - - ~TemporaryFile() - { - /* - * We can safely close here, because post-mmap the file - * will continue to exist until the mmap is unmapped from - * our address space upon deallocation (or process exit). - */ - if(fd != -1 && ::close(fd) == -1) - throw MemoryMapping_Failed("Could not close file"); - } - private: - int fd; - }; - - TemporaryFile file("/tmp/botan_"); - - if(file.get_fd() == -1) - throw MemoryMapping_Failed("Could not create file"); - - std::vector<byte> zeros(4096); - - size_t remaining = n; - - while(remaining) - { - const size_t write_try = std::min(zeros.size(), remaining); - - ssize_t wrote_got = ::write(file.get_fd(), - &zeros[0], - write_try); - - if(wrote_got == -1 && errno != EINTR) - throw MemoryMapping_Failed("Could not write to file"); - - remaining -= wrote_got; - } - -#ifndef MAP_NOSYNC - #define MAP_NOSYNC 0 -#endif - - void* ptr = ::mmap(0, n, - PROT_READ | PROT_WRITE, - MAP_SHARED | MAP_NOSYNC, - file.get_fd(), 0); - - if(ptr == static_cast<void*>(MAP_FAILED)) - throw MemoryMapping_Failed("Could not map file"); - - return ptr; - } - -/* -* Remove a Memory Mapping -*/ -void MemoryMapping_Allocator::dealloc_block(void* ptr, size_t n) - { - if(ptr == 0) - return; - - const byte PATTERNS[] = { 0x00, 0xF5, 0x5A, 0xAF, 0x00 }; - - for(size_t i = 0; i != sizeof(PATTERNS); ++i) - { - std::memset(ptr, PATTERNS[i], n); - - if(::msync((char*)ptr, n, MS_SYNC)) - throw MemoryMapping_Failed("Sync operation failed"); - } - - if(::munmap((char*)ptr, n)) - throw MemoryMapping_Failed("Could not unmap file"); - } - -} diff --git a/src/alloc/alloc_mmap/mmap_mem.h b/src/alloc/alloc_mmap/mmap_mem.h deleted file mode 100644 index fa4e5e715..000000000 --- a/src/alloc/alloc_mmap/mmap_mem.h +++ /dev/null @@ -1,36 +0,0 @@ -/* -* Memory Mapping Allocator -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_MMAP_ALLOCATOR_H__ -#define BOTAN_MMAP_ALLOCATOR_H__ - -#include <botan/internal/mem_pool.h> - -namespace Botan { - -/** -* Allocator that uses memory maps backed by disk. We zeroize the map -* upon deallocation. If swap occurs, the VM will swap to the shared -* file backing rather than to a swap device, which means we know where -* it is and can zap it later. -*/ -class MemoryMapping_Allocator : public Pooling_Allocator - { - public: - /** - * @param mutex used for internal locking - */ - MemoryMapping_Allocator(Mutex* mutex) : Pooling_Allocator(mutex) {} - std::string type() const { return "mmap"; } - private: - void* alloc_block(size_t); - void dealloc_block(void*, size_t); - }; - -} - -#endif diff --git a/src/alloc/allocate.h b/src/alloc/allocate.h deleted file mode 100644 index b8574be1e..000000000 --- a/src/alloc/allocate.h +++ /dev/null @@ -1,65 +0,0 @@ -/* -* Allocator -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_ALLOCATOR_H__ -#define BOTAN_ALLOCATOR_H__ - -#include <botan/types.h> -#include <string> - -namespace Botan { - -/** -* Allocator Interface -*/ -class BOTAN_DLL Allocator - { - public: - /** - * Acquire a pointer to an allocator - * @param locking is true if the allocator should attempt to - * secure the memory (eg for using to store keys) - * @return pointer to an allocator; ownership remains with library, - * so do not delete - */ - static Allocator* get(bool locking); - - /** - * Allocate a block of memory - * @param n how many bytes to allocate - * @return pointer to n bytes of memory - */ - virtual void* allocate(size_t n) = 0; - - /** - * Deallocate memory allocated with allocate() - * @param ptr the pointer returned by allocate() - * @param n the size of the block pointed to by ptr - */ - virtual void deallocate(void* ptr, size_t n) = 0; - - /** - * @return name of this allocator type - */ - virtual std::string type() const = 0; - - /** - * Initialize the allocator - */ - virtual void init() {} - - /** - * Shutdown the allocator - */ - virtual void destroy() {} - - virtual ~Allocator() {} - }; - -} - -#endif diff --git a/src/alloc/info.txt b/src/alloc/info.txt index 40e7bacdf..0ab7fa768 100644 --- a/src/alloc/info.txt +++ b/src/alloc/info.txt @@ -1,4 +1,3 @@ <header:public> -allocate.h secmem.h </header:public> diff --git a/src/alloc/locking_allocator/info.txt b/src/alloc/locking_allocator/info.txt new file mode 100644 index 000000000..34877e6bd --- /dev/null +++ b/src/alloc/locking_allocator/info.txt @@ -0,0 +1 @@ +define LOCKING_ALLOCATOR diff --git a/src/alloc/locking_allocator/locking_allocator.cpp b/src/alloc/locking_allocator/locking_allocator.cpp new file mode 100644 index 000000000..cc7d24c8d --- /dev/null +++ b/src/alloc/locking_allocator/locking_allocator.cpp @@ -0,0 +1,236 @@ +/* +* Mlock Allocator +* (C) 2012 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/locking_allocator.h> +#include <botan/internal/assert.h> +#include <algorithm> +#include <cstring> +#include <sys/mman.h> +#include <sys/resource.h> + +namespace Botan { + +namespace { + +size_t mlock_limit() + { + struct rlimit limits; + ::getrlimit(RLIMIT_MEMLOCK, &limits); + + if(limits.rlim_cur < limits.rlim_max) + { + limits.rlim_cur = limits.rlim_max; + ::setrlimit(RLIMIT_MEMLOCK, &limits); + ::getrlimit(RLIMIT_MEMLOCK, &limits); + } + + /* + * Linux defaults to only 64 KiB of mlockable memory per process + * (too small) but BSDs offer a small fraction of total RAM (more + * than we need). Bound the total mlock size to 256 KiB which is + * enough to run the entire test suite without spilling to non-mlock + * memory, but small enough that we should not cause problems if + * multiple processes are mlocking on the same machine. + */ + return std::min<size_t>(limits.rlim_cur, 256*1024); + } + +bool ptr_in_pool(const void* pool_ptr, size_t poolsize, + const void* buf_ptr, size_t bufsize) + { + const size_t pool = reinterpret_cast<size_t>(pool_ptr); + const size_t buf = reinterpret_cast<size_t>(buf_ptr); + + if(buf < pool || buf >= pool + poolsize) + return false; + + BOTAN_ASSERT(buf + bufsize <= pool + poolsize, + "Invalid pointer/length halfway into mem pool"); + + return true; + } + +size_t padding_for_alignment(size_t offset, size_t desired_alignment) + { + size_t mod = offset % desired_alignment; + if(mod == 0) + return 0; // already right on + return desired_alignment - mod; + } + +} + +void* mlock_allocator::allocate(size_t n, size_t alignment) + { + if(!m_pool || n >= m_poolsize) + return nullptr; // bigger than the whole pool! + + std::lock_guard<std::mutex> lock(m_mutex); + + auto best_fit = m_freelist.end(); + + for(auto i = m_freelist.begin(); i != m_freelist.end(); ++i) + { + // If we have a perfect fit, use it immediately + if(i->second == n && (i->first % alignment) == 0) + { + const size_t offset = i->first; + m_freelist.erase(i); + ::memset(m_pool + offset, 0, n); + + BOTAN_ASSERT((reinterpret_cast<size_t>(m_pool) + offset) % alignment == 0, + "Returning correctly aligned pointer"); + + return m_pool + offset; + } + + if((i->second >= (n + padding_for_alignment(i->first, alignment)) && + ((best_fit == m_freelist.end()) || (best_fit->second > i->second)))) + { + best_fit = i; + } + } + + if(best_fit != m_freelist.end()) + { + const size_t offset = best_fit->first; + + const size_t alignment_padding = padding_for_alignment(offset, alignment); + + best_fit->first += n + alignment_padding; + best_fit->second -= n + alignment_padding; + + // Need to realign, split the block + if(alignment_padding) + { + /* + If we used the entire block except for small piece used for + alignment at the beginning, so just update the entry already + in place (as it is in the correct location), rather than + deleting the empty range and inserting the new one in the + same location. + */ + if(best_fit->second == 0) + { + best_fit->first = offset; + best_fit->second = alignment_padding; + } + else + m_freelist.insert(best_fit, std::make_pair(offset, alignment_padding)); + } + + ::memset(m_pool + offset + alignment_padding, 0, n); + + BOTAN_ASSERT((reinterpret_cast<size_t>(m_pool) + offset + alignment_padding) % alignment == 0, + "Returning correctly aligned pointer"); + + return m_pool + offset + alignment_padding; + } + + return nullptr; + } + +bool mlock_allocator::deallocate(void* p, size_t n) + { + if(!m_pool || !ptr_in_pool(m_pool, m_poolsize, p, n)) + return false; + + std::lock_guard<std::mutex> lock(m_mutex); + + const size_t start = static_cast<byte*>(p) - m_pool; + + auto comp = [](std::pair<size_t, size_t> x, std::pair<size_t, size_t> y){ return x.first < y.first; }; + + auto i = std::lower_bound(m_freelist.begin(), m_freelist.end(), + std::make_pair(start, 0), comp); + + // try to merge with later block + if(i != m_freelist.end() && start + n == i->first) + { + i->first = start; + i->second += n; + n = 0; + } + + // try to merge with previous block + if(i != m_freelist.begin()) + { + auto prev = std::prev(i); + + if(prev->first + prev->second == start) + { + if(n) + { + prev->second += n; + n = 0; + } + else + { + // merge adjoining + prev->second += i->second; + m_freelist.erase(i); + } + } + } + + if(n != 0) // no merge possible? + m_freelist.insert(i, std::make_pair(start, n)); + + return true; + } + +mlock_allocator::mlock_allocator() : + m_poolsize(mlock_limit()), + m_pool(nullptr) + { +#if !defined(MAP_NOCORE) + #define MAP_NOCORE 0 +#endif + + if(m_poolsize) + { + m_pool = static_cast<byte*>( + ::mmap( + nullptr, m_poolsize, + PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_SHARED | MAP_NOCORE, + -1, 0)); + + if(m_pool == static_cast<byte*>(MAP_FAILED)) + throw std::runtime_error("Failed to mmap pool"); + + std::memset(m_pool, 0x00, m_poolsize); + + if(::mlock(m_pool, m_poolsize) != 0) + { + ::munmap(m_pool, m_poolsize); + m_pool = nullptr; + throw std::runtime_error("Failed to lock pool"); + } + + m_freelist.push_back(std::make_pair(0, m_poolsize)); + } + } + +mlock_allocator::~mlock_allocator() + { + if(m_pool) + { + std::memset(m_pool, 0, m_poolsize); + ::munlock(m_pool, m_poolsize); + ::munmap(m_pool, m_poolsize); + m_pool = nullptr; + } + } + +mlock_allocator& mlock_allocator::instance() + { + static mlock_allocator mlock; + return mlock; + } + +} diff --git a/src/alloc/locking_allocator/locking_allocator.h b/src/alloc/locking_allocator/locking_allocator.h new file mode 100644 index 000000000..2c756fcd1 --- /dev/null +++ b/src/alloc/locking_allocator/locking_allocator.h @@ -0,0 +1,39 @@ +/* +* Mlock Allocator +* (C) 2012 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_MLOCK_ALLOCATOR_H__ +#define BOTAN_MLOCK_ALLOCATOR_H__ + +#include <botan/types.h> +#include <vector> +#include <mutex> + +namespace Botan { + +class BOTAN_DLL mlock_allocator + { + public: + static mlock_allocator& instance(); + + void* allocate(size_t n, size_t alignment); + + bool deallocate(void* p, size_t n); + + private: + mlock_allocator(); + + ~mlock_allocator(); + + std::mutex m_mutex; + size_t m_poolsize; + std::vector<std::pair<size_t, size_t>> m_freelist; + byte* m_pool; + }; + +} + +#endif diff --git a/src/alloc/mem_pool/info.txt b/src/alloc/mem_pool/info.txt deleted file mode 100644 index 5097c325f..000000000 --- a/src/alloc/mem_pool/info.txt +++ /dev/null @@ -1,12 +0,0 @@ - -<source> -mem_pool.cpp -</source> - -<header:internal> -mem_pool.h -</header:internal> - -<requires> -mutex -</requires> diff --git a/src/alloc/mem_pool/mem_pool.cpp b/src/alloc/mem_pool/mem_pool.cpp deleted file mode 100644 index f32eb9604..000000000 --- a/src/alloc/mem_pool/mem_pool.cpp +++ /dev/null @@ -1,252 +0,0 @@ -/* -* Pooling Allocator -* (C) 1999-2008 Jack Lloyd -* 2005 Matthew Gregan -* 2005-2006 Matt Johnston -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/internal/mem_pool.h> -#include <botan/internal/rounding.h> -#include <botan/mem_ops.h> -#include <algorithm> -#include <exception> - -namespace Botan { - -/* -* Memory_Block Constructor -*/ -Pooling_Allocator::Memory_Block::Memory_Block(void* buf) - { - buffer = static_cast<byte*>(buf); - bitmap = 0; - buffer_end = buffer + (BLOCK_SIZE * BITMAP_SIZE); - } - -/* -* See if ptr is contained by this block -*/ -bool Pooling_Allocator::Memory_Block::contains(void* ptr, - size_t length) const - { - return ((buffer <= ptr) && - (buffer_end >= static_cast<byte*>(ptr) + length * BLOCK_SIZE)); - } - -/* -* Allocate some memory, if possible -*/ -byte* Pooling_Allocator::Memory_Block::alloc(size_t n) - { - if(n == 0 || n > BITMAP_SIZE) - return 0; - - if(n == BITMAP_SIZE) - { - if(bitmap) - return 0; - else - { - bitmap = ~bitmap; - return buffer; - } - } - - bitmap_type mask = (static_cast<bitmap_type>(1) << n) - 1; - size_t offset = 0; - - while(bitmap & mask) - { - mask <<= 1; - ++offset; - - if((bitmap & mask) == 0) - break; - if(mask >> 63) - break; - } - - if(bitmap & mask) - return 0; - - bitmap |= mask; - return buffer + offset * BLOCK_SIZE; - } - -/* -* Mark this memory as free, if we own it -*/ -void Pooling_Allocator::Memory_Block::free(void* ptr, size_t blocks) - { - clear_mem(static_cast<byte*>(ptr), blocks * BLOCK_SIZE); - - const size_t offset = (static_cast<byte*>(ptr) - buffer) / BLOCK_SIZE; - - if(offset == 0 && blocks == BITMAP_SIZE) - bitmap = ~bitmap; - else - { - for(size_t j = 0; j != blocks; ++j) - bitmap &= ~(static_cast<bitmap_type>(1) << (j+offset)); - } - } - -/* -* Pooling_Allocator Constructor -*/ -Pooling_Allocator::Pooling_Allocator(Mutex* m) : mutex(m) - { - last_used = blocks.begin(); - } - -/* -* Pooling_Allocator Destructor -*/ -Pooling_Allocator::~Pooling_Allocator() - { - delete mutex; - if(blocks.size()) - throw Invalid_State("Pooling_Allocator: Never released memory"); - } - -/* -* Free all remaining memory -*/ -void Pooling_Allocator::destroy() - { - Mutex_Holder lock(mutex); - - blocks.clear(); - - for(size_t j = 0; j != allocated.size(); ++j) - dealloc_block(allocated[j].first, allocated[j].second); - allocated.clear(); - } - -/* -* Allocation -*/ -void* Pooling_Allocator::allocate(size_t n) - { - const size_t BITMAP_SIZE = Memory_Block::bitmap_size(); - const size_t BLOCK_SIZE = Memory_Block::block_size(); - - Mutex_Holder lock(mutex); - - if(n <= BITMAP_SIZE * BLOCK_SIZE) - { - const size_t block_no = round_up(n, BLOCK_SIZE) / BLOCK_SIZE; - - byte* mem = allocate_blocks(block_no); - if(mem) - return mem; - - get_more_core(BOTAN_MEM_POOL_CHUNK_SIZE); - - mem = allocate_blocks(block_no); - if(mem) - return mem; - - throw Memory_Exhaustion(); - } - - void* new_buf = alloc_block(n); - if(new_buf) - return new_buf; - - throw Memory_Exhaustion(); - } - -/* -* Deallocation -*/ -void Pooling_Allocator::deallocate(void* ptr, size_t n) - { - const size_t BITMAP_SIZE = Memory_Block::bitmap_size(); - const size_t BLOCK_SIZE = Memory_Block::block_size(); - - if(ptr == 0 && n == 0) - return; - - Mutex_Holder lock(mutex); - - if(n > BITMAP_SIZE * BLOCK_SIZE) - dealloc_block(ptr, n); - else - { - const size_t block_no = round_up(n, BLOCK_SIZE) / BLOCK_SIZE; - - std::vector<Memory_Block>::iterator i = - std::lower_bound(blocks.begin(), blocks.end(), Memory_Block(ptr)); - - if(i == blocks.end() || !i->contains(ptr, block_no)) - throw Invalid_State("Pointer released to the wrong allocator"); - - i->free(ptr, block_no); - } - } - -/* -* Try to get some memory from an existing block -*/ -byte* Pooling_Allocator::allocate_blocks(size_t n) - { - if(blocks.empty()) - return 0; - - std::vector<Memory_Block>::iterator i = last_used; - - do - { - byte* mem = i->alloc(n); - if(mem) - { - last_used = i; - return mem; - } - - ++i; - if(i == blocks.end()) - i = blocks.begin(); - } - while(i != last_used); - - return 0; - } - -/* -* Allocate more memory for the pool -*/ -void Pooling_Allocator::get_more_core(size_t in_bytes) - { - const size_t BITMAP_SIZE = Memory_Block::bitmap_size(); - const size_t BLOCK_SIZE = Memory_Block::block_size(); - - const size_t TOTAL_BLOCK_SIZE = BLOCK_SIZE * BITMAP_SIZE; - - // upper bound on allocation is 1 MiB - in_bytes = std::min<size_t>(in_bytes, 1024 * 1024); - - const size_t in_blocks = round_up(in_bytes, BLOCK_SIZE) / TOTAL_BLOCK_SIZE; - const size_t to_allocate = in_blocks * TOTAL_BLOCK_SIZE; - - void* ptr = alloc_block(to_allocate); - if(ptr == 0) - throw Memory_Exhaustion(); - - allocated.push_back(std::make_pair(ptr, to_allocate)); - - for(size_t j = 0; j != in_blocks; ++j) - { - byte* byte_ptr = static_cast<byte*>(ptr); - blocks.push_back(Memory_Block(byte_ptr + j * TOTAL_BLOCK_SIZE)); - } - - std::sort(blocks.begin(), blocks.end()); - last_used = std::lower_bound(blocks.begin(), blocks.end(), - Memory_Block(ptr)); - } - -} diff --git a/src/alloc/mem_pool/mem_pool.h b/src/alloc/mem_pool/mem_pool.h deleted file mode 100644 index 28d4dd903..000000000 --- a/src/alloc/mem_pool/mem_pool.h +++ /dev/null @@ -1,77 +0,0 @@ -/* -* Pooling Allocator -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_POOLING_ALLOCATOR_H__ -#define BOTAN_POOLING_ALLOCATOR_H__ - -#include <botan/allocate.h> -#include <botan/exceptn.h> -#include <botan/internal/mutex.h> -#include <utility> -#include <vector> - -namespace Botan { - -/** -* Pooling Allocator -*/ -class Pooling_Allocator : public Allocator - { - public: - void* allocate(size_t); - void deallocate(void*, size_t); - - void destroy(); - - /** - * @param mutex used for internal locking - */ - Pooling_Allocator(Mutex* mutex); - ~Pooling_Allocator(); - private: - void get_more_core(size_t); - byte* allocate_blocks(size_t); - - virtual void* alloc_block(size_t) = 0; - virtual void dealloc_block(void*, size_t) = 0; - - class Memory_Block - { - public: - Memory_Block(void*); - - static size_t bitmap_size() { return BITMAP_SIZE; } - static size_t block_size() { return BLOCK_SIZE; } - - bool contains(void*, size_t) const; - byte* alloc(size_t); - void free(void*, size_t); - - bool operator<(const Memory_Block& other) const - { - if(buffer < other.buffer && other.buffer < buffer_end) - return false; - return (buffer < other.buffer); - } - private: - typedef u64bit bitmap_type; - static const size_t BITMAP_SIZE = 8 * sizeof(bitmap_type); - static const size_t BLOCK_SIZE = 64; - - bitmap_type bitmap; - byte* buffer, *buffer_end; - }; - - std::vector<Memory_Block> blocks; - std::vector<Memory_Block>::iterator last_used; - std::vector<std::pair<void*, size_t> > allocated; - Mutex* mutex; - }; - -} - -#endif diff --git a/src/alloc/secmem.h b/src/alloc/secmem.h index 6c8a75c44..739ba63a5 100644 --- a/src/alloc/secmem.h +++ b/src/alloc/secmem.h @@ -1,6 +1,6 @@ /* * Secure Memory Buffers -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2007,2012 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -8,369 +8,121 @@ #ifndef BOTAN_SECURE_MEMORY_BUFFERS_H__ #define BOTAN_SECURE_MEMORY_BUFFERS_H__ -#include <botan/allocate.h> #include <botan/mem_ops.h> #include <algorithm> +#if defined(BOTAN_HAS_LOCKING_ALLOCATOR) + #include <botan/locking_allocator.h> +#endif + namespace Botan { -/** -* This class represents variable length memory buffers. -*/ template<typename T> -class MemoryRegion +class secure_allocator { public: - /** - * Find out the size of the buffer, i.e. how many objects of type T it - * contains. - * @return size of the buffer - */ - size_t size() const { return used; } - - /** - * Find out whether this buffer is empty. - * @return true if the buffer is empty, false otherwise - */ - bool empty() const { return (used == 0); } - - /** - * Get a pointer to the first element in the buffer. - * @return pointer to the first element in the buffer - */ - operator T* () { return buf; } - - /** - * Get a constant pointer to the first element in the buffer. - * @return constant pointer to the first element in the buffer - */ - operator const T* () const { return buf; } - - /** - * Get a pointer to the first element in the buffer. - * @return pointer to the first element in the buffer - */ - T* begin() { return buf; } - - /** - * Get a constant pointer to the first element in the buffer. - * @return constant pointer to the first element in the buffer - */ - const T* begin() const { return buf; } - - /** - * Get a pointer to the last element in the buffer. - * @return pointer to the last element in the buffer - */ - T* end() { return (buf + size()); } - - /** - * Get a constant pointer to the last element in the buffer. - * @return constant pointer to the last element in the buffer - */ - const T* end() const { return (buf + size()); } - - /** - * Check two buffers for equality. - * @return true iff the content of both buffers is byte-wise equal - */ - bool operator==(const MemoryRegion<T>& other) const - { - return (size() == other.size() && - same_mem(buf, other.buf, size())); - } + typedef T value_type; - /** - * Compare two buffers - * @return true iff this is ordered before other - */ - bool operator<(const MemoryRegion<T>& other) const; - - /** - * Check two buffers for inequality. - * @return false if the content of both buffers is byte-wise equal, true - * otherwise. - */ - bool operator!=(const MemoryRegion<T>& other) const - { return (!(*this == other)); } - - /** - * Copy the contents of another buffer into this buffer. - * The former contents of *this are discarded. - * @param other the buffer to copy the contents from. - * @return reference to *this - */ - MemoryRegion<T>& operator=(const MemoryRegion<T>& other) - { - if(this != &other) - { - this->resize(other.size()); - this->copy(&other[0], other.size()); - } - return (*this); - } + typedef T* pointer; + typedef const T* const_pointer; + + typedef T& reference; + typedef const T& const_reference; - /** - * Copy the contents of an array of objects of type T into this buffer. - * The former contents of *this are discarded. - * The length of *this must be at least n, otherwise memory errors occur. - * @param in the array to copy the contents from - * @param n the length of in - */ - void copy(const T in[], size_t n) + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + secure_allocator() noexcept {} + + ~secure_allocator() noexcept {} + + pointer address(reference x) const noexcept + { return std::addressof(x); } + + const_pointer address(const_reference x) const noexcept + { return std::addressof(x); } + + pointer allocate(size_type n, const void* = 0) { - copy_mem(buf, in, std::min(n, size())); +#if defined(BOTAN_HAS_LOCKING_ALLOCATOR) + if(pointer p = static_cast<pointer>(mlock_allocator::instance().allocate(n*sizeof(T), sizeof(T)))) + return p; +#endif + + pointer p = new T[n]; + clear_mem(p, n); + return p; } - /** - * Copy the contents of an array of objects of type T into this buffer. - * The former contents of *this are discarded. - * The length of *this must be at least n, otherwise memory errors occur. - * @param off the offset position inside this buffer to start inserting - * the copied bytes - * @param in the array to copy the contents from - * @param n the length of in - */ - void copy(size_t off, const T in[], size_t n) + void deallocate(pointer p, size_type n) { - copy_mem(buf + off, in, std::min(n, size() - off)); + clear_mem(p, n); + +#if defined(BOTAN_HAS_LOCKING_ALLOCATOR) + if(mlock_allocator::instance().deallocate(p, n*sizeof(T))) + return; +#endif + + delete [] p; } - /** - * Append a single element. - * @param x the element to append - */ - void push_back(T x) + size_type max_size() const noexcept { - resize(size() + 1); - buf[size()-1] = x; + return static_cast<size_type>(-1) / sizeof(T); } - /** - * Reset this buffer to an empty buffer with size zero. - */ - void clear() { resize(0); } - - /** - * Inserts or erases elements at the end such that the size - * becomes n, leaving elements in the range 0...n unmodified if - * set or otherwise zero-initialized - * @param n length of the new buffer - */ - void resize(size_t n); - - /** - * Swap this buffer with another object. - */ - void swap(MemoryRegion<T>& other); - - virtual ~MemoryRegion() { deallocate(buf, allocated); } - protected: - MemoryRegion() : buf(0), used(0), allocated(0), alloc(0) {} - - /** - * Copy constructor - * @param other the other region to copy - */ - MemoryRegion(const MemoryRegion<T>& other) + template<typename U, typename... Args> + void construct(U* p, Args&&... args) { - buf = 0; - used = allocated = 0; - alloc = other.alloc; - resize(other.size()); - copy(&other[0], other.size()); + ::new(static_cast<void*>(p)) U(std::forward<Args>(args)...); } - /** - * @param locking should we use a locking allocator - * @param length the initial length to use - */ - void init(bool locking, size_t length = 0) - { alloc = Allocator::get(locking); resize(length); } + template<typename U> void destroy(U* p) { p->~U(); } + }; - private: - T* allocate(size_t n) - { - return static_cast<T*>(alloc->allocate(sizeof(T)*n)); - } +template<typename T> inline bool +operator==(const secure_allocator<T>&, const secure_allocator<T>&) + { return true; } - void deallocate(T* p, size_t n) - { if(alloc && p && n) alloc->deallocate(p, sizeof(T)*n); } +template<typename T> inline bool +operator!=(const secure_allocator<T>&, const secure_allocator<T>&) + { return false; } - T* buf; - size_t used; - size_t allocated; - Allocator* alloc; - }; +template<typename T> using secure_vector = std::vector<T, secure_allocator<T>>; -/* -* Change the size of the buffer -*/ template<typename T> -void MemoryRegion<T>::resize(size_t n) +std::vector<T> unlock(const secure_vector<T>& in) { - if(n <= allocated) - { - size_t zap = std::min(used, n); - clear_mem(buf + zap, allocated - zap); - used = n; - } - else - { - T* new_buf = allocate(n); - copy_mem(new_buf, buf, used); - deallocate(buf, allocated); - buf = new_buf; - allocated = used = n; - } + std::vector<T> out(in.size()); + copy_mem(&out[0], &in[0], in.size()); + return out; } -/* -* Compare this buffer with another one -*/ -template<typename T> -bool MemoryRegion<T>::operator<(const MemoryRegion<T>& other) const +template<typename T, typename Alloc> +size_t buffer_insert(std::vector<T, Alloc>& buf, + size_t buf_offset, + const T input[], + size_t input_length) { - const size_t min_size = std::min(size(), other.size()); - - // This should probably be rewritten to run in constant time - for(size_t i = 0; i != min_size; ++i) - { - if(buf[i] < other[i]) - return true; - if(buf[i] > other[i]) - return false; - } - - // First min_size bytes are equal, shorter is first - return (size() < other.size()); + const size_t to_copy = std::min(input_length, buf.size() - buf_offset); + copy_mem(&buf[buf_offset], input, to_copy); + return to_copy; } -/* -* Swap this buffer with another one -*/ -template<typename T> -void MemoryRegion<T>::swap(MemoryRegion<T>& x) +template<typename T, typename Alloc, typename Alloc2> +size_t buffer_insert(std::vector<T, Alloc>& buf, + size_t buf_offset, + const std::vector<T, Alloc2>& input) { - std::swap(buf, x.buf); - std::swap(used, x.used); - std::swap(allocated, x.allocated); - std::swap(alloc, x.alloc); + const size_t to_copy = std::min(input.size(), buf.size() - buf_offset); + copy_mem(&buf[buf_offset], &input[0], to_copy); + return to_copy; } -/** -* This class represents variable length buffers that do not -* make use of memory locking. -*/ -template<typename T> -class MemoryVector : public MemoryRegion<T> - { - public: - /** - * Copy the contents of another buffer into this buffer. - * @param in the buffer to copy the contents from - * @return reference to *this - */ - MemoryVector<T>& operator=(const MemoryRegion<T>& in) - { - if(this != &in) - { - this->resize(in.size()); - this->copy(&in[0], in.size()); - } - return (*this); - } - - /** - * Create a buffer of the specified length. - * @param n the length of the buffer to create. - */ - MemoryVector(size_t n = 0) { this->init(false, n); } - - /** - * Create a buffer with the specified contents. - * @param in the array containing the data to be initially copied - * into the newly created buffer - * @param n the size of the arry in - */ - MemoryVector(const T in[], size_t n) - { - this->init(false); - this->resize(n); - this->copy(in, n); - } - - /** - * Copy constructor. - */ - MemoryVector(const MemoryRegion<T>& in) - { - this->init(false); - this->resize(in.size()); - this->copy(&in[0], in.size()); - } - }; - -/** -* This class represents variable length buffers using the operating -* systems capability to lock memory, i.e. keeping it from being -* swapped out to disk. In this way, a security hole allowing attackers -* to find swapped out secret keys is closed. -*/ -template<typename T> -class SecureVector : public MemoryRegion<T> - { - public: - /** - * Copy the contents of another buffer into this buffer. - * @param other the buffer to copy the contents from - * @return reference to *this - */ - SecureVector<T>& operator=(const MemoryRegion<T>& other) - { - if(this != &other) - { - this->resize(other.size()); - this->copy(&other[0], other.size()); - } - return (*this); - } - - /** - * Create a buffer of the specified length. - * @param n the length of the buffer to create. - */ - SecureVector(size_t n = 0) { this->init(true, n); } - - /** - * Create a buffer with the specified contents. - * @param in the array containing the data to be initially copied - * into the newly created buffer - * @param n the size of the array in - */ - SecureVector(const T in[], size_t n) - { - this->init(true); - this->resize(n); - this->copy(&in[0], n); - } - - /** - * Create a buffer with contents specified contents. - * @param in the buffer holding the contents that will be - * copied into the newly created buffer. - */ - SecureVector(const MemoryRegion<T>& in) - { - this->init(true); - this->resize(in.size()); - this->copy(&in[0], in.size()); - } - }; - -template<typename T> -MemoryRegion<T>& operator+=(MemoryRegion<T>& out, - const MemoryRegion<T>& in) +template<typename T, typename Alloc, typename Alloc2> +std::vector<T, Alloc>& +operator+=(std::vector<T, Alloc>& out, + const std::vector<T, Alloc2>& in) { const size_t copy_offset = out.size(); out.resize(out.size() + in.size()); @@ -378,17 +130,16 @@ MemoryRegion<T>& operator+=(MemoryRegion<T>& out, return out; } -template<typename T> -MemoryRegion<T>& operator+=(MemoryRegion<T>& out, - T in) +template<typename T, typename Alloc> +std::vector<T, Alloc>& operator+=(std::vector<T, Alloc>& out, T in) { out.push_back(in); return out; } -template<typename T, typename L> -MemoryRegion<T>& operator+=(MemoryRegion<T>& out, - const std::pair<const T*, L>& in) +template<typename T, typename Alloc, typename L> +std::vector<T, Alloc>& operator+=(std::vector<T, Alloc>& out, + const std::pair<const T*, L>& in) { const size_t copy_offset = out.size(); out.resize(out.size() + in.second); @@ -396,9 +147,9 @@ MemoryRegion<T>& operator+=(MemoryRegion<T>& out, return out; } -template<typename T, typename L> -MemoryRegion<T>& operator+=(MemoryRegion<T>& out, - const std::pair<T*, L>& in) +template<typename T, typename Alloc, typename L> +std::vector<T, Alloc>& operator+=(std::vector<T, Alloc>& out, + const std::pair<T*, L>& in) { const size_t copy_offset = out.size(); out.resize(out.size() + in.second); @@ -410,22 +161,12 @@ MemoryRegion<T>& operator+=(MemoryRegion<T>& out, * Zeroise the values; length remains unchanged * @param vec the vector to zeroise */ -template<typename T> -void zeroise(MemoryRegion<T>& vec) +template<typename T, typename Alloc> +void zeroise(std::vector<T, Alloc>& vec) { clear_mem(&vec[0], vec.size()); } } -namespace std { - -template<typename T> -inline void swap(Botan::MemoryRegion<T>& x, Botan::MemoryRegion<T>& y) - { - x.swap(y); - } - -} - #endif diff --git a/src/alloc/system_alloc/defalloc.cpp b/src/alloc/system_alloc/defalloc.cpp deleted file mode 100644 index 8e178bb14..000000000 --- a/src/alloc/system_alloc/defalloc.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/* -* Basic Allocators -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/internal/defalloc.h> -#include <botan/internal/mlock.h> -#include <botan/libstate.h> -#include <cstdlib> -#include <cstring> - -namespace Botan { - -namespace { - -/* -* Perform Memory Allocation -*/ -void* do_malloc(size_t n, bool do_lock) - { - void* ptr = std::malloc(n); - - if(!ptr) - return 0; - - if(do_lock) - lock_mem(ptr, n); - - std::memset(ptr, 0, n); - return ptr; - } - -/* -* Perform Memory Deallocation -*/ -void do_free(void* ptr, size_t n, bool do_lock) - { - if(!ptr) - return; - - std::memset(ptr, 0, n); - if(do_lock) - unlock_mem(ptr, n); - - std::free(ptr); - } - -} - -/* -* Malloc_Allocator's Allocation -*/ -void* Malloc_Allocator::allocate(size_t n) - { - void* ptr = do_malloc(n, false); - if(!ptr) - throw Memory_Exhaustion(); - return ptr; - } - -/* -* Malloc_Allocator's Deallocation -*/ -void Malloc_Allocator::deallocate(void* ptr, size_t n) - { - do_free(ptr, n, false); - } - -/* -* Locking_Allocator's Allocation -*/ -void* Locking_Allocator::alloc_block(size_t n) - { - return do_malloc(n, true); - } - -/* -* Locking_Allocator's Deallocation -*/ -void Locking_Allocator::dealloc_block(void* ptr, size_t n) - { - do_free(ptr, n, true); - } - -/* -* Get an allocator -*/ -Allocator* Allocator::get(bool locking) - { - std::string type = ""; - if(!locking) - type = "malloc"; - - Allocator* alloc = global_state().get_allocator(type); - if(alloc) - return alloc; - - throw Internal_Error("Couldn't find an allocator to use in get_allocator"); - } - -} diff --git a/src/alloc/system_alloc/defalloc.h b/src/alloc/system_alloc/defalloc.h deleted file mode 100644 index 6fba0e511..000000000 --- a/src/alloc/system_alloc/defalloc.h +++ /dev/null @@ -1,46 +0,0 @@ -/* -* Basic Allocators -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_BASIC_ALLOC_H__ -#define BOTAN_BASIC_ALLOC_H__ - -#include <botan/internal/mem_pool.h> - -namespace Botan { - -/** -* Allocator using malloc -*/ -class Malloc_Allocator : public Allocator - { - public: - void* allocate(size_t); - void deallocate(void*, size_t); - - std::string type() const { return "malloc"; } - }; - -/** -* Allocator using malloc plus locking -*/ -class Locking_Allocator : public Pooling_Allocator - { - public: - /** - * @param mutex used for internal locking - */ - Locking_Allocator(Mutex* mutex) : Pooling_Allocator(mutex) {} - - std::string type() const { return "locking"; } - private: - void* alloc_block(size_t); - void dealloc_block(void*, size_t); - }; - -} - -#endif diff --git a/src/alloc/system_alloc/info.txt b/src/alloc/system_alloc/info.txt deleted file mode 100644 index 87de0cb67..000000000 --- a/src/alloc/system_alloc/info.txt +++ /dev/null @@ -1,13 +0,0 @@ - -<source> -defalloc.cpp -</source> - -<header:internal> -defalloc.h -</header:internal> - -<requires> -libstate -mem_pool -</requires> diff --git a/src/asn1/alg_id.cpp b/src/asn1/alg_id.cpp index 665e42fb3..c4c6b6e24 100644 --- a/src/asn1/alg_id.cpp +++ b/src/asn1/alg_id.cpp @@ -16,7 +16,7 @@ namespace Botan { * Create an AlgorithmIdentifier */ AlgorithmIdentifier::AlgorithmIdentifier(const OID& alg_id, - const MemoryRegion<byte>& param) + const std::vector<byte>& param) { oid = alg_id; parameters = param; @@ -26,7 +26,7 @@ AlgorithmIdentifier::AlgorithmIdentifier(const OID& alg_id, * Create an AlgorithmIdentifier */ AlgorithmIdentifier::AlgorithmIdentifier(const std::string& alg_id, - const MemoryRegion<byte>& param) + const std::vector<byte>& param) { oid = OIDS::lookup(alg_id); parameters = param; diff --git a/src/asn1/alg_id.h b/src/asn1/alg_id.h index 417a71b30..1ec6b62d3 100644 --- a/src/asn1/alg_id.h +++ b/src/asn1/alg_id.h @@ -29,11 +29,11 @@ class BOTAN_DLL AlgorithmIdentifier : public ASN1_Object AlgorithmIdentifier(const OID&, Encoding_Option); AlgorithmIdentifier(const std::string&, Encoding_Option); - AlgorithmIdentifier(const OID&, const MemoryRegion<byte>&); - AlgorithmIdentifier(const std::string&, const MemoryRegion<byte>&); + AlgorithmIdentifier(const OID&, const std::vector<byte>&); + AlgorithmIdentifier(const std::string&, const std::vector<byte>&); OID oid; - SecureVector<byte> parameters; + std::vector<byte> parameters; }; /* diff --git a/src/asn1/asn1_alt.cpp b/src/asn1/asn1_alt.cpp index 2d8e3a1d2..1a5c699cd 100644 --- a/src/asn1/asn1_alt.cpp +++ b/src/asn1/asn1_alt.cpp @@ -58,9 +58,8 @@ void AlternativeName::add_attribute(const std::string& type, if(type == "" || str == "") return; - typedef std::multimap<std::string, std::string>::iterator iter; - std::pair<iter, iter> range = alt_info.equal_range(type); - for(iter j = range.first; j != range.second; ++j) + auto range = alt_info.equal_range(type); + for(auto j = range.first; j != range.second; ++j) if(j->second == str) return; @@ -101,13 +100,11 @@ std::multimap<std::string, std::string> AlternativeName::contents() const { std::multimap<std::string, std::string> names; - typedef std::multimap<std::string, std::string>::const_iterator rdn_iter; - for(rdn_iter j = alt_info.begin(); j != alt_info.end(); ++j) - multimap_insert(names, j->first, j->second); + for(auto i = alt_info.begin(); i != alt_info.end(); ++i) + multimap_insert(names, i->first, i->second); - typedef std::multimap<OID, ASN1_String>::const_iterator on_iter; - for(on_iter j = othernames.begin(); j != othernames.end(); ++j) - multimap_insert(names, OIDS::lookup(j->first), j->second.value()); + for(auto i = othernames.begin(); i != othernames.end(); ++i) + multimap_insert(names, OIDS::lookup(i->first), i->second.value()); return names; } @@ -129,19 +126,18 @@ void encode_entries(DER_Encoder& encoder, const std::multimap<std::string, std::string>& attr, const std::string& type, ASN1_Tag tagging) { - typedef std::multimap<std::string, std::string>::const_iterator iter; + auto range = attr.equal_range(type); - std::pair<iter, iter> range = attr.equal_range(type); - for(iter j = range.first; j != range.second; ++j) + for(auto i = range.first; i != range.second; ++i) { if(type == "RFC822" || type == "DNS" || type == "URI") { - ASN1_String asn1_string(j->second, IA5_STRING); + ASN1_String asn1_string(i->second, IA5_STRING); encoder.add_object(tagging, CONTEXT_SPECIFIC, asn1_string.iso_8859()); } else if(type == "IP") { - const u32bit ip = string_to_ipv4(j->second); + const u32bit ip = string_to_ipv4(i->second); byte ip_buf[4] = { 0 }; store_be(ip, ip_buf); encoder.add_object(tagging, CONTEXT_SPECIFIC, ip_buf, 4); @@ -163,8 +159,7 @@ void AlternativeName::encode_into(DER_Encoder& der) const encode_entries(der, alt_info, "URI", ASN1_Tag(6)); encode_entries(der, alt_info, "IP", ASN1_Tag(7)); - std::multimap<OID, ASN1_String>::const_iterator i; - for(i = othernames.begin(); i != othernames.end(); ++i) + for(auto i = othernames.begin(); i != othernames.end(); ++i) { der.start_explicit(0) .encode(i->first) diff --git a/src/asn1/asn1_att.cpp b/src/asn1/asn1_att.cpp index c8d771e25..c0adae643 100644 --- a/src/asn1/asn1_att.cpp +++ b/src/asn1/asn1_att.cpp @@ -15,7 +15,7 @@ namespace Botan { /* * Create an Attribute */ -Attribute::Attribute(const OID& attr_oid, const MemoryRegion<byte>& attr_value) +Attribute::Attribute(const OID& attr_oid, const std::vector<byte>& attr_value) { oid = attr_oid; parameters = attr_value; @@ -25,7 +25,7 @@ Attribute::Attribute(const OID& attr_oid, const MemoryRegion<byte>& attr_value) * Create an Attribute */ Attribute::Attribute(const std::string& attr_oid, - const MemoryRegion<byte>& attr_value) + const std::vector<byte>& attr_value) { oid = OIDS::lookup(attr_oid); parameters = attr_value; diff --git a/src/asn1/asn1_int.cpp b/src/asn1/asn1_int.cpp index 75cb1f90c..ff8eba54e 100644 --- a/src/asn1/asn1_int.cpp +++ b/src/asn1/asn1_int.cpp @@ -20,24 +20,24 @@ BER_Decoding_Error::BER_Decoding_Error(const std::string& str) : Decoding_Error("BER: " + str) {} BER_Bad_Tag::BER_Bad_Tag(const std::string& str, ASN1_Tag tag) : - BER_Decoding_Error(str + ": " + to_string(tag)) {} + BER_Decoding_Error(str + ": " + std::to_string(tag)) {} BER_Bad_Tag::BER_Bad_Tag(const std::string& str, ASN1_Tag tag1, ASN1_Tag tag2) : - BER_Decoding_Error(str + ": " + to_string(tag1) + "/" + to_string(tag2)) {} + BER_Decoding_Error(str + ": " + std::to_string(tag1) + "/" + std::to_string(tag2)) {} namespace ASN1 { /* * Put some arbitrary bytes into a SEQUENCE */ -SecureVector<byte> put_in_sequence(const MemoryRegion<byte>& contents) +std::vector<byte> put_in_sequence(const std::vector<byte>& contents) { return DER_Encoder() .start_cons(SEQUENCE) .raw_bytes(contents) .end_cons() - .get_contents(); + .get_contents_unlocked(); } /* diff --git a/src/asn1/asn1_int.h b/src/asn1/asn1_int.h index 25b3cf100..37edc4e3c 100644 --- a/src/asn1/asn1_int.h +++ b/src/asn1/asn1_int.h @@ -80,7 +80,7 @@ class BOTAN_DLL BER_Object void assert_is_a(ASN1_Tag, ASN1_Tag); ASN1_Tag type_tag, class_tag; - SecureVector<byte> value; + secure_vector<byte> value; }; /* @@ -90,7 +90,7 @@ class DataSource; namespace ASN1 { -SecureVector<byte> put_in_sequence(const MemoryRegion<byte>& val); +std::vector<byte> put_in_sequence(const std::vector<byte>& val); std::string to_string(const BER_Object& obj); /** diff --git a/src/asn1/asn1_obj.h b/src/asn1/asn1_obj.h index 692a6fde6..cee5a18ed 100644 --- a/src/asn1/asn1_obj.h +++ b/src/asn1/asn1_obj.h @@ -15,6 +15,7 @@ #include <botan/alg_id.h> #include <vector> #include <map> +#include <chrono> namespace Botan { @@ -28,11 +29,11 @@ class BOTAN_DLL Attribute : public ASN1_Object void decode_from(class BER_Decoder& from); OID oid; - MemoryVector<byte> parameters; + std::vector<byte> parameters; Attribute() {} - Attribute(const OID&, const MemoryRegion<byte>&); - Attribute(const std::string&, const MemoryRegion<byte>&); + Attribute(const OID&, const std::vector<byte>&); + Attribute(const std::string&, const std::vector<byte>&); }; /** @@ -53,7 +54,7 @@ class BOTAN_DLL X509_Time : public ASN1_Object void set_to(const std::string&); void set_to(const std::string&, ASN1_Tag); - X509_Time(u64bit); + X509_Time(const std::chrono::system_clock::time_point& time); X509_Time(const std::string& = ""); X509_Time(const std::string&, ASN1_Tag); private: diff --git a/src/asn1/asn1_oid.cpp b/src/asn1/asn1_oid.cpp index ae3d48ce2..009b1c2fc 100644 --- a/src/asn1/asn1_oid.cpp +++ b/src/asn1/asn1_oid.cpp @@ -52,7 +52,7 @@ std::string OID::as_string() const std::string oid_str; for(size_t i = 0; i != id.size(); ++i) { - oid_str += to_string(id[i]); + oid_str += std::to_string(id[i]); if(i != id.size() - 1) oid_str += '.'; } @@ -129,7 +129,7 @@ void OID::encode_into(DER_Encoder& der) const if(id.size() < 2) throw Invalid_Argument("OID::encode_into: OID is invalid"); - MemoryVector<byte> encoding; + std::vector<byte> encoding; encoding.push_back(40 * id[0] + id[1]); for(size_t i = 2; i != id.size(); ++i) diff --git a/src/asn1/asn1_str.cpp b/src/asn1/asn1_str.cpp index b28f36d90..44db189f9 100644 --- a/src/asn1/asn1_str.cpp +++ b/src/asn1/asn1_str.cpp @@ -77,7 +77,7 @@ ASN1_String::ASN1_String(const std::string& str, ASN1_Tag t) : tag(t) tag != UTF8_STRING && tag != BMP_STRING) throw Invalid_Argument("ASN1_String: Unknown string type " + - to_string(tag)); + std::to_string(tag)); } /* diff --git a/src/asn1/asn1_tm.cpp b/src/asn1/asn1_tm.cpp index a059e0528..b8095a41c 100644 --- a/src/asn1/asn1_tm.cpp +++ b/src/asn1/asn1_tm.cpp @@ -10,7 +10,7 @@ #include <botan/ber_dec.h> #include <botan/charset.h> #include <botan/parsing.h> -#include <botan/time.h> +#include <botan/calendar.h> namespace Botan { @@ -23,11 +23,11 @@ X509_Time::X509_Time(const std::string& time_str) } /* -* Create an X509_Time +* Create a X509_Time from a time point */ -X509_Time::X509_Time(u64bit timer) +X509_Time::X509_Time(const std::chrono::system_clock::time_point& time) { - calendar_point cal = calendar_value(timer); + calendar_point cal = calendar_value(time); year = cal.year; month = cal.month; @@ -98,7 +98,7 @@ void X509_Time::set_to(const std::string& time_str) void X509_Time::set_to(const std::string& t_spec, ASN1_Tag spec_tag) { if(spec_tag != GENERALIZED_TIME && spec_tag != UTC_TIME) - throw Invalid_Argument("X509_Time: Invalid tag " + to_string(spec_tag)); + throw Invalid_Argument("X509_Time: Invalid tag " + std::to_string(spec_tag)); if(spec_tag == GENERALIZED_TIME && t_spec.size() != 13 && t_spec.size() != 15) throw Invalid_Argument("Invalid GeneralizedTime: " + t_spec); @@ -182,24 +182,30 @@ std::string X509_Time::as_string() const if(time_is_set() == false) throw Invalid_State("X509_Time::as_string: No time set"); - std::string asn1rep; - if(tag == GENERALIZED_TIME) - asn1rep = to_string(year, 4); - else if(tag == UTC_TIME) + u32bit full_year = year; + + if(tag == UTC_TIME) { if(year < 1950 || year >= 2050) throw Encoding_Error("X509_Time: The time " + readable_string() + " cannot be encoded as a UTCTime"); - u32bit asn1year = (year >= 2000) ? (year - 2000) : (year - 1900); - asn1rep = to_string(asn1year, 2); + + full_year = (year >= 2000) ? (year - 2000) : (year - 1900); } - else - throw Invalid_Argument("X509_Time: Invalid tag " + to_string(tag)); - asn1rep += to_string(month, 2) + to_string(day, 2); - asn1rep += to_string(hour, 2) + to_string(minute, 2) + to_string(second, 2); - asn1rep += "Z"; - return asn1rep; + std::string repr = std::to_string(full_year*10000000000 + + month*100000000 + + day*1000000 + + hour*10000 + + minute*100 + + second) + "Z"; + + u32bit desired_size = (tag == UTC_TIME) ? 13 : 15; + + while(repr.size() < desired_size) + repr = "0" + repr; + + return repr; } /* @@ -218,14 +224,12 @@ std::string X509_Time::readable_string() const if(time_is_set() == false) throw Invalid_State("X509_Time::readable_string: No time set"); - std::string readable; - readable += to_string(year, 4) + "/"; - readable += to_string(month ) + "/"; - readable += to_string(day ) + " "; - readable += to_string(hour ) + ":"; - readable += to_string(minute, 2) + ":"; - readable += to_string(second, 2) + " UTC"; - return readable; + std::string output(24, 0); + + std::sprintf(&output[0], "%04d/%02d/%02d %02d:%02d:%02d UTC", + year, month, day, hour, minute, second); + + return output; } /* diff --git a/src/asn1/ber_dec.cpp b/src/asn1/ber_dec.cpp index b31c7b903..dbd59988b 100644 --- a/src/asn1/ber_dec.cpp +++ b/src/asn1/ber_dec.cpp @@ -99,7 +99,7 @@ size_t decode_length(DataSource* ber) */ size_t find_eoc(DataSource* ber) { - SecureVector<byte> buffer(DEFAULT_BUFFERSIZE), data; + secure_vector<byte> buffer(DEFAULT_BUFFERSIZE), data; while(true) { @@ -141,7 +141,11 @@ size_t find_eoc(DataSource* ber) void BER_Object::assert_is_a(ASN1_Tag type_tag, ASN1_Tag class_tag) { if(this->type_tag != type_tag || this->class_tag != class_tag) - throw BER_Decoding_Error("Tag mismatch when decoding"); + throw BER_Decoding_Error("Tag mismatch when decoding got " + + std::to_string(this->type_tag) + "/" + + std::to_string(this->class_tag) + " expected " + + std::to_string(type_tag) + "/" + + std::to_string(class_tag)); } /* @@ -167,7 +171,16 @@ BER_Decoder& BER_Decoder::verify_end() /* * Save all the bytes remaining in the source */ -BER_Decoder& BER_Decoder::raw_bytes(MemoryRegion<byte>& out) +BER_Decoder& BER_Decoder::raw_bytes(secure_vector<byte>& out) + { + out.clear(); + byte buf; + while(source->read_byte(buf)) + out.push_back(buf); + return (*this); + } + +BER_Decoder& BER_Decoder::raw_bytes(std::vector<byte>& out) { out.clear(); byte buf; @@ -208,7 +221,10 @@ BER_Object BER_Decoder::get_next_object() size_t length = decode_length(source); next.value.resize(length); if(source->read(&next.value[0], length) != length) + { + abort(); throw BER_Decoding_Error("Value truncated"); + } if(next.type_tag == EOC && next.class_tag == UNIVERSAL) return get_next_object(); @@ -260,7 +276,7 @@ BER_Decoder::BER_Decoder(DataSource& src) source = &src; owns = false; pushed.type_tag = pushed.class_tag = NO_OBJECT; - parent = 0; + parent = nullptr; } /* @@ -271,18 +287,29 @@ BER_Decoder::BER_Decoder(const byte data[], size_t length) source = new DataSource_Memory(data, length); owns = true; pushed.type_tag = pushed.class_tag = NO_OBJECT; - parent = 0; + parent = nullptr; } /* * BER_Decoder Constructor */ -BER_Decoder::BER_Decoder(const MemoryRegion<byte>& data) +BER_Decoder::BER_Decoder(const secure_vector<byte>& data) { source = new DataSource_Memory(data); owns = true; pushed.type_tag = pushed.class_tag = NO_OBJECT; - parent = 0; + parent = nullptr; + } + +/* +* BER_Decoder Constructor +*/ +BER_Decoder::BER_Decoder(const std::vector<byte>& data) + { + source = new DataSource_Memory(&data[0], data.size()); + owns = true; + pushed.type_tag = pushed.class_tag = NO_OBJECT; + parent = nullptr; } /* @@ -308,7 +335,7 @@ BER_Decoder::~BER_Decoder() { if(owns) delete source; - source = 0; + source = nullptr; } /* @@ -358,7 +385,7 @@ BER_Decoder& BER_Decoder::decode(BigInt& out) BER_Decoder& BER_Decoder::decode_octet_string_bigint(BigInt& out) { - SecureVector<byte> out_vec; + secure_vector<byte> out_vec; decode(out_vec, OCTET_STRING); out = BigInt::decode(&out_vec[0], out_vec.size()); return (*this); @@ -400,6 +427,29 @@ BER_Decoder& BER_Decoder::decode(size_t& out, } /* +* Decode a small BER encoded INTEGER +*/ +u64bit BER_Decoder::decode_constrained_integer(ASN1_Tag type_tag, + ASN1_Tag class_tag, + size_t T_bytes) + { + if(T_bytes > 8) + throw BER_Decoding_Error("Can't decode small integer over 8 bytes"); + + BigInt integer; + decode(integer, type_tag, class_tag); + + if(integer.bits() > 8*T_bytes) + throw BER_Decoding_Error("Decoded integer value larger than expected"); + + u64bit out = 0; + for(size_t i = 0; i != 8; ++i) + out = (out << 8) | integer.byte_at(7-i); + + return out; + } + +/* * Decode a BER encoded INTEGER */ BER_Decoder& BER_Decoder::decode(BigInt& out, @@ -435,7 +485,15 @@ BER_Decoder& BER_Decoder::decode(BigInt& out, /* * BER decode a BIT STRING or OCTET STRING */ -BER_Decoder& BER_Decoder::decode(MemoryRegion<byte>& out, ASN1_Tag real_type) +BER_Decoder& BER_Decoder::decode(secure_vector<byte>& out, ASN1_Tag real_type) + { + return decode(out, real_type, real_type, UNIVERSAL); + } + +/* +* BER decode a BIT STRING or OCTET STRING +*/ +BER_Decoder& BER_Decoder::decode(std::vector<byte>& out, ASN1_Tag real_type) { return decode(out, real_type, real_type, UNIVERSAL); } @@ -443,7 +501,7 @@ BER_Decoder& BER_Decoder::decode(MemoryRegion<byte>& out, ASN1_Tag real_type) /* * BER decode a BIT STRING or OCTET STRING */ -BER_Decoder& BER_Decoder::decode(MemoryRegion<byte>& buffer, +BER_Decoder& BER_Decoder::decode(secure_vector<byte>& buffer, ASN1_Tag real_type, ASN1_Tag type_tag, ASN1_Tag class_tag) { @@ -466,10 +524,50 @@ BER_Decoder& BER_Decoder::decode(MemoryRegion<byte>& buffer, return (*this); } +BER_Decoder& BER_Decoder::decode(std::vector<byte>& buffer, + ASN1_Tag real_type, + ASN1_Tag type_tag, ASN1_Tag class_tag) + { + if(real_type != OCTET_STRING && real_type != BIT_STRING) + throw BER_Bad_Tag("Bad tag for {BIT,OCTET} STRING", real_type); + + BER_Object obj = get_next_object(); + obj.assert_is_a(type_tag, class_tag); + + if(real_type == OCTET_STRING) + buffer = unlock(obj.value); + else + { + if(obj.value[0] >= 8) + throw BER_Decoding_Error("Bad number of unused bits in BIT STRING"); + + buffer.resize(obj.value.size() - 1); + copy_mem(&buffer[0], &obj.value[1], obj.value.size() - 1); + } + return (*this); + } + /* * Decode an OPTIONAL string type */ -BER_Decoder& BER_Decoder::decode_optional_string(MemoryRegion<byte>& out, +BER_Decoder& BER_Decoder::decode_optional_string(secure_vector<byte>& out, + ASN1_Tag real_type, + u16bit type_no) + { + BER_Object obj = get_next_object(); + + ASN1_Tag type_tag = static_cast<ASN1_Tag>(type_no); + + out.clear(); + push_back(obj); + + if(obj.type_tag == type_tag && obj.class_tag == CONTEXT_SPECIFIC) + decode(out, real_type, type_tag, CONTEXT_SPECIFIC); + + return (*this); + } + +BER_Decoder& BER_Decoder::decode_optional_string(std::vector<byte>& out, ASN1_Tag real_type, u16bit type_no) { diff --git a/src/asn1/ber_dec.h b/src/asn1/ber_dec.h index 5f79d3fc1..6b010fcc4 100644 --- a/src/asn1/ber_dec.h +++ b/src/asn1/ber_dec.h @@ -20,33 +20,68 @@ class BOTAN_DLL BER_Decoder { public: BER_Object get_next_object(); - void push_back(const BER_Object&); + void push_back(const BER_Object& obj); bool more_items() const; BER_Decoder& verify_end(); BER_Decoder& discard_remaining(); - BER_Decoder start_cons(ASN1_Tag, ASN1_Tag = UNIVERSAL); + BER_Decoder start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag = UNIVERSAL); BER_Decoder& end_cons(); - BER_Decoder& raw_bytes(MemoryRegion<byte>&); + BER_Decoder& raw_bytes(secure_vector<byte>& v); + BER_Decoder& raw_bytes(std::vector<byte>& v); BER_Decoder& decode_null(); - BER_Decoder& decode(bool&); - BER_Decoder& decode(size_t&); - BER_Decoder& decode(class BigInt&); - BER_Decoder& decode(MemoryRegion<byte>&, ASN1_Tag); + BER_Decoder& decode(bool& v); + BER_Decoder& decode(size_t& v); + BER_Decoder& decode(class BigInt& v); + BER_Decoder& decode(std::vector<byte>& v, ASN1_Tag type_tag); + BER_Decoder& decode(secure_vector<byte>& v, ASN1_Tag type_tag); - BER_Decoder& decode(bool&, ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC); - BER_Decoder& decode(size_t&, ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC); - BER_Decoder& decode(class BigInt&, - ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC); - BER_Decoder& decode(MemoryRegion<byte>&, ASN1_Tag, - ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC); + BER_Decoder& decode(bool& v, + ASN1_Tag type_tag, + ASN1_Tag class_tag = CONTEXT_SPECIFIC); - BER_Decoder& decode(class ASN1_Object&); + BER_Decoder& decode(size_t& v, + ASN1_Tag type_tag, + ASN1_Tag class_tag = CONTEXT_SPECIFIC); - BER_Decoder& decode_octet_string_bigint(class BigInt&); + BER_Decoder& decode(class BigInt& v, + ASN1_Tag type_tag, + ASN1_Tag class_tag = CONTEXT_SPECIFIC); + + BER_Decoder& decode(std::vector<byte>& v, + ASN1_Tag real_type, + ASN1_Tag type_tag, + ASN1_Tag class_tag = CONTEXT_SPECIFIC); + + BER_Decoder& decode(secure_vector<byte>& v, + ASN1_Tag real_type, + ASN1_Tag type_tag, + ASN1_Tag class_tag = CONTEXT_SPECIFIC); + + BER_Decoder& decode(class ASN1_Object& obj); + + BER_Decoder& decode_octet_string_bigint(class BigInt& b); + + u64bit decode_constrained_integer(ASN1_Tag type_tag, + ASN1_Tag class_tag, + size_t T_bytes); + + template<typename T> BER_Decoder& decode_integer_type(T& out) + { + return decode_integer_type<T>(out, INTEGER, UNIVERSAL); + } + + template<typename T> + BER_Decoder& decode_integer_type(T& out, + ASN1_Tag type_tag, + ASN1_Tag class_tag = CONTEXT_SPECIFIC) + { + out = decode_constrained_integer(type_tag, class_tag, sizeof(out)); + return (*this); + } template<typename T> BER_Decoder& decode_optional(T& out, @@ -71,17 +106,27 @@ class BOTAN_DLL BER_Decoder return (*this); } - BER_Decoder& decode_optional_string(MemoryRegion<byte>&, - ASN1_Tag, u16bit); + BER_Decoder& decode_optional_string(std::vector<byte>& out, + ASN1_Tag real_type, + u16bit type_no); + + BER_Decoder& decode_optional_string(secure_vector<byte>& out, + ASN1_Tag real_type, + u16bit type_no); + + BER_Decoder& operator=(const BER_Decoder&) = delete; BER_Decoder(DataSource&); + BER_Decoder(const byte[], size_t); - BER_Decoder(const MemoryRegion<byte>&); + + BER_Decoder(const secure_vector<byte>&); + + BER_Decoder(const std::vector<byte>& vec); + BER_Decoder(const BER_Decoder&); ~BER_Decoder(); private: - BER_Decoder& operator=(const BER_Decoder&) { return (*this); } - BER_Decoder* parent; DataSource* source; BER_Object pushed; diff --git a/src/asn1/der_enc.cpp b/src/asn1/der_enc.cpp index a14b3c5e2..594c32539 100644 --- a/src/asn1/der_enc.cpp +++ b/src/asn1/der_enc.cpp @@ -20,13 +20,13 @@ namespace { /* * DER encode an ASN.1 type tag */ -SecureVector<byte> encode_tag(ASN1_Tag type_tag, ASN1_Tag class_tag) +secure_vector<byte> encode_tag(ASN1_Tag type_tag, ASN1_Tag class_tag) { if((class_tag | 0xE0) != 0xE0) throw Encoding_Error("DER_Encoder: Invalid class tag " + - to_string(class_tag)); + std::to_string(class_tag)); - SecureVector<byte> encoded_tag; + secure_vector<byte> encoded_tag; if(type_tag <= 30) encoded_tag.push_back(static_cast<byte>(type_tag | class_tag)); else @@ -46,9 +46,9 @@ SecureVector<byte> encode_tag(ASN1_Tag type_tag, ASN1_Tag class_tag) /* * DER encode an ASN.1 length field */ -SecureVector<byte> encode_length(size_t length) +secure_vector<byte> encode_length(size_t length) { - SecureVector<byte> encoded_length; + secure_vector<byte> encoded_length; if(length <= 127) encoded_length.push_back(static_cast<byte>(length)); else @@ -68,7 +68,7 @@ SecureVector<byte> encode_length(size_t length) /* * Return the encoded SEQUENCE/SET */ -SecureVector<byte> DER_Encoder::DER_Sequence::get_contents() +secure_vector<byte> DER_Encoder::DER_Sequence::get_contents() { const ASN1_Tag real_class_tag = ASN1_Tag(class_tag | CONSTRUCTED); @@ -80,7 +80,7 @@ SecureVector<byte> DER_Encoder::DER_Sequence::get_contents() set_contents.clear(); } - SecureVector<byte> result; + secure_vector<byte> result; result += encode_tag(type_tag, real_class_tag); result += encode_length(contents.size()); result += contents; @@ -95,7 +95,7 @@ SecureVector<byte> DER_Encoder::DER_Sequence::get_contents() void DER_Encoder::DER_Sequence::add_bytes(const byte data[], size_t length) { if(type_tag == SET) - set_contents.push_back(SecureVector<byte>(data, length)); + set_contents.push_back(secure_vector<byte>(data, data + length)); else contents += std::make_pair(data, length); } @@ -119,12 +119,12 @@ DER_Encoder::DER_Sequence::DER_Sequence(ASN1_Tag t1, ASN1_Tag t2) : /* * Return the encoded contents */ -SecureVector<byte> DER_Encoder::get_contents() +secure_vector<byte> DER_Encoder::get_contents() { if(subsequences.size() != 0) throw Invalid_State("DER_Encoder: Sequence hasn't been marked done"); - SecureVector<byte> output; + secure_vector<byte> output; std::swap(output, contents); return output; } @@ -147,7 +147,7 @@ DER_Encoder& DER_Encoder::end_cons() if(subsequences.empty()) throw Invalid_State("DER_Encoder::end_cons: No such sequence"); - SecureVector<byte> seq = subsequences[subsequences.size()-1].get_contents(); + secure_vector<byte> seq = subsequences[subsequences.size()-1].get_contents(); subsequences.pop_back(); raw_bytes(seq); return (*this); @@ -177,7 +177,12 @@ DER_Encoder& DER_Encoder::end_explicit() /* * Write raw bytes into the stream */ -DER_Encoder& DER_Encoder::raw_bytes(const MemoryRegion<byte>& val) +DER_Encoder& DER_Encoder::raw_bytes(const secure_vector<byte>& val) + { + return raw_bytes(&val[0], val.size()); + } + +DER_Encoder& DER_Encoder::raw_bytes(const std::vector<byte>& val) { return raw_bytes(&val[0], val.size()); } @@ -200,7 +205,7 @@ DER_Encoder& DER_Encoder::raw_bytes(const byte bytes[], size_t length) */ DER_Encoder& DER_Encoder::encode_null() { - return add_object(NULL_TAG, UNIVERSAL, 0, 0); + return add_object(NULL_TAG, UNIVERSAL, nullptr, 0); } /* @@ -230,7 +235,17 @@ DER_Encoder& DER_Encoder::encode(const BigInt& n) /* * DER encode an OCTET STRING or BIT STRING */ -DER_Encoder& DER_Encoder::encode(const MemoryRegion<byte>& bytes, +DER_Encoder& DER_Encoder::encode(const secure_vector<byte>& bytes, + ASN1_Tag real_type) + { + return encode(&bytes[0], bytes.size(), + real_type, real_type, UNIVERSAL); + } + +/* +* DER encode an OCTET STRING or BIT STRING +*/ +DER_Encoder& DER_Encoder::encode(const std::vector<byte>& bytes, ASN1_Tag real_type) { return encode(&bytes[0], bytes.size(), @@ -275,7 +290,7 @@ DER_Encoder& DER_Encoder::encode(const BigInt& n, return add_object(type_tag, class_tag, 0); bool extra_zero = (n.bits() % 8 == 0); - SecureVector<byte> contents(extra_zero + n.bytes()); + secure_vector<byte> contents(extra_zero + n.bytes()); BigInt::encode(&contents[extra_zero], n); if(n < 0) { @@ -292,7 +307,18 @@ DER_Encoder& DER_Encoder::encode(const BigInt& n, /* * DER encode an OCTET STRING or BIT STRING */ -DER_Encoder& DER_Encoder::encode(const MemoryRegion<byte>& bytes, +DER_Encoder& DER_Encoder::encode(const secure_vector<byte>& bytes, + ASN1_Tag real_type, + ASN1_Tag type_tag, ASN1_Tag class_tag) + { + return encode(&bytes[0], bytes.size(), + real_type, type_tag, class_tag); + } + +/* +* DER encode an OCTET STRING or BIT STRING +*/ +DER_Encoder& DER_Encoder::encode(const std::vector<byte>& bytes, ASN1_Tag real_type, ASN1_Tag type_tag, ASN1_Tag class_tag) { @@ -312,7 +338,7 @@ DER_Encoder& DER_Encoder::encode(const byte bytes[], size_t length, if(real_type == BIT_STRING) { - SecureVector<byte> encoded; + secure_vector<byte> encoded; encoded.push_back(0); encoded += std::make_pair(bytes, length); return add_object(type_tag, class_tag, encoded); @@ -346,7 +372,7 @@ DER_Encoder& DER_Encoder::encode(const ASN1_Object& obj) DER_Encoder& DER_Encoder::add_object(ASN1_Tag type_tag, ASN1_Tag class_tag, const byte rep[], size_t length) { - SecureVector<byte> buffer; + secure_vector<byte> buffer; buffer += encode_tag(type_tag, class_tag); buffer += encode_length(length); buffer += std::make_pair(rep, length); @@ -358,17 +384,6 @@ DER_Encoder& DER_Encoder::add_object(ASN1_Tag type_tag, ASN1_Tag class_tag, * Write the encoding of the byte(s) */ DER_Encoder& DER_Encoder::add_object(ASN1_Tag type_tag, ASN1_Tag class_tag, - const MemoryRegion<byte>& rep_buf) - { - const byte* rep = &rep_buf[0]; - const size_t rep_len = rep_buf.size(); - return add_object(type_tag, class_tag, rep, rep_len); - } - -/* -* Write the encoding of the byte(s) -*/ -DER_Encoder& DER_Encoder::add_object(ASN1_Tag type_tag, ASN1_Tag class_tag, const std::string& rep_str) { const byte* rep = reinterpret_cast<const byte*>(rep_str.data()); diff --git a/src/asn1/der_enc.h b/src/asn1/der_enc.h index 183e43b80..adab02247 100644 --- a/src/asn1/der_enc.h +++ b/src/asn1/der_enc.h @@ -22,7 +22,10 @@ class ASN1_Object; class BOTAN_DLL DER_Encoder { public: - SecureVector<byte> get_contents(); + secure_vector<byte> get_contents(); + + std::vector<byte> get_contents_unlocked() + { return unlock(get_contents()); } DER_Encoder& start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag = UNIVERSAL); @@ -32,13 +35,15 @@ class BOTAN_DLL DER_Encoder DER_Encoder& end_explicit(); DER_Encoder& raw_bytes(const byte val[], size_t len); - DER_Encoder& raw_bytes(const MemoryRegion<byte>& val); + DER_Encoder& raw_bytes(const secure_vector<byte>& val); + DER_Encoder& raw_bytes(const std::vector<byte>& val); DER_Encoder& encode_null(); DER_Encoder& encode(bool b); DER_Encoder& encode(size_t s); DER_Encoder& encode(const BigInt& n); - DER_Encoder& encode(const MemoryRegion<byte>& v, ASN1_Tag real_type); + DER_Encoder& encode(const secure_vector<byte>& v, ASN1_Tag real_type); + DER_Encoder& encode(const std::vector<byte>& v, ASN1_Tag real_type); DER_Encoder& encode(const byte val[], size_t len, ASN1_Tag real_type); DER_Encoder& encode(bool b, @@ -53,7 +58,12 @@ class BOTAN_DLL DER_Encoder ASN1_Tag type_tag, ASN1_Tag class_tag = CONTEXT_SPECIFIC); - DER_Encoder& encode(const MemoryRegion<byte>& v, + DER_Encoder& encode(const std::vector<byte>& v, + ASN1_Tag real_type, + ASN1_Tag type_tag, + ASN1_Tag class_tag = CONTEXT_SPECIFIC); + + DER_Encoder& encode(const secure_vector<byte>& v, ASN1_Tag real_type, ASN1_Tag type_tag, ASN1_Tag class_tag = CONTEXT_SPECIFIC); @@ -86,7 +96,16 @@ class BOTAN_DLL DER_Encoder const byte rep[], size_t length); DER_Encoder& add_object(ASN1_Tag type_tag, ASN1_Tag class_tag, - const MemoryRegion<byte>& rep); + const std::vector<byte>& rep) + { + return add_object(type_tag, class_tag, &rep[0], rep.size()); + } + + DER_Encoder& add_object(ASN1_Tag type_tag, ASN1_Tag class_tag, + const secure_vector<byte>& rep) + { + return add_object(type_tag, class_tag, &rep[0], rep.size()); + } DER_Encoder& add_object(ASN1_Tag type_tag, ASN1_Tag class_tag, const std::string& str); @@ -99,16 +118,16 @@ class BOTAN_DLL DER_Encoder { public: ASN1_Tag tag_of() const; - SecureVector<byte> get_contents(); + secure_vector<byte> get_contents(); void add_bytes(const byte[], size_t); DER_Sequence(ASN1_Tag, ASN1_Tag); private: ASN1_Tag type_tag, class_tag; - SecureVector<byte> contents; - std::vector< SecureVector<byte> > set_contents; + secure_vector<byte> contents; + std::vector< secure_vector<byte> > set_contents; }; - SecureVector<byte> contents; + secure_vector<byte> contents; std::vector<DER_Sequence> subsequences; }; diff --git a/src/asn1/x509_dn.cpp b/src/asn1/x509_dn.cpp index ceb12cee6..c6bc70553 100644 --- a/src/asn1/x509_dn.cpp +++ b/src/asn1/x509_dn.cpp @@ -27,9 +27,8 @@ X509_DN::X509_DN() */ X509_DN::X509_DN(const std::multimap<OID, std::string>& args) { - std::multimap<OID, std::string>::const_iterator j; - for(j = args.begin(); j != args.end(); ++j) - add_attribute(j->first, j->second); + for(auto i = args.begin(); i != args.end(); ++i) + add_attribute(i->first, i->second); } /* @@ -37,9 +36,8 @@ X509_DN::X509_DN(const std::multimap<OID, std::string>& args) */ X509_DN::X509_DN(const std::multimap<std::string, std::string>& args) { - std::multimap<std::string, std::string>::const_iterator j; - for(j = args.begin(); j != args.end(); ++j) - add_attribute(OIDS::lookup(j->first), j->second); + for(auto i = args.begin(); i != args.end(); ++i) + add_attribute(OIDS::lookup(i->first), i->second); } /* @@ -60,11 +58,9 @@ void X509_DN::add_attribute(const OID& oid, const std::string& str) if(str == "") return; - typedef std::multimap<OID, ASN1_String>::iterator rdn_iter; - - std::pair<rdn_iter, rdn_iter> range = dn_info.equal_range(oid); - for(rdn_iter j = range.first; j != range.second; ++j) - if(j->second.value() == str) + auto range = dn_info.equal_range(oid); + for(auto i = range.first; i != range.second; ++i) + if(i->second.value() == str) return; multimap_insert(dn_info, oid, ASN1_String(str)); @@ -76,11 +72,9 @@ void X509_DN::add_attribute(const OID& oid, const std::string& str) */ std::multimap<OID, std::string> X509_DN::get_attributes() const { - typedef std::multimap<OID, ASN1_String>::const_iterator rdn_iter; - std::multimap<OID, std::string> retval; - for(rdn_iter j = dn_info.begin(); j != dn_info.end(); ++j) - multimap_insert(retval, j->first, j->second.value()); + for(auto i = dn_info.begin(); i != dn_info.end(); ++i) + multimap_insert(retval, i->first, i->second.value()); return retval; } @@ -89,11 +83,9 @@ std::multimap<OID, std::string> X509_DN::get_attributes() const */ std::multimap<std::string, std::string> X509_DN::contents() const { - typedef std::multimap<OID, ASN1_String>::const_iterator rdn_iter; - std::multimap<std::string, std::string> retval; - for(rdn_iter j = dn_info.begin(); j != dn_info.end(); ++j) - multimap_insert(retval, OIDS::lookup(j->first), j->second.value()); + for(auto i = dn_info.begin(); i != dn_info.end(); ++i) + multimap_insert(retval, OIDS::lookup(i->first), i->second.value()); return retval; } @@ -102,21 +94,20 @@ std::multimap<std::string, std::string> X509_DN::contents() const */ std::vector<std::string> X509_DN::get_attribute(const std::string& attr) const { - typedef std::multimap<OID, ASN1_String>::const_iterator rdn_iter; - const OID oid = OIDS::lookup(deref_info_field(attr)); - std::pair<rdn_iter, rdn_iter> range = dn_info.equal_range(oid); + + auto range = dn_info.equal_range(oid); std::vector<std::string> values; - for(rdn_iter j = range.first; j != range.second; ++j) - values.push_back(j->second.value()); + for(auto i = range.first; i != range.second; ++i) + values.push_back(i->second.value()); return values; } /* * Return the BER encoded data, if any */ -MemoryVector<byte> X509_DN::get_bits() const +std::vector<byte> X509_DN::get_bits() const { return dn_bits; } @@ -143,15 +134,13 @@ std::string X509_DN::deref_info_field(const std::string& info) */ bool operator==(const X509_DN& dn1, const X509_DN& dn2) { - typedef std::multimap<OID, std::string>::const_iterator rdn_iter; - - std::multimap<OID, std::string> attr1 = dn1.get_attributes(); - std::multimap<OID, std::string> attr2 = dn2.get_attributes(); + auto attr1 = dn1.get_attributes(); + auto attr2 = dn2.get_attributes(); if(attr1.size() != attr2.size()) return false; - rdn_iter p1 = attr1.begin(); - rdn_iter p2 = attr2.begin(); + auto p1 = attr1.begin(); + auto p2 = attr2.begin(); while(true) { @@ -181,18 +170,15 @@ bool operator!=(const X509_DN& dn1, const X509_DN& dn2) */ bool operator<(const X509_DN& dn1, const X509_DN& dn2) { - typedef std::multimap<OID, std::string>::const_iterator rdn_iter; - - std::multimap<OID, std::string> attr1 = dn1.get_attributes(); - std::multimap<OID, std::string> attr2 = dn2.get_attributes(); + auto attr1 = dn1.get_attributes(); + auto attr2 = dn2.get_attributes(); if(attr1.size() < attr2.size()) return true; if(attr1.size() > attr2.size()) return false; - for(rdn_iter p1 = attr1.begin(); p1 != attr1.end(); ++p1) + for(auto p1 = attr1.begin(); p1 != attr1.end(); ++p1) { - std::multimap<OID, std::string>::const_iterator p2; - p2 = attr2.find(p1->first); + auto p2 = attr2.find(p1->first); if(p2 == attr2.end()) return false; if(p1->second > p2->second) return false; if(p1->second < p2->second) return true; @@ -210,8 +196,6 @@ void do_ava(DER_Encoder& encoder, ASN1_Tag string_type, const std::string& oid_str, bool must_exist = false) { - typedef std::multimap<OID, std::string>::const_iterator rdn_iter; - const OID oid = OIDS::lookup(oid_str); const bool exists = (dn_info.find(oid) != dn_info.end()); @@ -219,14 +203,14 @@ void do_ava(DER_Encoder& encoder, throw Encoding_Error("X509_DN: No entry for " + oid_str); if(!exists) return; - std::pair<rdn_iter, rdn_iter> range = dn_info.equal_range(oid); + auto range = dn_info.equal_range(oid); - for(rdn_iter j = range.first; j != range.second; ++j) + for(auto i = range.first; i != range.second; ++i) { encoder.start_cons(SET) .start_cons(SEQUENCE) .encode(oid) - .encode(ASN1_String(j->second, string_type)) + .encode(ASN1_String(i->second, string_type)) .end_cons() .end_cons(); } @@ -239,7 +223,7 @@ void do_ava(DER_Encoder& encoder, */ void X509_DN::encode_into(DER_Encoder& der) const { - std::multimap<OID, std::string> dn_info = get_attributes(); + auto dn_info = get_attributes(); der.start_cons(SEQUENCE); @@ -264,7 +248,7 @@ void X509_DN::encode_into(DER_Encoder& der) const */ void X509_DN::decode_from(BER_Decoder& source) { - MemoryVector<byte> bits; + std::vector<byte> bits; source.start_cons(SEQUENCE) .raw_bytes(bits) diff --git a/src/asn1/x509_dn.h b/src/asn1/x509_dn.h index de44f8c78..f8dc9e782 100644 --- a/src/asn1/x509_dn.h +++ b/src/asn1/x509_dn.h @@ -35,14 +35,14 @@ class BOTAN_DLL X509_DN : public ASN1_Object static std::string deref_info_field(const std::string&); - MemoryVector<byte> get_bits() const; + std::vector<byte> get_bits() const; X509_DN(); X509_DN(const std::multimap<OID, std::string>&); X509_DN(const std::multimap<std::string, std::string>&); private: std::multimap<OID, ASN1_String> dn_info; - MemoryVector<byte> dn_bits; + std::vector<byte> dn_bits; }; bool BOTAN_DLL operator==(const X509_DN&, const X509_DN&); diff --git a/src/benchmark/benchmark.cpp b/src/benchmark/benchmark.cpp index dbccd45c1..a9b84f252 100644 --- a/src/benchmark/benchmark.cpp +++ b/src/benchmark/benchmark.cpp @@ -1,6 +1,6 @@ /* * Runtime benchmarking -* (C) 2008 Jack Lloyd +* (C) 2008-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -11,33 +11,40 @@ #include <botan/stream_cipher.h> #include <botan/hash.h> #include <botan/mac.h> -#include <botan/time.h> #include <memory> +#include <vector> +#include <chrono> namespace Botan { namespace { +typedef std::chrono::high_resolution_clock benchmark_clock; + /** * Benchmark Buffered_Computation (hash or MAC) */ std::pair<u64bit, u64bit> bench_buf_comp(Buffered_Computation* buf_comp, - u64bit nanoseconds_max, + std::chrono::nanoseconds max_time, const byte buf[], size_t buf_len) { u64bit reps = 0; - u64bit nanoseconds_used = 0; - while(nanoseconds_used < nanoseconds_max) + std::chrono::nanoseconds time_used(0); + + while(time_used < max_time) { - const u64bit start = get_nanoseconds_clock(); + auto start = benchmark_clock::now(); buf_comp->update(buf, buf_len); - nanoseconds_used += get_nanoseconds_clock() - start; + time_used += std::chrono::duration_cast<std::chrono::nanoseconds>(benchmark_clock::now() - start); ++reps; } - return std::make_pair(reps * buf_len, nanoseconds_used); + u64bit ns_taken = + std::chrono::duration_cast<std::chrono::nanoseconds>(time_used).count(); + + return std::make_pair(reps * buf_len, ns_taken); } /** @@ -45,27 +52,32 @@ std::pair<u64bit, u64bit> bench_buf_comp(Buffered_Computation* buf_comp, */ std::pair<u64bit, u64bit> bench_block_cipher(BlockCipher* block_cipher, - u64bit nanoseconds_max, + std::chrono::nanoseconds max_time, byte buf[], size_t buf_len) { const size_t in_blocks = buf_len / block_cipher->block_size(); u64bit reps = 0; - u64bit nanoseconds_used = 0; + + std::chrono::nanoseconds time_used(0); block_cipher->set_key(buf, block_cipher->maximum_keylength()); - while(nanoseconds_used < nanoseconds_max) + while(time_used < max_time) { - const u64bit start = get_nanoseconds_clock(); + auto start = benchmark_clock::now(); block_cipher->encrypt_n(buf, buf, in_blocks); - nanoseconds_used += get_nanoseconds_clock() - start; + time_used += std::chrono::duration_cast<std::chrono::nanoseconds>(benchmark_clock::now() - start); + //time_used += benchmark_clock::now() - start; ++reps; } + u64bit ns_taken = + std::chrono::duration_cast<std::chrono::nanoseconds>(time_used).count(); + return std::make_pair(reps * in_blocks * block_cipher->block_size(), - nanoseconds_used); + ns_taken); } /** @@ -73,24 +85,28 @@ bench_block_cipher(BlockCipher* block_cipher, */ std::pair<u64bit, u64bit> bench_stream_cipher(StreamCipher* stream_cipher, - u64bit nanoseconds_max, + std::chrono::nanoseconds max_time, byte buf[], size_t buf_len) { u64bit reps = 0; - u64bit nanoseconds_used = 0; stream_cipher->set_key(buf, stream_cipher->maximum_keylength()); - while(nanoseconds_used < nanoseconds_max) + std::chrono::nanoseconds time_used(0); + + while(time_used < max_time) { - const u64bit start = get_nanoseconds_clock(); + auto start = benchmark_clock::now(); stream_cipher->cipher1(buf, buf_len); - nanoseconds_used += get_nanoseconds_clock() - start; + time_used += benchmark_clock::now() - start; ++reps; } - return std::make_pair(reps * buf_len, nanoseconds_used); + u64bit ns_taken = + std::chrono::duration_cast<std::chrono::nanoseconds>(time_used).count(); + + return std::make_pair(reps * buf_len, ns_taken); } /** @@ -98,10 +114,10 @@ bench_stream_cipher(StreamCipher* stream_cipher, */ std::pair<u64bit, u64bit> bench_hash(HashFunction* hash, - u64bit nanoseconds_max, + std::chrono::nanoseconds max_time, const byte buf[], size_t buf_len) { - return bench_buf_comp(hash, nanoseconds_max, buf, buf_len); + return bench_buf_comp(hash, max_time, buf, buf_len); } /** @@ -109,11 +125,11 @@ bench_hash(HashFunction* hash, */ std::pair<u64bit, u64bit> bench_mac(MessageAuthenticationCode* mac, - u64bit nanoseconds_max, + std::chrono::nanoseconds max_time, const byte buf[], size_t buf_len) { mac->set_key(buf, mac->maximum_keylength()); - return bench_buf_comp(mac, nanoseconds_max, buf, buf_len); + return bench_buf_comp(mac, max_time, buf, buf_len); } } @@ -122,7 +138,7 @@ std::map<std::string, double> algorithm_benchmark(const std::string& name, Algorithm_Factory& af, RandomNumberGenerator& rng, - u32bit milliseconds, + std::chrono::milliseconds milliseconds, size_t buf_size) { std::vector<std::string> providers = af.providers_of(name); @@ -131,8 +147,7 @@ algorithm_benchmark(const std::string& name, if(providers.empty()) // no providers, nothing to do return all_results; - const u64bit ns_per_provider = - (static_cast<u64bit>(milliseconds) * 1000 * 1000) / providers.size(); + std::chrono::nanoseconds ns_per_provider = milliseconds / providers.size(); std::vector<byte> buf(buf_size * 1024); rng.randomize(&buf[0], buf.size()); @@ -146,7 +161,7 @@ algorithm_benchmark(const std::string& name, if(const BlockCipher* proto = af.prototype_block_cipher(name, provider)) { - std::auto_ptr<BlockCipher> block_cipher(proto->clone()); + std::unique_ptr<BlockCipher> block_cipher(proto->clone()); results = bench_block_cipher(block_cipher.get(), ns_per_provider, &buf[0], buf.size()); @@ -154,7 +169,7 @@ algorithm_benchmark(const std::string& name, else if(const StreamCipher* proto = af.prototype_stream_cipher(name, provider)) { - std::auto_ptr<StreamCipher> stream_cipher(proto->clone()); + std::unique_ptr<StreamCipher> stream_cipher(proto->clone()); results = bench_stream_cipher(stream_cipher.get(), ns_per_provider, &buf[0], buf.size()); @@ -162,14 +177,14 @@ algorithm_benchmark(const std::string& name, else if(const HashFunction* proto = af.prototype_hash_function(name, provider)) { - std::auto_ptr<HashFunction> hash(proto->clone()); + std::unique_ptr<HashFunction> hash(proto->clone()); results = bench_hash(hash.get(), ns_per_provider, &buf[0], buf.size()); } else if(const MessageAuthenticationCode* proto = af.prototype_mac(name, provider)) { - std::auto_ptr<MessageAuthenticationCode> mac(proto->clone()); + std::unique_ptr<MessageAuthenticationCode> mac(proto->clone()); results = bench_mac(mac.get(), ns_per_provider, &buf[0], buf.size()); } diff --git a/src/benchmark/benchmark.h b/src/benchmark/benchmark.h index c47fdc166..17df85e4e 100644 --- a/src/benchmark/benchmark.h +++ b/src/benchmark/benchmark.h @@ -1,6 +1,6 @@ /* * Runtime benchmarking -* (C) 2008 Jack Lloyd +* (C) 2008-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -12,6 +12,7 @@ #include <botan/rng.h> #include <map> #include <string> +#include <chrono> namespace Botan { @@ -28,7 +29,7 @@ std::map<std::string, double> BOTAN_DLL algorithm_benchmark(const std::string& name, Algorithm_Factory& af, RandomNumberGenerator& rng, - u32bit milliseconds, + std::chrono::milliseconds milliseconds, size_t buf_size); } diff --git a/src/block/aes/aes.cpp b/src/block/aes/aes.cpp index 5f47762a8..6a706fd24 100644 --- a/src/block/aes/aes.cpp +++ b/src/block/aes/aes.cpp @@ -414,8 +414,8 @@ const u32bit TD[1024] = { */ void aes_encrypt_n(const byte in[], byte out[], size_t blocks, - const MemoryRegion<u32bit>& EK, - const MemoryRegion<byte>& ME) + const secure_vector<u32bit>& EK, + const secure_vector<byte>& ME) { const size_t BLOCK_SIZE = 16; @@ -525,8 +525,8 @@ void aes_encrypt_n(const byte in[], byte out[], * AES Decryption */ void aes_decrypt_n(const byte in[], byte out[], size_t blocks, - const MemoryRegion<u32bit>& DK, - const MemoryRegion<byte>& MD) + const secure_vector<u32bit>& DK, + const secure_vector<byte>& MD) { const size_t BLOCK_SIZE = 16; @@ -606,10 +606,10 @@ void aes_decrypt_n(const byte in[], byte out[], size_t blocks, } void aes_key_schedule(const byte key[], size_t length, - MemoryRegion<u32bit>& EK, - MemoryRegion<u32bit>& DK, - MemoryRegion<byte>& ME, - MemoryRegion<byte>& MD) + secure_vector<u32bit>& EK, + secure_vector<u32bit>& DK, + secure_vector<byte>& ME, + secure_vector<byte>& MD) { static const u32bit RC[10] = { 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, @@ -617,7 +617,7 @@ void aes_key_schedule(const byte key[], size_t length, const size_t rounds = (length / 4) + 6; - SecureVector<u32bit> XEK(length + 32), XDK(length + 32); + secure_vector<u32bit> XEK(length + 32), XDK(length + 32); const size_t X = length / 4; for(size_t i = 0; i != X; ++i) @@ -659,6 +659,9 @@ void aes_key_schedule(const byte key[], size_t length, TD[SE[get_byte(2, XDK[i])] + 512] ^ TD[SE[get_byte(3, XDK[i])] + 768]; + ME.resize(16); + MD.resize(16); + for(size_t i = 0; i != 4; ++i) { store_be(XEK[i+4*rounds], &ME[4*i]); diff --git a/src/block/aes/aes.h b/src/block/aes/aes.h index a165f83b5..5ddd39b08 100644 --- a/src/block/aes/aes.h +++ b/src/block/aes/aes.h @@ -18,8 +18,6 @@ namespace Botan { class BOTAN_DLL AES_128 : public Block_Cipher_Fixed_Params<16, 16> { public: - AES_128() : EK(40), DK(40), ME(16), MD(16) {} - void encrypt_n(const byte in[], byte out[], size_t blocks) const; void decrypt_n(const byte in[], byte out[], size_t blocks) const; @@ -30,8 +28,8 @@ class BOTAN_DLL AES_128 : public Block_Cipher_Fixed_Params<16, 16> private: void key_schedule(const byte key[], size_t length); - SecureVector<u32bit> EK, DK; - SecureVector<byte> ME, MD; + secure_vector<u32bit> EK, DK; + secure_vector<byte> ME, MD; }; /** @@ -40,8 +38,6 @@ class BOTAN_DLL AES_128 : public Block_Cipher_Fixed_Params<16, 16> class BOTAN_DLL AES_192 : public Block_Cipher_Fixed_Params<16, 24> { public: - AES_192() : EK(48), DK(48), ME(16), MD(16) {} - void encrypt_n(const byte in[], byte out[], size_t blocks) const; void decrypt_n(const byte in[], byte out[], size_t blocks) const; @@ -52,8 +48,8 @@ class BOTAN_DLL AES_192 : public Block_Cipher_Fixed_Params<16, 24> private: void key_schedule(const byte key[], size_t length); - SecureVector<u32bit> EK, DK; - SecureVector<byte> ME, MD; + secure_vector<u32bit> EK, DK; + secure_vector<byte> ME, MD; }; /** @@ -62,8 +58,6 @@ class BOTAN_DLL AES_192 : public Block_Cipher_Fixed_Params<16, 24> class BOTAN_DLL AES_256 : public Block_Cipher_Fixed_Params<16, 32> { public: - AES_256() : EK(56), DK(56), ME(16), MD(16) {} - void encrypt_n(const byte in[], byte out[], size_t blocks) const; void decrypt_n(const byte in[], byte out[], size_t blocks) const; @@ -74,8 +68,8 @@ class BOTAN_DLL AES_256 : public Block_Cipher_Fixed_Params<16, 32> private: void key_schedule(const byte key[], size_t length); - SecureVector<u32bit> EK, DK; - SecureVector<byte> ME, MD; + secure_vector<u32bit> EK, DK; + secure_vector<byte> ME, MD; }; } diff --git a/src/block/aes_ni/aes_ni.h b/src/block/aes_ni/aes_ni.h index ae9e5b3f4..4844b7fe8 100644 --- a/src/block/aes_ni/aes_ni.h +++ b/src/block/aes_ni/aes_ni.h @@ -31,7 +31,7 @@ class BOTAN_DLL AES_128_NI : public Block_Cipher_Fixed_Params<16, 16> private: void key_schedule(const byte[], size_t); - SecureVector<u32bit> EK, DK; + secure_vector<u32bit> EK, DK; }; /** @@ -53,7 +53,7 @@ class BOTAN_DLL AES_192_NI : public Block_Cipher_Fixed_Params<16, 24> private: void key_schedule(const byte[], size_t); - SecureVector<u32bit> EK, DK; + secure_vector<u32bit> EK, DK; }; /** @@ -75,7 +75,7 @@ class BOTAN_DLL AES_256_NI : public Block_Cipher_Fixed_Params<16, 32> private: void key_schedule(const byte[], size_t); - SecureVector<u32bit> EK, DK; + secure_vector<u32bit> EK, DK; }; } diff --git a/src/block/aes_ssse3/aes_ssse3.cpp b/src/block/aes_ssse3/aes_ssse3.cpp index 774ccbabb..648f96d67 100644 --- a/src/block/aes_ssse3/aes_ssse3.cpp +++ b/src/block/aes_ssse3/aes_ssse3.cpp @@ -378,6 +378,9 @@ void AES_128_SSSE3::key_schedule(const byte keyb[], size_t) __m128i key = _mm_loadu_si128(reinterpret_cast<const __m128i*>(keyb)); + EK.resize(11*4); + DK.resize(11*4); + __m128i* EK_mm = reinterpret_cast<__m128i*>(&EK[0]); __m128i* DK_mm = reinterpret_cast<__m128i*>(&DK[0]); @@ -445,6 +448,9 @@ void AES_192_SSSE3::key_schedule(const byte keyb[], size_t) __m128i rcon = _mm_set_epi32(0x702A9808, 0x4D7C7D81, 0x1F8391B9, 0xAF9DEEB6); + EK.resize(13*4); + DK.resize(13*4); + __m128i* EK_mm = reinterpret_cast<__m128i*>(&EK[0]); __m128i* DK_mm = reinterpret_cast<__m128i*>(&DK[0]); @@ -544,6 +550,9 @@ void AES_256_SSSE3::key_schedule(const byte keyb[], size_t) __m128i rcon = _mm_set_epi32(0x702A9808, 0x4D7C7D81, 0x1F8391B9, 0xAF9DEEB6); + EK.resize(15*4); + DK.resize(15*4); + __m128i* EK_mm = reinterpret_cast<__m128i*>(&EK[0]); __m128i* DK_mm = reinterpret_cast<__m128i*>(&DK[0]); @@ -568,7 +577,7 @@ void AES_256_SSSE3::key_schedule(const byte keyb[], size_t) _mm_storeu_si128(EK_mm + i, aes_schedule_mangle(key2, i % 4)); _mm_storeu_si128(DK_mm + (14-i), aes_schedule_mangle_dec(key2, (i+2) % 4)); - key2 = aes_schedule_round(NULL, _mm_shuffle_epi32(key2, 0xFF), k_t); + key2 = aes_schedule_round(nullptr, _mm_shuffle_epi32(key2, 0xFF), k_t); _mm_storeu_si128(EK_mm + i + 1, aes_schedule_mangle(key2, (i - 1) % 4)); _mm_storeu_si128(DK_mm + (13-i), aes_schedule_mangle_dec(key2, (i+1) % 4)); } diff --git a/src/block/aes_ssse3/aes_ssse3.h b/src/block/aes_ssse3/aes_ssse3.h index 686b7999f..46bae1450 100644 --- a/src/block/aes_ssse3/aes_ssse3.h +++ b/src/block/aes_ssse3/aes_ssse3.h @@ -24,12 +24,10 @@ class BOTAN_DLL AES_128_SSSE3 : public Block_Cipher_Fixed_Params<16, 16> void clear() { zeroise(EK); zeroise(DK); } std::string name() const { return "AES-128"; } BlockCipher* clone() const { return new AES_128_SSSE3; } - - AES_128_SSSE3() : EK(44), DK(44) {} private: void key_schedule(const byte[], size_t); - SecureVector<u32bit> EK, DK; + secure_vector<u32bit> EK, DK; }; /** @@ -44,12 +42,10 @@ class BOTAN_DLL AES_192_SSSE3 : public Block_Cipher_Fixed_Params<16, 24> void clear() { zeroise(EK); zeroise(DK); } std::string name() const { return "AES-192"; } BlockCipher* clone() const { return new AES_192_SSSE3; } - - AES_192_SSSE3() : EK(52), DK(52) {} private: void key_schedule(const byte[], size_t); - SecureVector<u32bit> EK, DK; + secure_vector<u32bit> EK, DK; }; /** @@ -64,12 +60,10 @@ class BOTAN_DLL AES_256_SSSE3 : public Block_Cipher_Fixed_Params<16, 32> void clear() { zeroise(EK); zeroise(DK); } std::string name() const { return "AES-256"; } BlockCipher* clone() const { return new AES_256_SSSE3; } - - AES_256_SSSE3() : EK(60), DK(60) {} private: void key_schedule(const byte[], size_t); - SecureVector<u32bit> EK, DK; + secure_vector<u32bit> EK, DK; }; } diff --git a/src/block/block_cipher.h b/src/block/block_cipher.h index 8e820fc5a..4a07bb048 100644 --- a/src/block/block_cipher.h +++ b/src/block/block_cipher.h @@ -75,6 +75,50 @@ class BOTAN_DLL BlockCipher : public SymmetricAlgorithm /** * Encrypt one or more blocks + * @param block the input/output buffer (multiple of block_size()) + */ + template<typename Alloc> + void encrypt(std::vector<byte, Alloc>& block) const + { + return encrypt_n(&block[0], &block[0], block.size() / block_size()); + } + + /** + * Decrypt one or more blocks + * @param block the input/output buffer (multiple of block_size()) + */ + template<typename Alloc> + void decrypt(std::vector<byte, Alloc>& block) const + { + return decrypt_n(&block[0], &block[0], block.size() / block_size()); + } + + /** + * Encrypt one or more blocks + * @param in the input buffer (multiple of block_size()) + * @param out the output buffer (same size as in) + */ + template<typename Alloc, typename Alloc2> + void encrypt(const std::vector<byte, Alloc>& in, + std::vector<byte, Alloc2>& out) const + { + return encrypt_n(&in[0], &out[0], in.size() / block_size()); + } + + /** + * Decrypt one or more blocks + * @param in the input buffer (multiple of block_size()) + * @param out the output buffer (same size as in) + */ + template<typename Alloc, typename Alloc2> + void decrypt(const std::vector<byte, Alloc>& in, + std::vector<byte, Alloc2>& out) const + { + return decrypt_n(&in[0], &out[0], in.size() / block_size()); + } + + /** + * Encrypt one or more blocks * @param in the input buffer (multiple of block_size()) * @param out the output buffer (same size as in) * @param blocks the number of blocks to process diff --git a/src/block/blowfish/blowfish.cpp b/src/block/blowfish/blowfish.cpp index b6319eec0..c224f479b 100644 --- a/src/block/blowfish/blowfish.cpp +++ b/src/block/blowfish/blowfish.cpp @@ -85,7 +85,11 @@ void Blowfish::decrypt_n(const byte in[], byte out[], size_t blocks) const */ void Blowfish::key_schedule(const byte key[], size_t length) { - clear(); + P.resize(18); + std::copy(P_INIT, P_INIT + 18, P.begin()); + + S.resize(1024); + std::copy(S_INIT, S_INIT + 1024, S.begin()); const byte null_salt[16] = { 0 }; @@ -125,12 +129,15 @@ void Blowfish::eks_key_schedule(const byte key[], size_t length, if(workfactor > 18) throw std::invalid_argument("Requested Bcrypt work factor too large"); - clear(); + P.resize(18); + std::copy(P_INIT, P_INIT + 18, P.begin()); - const byte null_salt[16] = { 0 }; + S.resize(1024); + std::copy(S_INIT, S_INIT + 1024, S.begin()); key_expansion(key, length, salt); + const byte null_salt[16] = { 0 }; const size_t rounds = 1 << workfactor; for(size_t r = 0; r != rounds; ++r) @@ -143,7 +150,7 @@ void Blowfish::eks_key_schedule(const byte key[], size_t length, /* * Generate one of the Sboxes */ -void Blowfish::generate_sbox(MemoryRegion<u32bit>& box, +void Blowfish::generate_sbox(secure_vector<u32bit>& box, u32bit& L, u32bit& R, const byte salt[16], size_t salt_off) const @@ -180,8 +187,8 @@ void Blowfish::generate_sbox(MemoryRegion<u32bit>& box, */ void Blowfish::clear() { - std::copy(P_INIT, P_INIT + 18, P.begin()); - std::copy(S_INIT, S_INIT + 1024, S.begin()); + P.clear(); + S.clear(); } } diff --git a/src/block/blowfish/blowfish.h b/src/block/blowfish/blowfish.h index 13706d21e..cdf65f285 100644 --- a/src/block/blowfish/blowfish.h +++ b/src/block/blowfish/blowfish.h @@ -30,8 +30,6 @@ class BOTAN_DLL Blowfish : public Block_Cipher_Fixed_Params<8, 1, 56> void clear(); std::string name() const { return "Blowfish"; } BlockCipher* clone() const { return new Blowfish; } - - Blowfish() : S(1024), P(18) {} private: void key_schedule(const byte key[], size_t length); @@ -39,7 +37,7 @@ class BOTAN_DLL Blowfish : public Block_Cipher_Fixed_Params<8, 1, 56> size_t key_length, const byte salt[16]); - void generate_sbox(MemoryRegion<u32bit>& box, + void generate_sbox(secure_vector<u32bit>& box, u32bit& L, u32bit& R, const byte salt[16], size_t salt_off) const; @@ -47,8 +45,7 @@ class BOTAN_DLL Blowfish : public Block_Cipher_Fixed_Params<8, 1, 56> static const u32bit P_INIT[18]; static const u32bit S_INIT[1024]; - SecureVector<u32bit> S; - SecureVector<u32bit> P; + secure_vector<u32bit> S, P; }; } diff --git a/src/block/camellia/camellia.cpp b/src/block/camellia/camellia.cpp index 054558c35..bea5d4c51 100644 --- a/src/block/camellia/camellia.cpp +++ b/src/block/camellia/camellia.cpp @@ -6,13 +6,20 @@ */ #include <botan/camellia.h> +#include <botan/internal/camellia_sbox.h> #include <botan/loadstor.h> namespace Botan { namespace Camellia_F { -u64bit F(u64bit v, u64bit K) +namespace { + +/* +* We use the slow byte-wise version of F in the first and last rounds +* to help protect against timing attacks +*/ +u64bit F_SLOW(u64bit v, u64bit K) { static const byte SBOX[256] = { 0x70, 0x82, 0x2C, 0xEC, 0xB3, 0x27, 0xC0, 0xE5, 0xE4, 0x85, 0x57, @@ -63,7 +70,21 @@ u64bit F(u64bit v, u64bit K) return make_u64bit(y1, y2, y3, y4, y5, y6, y7, y8); } -u64bit FL(u64bit v, u64bit K) +inline u64bit F(u64bit v, u64bit K) + { + const u64bit x = v ^ K; + + return Camellia_SBOX1[get_byte(0, x)] ^ + Camellia_SBOX2[get_byte(1, x)] ^ + Camellia_SBOX3[get_byte(2, x)] ^ + Camellia_SBOX4[get_byte(3, x)] ^ + Camellia_SBOX5[get_byte(4, x)] ^ + Camellia_SBOX6[get_byte(5, x)] ^ + Camellia_SBOX7[get_byte(6, x)] ^ + Camellia_SBOX8[get_byte(7, x)]; + } + +inline u64bit FL(u64bit v, u64bit K) { u32bit x1 = (v >> 32); u32bit x2 = (v & 0xFFFFFFFF); @@ -77,7 +98,7 @@ u64bit FL(u64bit v, u64bit K) return ((static_cast<u64bit>(x1) << 32) | x2); } -u64bit FLINV(u64bit v, u64bit K) +inline u64bit FLINV(u64bit v, u64bit K) { u32bit x1 = (v >> 32); u32bit x2 = (v & 0xFFFFFFFF); @@ -91,25 +112,12 @@ u64bit FLINV(u64bit v, u64bit K) return ((static_cast<u64bit>(x1) << 32) | x2); } -u64bit left_rot_hi(u64bit h, u64bit l, size_t shift) - { - return (h << shift) | ((l >> (64-shift))); - } - -u64bit left_rot_lo(u64bit h, u64bit l, size_t shift) - { - return (h >> (64-shift)) | (l << shift); - } - -} - /* * Camellia Encryption */ -void Camellia::encrypt_n(const byte in[], byte out[], size_t blocks) const +void encrypt(const byte in[], byte out[], size_t blocks, + const secure_vector<u64bit>& SK, const size_t rounds) { - using namespace Camellia_F; - for(size_t i = 0; i != blocks; ++i) { u64bit D1 = load_be<u64bit>(in, 0); @@ -120,39 +128,40 @@ void Camellia::encrypt_n(const byte in[], byte out[], size_t blocks) const D1 ^= *K++; D2 ^= *K++; - while(true) + D2 ^= F_SLOW(D1, *K++); + D1 ^= F_SLOW(D2, *K++); + + for(size_t r = 1; r != rounds - 1; ++r) { + if(r % 3 == 0) + { + D1 = FL (D1, *K++); + D2 = FLINV(D2, *K++); + } + D2 ^= F(D1, *K++); D1 ^= F(D2, *K++); - D2 ^= F(D1, *K++); - D1 ^= F(D2, *K++); - D2 ^= F(D1, *K++); - D1 ^= F(D2, *K++); - - if(K == &SK[SK.size()-2]) - break; - - D1 = FL (D1, *K++); - D2 = FLINV(D2, *K++); } + D2 ^= F_SLOW(D1, *K++); + D1 ^= F_SLOW(D2, *K++); + D2 ^= *K++; D1 ^= *K++; store_be(out, D2, D1); - in += BLOCK_SIZE; - out += BLOCK_SIZE; + in += 16; + out += 16; } } /* * Camellia Decryption */ -void Camellia::decrypt_n(const byte in[], byte out[], size_t blocks) const +void decrypt(const byte in[], byte out[], size_t blocks, + const secure_vector<u64bit>& SK, const size_t rounds) { - using namespace Camellia_F; - for(size_t i = 0; i != blocks; ++i) { u64bit D1 = load_be<u64bit>(in, 0); @@ -163,39 +172,49 @@ void Camellia::decrypt_n(const byte in[], byte out[], size_t blocks) const D2 ^= *K--; D1 ^= *K--; - while(true) + D2 ^= F_SLOW(D1, *K--); + D1 ^= F_SLOW(D2, *K--); + + for(size_t r = 1; r != rounds - 1; ++r) { + if(r % 3 == 0) + { + D1 = FL (D1, *K--); + D2 = FLINV(D2, *K--); + } + D2 ^= F(D1, *K--); D1 ^= F(D2, *K--); - D2 ^= F(D1, *K--); - D1 ^= F(D2, *K--); - D2 ^= F(D1, *K--); - D1 ^= F(D2, *K--); - - if(K == &SK[1]) - break; - - D1 = FL (D1, *K--); - D2 = FLINV(D2, *K--); } + D2 ^= F_SLOW(D1, *K--); + D1 ^= F_SLOW(D2, *K--); + D1 ^= *K--; D2 ^= *K; store_be(out, D2, D1); - in += BLOCK_SIZE; - out += BLOCK_SIZE; + in += 16; + out += 16; } } +u64bit left_rot_hi(u64bit h, u64bit l, size_t shift) + { + return (h << shift) | ((l >> (64-shift))); + } + +u64bit left_rot_lo(u64bit h, u64bit l, size_t shift) + { + return (h >> (64-shift)) | (l << shift); + } + /* * Camellia Key Schedule */ -void Camellia::key_schedule(const byte key[], size_t length) +void key_schedule(secure_vector<u64bit>& SK, const byte key[], size_t length) { - using namespace Camellia_F; - const u64bit Sigma1 = 0xA09E667F3BCC908B; const u64bit Sigma2 = 0xB67AE8584CAA73B2; const u64bit Sigma3 = 0xC6EF372FE94F82BE; @@ -309,3 +328,52 @@ void Camellia::key_schedule(const byte key[], size_t length) } } + +} + +void Camellia_128::encrypt_n(const byte in[], byte out[], size_t blocks) const + { + Camellia_F::encrypt(in, out, blocks, SK, 9); + } + +void Camellia_192::encrypt_n(const byte in[], byte out[], size_t blocks) const + { + Camellia_F::encrypt(in, out, blocks, SK, 12); + } + +void Camellia_256::encrypt_n(const byte in[], byte out[], size_t blocks) const + { + Camellia_F::encrypt(in, out, blocks, SK, 12); + } + +void Camellia_128::decrypt_n(const byte in[], byte out[], size_t blocks) const + { + Camellia_F::decrypt(in, out, blocks, SK, 9); + } + +void Camellia_192::decrypt_n(const byte in[], byte out[], size_t blocks) const + { + Camellia_F::decrypt(in, out, blocks, SK, 12); + } + +void Camellia_256::decrypt_n(const byte in[], byte out[], size_t blocks) const + { + Camellia_F::decrypt(in, out, blocks, SK, 12); + } + +void Camellia_128::key_schedule(const byte key[], size_t length) + { + Camellia_F::key_schedule(SK, key, length); + } + +void Camellia_192::key_schedule(const byte key[], size_t length) + { + Camellia_F::key_schedule(SK, key, length); + } + +void Camellia_256::key_schedule(const byte key[], size_t length) + { + Camellia_F::key_schedule(SK, key, length); + } + +} diff --git a/src/block/camellia/camellia.h b/src/block/camellia/camellia.h index aaf3ad9e3..4db115f2c 100644 --- a/src/block/camellia/camellia.h +++ b/src/block/camellia/camellia.h @@ -13,21 +13,57 @@ namespace Botan { /** -* Camellia +* Camellia-128 +*/ +class BOTAN_DLL Camellia_128 : public Block_Cipher_Fixed_Params<16, 16> + { + public: + void encrypt_n(const byte in[], byte out[], size_t blocks) const; + void decrypt_n(const byte in[], byte out[], size_t blocks) const; + + void clear() { SK.clear(); } + std::string name() const { return "Camellia-128"; } + BlockCipher* clone() const { return new Camellia_128; } + private: + void key_schedule(const byte key[], size_t length); + + secure_vector<u64bit> SK; + }; + +/** +* Camellia-192 +*/ +class BOTAN_DLL Camellia_192 : public Block_Cipher_Fixed_Params<16, 24> + { + public: + void encrypt_n(const byte in[], byte out[], size_t blocks) const; + void decrypt_n(const byte in[], byte out[], size_t blocks) const; + + void clear() { SK.clear(); } + std::string name() const { return "Camellia-192"; } + BlockCipher* clone() const { return new Camellia_192; } + private: + void key_schedule(const byte key[], size_t length); + + secure_vector<u64bit> SK; + }; + +/** +* Camellia-256 */ -class BOTAN_DLL Camellia : public Block_Cipher_Fixed_Params<16, 16, 32, 8> +class BOTAN_DLL Camellia_256 : public Block_Cipher_Fixed_Params<16, 32> { public: void encrypt_n(const byte in[], byte out[], size_t blocks) const; void decrypt_n(const byte in[], byte out[], size_t blocks) const; void clear() { SK.clear(); } - std::string name() const { return "Camellia"; } - BlockCipher* clone() const { return new Camellia; } + std::string name() const { return "Camellia-256"; } + BlockCipher* clone() const { return new Camellia_256; } private: void key_schedule(const byte key[], size_t length); - SecureVector<u64bit> SK; + secure_vector<u64bit> SK; }; } diff --git a/src/block/camellia/camellia_sbox.h b/src/block/camellia/camellia_sbox.h new file mode 100644 index 000000000..24c849a16 --- /dev/null +++ b/src/block/camellia/camellia_sbox.h @@ -0,0 +1,545 @@ +/* +* Camellia SBox Tables +* (C) 2012 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_CAMELLIA_SBOX_H__ +#define BOTAN_CAMELLIA_SBOX_H__ + +#include <botan/types.h> + +namespace Botan { + +const u64bit Camellia_SBOX1[256] = { +0x7070700070000070, 0x8282820082000082, 0x2C2C2C002C00002C, 0xECECEC00EC0000EC, +0xB3B3B300B30000B3, 0x2727270027000027, 0xC0C0C000C00000C0, 0xE5E5E500E50000E5, +0xE4E4E400E40000E4, 0x8585850085000085, 0x5757570057000057, 0x3535350035000035, +0xEAEAEA00EA0000EA, 0x0C0C0C000C00000C, 0xAEAEAE00AE0000AE, 0x4141410041000041, +0x2323230023000023, 0xEFEFEF00EF0000EF, 0x6B6B6B006B00006B, 0x9393930093000093, +0x4545450045000045, 0x1919190019000019, 0xA5A5A500A50000A5, 0x2121210021000021, +0xEDEDED00ED0000ED, 0x0E0E0E000E00000E, 0x4F4F4F004F00004F, 0x4E4E4E004E00004E, +0x1D1D1D001D00001D, 0x6565650065000065, 0x9292920092000092, 0xBDBDBD00BD0000BD, +0x8686860086000086, 0xB8B8B800B80000B8, 0xAFAFAF00AF0000AF, 0x8F8F8F008F00008F, +0x7C7C7C007C00007C, 0xEBEBEB00EB0000EB, 0x1F1F1F001F00001F, 0xCECECE00CE0000CE, +0x3E3E3E003E00003E, 0x3030300030000030, 0xDCDCDC00DC0000DC, 0x5F5F5F005F00005F, +0x5E5E5E005E00005E, 0xC5C5C500C50000C5, 0x0B0B0B000B00000B, 0x1A1A1A001A00001A, +0xA6A6A600A60000A6, 0xE1E1E100E10000E1, 0x3939390039000039, 0xCACACA00CA0000CA, +0xD5D5D500D50000D5, 0x4747470047000047, 0x5D5D5D005D00005D, 0x3D3D3D003D00003D, +0xD9D9D900D90000D9, 0x0101010001000001, 0x5A5A5A005A00005A, 0xD6D6D600D60000D6, +0x5151510051000051, 0x5656560056000056, 0x6C6C6C006C00006C, 0x4D4D4D004D00004D, +0x8B8B8B008B00008B, 0x0D0D0D000D00000D, 0x9A9A9A009A00009A, 0x6666660066000066, +0xFBFBFB00FB0000FB, 0xCCCCCC00CC0000CC, 0xB0B0B000B00000B0, 0x2D2D2D002D00002D, +0x7474740074000074, 0x1212120012000012, 0x2B2B2B002B00002B, 0x2020200020000020, +0xF0F0F000F00000F0, 0xB1B1B100B10000B1, 0x8484840084000084, 0x9999990099000099, +0xDFDFDF00DF0000DF, 0x4C4C4C004C00004C, 0xCBCBCB00CB0000CB, 0xC2C2C200C20000C2, +0x3434340034000034, 0x7E7E7E007E00007E, 0x7676760076000076, 0x0505050005000005, +0x6D6D6D006D00006D, 0xB7B7B700B70000B7, 0xA9A9A900A90000A9, 0x3131310031000031, +0xD1D1D100D10000D1, 0x1717170017000017, 0x0404040004000004, 0xD7D7D700D70000D7, +0x1414140014000014, 0x5858580058000058, 0x3A3A3A003A00003A, 0x6161610061000061, +0xDEDEDE00DE0000DE, 0x1B1B1B001B00001B, 0x1111110011000011, 0x1C1C1C001C00001C, +0x3232320032000032, 0x0F0F0F000F00000F, 0x9C9C9C009C00009C, 0x1616160016000016, +0x5353530053000053, 0x1818180018000018, 0xF2F2F200F20000F2, 0x2222220022000022, +0xFEFEFE00FE0000FE, 0x4444440044000044, 0xCFCFCF00CF0000CF, 0xB2B2B200B20000B2, +0xC3C3C300C30000C3, 0xB5B5B500B50000B5, 0x7A7A7A007A00007A, 0x9191910091000091, +0x2424240024000024, 0x0808080008000008, 0xE8E8E800E80000E8, 0xA8A8A800A80000A8, +0x6060600060000060, 0xFCFCFC00FC0000FC, 0x6969690069000069, 0x5050500050000050, +0xAAAAAA00AA0000AA, 0xD0D0D000D00000D0, 0xA0A0A000A00000A0, 0x7D7D7D007D00007D, +0xA1A1A100A10000A1, 0x8989890089000089, 0x6262620062000062, 0x9797970097000097, +0x5454540054000054, 0x5B5B5B005B00005B, 0x1E1E1E001E00001E, 0x9595950095000095, +0xE0E0E000E00000E0, 0xFFFFFF00FF0000FF, 0x6464640064000064, 0xD2D2D200D20000D2, +0x1010100010000010, 0xC4C4C400C40000C4, 0x0000000000000000, 0x4848480048000048, +0xA3A3A300A30000A3, 0xF7F7F700F70000F7, 0x7575750075000075, 0xDBDBDB00DB0000DB, +0x8A8A8A008A00008A, 0x0303030003000003, 0xE6E6E600E60000E6, 0xDADADA00DA0000DA, +0x0909090009000009, 0x3F3F3F003F00003F, 0xDDDDDD00DD0000DD, 0x9494940094000094, +0x8787870087000087, 0x5C5C5C005C00005C, 0x8383830083000083, 0x0202020002000002, +0xCDCDCD00CD0000CD, 0x4A4A4A004A00004A, 0x9090900090000090, 0x3333330033000033, +0x7373730073000073, 0x6767670067000067, 0xF6F6F600F60000F6, 0xF3F3F300F30000F3, +0x9D9D9D009D00009D, 0x7F7F7F007F00007F, 0xBFBFBF00BF0000BF, 0xE2E2E200E20000E2, +0x5252520052000052, 0x9B9B9B009B00009B, 0xD8D8D800D80000D8, 0x2626260026000026, +0xC8C8C800C80000C8, 0x3737370037000037, 0xC6C6C600C60000C6, 0x3B3B3B003B00003B, +0x8181810081000081, 0x9696960096000096, 0x6F6F6F006F00006F, 0x4B4B4B004B00004B, +0x1313130013000013, 0xBEBEBE00BE0000BE, 0x6363630063000063, 0x2E2E2E002E00002E, +0xE9E9E900E90000E9, 0x7979790079000079, 0xA7A7A700A70000A7, 0x8C8C8C008C00008C, +0x9F9F9F009F00009F, 0x6E6E6E006E00006E, 0xBCBCBC00BC0000BC, 0x8E8E8E008E00008E, +0x2929290029000029, 0xF5F5F500F50000F5, 0xF9F9F900F90000F9, 0xB6B6B600B60000B6, +0x2F2F2F002F00002F, 0xFDFDFD00FD0000FD, 0xB4B4B400B40000B4, 0x5959590059000059, +0x7878780078000078, 0x9898980098000098, 0x0606060006000006, 0x6A6A6A006A00006A, +0xE7E7E700E70000E7, 0x4646460046000046, 0x7171710071000071, 0xBABABA00BA0000BA, +0xD4D4D400D40000D4, 0x2525250025000025, 0xABABAB00AB0000AB, 0x4242420042000042, +0x8888880088000088, 0xA2A2A200A20000A2, 0x8D8D8D008D00008D, 0xFAFAFA00FA0000FA, +0x7272720072000072, 0x0707070007000007, 0xB9B9B900B90000B9, 0x5555550055000055, +0xF8F8F800F80000F8, 0xEEEEEE00EE0000EE, 0xACACAC00AC0000AC, 0x0A0A0A000A00000A, +0x3636360036000036, 0x4949490049000049, 0x2A2A2A002A00002A, 0x6868680068000068, +0x3C3C3C003C00003C, 0x3838380038000038, 0xF1F1F100F10000F1, 0xA4A4A400A40000A4, +0x4040400040000040, 0x2828280028000028, 0xD3D3D300D30000D3, 0x7B7B7B007B00007B, +0xBBBBBB00BB0000BB, 0xC9C9C900C90000C9, 0x4343430043000043, 0xC1C1C100C10000C1, +0x1515150015000015, 0xE3E3E300E30000E3, 0xADADAD00AD0000AD, 0xF4F4F400F40000F4, +0x7777770077000077, 0xC7C7C700C70000C7, 0x8080800080000080, 0x9E9E9E009E00009E }; + +const u64bit Camellia_SBOX2[256] = { +0x00E0E0E0E0E00000, 0x0005050505050000, 0x0058585858580000, 0x00D9D9D9D9D90000, +0x0067676767670000, 0x004E4E4E4E4E0000, 0x0081818181810000, 0x00CBCBCBCBCB0000, +0x00C9C9C9C9C90000, 0x000B0B0B0B0B0000, 0x00AEAEAEAEAE0000, 0x006A6A6A6A6A0000, +0x00D5D5D5D5D50000, 0x0018181818180000, 0x005D5D5D5D5D0000, 0x0082828282820000, +0x0046464646460000, 0x00DFDFDFDFDF0000, 0x00D6D6D6D6D60000, 0x0027272727270000, +0x008A8A8A8A8A0000, 0x0032323232320000, 0x004B4B4B4B4B0000, 0x0042424242420000, +0x00DBDBDBDBDB0000, 0x001C1C1C1C1C0000, 0x009E9E9E9E9E0000, 0x009C9C9C9C9C0000, +0x003A3A3A3A3A0000, 0x00CACACACACA0000, 0x0025252525250000, 0x007B7B7B7B7B0000, +0x000D0D0D0D0D0000, 0x0071717171710000, 0x005F5F5F5F5F0000, 0x001F1F1F1F1F0000, +0x00F8F8F8F8F80000, 0x00D7D7D7D7D70000, 0x003E3E3E3E3E0000, 0x009D9D9D9D9D0000, +0x007C7C7C7C7C0000, 0x0060606060600000, 0x00B9B9B9B9B90000, 0x00BEBEBEBEBE0000, +0x00BCBCBCBCBC0000, 0x008B8B8B8B8B0000, 0x0016161616160000, 0x0034343434340000, +0x004D4D4D4D4D0000, 0x00C3C3C3C3C30000, 0x0072727272720000, 0x0095959595950000, +0x00ABABABABAB0000, 0x008E8E8E8E8E0000, 0x00BABABABABA0000, 0x007A7A7A7A7A0000, +0x00B3B3B3B3B30000, 0x0002020202020000, 0x00B4B4B4B4B40000, 0x00ADADADADAD0000, +0x00A2A2A2A2A20000, 0x00ACACACACAC0000, 0x00D8D8D8D8D80000, 0x009A9A9A9A9A0000, +0x0017171717170000, 0x001A1A1A1A1A0000, 0x0035353535350000, 0x00CCCCCCCCCC0000, +0x00F7F7F7F7F70000, 0x0099999999990000, 0x0061616161610000, 0x005A5A5A5A5A0000, +0x00E8E8E8E8E80000, 0x0024242424240000, 0x0056565656560000, 0x0040404040400000, +0x00E1E1E1E1E10000, 0x0063636363630000, 0x0009090909090000, 0x0033333333330000, +0x00BFBFBFBFBF0000, 0x0098989898980000, 0x0097979797970000, 0x0085858585850000, +0x0068686868680000, 0x00FCFCFCFCFC0000, 0x00ECECECECEC0000, 0x000A0A0A0A0A0000, +0x00DADADADADA0000, 0x006F6F6F6F6F0000, 0x0053535353530000, 0x0062626262620000, +0x00A3A3A3A3A30000, 0x002E2E2E2E2E0000, 0x0008080808080000, 0x00AFAFAFAFAF0000, +0x0028282828280000, 0x00B0B0B0B0B00000, 0x0074747474740000, 0x00C2C2C2C2C20000, +0x00BDBDBDBDBD0000, 0x0036363636360000, 0x0022222222220000, 0x0038383838380000, +0x0064646464640000, 0x001E1E1E1E1E0000, 0x0039393939390000, 0x002C2C2C2C2C0000, +0x00A6A6A6A6A60000, 0x0030303030300000, 0x00E5E5E5E5E50000, 0x0044444444440000, +0x00FDFDFDFDFD0000, 0x0088888888880000, 0x009F9F9F9F9F0000, 0x0065656565650000, +0x0087878787870000, 0x006B6B6B6B6B0000, 0x00F4F4F4F4F40000, 0x0023232323230000, +0x0048484848480000, 0x0010101010100000, 0x00D1D1D1D1D10000, 0x0051515151510000, +0x00C0C0C0C0C00000, 0x00F9F9F9F9F90000, 0x00D2D2D2D2D20000, 0x00A0A0A0A0A00000, +0x0055555555550000, 0x00A1A1A1A1A10000, 0x0041414141410000, 0x00FAFAFAFAFA0000, +0x0043434343430000, 0x0013131313130000, 0x00C4C4C4C4C40000, 0x002F2F2F2F2F0000, +0x00A8A8A8A8A80000, 0x00B6B6B6B6B60000, 0x003C3C3C3C3C0000, 0x002B2B2B2B2B0000, +0x00C1C1C1C1C10000, 0x00FFFFFFFFFF0000, 0x00C8C8C8C8C80000, 0x00A5A5A5A5A50000, +0x0020202020200000, 0x0089898989890000, 0x0000000000000000, 0x0090909090900000, +0x0047474747470000, 0x00EFEFEFEFEF0000, 0x00EAEAEAEAEA0000, 0x00B7B7B7B7B70000, +0x0015151515150000, 0x0006060606060000, 0x00CDCDCDCDCD0000, 0x00B5B5B5B5B50000, +0x0012121212120000, 0x007E7E7E7E7E0000, 0x00BBBBBBBBBB0000, 0x0029292929290000, +0x000F0F0F0F0F0000, 0x00B8B8B8B8B80000, 0x0007070707070000, 0x0004040404040000, +0x009B9B9B9B9B0000, 0x0094949494940000, 0x0021212121210000, 0x0066666666660000, +0x00E6E6E6E6E60000, 0x00CECECECECE0000, 0x00EDEDEDEDED0000, 0x00E7E7E7E7E70000, +0x003B3B3B3B3B0000, 0x00FEFEFEFEFE0000, 0x007F7F7F7F7F0000, 0x00C5C5C5C5C50000, +0x00A4A4A4A4A40000, 0x0037373737370000, 0x00B1B1B1B1B10000, 0x004C4C4C4C4C0000, +0x0091919191910000, 0x006E6E6E6E6E0000, 0x008D8D8D8D8D0000, 0x0076767676760000, +0x0003030303030000, 0x002D2D2D2D2D0000, 0x00DEDEDEDEDE0000, 0x0096969696960000, +0x0026262626260000, 0x007D7D7D7D7D0000, 0x00C6C6C6C6C60000, 0x005C5C5C5C5C0000, +0x00D3D3D3D3D30000, 0x00F2F2F2F2F20000, 0x004F4F4F4F4F0000, 0x0019191919190000, +0x003F3F3F3F3F0000, 0x00DCDCDCDCDC0000, 0x0079797979790000, 0x001D1D1D1D1D0000, +0x0052525252520000, 0x00EBEBEBEBEB0000, 0x00F3F3F3F3F30000, 0x006D6D6D6D6D0000, +0x005E5E5E5E5E0000, 0x00FBFBFBFBFB0000, 0x0069696969690000, 0x00B2B2B2B2B20000, +0x00F0F0F0F0F00000, 0x0031313131310000, 0x000C0C0C0C0C0000, 0x00D4D4D4D4D40000, +0x00CFCFCFCFCF0000, 0x008C8C8C8C8C0000, 0x00E2E2E2E2E20000, 0x0075757575750000, +0x00A9A9A9A9A90000, 0x004A4A4A4A4A0000, 0x0057575757570000, 0x0084848484840000, +0x0011111111110000, 0x0045454545450000, 0x001B1B1B1B1B0000, 0x00F5F5F5F5F50000, +0x00E4E4E4E4E40000, 0x000E0E0E0E0E0000, 0x0073737373730000, 0x00AAAAAAAAAA0000, +0x00F1F1F1F1F10000, 0x00DDDDDDDDDD0000, 0x0059595959590000, 0x0014141414140000, +0x006C6C6C6C6C0000, 0x0092929292920000, 0x0054545454540000, 0x00D0D0D0D0D00000, +0x0078787878780000, 0x0070707070700000, 0x00E3E3E3E3E30000, 0x0049494949490000, +0x0080808080800000, 0x0050505050500000, 0x00A7A7A7A7A70000, 0x00F6F6F6F6F60000, +0x0077777777770000, 0x0093939393930000, 0x0086868686860000, 0x0083838383830000, +0x002A2A2A2A2A0000, 0x00C7C7C7C7C70000, 0x005B5B5B5B5B0000, 0x00E9E9E9E9E90000, +0x00EEEEEEEEEE0000, 0x008F8F8F8F8F0000, 0x0001010101010000, 0x003D3D3D3D3D0000 }; + +const u64bit Camellia_SBOX3[256] = { +0x3800383800383800, 0x4100414100414100, 0x1600161600161600, 0x7600767600767600, +0xD900D9D900D9D900, 0x9300939300939300, 0x6000606000606000, 0xF200F2F200F2F200, +0x7200727200727200, 0xC200C2C200C2C200, 0xAB00ABAB00ABAB00, 0x9A009A9A009A9A00, +0x7500757500757500, 0x0600060600060600, 0x5700575700575700, 0xA000A0A000A0A000, +0x9100919100919100, 0xF700F7F700F7F700, 0xB500B5B500B5B500, 0xC900C9C900C9C900, +0xA200A2A200A2A200, 0x8C008C8C008C8C00, 0xD200D2D200D2D200, 0x9000909000909000, +0xF600F6F600F6F600, 0x0700070700070700, 0xA700A7A700A7A700, 0x2700272700272700, +0x8E008E8E008E8E00, 0xB200B2B200B2B200, 0x4900494900494900, 0xDE00DEDE00DEDE00, +0x4300434300434300, 0x5C005C5C005C5C00, 0xD700D7D700D7D700, 0xC700C7C700C7C700, +0x3E003E3E003E3E00, 0xF500F5F500F5F500, 0x8F008F8F008F8F00, 0x6700676700676700, +0x1F001F1F001F1F00, 0x1800181800181800, 0x6E006E6E006E6E00, 0xAF00AFAF00AFAF00, +0x2F002F2F002F2F00, 0xE200E2E200E2E200, 0x8500858500858500, 0x0D000D0D000D0D00, +0x5300535300535300, 0xF000F0F000F0F000, 0x9C009C9C009C9C00, 0x6500656500656500, +0xEA00EAEA00EAEA00, 0xA300A3A300A3A300, 0xAE00AEAE00AEAE00, 0x9E009E9E009E9E00, +0xEC00ECEC00ECEC00, 0x8000808000808000, 0x2D002D2D002D2D00, 0x6B006B6B006B6B00, +0xA800A8A800A8A800, 0x2B002B2B002B2B00, 0x3600363600363600, 0xA600A6A600A6A600, +0xC500C5C500C5C500, 0x8600868600868600, 0x4D004D4D004D4D00, 0x3300333300333300, +0xFD00FDFD00FDFD00, 0x6600666600666600, 0x5800585800585800, 0x9600969600969600, +0x3A003A3A003A3A00, 0x0900090900090900, 0x9500959500959500, 0x1000101000101000, +0x7800787800787800, 0xD800D8D800D8D800, 0x4200424200424200, 0xCC00CCCC00CCCC00, +0xEF00EFEF00EFEF00, 0x2600262600262600, 0xE500E5E500E5E500, 0x6100616100616100, +0x1A001A1A001A1A00, 0x3F003F3F003F3F00, 0x3B003B3B003B3B00, 0x8200828200828200, +0xB600B6B600B6B600, 0xDB00DBDB00DBDB00, 0xD400D4D400D4D400, 0x9800989800989800, +0xE800E8E800E8E800, 0x8B008B8B008B8B00, 0x0200020200020200, 0xEB00EBEB00EBEB00, +0x0A000A0A000A0A00, 0x2C002C2C002C2C00, 0x1D001D1D001D1D00, 0xB000B0B000B0B000, +0x6F006F6F006F6F00, 0x8D008D8D008D8D00, 0x8800888800888800, 0x0E000E0E000E0E00, +0x1900191900191900, 0x8700878700878700, 0x4E004E4E004E4E00, 0x0B000B0B000B0B00, +0xA900A9A900A9A900, 0x0C000C0C000C0C00, 0x7900797900797900, 0x1100111100111100, +0x7F007F7F007F7F00, 0x2200222200222200, 0xE700E7E700E7E700, 0x5900595900595900, +0xE100E1E100E1E100, 0xDA00DADA00DADA00, 0x3D003D3D003D3D00, 0xC800C8C800C8C800, +0x1200121200121200, 0x0400040400040400, 0x7400747400747400, 0x5400545400545400, +0x3000303000303000, 0x7E007E7E007E7E00, 0xB400B4B400B4B400, 0x2800282800282800, +0x5500555500555500, 0x6800686800686800, 0x5000505000505000, 0xBE00BEBE00BEBE00, +0xD000D0D000D0D000, 0xC400C4C400C4C400, 0x3100313100313100, 0xCB00CBCB00CBCB00, +0x2A002A2A002A2A00, 0xAD00ADAD00ADAD00, 0x0F000F0F000F0F00, 0xCA00CACA00CACA00, +0x7000707000707000, 0xFF00FFFF00FFFF00, 0x3200323200323200, 0x6900696900696900, +0x0800080800080800, 0x6200626200626200, 0x0000000000000000, 0x2400242400242400, +0xD100D1D100D1D100, 0xFB00FBFB00FBFB00, 0xBA00BABA00BABA00, 0xED00EDED00EDED00, +0x4500454500454500, 0x8100818100818100, 0x7300737300737300, 0x6D006D6D006D6D00, +0x8400848400848400, 0x9F009F9F009F9F00, 0xEE00EEEE00EEEE00, 0x4A004A4A004A4A00, +0xC300C3C300C3C300, 0x2E002E2E002E2E00, 0xC100C1C100C1C100, 0x0100010100010100, +0xE600E6E600E6E600, 0x2500252500252500, 0x4800484800484800, 0x9900999900999900, +0xB900B9B900B9B900, 0xB300B3B300B3B300, 0x7B007B7B007B7B00, 0xF900F9F900F9F900, +0xCE00CECE00CECE00, 0xBF00BFBF00BFBF00, 0xDF00DFDF00DFDF00, 0x7100717100717100, +0x2900292900292900, 0xCD00CDCD00CDCD00, 0x6C006C6C006C6C00, 0x1300131300131300, +0x6400646400646400, 0x9B009B9B009B9B00, 0x6300636300636300, 0x9D009D9D009D9D00, +0xC000C0C000C0C000, 0x4B004B4B004B4B00, 0xB700B7B700B7B700, 0xA500A5A500A5A500, +0x8900898900898900, 0x5F005F5F005F5F00, 0xB100B1B100B1B100, 0x1700171700171700, +0xF400F4F400F4F400, 0xBC00BCBC00BCBC00, 0xD300D3D300D3D300, 0x4600464600464600, +0xCF00CFCF00CFCF00, 0x3700373700373700, 0x5E005E5E005E5E00, 0x4700474700474700, +0x9400949400949400, 0xFA00FAFA00FAFA00, 0xFC00FCFC00FCFC00, 0x5B005B5B005B5B00, +0x9700979700979700, 0xFE00FEFE00FEFE00, 0x5A005A5A005A5A00, 0xAC00ACAC00ACAC00, +0x3C003C3C003C3C00, 0x4C004C4C004C4C00, 0x0300030300030300, 0x3500353500353500, +0xF300F3F300F3F300, 0x2300232300232300, 0xB800B8B800B8B800, 0x5D005D5D005D5D00, +0x6A006A6A006A6A00, 0x9200929200929200, 0xD500D5D500D5D500, 0x2100212100212100, +0x4400444400444400, 0x5100515100515100, 0xC600C6C600C6C600, 0x7D007D7D007D7D00, +0x3900393900393900, 0x8300838300838300, 0xDC00DCDC00DCDC00, 0xAA00AAAA00AAAA00, +0x7C007C7C007C7C00, 0x7700777700777700, 0x5600565600565600, 0x0500050500050500, +0x1B001B1B001B1B00, 0xA400A4A400A4A400, 0x1500151500151500, 0x3400343400343400, +0x1E001E1E001E1E00, 0x1C001C1C001C1C00, 0xF800F8F800F8F800, 0x5200525200525200, +0x2000202000202000, 0x1400141400141400, 0xE900E9E900E9E900, 0xBD00BDBD00BDBD00, +0xDD00DDDD00DDDD00, 0xE400E4E400E4E400, 0xA100A1A100A1A100, 0xE000E0E000E0E000, +0x8A008A8A008A8A00, 0xF100F1F100F1F100, 0xD600D6D600D6D600, 0x7A007A7A007A7A00, +0xBB00BBBB00BBBB00, 0xE300E3E300E3E300, 0x4000404000404000, 0x4F004F4F004F4F00 }; + +const u64bit Camellia_SBOX4[256] = { +0x7070007000007070, 0x2C2C002C00002C2C, 0xB3B300B30000B3B3, 0xC0C000C00000C0C0, +0xE4E400E40000E4E4, 0x5757005700005757, 0xEAEA00EA0000EAEA, 0xAEAE00AE0000AEAE, +0x2323002300002323, 0x6B6B006B00006B6B, 0x4545004500004545, 0xA5A500A50000A5A5, +0xEDED00ED0000EDED, 0x4F4F004F00004F4F, 0x1D1D001D00001D1D, 0x9292009200009292, +0x8686008600008686, 0xAFAF00AF0000AFAF, 0x7C7C007C00007C7C, 0x1F1F001F00001F1F, +0x3E3E003E00003E3E, 0xDCDC00DC0000DCDC, 0x5E5E005E00005E5E, 0x0B0B000B00000B0B, +0xA6A600A60000A6A6, 0x3939003900003939, 0xD5D500D50000D5D5, 0x5D5D005D00005D5D, +0xD9D900D90000D9D9, 0x5A5A005A00005A5A, 0x5151005100005151, 0x6C6C006C00006C6C, +0x8B8B008B00008B8B, 0x9A9A009A00009A9A, 0xFBFB00FB0000FBFB, 0xB0B000B00000B0B0, +0x7474007400007474, 0x2B2B002B00002B2B, 0xF0F000F00000F0F0, 0x8484008400008484, +0xDFDF00DF0000DFDF, 0xCBCB00CB0000CBCB, 0x3434003400003434, 0x7676007600007676, +0x6D6D006D00006D6D, 0xA9A900A90000A9A9, 0xD1D100D10000D1D1, 0x0404000400000404, +0x1414001400001414, 0x3A3A003A00003A3A, 0xDEDE00DE0000DEDE, 0x1111001100001111, +0x3232003200003232, 0x9C9C009C00009C9C, 0x5353005300005353, 0xF2F200F20000F2F2, +0xFEFE00FE0000FEFE, 0xCFCF00CF0000CFCF, 0xC3C300C30000C3C3, 0x7A7A007A00007A7A, +0x2424002400002424, 0xE8E800E80000E8E8, 0x6060006000006060, 0x6969006900006969, +0xAAAA00AA0000AAAA, 0xA0A000A00000A0A0, 0xA1A100A10000A1A1, 0x6262006200006262, +0x5454005400005454, 0x1E1E001E00001E1E, 0xE0E000E00000E0E0, 0x6464006400006464, +0x1010001000001010, 0x0000000000000000, 0xA3A300A30000A3A3, 0x7575007500007575, +0x8A8A008A00008A8A, 0xE6E600E60000E6E6, 0x0909000900000909, 0xDDDD00DD0000DDDD, +0x8787008700008787, 0x8383008300008383, 0xCDCD00CD0000CDCD, 0x9090009000009090, +0x7373007300007373, 0xF6F600F60000F6F6, 0x9D9D009D00009D9D, 0xBFBF00BF0000BFBF, +0x5252005200005252, 0xD8D800D80000D8D8, 0xC8C800C80000C8C8, 0xC6C600C60000C6C6, +0x8181008100008181, 0x6F6F006F00006F6F, 0x1313001300001313, 0x6363006300006363, +0xE9E900E90000E9E9, 0xA7A700A70000A7A7, 0x9F9F009F00009F9F, 0xBCBC00BC0000BCBC, +0x2929002900002929, 0xF9F900F90000F9F9, 0x2F2F002F00002F2F, 0xB4B400B40000B4B4, +0x7878007800007878, 0x0606000600000606, 0xE7E700E70000E7E7, 0x7171007100007171, +0xD4D400D40000D4D4, 0xABAB00AB0000ABAB, 0x8888008800008888, 0x8D8D008D00008D8D, +0x7272007200007272, 0xB9B900B90000B9B9, 0xF8F800F80000F8F8, 0xACAC00AC0000ACAC, +0x3636003600003636, 0x2A2A002A00002A2A, 0x3C3C003C00003C3C, 0xF1F100F10000F1F1, +0x4040004000004040, 0xD3D300D30000D3D3, 0xBBBB00BB0000BBBB, 0x4343004300004343, +0x1515001500001515, 0xADAD00AD0000ADAD, 0x7777007700007777, 0x8080008000008080, +0x8282008200008282, 0xECEC00EC0000ECEC, 0x2727002700002727, 0xE5E500E50000E5E5, +0x8585008500008585, 0x3535003500003535, 0x0C0C000C00000C0C, 0x4141004100004141, +0xEFEF00EF0000EFEF, 0x9393009300009393, 0x1919001900001919, 0x2121002100002121, +0x0E0E000E00000E0E, 0x4E4E004E00004E4E, 0x6565006500006565, 0xBDBD00BD0000BDBD, +0xB8B800B80000B8B8, 0x8F8F008F00008F8F, 0xEBEB00EB0000EBEB, 0xCECE00CE0000CECE, +0x3030003000003030, 0x5F5F005F00005F5F, 0xC5C500C50000C5C5, 0x1A1A001A00001A1A, +0xE1E100E10000E1E1, 0xCACA00CA0000CACA, 0x4747004700004747, 0x3D3D003D00003D3D, +0x0101000100000101, 0xD6D600D60000D6D6, 0x5656005600005656, 0x4D4D004D00004D4D, +0x0D0D000D00000D0D, 0x6666006600006666, 0xCCCC00CC0000CCCC, 0x2D2D002D00002D2D, +0x1212001200001212, 0x2020002000002020, 0xB1B100B10000B1B1, 0x9999009900009999, +0x4C4C004C00004C4C, 0xC2C200C20000C2C2, 0x7E7E007E00007E7E, 0x0505000500000505, +0xB7B700B70000B7B7, 0x3131003100003131, 0x1717001700001717, 0xD7D700D70000D7D7, +0x5858005800005858, 0x6161006100006161, 0x1B1B001B00001B1B, 0x1C1C001C00001C1C, +0x0F0F000F00000F0F, 0x1616001600001616, 0x1818001800001818, 0x2222002200002222, +0x4444004400004444, 0xB2B200B20000B2B2, 0xB5B500B50000B5B5, 0x9191009100009191, +0x0808000800000808, 0xA8A800A80000A8A8, 0xFCFC00FC0000FCFC, 0x5050005000005050, +0xD0D000D00000D0D0, 0x7D7D007D00007D7D, 0x8989008900008989, 0x9797009700009797, +0x5B5B005B00005B5B, 0x9595009500009595, 0xFFFF00FF0000FFFF, 0xD2D200D20000D2D2, +0xC4C400C40000C4C4, 0x4848004800004848, 0xF7F700F70000F7F7, 0xDBDB00DB0000DBDB, +0x0303000300000303, 0xDADA00DA0000DADA, 0x3F3F003F00003F3F, 0x9494009400009494, +0x5C5C005C00005C5C, 0x0202000200000202, 0x4A4A004A00004A4A, 0x3333003300003333, +0x6767006700006767, 0xF3F300F30000F3F3, 0x7F7F007F00007F7F, 0xE2E200E20000E2E2, +0x9B9B009B00009B9B, 0x2626002600002626, 0x3737003700003737, 0x3B3B003B00003B3B, +0x9696009600009696, 0x4B4B004B00004B4B, 0xBEBE00BE0000BEBE, 0x2E2E002E00002E2E, +0x7979007900007979, 0x8C8C008C00008C8C, 0x6E6E006E00006E6E, 0x8E8E008E00008E8E, +0xF5F500F50000F5F5, 0xB6B600B60000B6B6, 0xFDFD00FD0000FDFD, 0x5959005900005959, +0x9898009800009898, 0x6A6A006A00006A6A, 0x4646004600004646, 0xBABA00BA0000BABA, +0x2525002500002525, 0x4242004200004242, 0xA2A200A20000A2A2, 0xFAFA00FA0000FAFA, +0x0707000700000707, 0x5555005500005555, 0xEEEE00EE0000EEEE, 0x0A0A000A00000A0A, +0x4949004900004949, 0x6868006800006868, 0x3838003800003838, 0xA4A400A40000A4A4, +0x2828002800002828, 0x7B7B007B00007B7B, 0xC9C900C90000C9C9, 0xC1C100C10000C1C1, +0xE3E300E30000E3E3, 0xF4F400F40000F4F4, 0xC7C700C70000C7C7, 0x9E9E009E00009E9E }; + +const u64bit Camellia_SBOX5[256] = { +0x00E0E0E000E0E0E0, 0x0005050500050505, 0x0058585800585858, 0x00D9D9D900D9D9D9, +0x0067676700676767, 0x004E4E4E004E4E4E, 0x0081818100818181, 0x00CBCBCB00CBCBCB, +0x00C9C9C900C9C9C9, 0x000B0B0B000B0B0B, 0x00AEAEAE00AEAEAE, 0x006A6A6A006A6A6A, +0x00D5D5D500D5D5D5, 0x0018181800181818, 0x005D5D5D005D5D5D, 0x0082828200828282, +0x0046464600464646, 0x00DFDFDF00DFDFDF, 0x00D6D6D600D6D6D6, 0x0027272700272727, +0x008A8A8A008A8A8A, 0x0032323200323232, 0x004B4B4B004B4B4B, 0x0042424200424242, +0x00DBDBDB00DBDBDB, 0x001C1C1C001C1C1C, 0x009E9E9E009E9E9E, 0x009C9C9C009C9C9C, +0x003A3A3A003A3A3A, 0x00CACACA00CACACA, 0x0025252500252525, 0x007B7B7B007B7B7B, +0x000D0D0D000D0D0D, 0x0071717100717171, 0x005F5F5F005F5F5F, 0x001F1F1F001F1F1F, +0x00F8F8F800F8F8F8, 0x00D7D7D700D7D7D7, 0x003E3E3E003E3E3E, 0x009D9D9D009D9D9D, +0x007C7C7C007C7C7C, 0x0060606000606060, 0x00B9B9B900B9B9B9, 0x00BEBEBE00BEBEBE, +0x00BCBCBC00BCBCBC, 0x008B8B8B008B8B8B, 0x0016161600161616, 0x0034343400343434, +0x004D4D4D004D4D4D, 0x00C3C3C300C3C3C3, 0x0072727200727272, 0x0095959500959595, +0x00ABABAB00ABABAB, 0x008E8E8E008E8E8E, 0x00BABABA00BABABA, 0x007A7A7A007A7A7A, +0x00B3B3B300B3B3B3, 0x0002020200020202, 0x00B4B4B400B4B4B4, 0x00ADADAD00ADADAD, +0x00A2A2A200A2A2A2, 0x00ACACAC00ACACAC, 0x00D8D8D800D8D8D8, 0x009A9A9A009A9A9A, +0x0017171700171717, 0x001A1A1A001A1A1A, 0x0035353500353535, 0x00CCCCCC00CCCCCC, +0x00F7F7F700F7F7F7, 0x0099999900999999, 0x0061616100616161, 0x005A5A5A005A5A5A, +0x00E8E8E800E8E8E8, 0x0024242400242424, 0x0056565600565656, 0x0040404000404040, +0x00E1E1E100E1E1E1, 0x0063636300636363, 0x0009090900090909, 0x0033333300333333, +0x00BFBFBF00BFBFBF, 0x0098989800989898, 0x0097979700979797, 0x0085858500858585, +0x0068686800686868, 0x00FCFCFC00FCFCFC, 0x00ECECEC00ECECEC, 0x000A0A0A000A0A0A, +0x00DADADA00DADADA, 0x006F6F6F006F6F6F, 0x0053535300535353, 0x0062626200626262, +0x00A3A3A300A3A3A3, 0x002E2E2E002E2E2E, 0x0008080800080808, 0x00AFAFAF00AFAFAF, +0x0028282800282828, 0x00B0B0B000B0B0B0, 0x0074747400747474, 0x00C2C2C200C2C2C2, +0x00BDBDBD00BDBDBD, 0x0036363600363636, 0x0022222200222222, 0x0038383800383838, +0x0064646400646464, 0x001E1E1E001E1E1E, 0x0039393900393939, 0x002C2C2C002C2C2C, +0x00A6A6A600A6A6A6, 0x0030303000303030, 0x00E5E5E500E5E5E5, 0x0044444400444444, +0x00FDFDFD00FDFDFD, 0x0088888800888888, 0x009F9F9F009F9F9F, 0x0065656500656565, +0x0087878700878787, 0x006B6B6B006B6B6B, 0x00F4F4F400F4F4F4, 0x0023232300232323, +0x0048484800484848, 0x0010101000101010, 0x00D1D1D100D1D1D1, 0x0051515100515151, +0x00C0C0C000C0C0C0, 0x00F9F9F900F9F9F9, 0x00D2D2D200D2D2D2, 0x00A0A0A000A0A0A0, +0x0055555500555555, 0x00A1A1A100A1A1A1, 0x0041414100414141, 0x00FAFAFA00FAFAFA, +0x0043434300434343, 0x0013131300131313, 0x00C4C4C400C4C4C4, 0x002F2F2F002F2F2F, +0x00A8A8A800A8A8A8, 0x00B6B6B600B6B6B6, 0x003C3C3C003C3C3C, 0x002B2B2B002B2B2B, +0x00C1C1C100C1C1C1, 0x00FFFFFF00FFFFFF, 0x00C8C8C800C8C8C8, 0x00A5A5A500A5A5A5, +0x0020202000202020, 0x0089898900898989, 0x0000000000000000, 0x0090909000909090, +0x0047474700474747, 0x00EFEFEF00EFEFEF, 0x00EAEAEA00EAEAEA, 0x00B7B7B700B7B7B7, +0x0015151500151515, 0x0006060600060606, 0x00CDCDCD00CDCDCD, 0x00B5B5B500B5B5B5, +0x0012121200121212, 0x007E7E7E007E7E7E, 0x00BBBBBB00BBBBBB, 0x0029292900292929, +0x000F0F0F000F0F0F, 0x00B8B8B800B8B8B8, 0x0007070700070707, 0x0004040400040404, +0x009B9B9B009B9B9B, 0x0094949400949494, 0x0021212100212121, 0x0066666600666666, +0x00E6E6E600E6E6E6, 0x00CECECE00CECECE, 0x00EDEDED00EDEDED, 0x00E7E7E700E7E7E7, +0x003B3B3B003B3B3B, 0x00FEFEFE00FEFEFE, 0x007F7F7F007F7F7F, 0x00C5C5C500C5C5C5, +0x00A4A4A400A4A4A4, 0x0037373700373737, 0x00B1B1B100B1B1B1, 0x004C4C4C004C4C4C, +0x0091919100919191, 0x006E6E6E006E6E6E, 0x008D8D8D008D8D8D, 0x0076767600767676, +0x0003030300030303, 0x002D2D2D002D2D2D, 0x00DEDEDE00DEDEDE, 0x0096969600969696, +0x0026262600262626, 0x007D7D7D007D7D7D, 0x00C6C6C600C6C6C6, 0x005C5C5C005C5C5C, +0x00D3D3D300D3D3D3, 0x00F2F2F200F2F2F2, 0x004F4F4F004F4F4F, 0x0019191900191919, +0x003F3F3F003F3F3F, 0x00DCDCDC00DCDCDC, 0x0079797900797979, 0x001D1D1D001D1D1D, +0x0052525200525252, 0x00EBEBEB00EBEBEB, 0x00F3F3F300F3F3F3, 0x006D6D6D006D6D6D, +0x005E5E5E005E5E5E, 0x00FBFBFB00FBFBFB, 0x0069696900696969, 0x00B2B2B200B2B2B2, +0x00F0F0F000F0F0F0, 0x0031313100313131, 0x000C0C0C000C0C0C, 0x00D4D4D400D4D4D4, +0x00CFCFCF00CFCFCF, 0x008C8C8C008C8C8C, 0x00E2E2E200E2E2E2, 0x0075757500757575, +0x00A9A9A900A9A9A9, 0x004A4A4A004A4A4A, 0x0057575700575757, 0x0084848400848484, +0x0011111100111111, 0x0045454500454545, 0x001B1B1B001B1B1B, 0x00F5F5F500F5F5F5, +0x00E4E4E400E4E4E4, 0x000E0E0E000E0E0E, 0x0073737300737373, 0x00AAAAAA00AAAAAA, +0x00F1F1F100F1F1F1, 0x00DDDDDD00DDDDDD, 0x0059595900595959, 0x0014141400141414, +0x006C6C6C006C6C6C, 0x0092929200929292, 0x0054545400545454, 0x00D0D0D000D0D0D0, +0x0078787800787878, 0x0070707000707070, 0x00E3E3E300E3E3E3, 0x0049494900494949, +0x0080808000808080, 0x0050505000505050, 0x00A7A7A700A7A7A7, 0x00F6F6F600F6F6F6, +0x0077777700777777, 0x0093939300939393, 0x0086868600868686, 0x0083838300838383, +0x002A2A2A002A2A2A, 0x00C7C7C700C7C7C7, 0x005B5B5B005B5B5B, 0x00E9E9E900E9E9E9, +0x00EEEEEE00EEEEEE, 0x008F8F8F008F8F8F, 0x0001010100010101, 0x003D3D3D003D3D3D }; + +const u64bit Camellia_SBOX6[256] = { +0x3800383838003838, 0x4100414141004141, 0x1600161616001616, 0x7600767676007676, +0xD900D9D9D900D9D9, 0x9300939393009393, 0x6000606060006060, 0xF200F2F2F200F2F2, +0x7200727272007272, 0xC200C2C2C200C2C2, 0xAB00ABABAB00ABAB, 0x9A009A9A9A009A9A, +0x7500757575007575, 0x0600060606000606, 0x5700575757005757, 0xA000A0A0A000A0A0, +0x9100919191009191, 0xF700F7F7F700F7F7, 0xB500B5B5B500B5B5, 0xC900C9C9C900C9C9, +0xA200A2A2A200A2A2, 0x8C008C8C8C008C8C, 0xD200D2D2D200D2D2, 0x9000909090009090, +0xF600F6F6F600F6F6, 0x0700070707000707, 0xA700A7A7A700A7A7, 0x2700272727002727, +0x8E008E8E8E008E8E, 0xB200B2B2B200B2B2, 0x4900494949004949, 0xDE00DEDEDE00DEDE, +0x4300434343004343, 0x5C005C5C5C005C5C, 0xD700D7D7D700D7D7, 0xC700C7C7C700C7C7, +0x3E003E3E3E003E3E, 0xF500F5F5F500F5F5, 0x8F008F8F8F008F8F, 0x6700676767006767, +0x1F001F1F1F001F1F, 0x1800181818001818, 0x6E006E6E6E006E6E, 0xAF00AFAFAF00AFAF, +0x2F002F2F2F002F2F, 0xE200E2E2E200E2E2, 0x8500858585008585, 0x0D000D0D0D000D0D, +0x5300535353005353, 0xF000F0F0F000F0F0, 0x9C009C9C9C009C9C, 0x6500656565006565, +0xEA00EAEAEA00EAEA, 0xA300A3A3A300A3A3, 0xAE00AEAEAE00AEAE, 0x9E009E9E9E009E9E, +0xEC00ECECEC00ECEC, 0x8000808080008080, 0x2D002D2D2D002D2D, 0x6B006B6B6B006B6B, +0xA800A8A8A800A8A8, 0x2B002B2B2B002B2B, 0x3600363636003636, 0xA600A6A6A600A6A6, +0xC500C5C5C500C5C5, 0x8600868686008686, 0x4D004D4D4D004D4D, 0x3300333333003333, +0xFD00FDFDFD00FDFD, 0x6600666666006666, 0x5800585858005858, 0x9600969696009696, +0x3A003A3A3A003A3A, 0x0900090909000909, 0x9500959595009595, 0x1000101010001010, +0x7800787878007878, 0xD800D8D8D800D8D8, 0x4200424242004242, 0xCC00CCCCCC00CCCC, +0xEF00EFEFEF00EFEF, 0x2600262626002626, 0xE500E5E5E500E5E5, 0x6100616161006161, +0x1A001A1A1A001A1A, 0x3F003F3F3F003F3F, 0x3B003B3B3B003B3B, 0x8200828282008282, +0xB600B6B6B600B6B6, 0xDB00DBDBDB00DBDB, 0xD400D4D4D400D4D4, 0x9800989898009898, +0xE800E8E8E800E8E8, 0x8B008B8B8B008B8B, 0x0200020202000202, 0xEB00EBEBEB00EBEB, +0x0A000A0A0A000A0A, 0x2C002C2C2C002C2C, 0x1D001D1D1D001D1D, 0xB000B0B0B000B0B0, +0x6F006F6F6F006F6F, 0x8D008D8D8D008D8D, 0x8800888888008888, 0x0E000E0E0E000E0E, +0x1900191919001919, 0x8700878787008787, 0x4E004E4E4E004E4E, 0x0B000B0B0B000B0B, +0xA900A9A9A900A9A9, 0x0C000C0C0C000C0C, 0x7900797979007979, 0x1100111111001111, +0x7F007F7F7F007F7F, 0x2200222222002222, 0xE700E7E7E700E7E7, 0x5900595959005959, +0xE100E1E1E100E1E1, 0xDA00DADADA00DADA, 0x3D003D3D3D003D3D, 0xC800C8C8C800C8C8, +0x1200121212001212, 0x0400040404000404, 0x7400747474007474, 0x5400545454005454, +0x3000303030003030, 0x7E007E7E7E007E7E, 0xB400B4B4B400B4B4, 0x2800282828002828, +0x5500555555005555, 0x6800686868006868, 0x5000505050005050, 0xBE00BEBEBE00BEBE, +0xD000D0D0D000D0D0, 0xC400C4C4C400C4C4, 0x3100313131003131, 0xCB00CBCBCB00CBCB, +0x2A002A2A2A002A2A, 0xAD00ADADAD00ADAD, 0x0F000F0F0F000F0F, 0xCA00CACACA00CACA, +0x7000707070007070, 0xFF00FFFFFF00FFFF, 0x3200323232003232, 0x6900696969006969, +0x0800080808000808, 0x6200626262006262, 0x0000000000000000, 0x2400242424002424, +0xD100D1D1D100D1D1, 0xFB00FBFBFB00FBFB, 0xBA00BABABA00BABA, 0xED00EDEDED00EDED, +0x4500454545004545, 0x8100818181008181, 0x7300737373007373, 0x6D006D6D6D006D6D, +0x8400848484008484, 0x9F009F9F9F009F9F, 0xEE00EEEEEE00EEEE, 0x4A004A4A4A004A4A, +0xC300C3C3C300C3C3, 0x2E002E2E2E002E2E, 0xC100C1C1C100C1C1, 0x0100010101000101, +0xE600E6E6E600E6E6, 0x2500252525002525, 0x4800484848004848, 0x9900999999009999, +0xB900B9B9B900B9B9, 0xB300B3B3B300B3B3, 0x7B007B7B7B007B7B, 0xF900F9F9F900F9F9, +0xCE00CECECE00CECE, 0xBF00BFBFBF00BFBF, 0xDF00DFDFDF00DFDF, 0x7100717171007171, +0x2900292929002929, 0xCD00CDCDCD00CDCD, 0x6C006C6C6C006C6C, 0x1300131313001313, +0x6400646464006464, 0x9B009B9B9B009B9B, 0x6300636363006363, 0x9D009D9D9D009D9D, +0xC000C0C0C000C0C0, 0x4B004B4B4B004B4B, 0xB700B7B7B700B7B7, 0xA500A5A5A500A5A5, +0x8900898989008989, 0x5F005F5F5F005F5F, 0xB100B1B1B100B1B1, 0x1700171717001717, +0xF400F4F4F400F4F4, 0xBC00BCBCBC00BCBC, 0xD300D3D3D300D3D3, 0x4600464646004646, +0xCF00CFCFCF00CFCF, 0x3700373737003737, 0x5E005E5E5E005E5E, 0x4700474747004747, +0x9400949494009494, 0xFA00FAFAFA00FAFA, 0xFC00FCFCFC00FCFC, 0x5B005B5B5B005B5B, +0x9700979797009797, 0xFE00FEFEFE00FEFE, 0x5A005A5A5A005A5A, 0xAC00ACACAC00ACAC, +0x3C003C3C3C003C3C, 0x4C004C4C4C004C4C, 0x0300030303000303, 0x3500353535003535, +0xF300F3F3F300F3F3, 0x2300232323002323, 0xB800B8B8B800B8B8, 0x5D005D5D5D005D5D, +0x6A006A6A6A006A6A, 0x9200929292009292, 0xD500D5D5D500D5D5, 0x2100212121002121, +0x4400444444004444, 0x5100515151005151, 0xC600C6C6C600C6C6, 0x7D007D7D7D007D7D, +0x3900393939003939, 0x8300838383008383, 0xDC00DCDCDC00DCDC, 0xAA00AAAAAA00AAAA, +0x7C007C7C7C007C7C, 0x7700777777007777, 0x5600565656005656, 0x0500050505000505, +0x1B001B1B1B001B1B, 0xA400A4A4A400A4A4, 0x1500151515001515, 0x3400343434003434, +0x1E001E1E1E001E1E, 0x1C001C1C1C001C1C, 0xF800F8F8F800F8F8, 0x5200525252005252, +0x2000202020002020, 0x1400141414001414, 0xE900E9E9E900E9E9, 0xBD00BDBDBD00BDBD, +0xDD00DDDDDD00DDDD, 0xE400E4E4E400E4E4, 0xA100A1A1A100A1A1, 0xE000E0E0E000E0E0, +0x8A008A8A8A008A8A, 0xF100F1F1F100F1F1, 0xD600D6D6D600D6D6, 0x7A007A7A7A007A7A, +0xBB00BBBBBB00BBBB, 0xE300E3E3E300E3E3, 0x4000404040004040, 0x4F004F4F4F004F4F }; + +const u64bit Camellia_SBOX7[256] = { +0x7070007070700070, 0x2C2C002C2C2C002C, 0xB3B300B3B3B300B3, 0xC0C000C0C0C000C0, +0xE4E400E4E4E400E4, 0x5757005757570057, 0xEAEA00EAEAEA00EA, 0xAEAE00AEAEAE00AE, +0x2323002323230023, 0x6B6B006B6B6B006B, 0x4545004545450045, 0xA5A500A5A5A500A5, +0xEDED00EDEDED00ED, 0x4F4F004F4F4F004F, 0x1D1D001D1D1D001D, 0x9292009292920092, +0x8686008686860086, 0xAFAF00AFAFAF00AF, 0x7C7C007C7C7C007C, 0x1F1F001F1F1F001F, +0x3E3E003E3E3E003E, 0xDCDC00DCDCDC00DC, 0x5E5E005E5E5E005E, 0x0B0B000B0B0B000B, +0xA6A600A6A6A600A6, 0x3939003939390039, 0xD5D500D5D5D500D5, 0x5D5D005D5D5D005D, +0xD9D900D9D9D900D9, 0x5A5A005A5A5A005A, 0x5151005151510051, 0x6C6C006C6C6C006C, +0x8B8B008B8B8B008B, 0x9A9A009A9A9A009A, 0xFBFB00FBFBFB00FB, 0xB0B000B0B0B000B0, +0x7474007474740074, 0x2B2B002B2B2B002B, 0xF0F000F0F0F000F0, 0x8484008484840084, +0xDFDF00DFDFDF00DF, 0xCBCB00CBCBCB00CB, 0x3434003434340034, 0x7676007676760076, +0x6D6D006D6D6D006D, 0xA9A900A9A9A900A9, 0xD1D100D1D1D100D1, 0x0404000404040004, +0x1414001414140014, 0x3A3A003A3A3A003A, 0xDEDE00DEDEDE00DE, 0x1111001111110011, +0x3232003232320032, 0x9C9C009C9C9C009C, 0x5353005353530053, 0xF2F200F2F2F200F2, +0xFEFE00FEFEFE00FE, 0xCFCF00CFCFCF00CF, 0xC3C300C3C3C300C3, 0x7A7A007A7A7A007A, +0x2424002424240024, 0xE8E800E8E8E800E8, 0x6060006060600060, 0x6969006969690069, +0xAAAA00AAAAAA00AA, 0xA0A000A0A0A000A0, 0xA1A100A1A1A100A1, 0x6262006262620062, +0x5454005454540054, 0x1E1E001E1E1E001E, 0xE0E000E0E0E000E0, 0x6464006464640064, +0x1010001010100010, 0x0000000000000000, 0xA3A300A3A3A300A3, 0x7575007575750075, +0x8A8A008A8A8A008A, 0xE6E600E6E6E600E6, 0x0909000909090009, 0xDDDD00DDDDDD00DD, +0x8787008787870087, 0x8383008383830083, 0xCDCD00CDCDCD00CD, 0x9090009090900090, +0x7373007373730073, 0xF6F600F6F6F600F6, 0x9D9D009D9D9D009D, 0xBFBF00BFBFBF00BF, +0x5252005252520052, 0xD8D800D8D8D800D8, 0xC8C800C8C8C800C8, 0xC6C600C6C6C600C6, +0x8181008181810081, 0x6F6F006F6F6F006F, 0x1313001313130013, 0x6363006363630063, +0xE9E900E9E9E900E9, 0xA7A700A7A7A700A7, 0x9F9F009F9F9F009F, 0xBCBC00BCBCBC00BC, +0x2929002929290029, 0xF9F900F9F9F900F9, 0x2F2F002F2F2F002F, 0xB4B400B4B4B400B4, +0x7878007878780078, 0x0606000606060006, 0xE7E700E7E7E700E7, 0x7171007171710071, +0xD4D400D4D4D400D4, 0xABAB00ABABAB00AB, 0x8888008888880088, 0x8D8D008D8D8D008D, +0x7272007272720072, 0xB9B900B9B9B900B9, 0xF8F800F8F8F800F8, 0xACAC00ACACAC00AC, +0x3636003636360036, 0x2A2A002A2A2A002A, 0x3C3C003C3C3C003C, 0xF1F100F1F1F100F1, +0x4040004040400040, 0xD3D300D3D3D300D3, 0xBBBB00BBBBBB00BB, 0x4343004343430043, +0x1515001515150015, 0xADAD00ADADAD00AD, 0x7777007777770077, 0x8080008080800080, +0x8282008282820082, 0xECEC00ECECEC00EC, 0x2727002727270027, 0xE5E500E5E5E500E5, +0x8585008585850085, 0x3535003535350035, 0x0C0C000C0C0C000C, 0x4141004141410041, +0xEFEF00EFEFEF00EF, 0x9393009393930093, 0x1919001919190019, 0x2121002121210021, +0x0E0E000E0E0E000E, 0x4E4E004E4E4E004E, 0x6565006565650065, 0xBDBD00BDBDBD00BD, +0xB8B800B8B8B800B8, 0x8F8F008F8F8F008F, 0xEBEB00EBEBEB00EB, 0xCECE00CECECE00CE, +0x3030003030300030, 0x5F5F005F5F5F005F, 0xC5C500C5C5C500C5, 0x1A1A001A1A1A001A, +0xE1E100E1E1E100E1, 0xCACA00CACACA00CA, 0x4747004747470047, 0x3D3D003D3D3D003D, +0x0101000101010001, 0xD6D600D6D6D600D6, 0x5656005656560056, 0x4D4D004D4D4D004D, +0x0D0D000D0D0D000D, 0x6666006666660066, 0xCCCC00CCCCCC00CC, 0x2D2D002D2D2D002D, +0x1212001212120012, 0x2020002020200020, 0xB1B100B1B1B100B1, 0x9999009999990099, +0x4C4C004C4C4C004C, 0xC2C200C2C2C200C2, 0x7E7E007E7E7E007E, 0x0505000505050005, +0xB7B700B7B7B700B7, 0x3131003131310031, 0x1717001717170017, 0xD7D700D7D7D700D7, +0x5858005858580058, 0x6161006161610061, 0x1B1B001B1B1B001B, 0x1C1C001C1C1C001C, +0x0F0F000F0F0F000F, 0x1616001616160016, 0x1818001818180018, 0x2222002222220022, +0x4444004444440044, 0xB2B200B2B2B200B2, 0xB5B500B5B5B500B5, 0x9191009191910091, +0x0808000808080008, 0xA8A800A8A8A800A8, 0xFCFC00FCFCFC00FC, 0x5050005050500050, +0xD0D000D0D0D000D0, 0x7D7D007D7D7D007D, 0x8989008989890089, 0x9797009797970097, +0x5B5B005B5B5B005B, 0x9595009595950095, 0xFFFF00FFFFFF00FF, 0xD2D200D2D2D200D2, +0xC4C400C4C4C400C4, 0x4848004848480048, 0xF7F700F7F7F700F7, 0xDBDB00DBDBDB00DB, +0x0303000303030003, 0xDADA00DADADA00DA, 0x3F3F003F3F3F003F, 0x9494009494940094, +0x5C5C005C5C5C005C, 0x0202000202020002, 0x4A4A004A4A4A004A, 0x3333003333330033, +0x6767006767670067, 0xF3F300F3F3F300F3, 0x7F7F007F7F7F007F, 0xE2E200E2E2E200E2, +0x9B9B009B9B9B009B, 0x2626002626260026, 0x3737003737370037, 0x3B3B003B3B3B003B, +0x9696009696960096, 0x4B4B004B4B4B004B, 0xBEBE00BEBEBE00BE, 0x2E2E002E2E2E002E, +0x7979007979790079, 0x8C8C008C8C8C008C, 0x6E6E006E6E6E006E, 0x8E8E008E8E8E008E, +0xF5F500F5F5F500F5, 0xB6B600B6B6B600B6, 0xFDFD00FDFDFD00FD, 0x5959005959590059, +0x9898009898980098, 0x6A6A006A6A6A006A, 0x4646004646460046, 0xBABA00BABABA00BA, +0x2525002525250025, 0x4242004242420042, 0xA2A200A2A2A200A2, 0xFAFA00FAFAFA00FA, +0x0707000707070007, 0x5555005555550055, 0xEEEE00EEEEEE00EE, 0x0A0A000A0A0A000A, +0x4949004949490049, 0x6868006868680068, 0x3838003838380038, 0xA4A400A4A4A400A4, +0x2828002828280028, 0x7B7B007B7B7B007B, 0xC9C900C9C9C900C9, 0xC1C100C1C1C100C1, +0xE3E300E3E3E300E3, 0xF4F400F4F4F400F4, 0xC7C700C7C7C700C7, 0x9E9E009E9E9E009E }; + +const u64bit Camellia_SBOX8[256] = { +0x7070700070707000, 0x8282820082828200, 0x2C2C2C002C2C2C00, 0xECECEC00ECECEC00, +0xB3B3B300B3B3B300, 0x2727270027272700, 0xC0C0C000C0C0C000, 0xE5E5E500E5E5E500, +0xE4E4E400E4E4E400, 0x8585850085858500, 0x5757570057575700, 0x3535350035353500, +0xEAEAEA00EAEAEA00, 0x0C0C0C000C0C0C00, 0xAEAEAE00AEAEAE00, 0x4141410041414100, +0x2323230023232300, 0xEFEFEF00EFEFEF00, 0x6B6B6B006B6B6B00, 0x9393930093939300, +0x4545450045454500, 0x1919190019191900, 0xA5A5A500A5A5A500, 0x2121210021212100, +0xEDEDED00EDEDED00, 0x0E0E0E000E0E0E00, 0x4F4F4F004F4F4F00, 0x4E4E4E004E4E4E00, +0x1D1D1D001D1D1D00, 0x6565650065656500, 0x9292920092929200, 0xBDBDBD00BDBDBD00, +0x8686860086868600, 0xB8B8B800B8B8B800, 0xAFAFAF00AFAFAF00, 0x8F8F8F008F8F8F00, +0x7C7C7C007C7C7C00, 0xEBEBEB00EBEBEB00, 0x1F1F1F001F1F1F00, 0xCECECE00CECECE00, +0x3E3E3E003E3E3E00, 0x3030300030303000, 0xDCDCDC00DCDCDC00, 0x5F5F5F005F5F5F00, +0x5E5E5E005E5E5E00, 0xC5C5C500C5C5C500, 0x0B0B0B000B0B0B00, 0x1A1A1A001A1A1A00, +0xA6A6A600A6A6A600, 0xE1E1E100E1E1E100, 0x3939390039393900, 0xCACACA00CACACA00, +0xD5D5D500D5D5D500, 0x4747470047474700, 0x5D5D5D005D5D5D00, 0x3D3D3D003D3D3D00, +0xD9D9D900D9D9D900, 0x0101010001010100, 0x5A5A5A005A5A5A00, 0xD6D6D600D6D6D600, +0x5151510051515100, 0x5656560056565600, 0x6C6C6C006C6C6C00, 0x4D4D4D004D4D4D00, +0x8B8B8B008B8B8B00, 0x0D0D0D000D0D0D00, 0x9A9A9A009A9A9A00, 0x6666660066666600, +0xFBFBFB00FBFBFB00, 0xCCCCCC00CCCCCC00, 0xB0B0B000B0B0B000, 0x2D2D2D002D2D2D00, +0x7474740074747400, 0x1212120012121200, 0x2B2B2B002B2B2B00, 0x2020200020202000, +0xF0F0F000F0F0F000, 0xB1B1B100B1B1B100, 0x8484840084848400, 0x9999990099999900, +0xDFDFDF00DFDFDF00, 0x4C4C4C004C4C4C00, 0xCBCBCB00CBCBCB00, 0xC2C2C200C2C2C200, +0x3434340034343400, 0x7E7E7E007E7E7E00, 0x7676760076767600, 0x0505050005050500, +0x6D6D6D006D6D6D00, 0xB7B7B700B7B7B700, 0xA9A9A900A9A9A900, 0x3131310031313100, +0xD1D1D100D1D1D100, 0x1717170017171700, 0x0404040004040400, 0xD7D7D700D7D7D700, +0x1414140014141400, 0x5858580058585800, 0x3A3A3A003A3A3A00, 0x6161610061616100, +0xDEDEDE00DEDEDE00, 0x1B1B1B001B1B1B00, 0x1111110011111100, 0x1C1C1C001C1C1C00, +0x3232320032323200, 0x0F0F0F000F0F0F00, 0x9C9C9C009C9C9C00, 0x1616160016161600, +0x5353530053535300, 0x1818180018181800, 0xF2F2F200F2F2F200, 0x2222220022222200, +0xFEFEFE00FEFEFE00, 0x4444440044444400, 0xCFCFCF00CFCFCF00, 0xB2B2B200B2B2B200, +0xC3C3C300C3C3C300, 0xB5B5B500B5B5B500, 0x7A7A7A007A7A7A00, 0x9191910091919100, +0x2424240024242400, 0x0808080008080800, 0xE8E8E800E8E8E800, 0xA8A8A800A8A8A800, +0x6060600060606000, 0xFCFCFC00FCFCFC00, 0x6969690069696900, 0x5050500050505000, +0xAAAAAA00AAAAAA00, 0xD0D0D000D0D0D000, 0xA0A0A000A0A0A000, 0x7D7D7D007D7D7D00, +0xA1A1A100A1A1A100, 0x8989890089898900, 0x6262620062626200, 0x9797970097979700, +0x5454540054545400, 0x5B5B5B005B5B5B00, 0x1E1E1E001E1E1E00, 0x9595950095959500, +0xE0E0E000E0E0E000, 0xFFFFFF00FFFFFF00, 0x6464640064646400, 0xD2D2D200D2D2D200, +0x1010100010101000, 0xC4C4C400C4C4C400, 0x0000000000000000, 0x4848480048484800, +0xA3A3A300A3A3A300, 0xF7F7F700F7F7F700, 0x7575750075757500, 0xDBDBDB00DBDBDB00, +0x8A8A8A008A8A8A00, 0x0303030003030300, 0xE6E6E600E6E6E600, 0xDADADA00DADADA00, +0x0909090009090900, 0x3F3F3F003F3F3F00, 0xDDDDDD00DDDDDD00, 0x9494940094949400, +0x8787870087878700, 0x5C5C5C005C5C5C00, 0x8383830083838300, 0x0202020002020200, +0xCDCDCD00CDCDCD00, 0x4A4A4A004A4A4A00, 0x9090900090909000, 0x3333330033333300, +0x7373730073737300, 0x6767670067676700, 0xF6F6F600F6F6F600, 0xF3F3F300F3F3F300, +0x9D9D9D009D9D9D00, 0x7F7F7F007F7F7F00, 0xBFBFBF00BFBFBF00, 0xE2E2E200E2E2E200, +0x5252520052525200, 0x9B9B9B009B9B9B00, 0xD8D8D800D8D8D800, 0x2626260026262600, +0xC8C8C800C8C8C800, 0x3737370037373700, 0xC6C6C600C6C6C600, 0x3B3B3B003B3B3B00, +0x8181810081818100, 0x9696960096969600, 0x6F6F6F006F6F6F00, 0x4B4B4B004B4B4B00, +0x1313130013131300, 0xBEBEBE00BEBEBE00, 0x6363630063636300, 0x2E2E2E002E2E2E00, +0xE9E9E900E9E9E900, 0x7979790079797900, 0xA7A7A700A7A7A700, 0x8C8C8C008C8C8C00, +0x9F9F9F009F9F9F00, 0x6E6E6E006E6E6E00, 0xBCBCBC00BCBCBC00, 0x8E8E8E008E8E8E00, +0x2929290029292900, 0xF5F5F500F5F5F500, 0xF9F9F900F9F9F900, 0xB6B6B600B6B6B600, +0x2F2F2F002F2F2F00, 0xFDFDFD00FDFDFD00, 0xB4B4B400B4B4B400, 0x5959590059595900, +0x7878780078787800, 0x9898980098989800, 0x0606060006060600, 0x6A6A6A006A6A6A00, +0xE7E7E700E7E7E700, 0x4646460046464600, 0x7171710071717100, 0xBABABA00BABABA00, +0xD4D4D400D4D4D400, 0x2525250025252500, 0xABABAB00ABABAB00, 0x4242420042424200, +0x8888880088888800, 0xA2A2A200A2A2A200, 0x8D8D8D008D8D8D00, 0xFAFAFA00FAFAFA00, +0x7272720072727200, 0x0707070007070700, 0xB9B9B900B9B9B900, 0x5555550055555500, +0xF8F8F800F8F8F800, 0xEEEEEE00EEEEEE00, 0xACACAC00ACACAC00, 0x0A0A0A000A0A0A00, +0x3636360036363600, 0x4949490049494900, 0x2A2A2A002A2A2A00, 0x6868680068686800, +0x3C3C3C003C3C3C00, 0x3838380038383800, 0xF1F1F100F1F1F100, 0xA4A4A400A4A4A400, +0x4040400040404000, 0x2828280028282800, 0xD3D3D300D3D3D300, 0x7B7B7B007B7B7B00, +0xBBBBBB00BBBBBB00, 0xC9C9C900C9C9C900, 0x4343430043434300, 0xC1C1C100C1C1C100, +0x1515150015151500, 0xE3E3E300E3E3E300, 0xADADAD00ADADAD00, 0xF4F4F400F4F4F400, +0x7777770077777700, 0xC7C7C700C7C7C700, 0x8080800080808000, 0x9E9E9E009E9E9E00 }; + +} + +#endif diff --git a/src/block/camellia/info.txt b/src/block/camellia/info.txt index cdb7b3d25..eb8d6c411 100644 --- a/src/block/camellia/info.txt +++ b/src/block/camellia/info.txt @@ -1 +1,9 @@ define CAMELLIA + +<header:internal> +camellia_sbox.h +</header:internal> + +<header:public> +camellia.h +</header:public> diff --git a/src/block/cast/cast128.cpp b/src/block/cast/cast128.cpp index 24469e025..d64523c8b 100644 --- a/src/block/cast/cast128.cpp +++ b/src/block/cast/cast128.cpp @@ -16,7 +16,7 @@ namespace { /* * CAST-128 Round Type 1 */ -inline void R1(u32bit& L, u32bit R, u32bit MK, u32bit RK) +inline void R1(u32bit& L, u32bit R, u32bit MK, byte RK) { u32bit T = rotate_left(MK + R, RK); L ^= (CAST_SBOX1[get_byte(0, T)] ^ CAST_SBOX2[get_byte(1, T)]) - @@ -26,7 +26,7 @@ inline void R1(u32bit& L, u32bit R, u32bit MK, u32bit RK) /* * CAST-128 Round Type 2 */ -inline void R2(u32bit& L, u32bit R, u32bit MK, u32bit RK) +inline void R2(u32bit& L, u32bit R, u32bit MK, byte RK) { u32bit T = rotate_left(MK ^ R, RK); L ^= (CAST_SBOX1[get_byte(0, T)] - CAST_SBOX2[get_byte(1, T)] + @@ -36,7 +36,7 @@ inline void R2(u32bit& L, u32bit R, u32bit MK, u32bit RK) /* * CAST-128 Round Type 3 */ -inline void R3(u32bit& L, u32bit R, u32bit MK, u32bit RK) +inline void R3(u32bit& L, u32bit R, u32bit MK, byte RK) { u32bit T = rotate_left(MK - R, RK); L ^= ((CAST_SBOX1[get_byte(0, T)] + CAST_SBOX2[get_byte(1, T)]) ^ @@ -118,23 +118,27 @@ void CAST_128::decrypt_n(const byte in[], byte out[], size_t blocks) const */ void CAST_128::key_schedule(const byte key[], size_t length) { - clear(); - SecureVector<u32bit> X(4); - for(size_t j = 0; j != length; ++j) - X[j/4] = (X[j/4] << 8) + key[j]; + MK.resize(48); + RK.resize(48); + + secure_vector<u32bit> X(4); + for(size_t i = 0; i != length; ++i) + X[i/4] = (X[i/4] << 8) + key[i]; cast_ks(MK, X); - cast_ks(RK, X); - for(size_t j = 0; j != 16; ++j) - RK[j] %= 32; + secure_vector<u32bit> RK32(48); + cast_ks(RK32, X); + + for(size_t i = 0; i != 16; ++i) + RK[i] = RK32[i] % 32; } /* * S-Box Based Key Expansion */ -void CAST_128::cast_ks(MemoryRegion<u32bit>& K, - MemoryRegion<u32bit>& X) +void CAST_128::cast_ks(secure_vector<u32bit>& K, + secure_vector<u32bit>& X) { class ByteReader { @@ -145,7 +149,7 @@ void CAST_128::cast_ks(MemoryRegion<u32bit>& K, const u32bit* X; }; - SecureVector<u32bit> Z(4); + secure_vector<u32bit> Z(4); ByteReader x(&X[0]), z(&Z[0]); Z[0] = X[0] ^ S5[x(13)] ^ S6[x(15)] ^ S7[x(12)] ^ S8[x(14)] ^ S7[x( 8)]; diff --git a/src/block/cast/cast128.h b/src/block/cast/cast128.h index 10c646c94..f3f23b14a 100644 --- a/src/block/cast/cast128.h +++ b/src/block/cast/cast128.h @@ -21,23 +21,23 @@ class BOTAN_DLL CAST_128 : public Block_Cipher_Fixed_Params<8, 11, 16> void encrypt_n(const byte in[], byte out[], size_t blocks) const; void decrypt_n(const byte in[], byte out[], size_t blocks) const; - void clear() { zeroise(MK); zeroise(RK); } + void clear() { MK.clear(); RK.clear(); } std::string name() const { return "CAST-128"; } BlockCipher* clone() const { return new CAST_128; } - CAST_128() : MK(16), RK(16) {} private: void key_schedule(const byte[], size_t); - static void cast_ks(MemoryRegion<u32bit>& ks, - MemoryRegion<u32bit>& user_key); + static void cast_ks(secure_vector<u32bit>& ks, + secure_vector<u32bit>& user_key); static const u32bit S5[256]; static const u32bit S6[256]; static const u32bit S7[256]; static const u32bit S8[256]; - SecureVector<u32bit> MK, RK; + secure_vector<u32bit> MK; + secure_vector<byte> RK; }; extern const u32bit CAST_SBOX1[256]; diff --git a/src/block/cast/cast256.cpp b/src/block/cast/cast256.cpp index 8be0a8dd6..9476d3faf 100644 --- a/src/block/cast/cast256.cpp +++ b/src/block/cast/cast256.cpp @@ -138,40 +138,43 @@ void CAST_256::decrypt_n(const byte in[], byte out[], size_t blocks) const */ void CAST_256::key_schedule(const byte key[], size_t length) { - SecureVector<u32bit> K(8); - for(size_t j = 0; j != length; ++j) - K[j/4] = (K[j/4] << 8) + key[j]; + MK.resize(48); + RK.resize(48); + + secure_vector<u32bit> K(8); + for(size_t i = 0; i != length; ++i) + K[i/4] = (K[i/4] << 8) + key[i]; u32bit A = K[0], B = K[1], C = K[2], D = K[3], E = K[4], F = K[5], G = K[6], H = K[7]; - for(size_t j = 0; j != 48; j += 4) + for(size_t i = 0; i != 48; i += 4) { - round1(G, H, KEY_MASK[4*j+ 0], KEY_ROT[(4*j+ 0) % 32]); - round2(F, G, KEY_MASK[4*j+ 1], KEY_ROT[(4*j+ 1) % 32]); - round3(E, F, KEY_MASK[4*j+ 2], KEY_ROT[(4*j+ 2) % 32]); - round1(D, E, KEY_MASK[4*j+ 3], KEY_ROT[(4*j+ 3) % 32]); - round2(C, D, KEY_MASK[4*j+ 4], KEY_ROT[(4*j+ 4) % 32]); - round3(B, C, KEY_MASK[4*j+ 5], KEY_ROT[(4*j+ 5) % 32]); - round1(A, B, KEY_MASK[4*j+ 6], KEY_ROT[(4*j+ 6) % 32]); - round2(H, A, KEY_MASK[4*j+ 7], KEY_ROT[(4*j+ 7) % 32]); - round1(G, H, KEY_MASK[4*j+ 8], KEY_ROT[(4*j+ 8) % 32]); - round2(F, G, KEY_MASK[4*j+ 9], KEY_ROT[(4*j+ 9) % 32]); - round3(E, F, KEY_MASK[4*j+10], KEY_ROT[(4*j+10) % 32]); - round1(D, E, KEY_MASK[4*j+11], KEY_ROT[(4*j+11) % 32]); - round2(C, D, KEY_MASK[4*j+12], KEY_ROT[(4*j+12) % 32]); - round3(B, C, KEY_MASK[4*j+13], KEY_ROT[(4*j+13) % 32]); - round1(A, B, KEY_MASK[4*j+14], KEY_ROT[(4*j+14) % 32]); - round2(H, A, KEY_MASK[4*j+15], KEY_ROT[(4*j+15) % 32]); - - RK[j ] = (A % 32); - RK[j+1] = (C % 32); - RK[j+2] = (E % 32); - RK[j+3] = (G % 32); - MK[j ] = H; - MK[j+1] = F; - MK[j+2] = D; - MK[j+3] = B; + round1(G, H, KEY_MASK[4*i+ 0], KEY_ROT[(4*i+ 0) % 32]); + round2(F, G, KEY_MASK[4*i+ 1], KEY_ROT[(4*i+ 1) % 32]); + round3(E, F, KEY_MASK[4*i+ 2], KEY_ROT[(4*i+ 2) % 32]); + round1(D, E, KEY_MASK[4*i+ 3], KEY_ROT[(4*i+ 3) % 32]); + round2(C, D, KEY_MASK[4*i+ 4], KEY_ROT[(4*i+ 4) % 32]); + round3(B, C, KEY_MASK[4*i+ 5], KEY_ROT[(4*i+ 5) % 32]); + round1(A, B, KEY_MASK[4*i+ 6], KEY_ROT[(4*i+ 6) % 32]); + round2(H, A, KEY_MASK[4*i+ 7], KEY_ROT[(4*i+ 7) % 32]); + round1(G, H, KEY_MASK[4*i+ 8], KEY_ROT[(4*i+ 8) % 32]); + round2(F, G, KEY_MASK[4*i+ 9], KEY_ROT[(4*i+ 9) % 32]); + round3(E, F, KEY_MASK[4*i+10], KEY_ROT[(4*i+10) % 32]); + round1(D, E, KEY_MASK[4*i+11], KEY_ROT[(4*i+11) % 32]); + round2(C, D, KEY_MASK[4*i+12], KEY_ROT[(4*i+12) % 32]); + round3(B, C, KEY_MASK[4*i+13], KEY_ROT[(4*i+13) % 32]); + round1(A, B, KEY_MASK[4*i+14], KEY_ROT[(4*i+14) % 32]); + round2(H, A, KEY_MASK[4*i+15], KEY_ROT[(4*i+15) % 32]); + + RK[i ] = (A % 32); + RK[i+1] = (C % 32); + RK[i+2] = (E % 32); + RK[i+3] = (G % 32); + MK[i ] = H; + MK[i+1] = F; + MK[i+2] = D; + MK[i+3] = B; } } diff --git a/src/block/cast/cast256.h b/src/block/cast/cast256.h index 2f2beef47..4f31f187d 100644 --- a/src/block/cast/cast256.h +++ b/src/block/cast/cast256.h @@ -21,19 +21,17 @@ class BOTAN_DLL CAST_256 : public Block_Cipher_Fixed_Params<16, 4, 32, 4> void encrypt_n(const byte in[], byte out[], size_t blocks) const; void decrypt_n(const byte in[], byte out[], size_t blocks) const; - void clear() { zeroise(MK); zeroise(RK); } + void clear() { MK.clear(); RK.clear(); } std::string name() const { return "CAST-256"; } BlockCipher* clone() const { return new CAST_256; } - - CAST_256() : MK(48), RK(48) {} private: void key_schedule(const byte[], size_t); static const u32bit KEY_MASK[192]; static const byte KEY_ROT[32]; - SecureVector<u32bit> MK; - SecureVector<byte> RK; + secure_vector<u32bit> MK; + secure_vector<byte> RK; }; extern const u32bit CAST_SBOX1[256]; diff --git a/src/block/des/des.cpp b/src/block/des/des.cpp index c500e9bab..2f0a3635d 100644 --- a/src/block/des/des.cpp +++ b/src/block/des/des.cpp @@ -206,6 +206,7 @@ void DES::decrypt_n(const byte in[], byte out[], size_t blocks) const */ void DES::key_schedule(const byte key[], size_t) { + round_key.resize(32); des_key_schedule(&round_key[0], key); } @@ -280,6 +281,7 @@ void TripleDES::decrypt_n(const byte in[], byte out[], size_t blocks) const */ void TripleDES::key_schedule(const byte key[], size_t length) { + round_key.resize(3*32); des_key_schedule(&round_key[0], key); des_key_schedule(&round_key[32], key + 8); diff --git a/src/block/des/des.h b/src/block/des/des.h index db5a375e0..fc42cfee5 100644 --- a/src/block/des/des.h +++ b/src/block/des/des.h @@ -21,15 +21,13 @@ class BOTAN_DLL DES : public Block_Cipher_Fixed_Params<8, 8> void encrypt_n(const byte in[], byte out[], size_t blocks) const; void decrypt_n(const byte in[], byte out[], size_t blocks) const; - void clear() { zeroise(round_key); } + void clear() { round_key.clear(); } std::string name() const { return "DES"; } BlockCipher* clone() const { return new DES; } - - DES() : round_key(32) {} private: void key_schedule(const byte[], size_t); - SecureVector<u32bit> round_key; + secure_vector<u32bit> round_key; }; /** @@ -41,7 +39,7 @@ class BOTAN_DLL TripleDES : public Block_Cipher_Fixed_Params<8, 16, 24, 8> void encrypt_n(const byte in[], byte out[], size_t blocks) const; void decrypt_n(const byte in[], byte out[], size_t blocks) const; - void clear() { zeroise(round_key); } + void clear() { round_key.clear(); } std::string name() const { return "TripleDES"; } BlockCipher* clone() const { return new TripleDES; } @@ -49,7 +47,7 @@ class BOTAN_DLL TripleDES : public Block_Cipher_Fixed_Params<8, 16, 24, 8> private: void key_schedule(const byte[], size_t); - SecureVector<u32bit> round_key; + secure_vector<u32bit> round_key; }; /* diff --git a/src/block/des/desx.cpp b/src/block/des/desx.cpp index b92011e56..7f68e406a 100644 --- a/src/block/des/desx.cpp +++ b/src/block/des/desx.cpp @@ -47,9 +47,9 @@ void DESX::decrypt_n(const byte in[], byte out[], size_t blocks) const */ void DESX::key_schedule(const byte key[], size_t) { - K1.copy(key, 8); + K1.assign(key, key + 8); des.set_key(key + 8, 8); - K2.copy(key + 16, 8); + K2.assign(key + 16, key + 24); } } diff --git a/src/block/des/desx.h b/src/block/des/desx.h index 993eca86b..4ff41328f 100644 --- a/src/block/des/desx.h +++ b/src/block/des/desx.h @@ -21,14 +21,12 @@ class BOTAN_DLL DESX : public Block_Cipher_Fixed_Params<8, 24> void encrypt_n(const byte in[], byte out[], size_t blocks) const; void decrypt_n(const byte in[], byte out[], size_t blocks) const; - void clear() { des.clear(); zeroise(K1); zeroise(K2); } + void clear() { des.clear(); K1.clear(); K2.clear(); } std::string name() const { return "DESX"; } BlockCipher* clone() const { return new DESX; } - - DESX() : K1(8), K2(8) {} private: void key_schedule(const byte[], size_t); - SecureVector<byte> K1, K2; + secure_vector<byte> K1, K2; DES des; }; diff --git a/src/block/gost_28147/gost_28147.cpp b/src/block/gost_28147/gost_28147.cpp index d4a9faa40..db144a81f 100644 --- a/src/block/gost_28147/gost_28147.cpp +++ b/src/block/gost_28147/gost_28147.cpp @@ -51,8 +51,7 @@ GOST_28147_89_Params::GOST_28147_89_Params(const std::string& n) : name(n) /* * GOST Constructor */ -GOST_28147_89::GOST_28147_89(const GOST_28147_89_Params& param) : - SBOX(1024), EK(8) +GOST_28147_89::GOST_28147_89(const GOST_28147_89_Params& param) : SBOX(1024) { // Convert the parallel 4x4 sboxes into larger word-based sboxes for(size_t i = 0; i != 4; ++i) @@ -165,6 +164,7 @@ void GOST_28147_89::decrypt_n(const byte in[], byte out[], size_t blocks) const */ void GOST_28147_89::key_schedule(const byte key[], size_t) { + EK.resize(8); for(size_t i = 0; i != 8; ++i) EK[i] = load_le<u32bit>(key, i); } diff --git a/src/block/gost_28147/gost_28147.h b/src/block/gost_28147/gost_28147.h index bc26da774..7c77fea06 100644 --- a/src/block/gost_28147/gost_28147.h +++ b/src/block/gost_28147/gost_28147.h @@ -55,7 +55,7 @@ class BOTAN_DLL GOST_28147_89 : public Block_Cipher_Fixed_Params<8, 32> void encrypt_n(const byte in[], byte out[], size_t blocks) const; void decrypt_n(const byte in[], byte out[], size_t blocks) const; - void clear() { zeroise(EK); } + void clear() { EK.clear(); } std::string name() const; BlockCipher* clone() const { return new GOST_28147_89(SBOX); } @@ -65,13 +65,18 @@ class BOTAN_DLL GOST_28147_89 : public Block_Cipher_Fixed_Params<8, 32> */ GOST_28147_89(const GOST_28147_89_Params& params); private: - GOST_28147_89(const SecureVector<u32bit>& other_SBOX) : + GOST_28147_89(const std::vector<u32bit>& other_SBOX) : SBOX(other_SBOX), EK(8) {} void key_schedule(const byte[], size_t); - SecureVector<u32bit> SBOX; - SecureVector<u32bit> EK; + /* + * The sbox is not secret, this is just a larger expansion of it + * which we generate at runtime for faster execution + */ + std::vector<u32bit> SBOX; + + secure_vector<u32bit> EK; }; } diff --git a/src/block/idea/idea.cpp b/src/block/idea/idea.cpp index f9b6cc874..15062abdf 100644 --- a/src/block/idea/idea.cpp +++ b/src/block/idea/idea.cpp @@ -124,6 +124,9 @@ void IDEA::decrypt_n(const byte in[], byte out[], size_t blocks) const */ void IDEA::key_schedule(const byte key[], size_t) { + EK.resize(52); + DK.resize(52); + for(size_t i = 0; i != 8; ++i) EK[i] = load_be<u16bit>(key, i); diff --git a/src/block/idea/idea.h b/src/block/idea/idea.h index 42fa60c47..03ecb1f03 100644 --- a/src/block/idea/idea.h +++ b/src/block/idea/idea.h @@ -21,25 +21,24 @@ class BOTAN_DLL IDEA : public Block_Cipher_Fixed_Params<8, 16> void encrypt_n(const byte in[], byte out[], size_t blocks) const; void decrypt_n(const byte in[], byte out[], size_t blocks) const; - void clear() { zeroise(EK); zeroise(DK); } + void clear() { EK.clear(); DK.clear(); } std::string name() const { return "IDEA"; } BlockCipher* clone() const { return new IDEA; } - - IDEA() : EK(52), DK(52) {} protected: /** * @return const reference to encryption subkeys */ - const SecureVector<u16bit>& get_EK() const { return EK; } + const secure_vector<u16bit>& get_EK() const { return EK; } /** * @return const reference to decryption subkeys */ - const SecureVector<u16bit>& get_DK() const { return DK; } + const secure_vector<u16bit>& get_DK() const { return DK; } private: void key_schedule(const byte[], size_t); - SecureVector<u16bit> EK, DK; + + secure_vector<u16bit> EK, DK; }; } diff --git a/src/block/kasumi/kasumi.cpp b/src/block/kasumi/kasumi.cpp index a57c0396a..ae21338c6 100644 --- a/src/block/kasumi/kasumi.cpp +++ b/src/block/kasumi/kasumi.cpp @@ -204,13 +204,15 @@ void KASUMI::key_schedule(const byte key[], size_t) static const u16bit RC[] = { 0x0123, 0x4567, 0x89AB, 0xCDEF, 0xFEDC, 0xBA98, 0x7654, 0x3210 }; - SecureVector<u16bit> K(16); + secure_vector<u16bit> K(16); for(size_t i = 0; i != 8; ++i) { K[i] = load_be<u16bit>(key, i); K[i+8] = K[i] ^ RC[i]; } + EK.resize(64); + for(size_t i = 0; i != 8; ++i) { EK[8*i ] = rotate_left(K[(i+0) % 8 ], 2); diff --git a/src/block/kasumi/kasumi.h b/src/block/kasumi/kasumi.h index 7871aa170..571085612 100644 --- a/src/block/kasumi/kasumi.h +++ b/src/block/kasumi/kasumi.h @@ -21,15 +21,13 @@ class BOTAN_DLL KASUMI : public Block_Cipher_Fixed_Params<8, 16> void encrypt_n(const byte in[], byte out[], size_t blocks) const; void decrypt_n(const byte in[], byte out[], size_t blocks) const; - void clear() { zeroise(EK); } + void clear() { EK.clear(); } std::string name() const { return "KASUMI"; } BlockCipher* clone() const { return new KASUMI; } - - KASUMI() : EK(64) {} private: void key_schedule(const byte[], size_t); - SecureVector<u16bit> EK; + secure_vector<u16bit> EK; }; } diff --git a/src/block/lion/lion.cpp b/src/block/lion/lion.cpp index 46308e428..9026f194a 100644 --- a/src/block/lion/lion.cpp +++ b/src/block/lion/lion.cpp @@ -16,7 +16,7 @@ namespace Botan { */ void Lion::encrypt_n(const byte in[], byte out[], size_t blocks) const { - SecureVector<byte> buffer_vec(LEFT_SIZE); + secure_vector<byte> buffer_vec(LEFT_SIZE); byte* buffer = &buffer_vec[0]; for(size_t i = 0; i != blocks; ++i) @@ -43,7 +43,7 @@ void Lion::encrypt_n(const byte in[], byte out[], size_t blocks) const */ void Lion::decrypt_n(const byte in[], byte out[], size_t blocks) const { - SecureVector<byte> buffer_vec(LEFT_SIZE); + secure_vector<byte> buffer_vec(LEFT_SIZE); byte* buffer = &buffer_vec[0]; for(size_t i = 0; i != blocks; ++i) @@ -72,8 +72,8 @@ void Lion::key_schedule(const byte key[], size_t length) { clear(); - key1.copy(key, length / 2); - key2.copy(key + length / 2, length / 2); + key1.assign(key, key + (length / 2)); + key2.assign(key + (length / 2), key + length); } /* @@ -83,7 +83,7 @@ std::string Lion::name() const { return "Lion(" + hash->name() + "," + cipher->name() + "," + - to_string(BLOCK_SIZE) + ")"; + std::to_string(BLOCK_SIZE) + ")"; } /* @@ -99,10 +99,10 @@ BlockCipher* Lion::clone() const */ void Lion::clear() { + key1.clear(); + key2.clear(); hash->clear(); cipher->clear(); - zeroise(key1); - zeroise(key2); } /* diff --git a/src/block/lion/lion.h b/src/block/lion/lion.h index 5076f4461..d016c0e82 100644 --- a/src/block/lion/lion.h +++ b/src/block/lion/lion.h @@ -56,7 +56,7 @@ class BOTAN_DLL Lion : public BlockCipher HashFunction* hash; StreamCipher* cipher; - SecureVector<byte> key1, key2; + secure_vector<byte> key1, key2; }; } diff --git a/src/block/lubyrack/lubyrack.cpp b/src/block/lubyrack/lubyrack.cpp index ef4a11e9d..77f2a7542 100644 --- a/src/block/lubyrack/lubyrack.cpp +++ b/src/block/lubyrack/lubyrack.cpp @@ -17,7 +17,7 @@ void LubyRackoff::encrypt_n(const byte in[], byte out[], size_t blocks) const { const size_t len = hash->output_length(); - SecureVector<byte> buffer_vec(len); + secure_vector<byte> buffer_vec(len); byte* buffer = &buffer_vec[0]; for(size_t i = 0; i != blocks; ++i) @@ -54,7 +54,7 @@ void LubyRackoff::decrypt_n(const byte in[], byte out[], size_t blocks) const { const size_t len = hash->output_length(); - SecureVector<byte> buffer_vec(len); + secure_vector<byte> buffer_vec(len); byte* buffer = &buffer_vec[0]; for(size_t i = 0; i != blocks; ++i) @@ -89,10 +89,8 @@ void LubyRackoff::decrypt_n(const byte in[], byte out[], size_t blocks) const */ void LubyRackoff::key_schedule(const byte key[], size_t length) { - K1.resize(length / 2); - K2.resize(length / 2); - copy_mem(&K1[0], key , length / 2); - copy_mem(&K2[0], key + length / 2, length / 2); + K1.assign(key, key + (length / 2)); + K2.assign(key + (length / 2), key + length); } /* @@ -100,8 +98,8 @@ void LubyRackoff::key_schedule(const byte key[], size_t length) */ void LubyRackoff::clear() { - zeroise(K1); - zeroise(K2); + K1.clear(); + K2.clear(); hash->clear(); } diff --git a/src/block/lubyrack/lubyrack.h b/src/block/lubyrack/lubyrack.h index 81dddf579..e28c60be7 100644 --- a/src/block/lubyrack/lubyrack.h +++ b/src/block/lubyrack/lubyrack.h @@ -42,7 +42,7 @@ class BOTAN_DLL LubyRackoff : public BlockCipher void key_schedule(const byte[], size_t); HashFunction* hash; - SecureVector<byte> K1, K2; + secure_vector<byte> K1, K2; }; } diff --git a/src/block/mars/mars.cpp b/src/block/mars/mars.cpp index 171ce2945..5badc40cc 100644 --- a/src/block/mars/mars.cpp +++ b/src/block/mars/mars.cpp @@ -320,12 +320,14 @@ void MARS::decrypt_n(const byte in[], byte out[], size_t blocks) const */ void MARS::key_schedule(const byte key[], size_t length) { - SecureVector<u32bit> T(15); + secure_vector<u32bit> T(15); for(size_t i = 0; i != length / 4; ++i) T[i] = load_le<u32bit>(key, i); T[length / 4] = static_cast<u32bit>(length) / 4; + EK.resize(40); + for(u32bit i = 0; i != 4; ++i) { T[ 0] ^= rotate_left(T[ 8] ^ T[13], 3) ^ (i ); diff --git a/src/block/mars/mars.h b/src/block/mars/mars.h index 5ca05f886..488ea1b83 100644 --- a/src/block/mars/mars.h +++ b/src/block/mars/mars.h @@ -21,15 +21,13 @@ class BOTAN_DLL MARS : public Block_Cipher_Fixed_Params<16, 16, 32, 4> void encrypt_n(const byte in[], byte out[], size_t blocks) const; void decrypt_n(const byte in[], byte out[], size_t blocks) const; - void clear() { zeroise(EK); } + void clear() { EK.clear(); } std::string name() const { return "MARS"; } BlockCipher* clone() const { return new MARS; } - - MARS() : EK(40) {} private: void key_schedule(const byte[], size_t); - SecureVector<u32bit> EK; + secure_vector<u32bit> EK; }; } diff --git a/src/block/misty1/misty1.cpp b/src/block/misty1/misty1.cpp index 36c25a814..97f1e0341 100644 --- a/src/block/misty1/misty1.cpp +++ b/src/block/misty1/misty1.cpp @@ -204,7 +204,7 @@ void MISTY1::decrypt_n(const byte in[], byte out[], size_t blocks) const */ void MISTY1::key_schedule(const byte key[], size_t length) { - SecureVector<u16bit> KS(32); + secure_vector<u16bit> KS(32); for(size_t i = 0; i != length / 2; ++i) KS[i] = load_be<u16bit>(key, i); @@ -241,6 +241,9 @@ void MISTY1::key_schedule(const byte key[], size_t length) 0x1C, 0x05, 0x00, 0x15, 0x1D, 0x02, 0x11, 0x19, 0x07, 0x13, 0x1B, 0x04, 0x04, 0x0A, 0x0E, 0x00 }; + EK.resize(100); + DK.resize(100); + for(size_t i = 0; i != 100; ++i) { EK[i] = KS[EK_ORDER[i]]; @@ -251,11 +254,11 @@ void MISTY1::key_schedule(const byte key[], size_t length) /* * MISTY1 Constructor */ -MISTY1::MISTY1(size_t rounds) : EK(100), DK(100) +MISTY1::MISTY1(size_t rounds) { if(rounds != 8) throw Invalid_Argument("MISTY1: Invalid number of rounds: " - + to_string(rounds)); + + std::to_string(rounds)); } } diff --git a/src/block/misty1/misty1.h b/src/block/misty1/misty1.h index 14d8a2958..81324a0b2 100644 --- a/src/block/misty1/misty1.h +++ b/src/block/misty1/misty1.h @@ -21,7 +21,7 @@ class BOTAN_DLL MISTY1 : public Block_Cipher_Fixed_Params<8, 16> void encrypt_n(const byte in[], byte out[], size_t blocks) const; void decrypt_n(const byte in[], byte out[], size_t blocks) const; - void clear() { zeroise(EK); zeroise(DK); } + void clear() { EK.clear(); DK.clear(); } std::string name() const { return "MISTY1"; } BlockCipher* clone() const { return new MISTY1; } @@ -33,7 +33,7 @@ class BOTAN_DLL MISTY1 : public Block_Cipher_Fixed_Params<8, 16> private: void key_schedule(const byte[], size_t); - SecureVector<u16bit> EK, DK; + secure_vector<u16bit> EK, DK; }; } diff --git a/src/block/noekeon/noekeon.cpp b/src/block/noekeon/noekeon.cpp index 06c415be9..3929d57d1 100644 --- a/src/block/noekeon/noekeon.cpp +++ b/src/block/noekeon/noekeon.cpp @@ -185,6 +185,7 @@ void Noekeon::key_schedule(const byte key[], size_t) A0 ^= RC[16]; + DK.resize(4); DK[0] = A0; DK[1] = A1; DK[2] = A2; @@ -192,6 +193,7 @@ void Noekeon::key_schedule(const byte key[], size_t) theta(A0, A1, A2, A3); + EK.resize(4); EK[0] = A0; EK[1] = A1; EK[2] = A2; @@ -203,8 +205,8 @@ void Noekeon::key_schedule(const byte key[], size_t) */ void Noekeon::clear() { - zeroise(EK); - zeroise(DK); + EK.clear(); + DK.clear(); } } diff --git a/src/block/noekeon/noekeon.h b/src/block/noekeon/noekeon.h index 7c5c73dcb..108b34cd6 100644 --- a/src/block/noekeon/noekeon.h +++ b/src/block/noekeon/noekeon.h @@ -24,8 +24,6 @@ class BOTAN_DLL Noekeon : public Block_Cipher_Fixed_Params<16, 16> void clear(); std::string name() const { return "Noekeon"; } BlockCipher* clone() const { return new Noekeon; } - - Noekeon() : EK(4), DK(4) {} protected: /** * The Noekeon round constants @@ -35,16 +33,16 @@ class BOTAN_DLL Noekeon : public Block_Cipher_Fixed_Params<16, 16> /** * @return const reference to encryption subkeys */ - const SecureVector<u32bit>& get_EK() const { return EK; } + const secure_vector<u32bit>& get_EK() const { return EK; } /** * @return const reference to decryption subkeys */ - const SecureVector<u32bit>& get_DK() const { return DK; } + const secure_vector<u32bit>& get_DK() const { return DK; } private: void key_schedule(const byte[], size_t); - SecureVector<u32bit> EK, DK; + secure_vector<u32bit> EK, DK; }; } diff --git a/src/block/noekeon_simd/noekeon_simd.cpp b/src/block/noekeon_simd/noekeon_simd.cpp index b2beafc82..2a4c1fd74 100644 --- a/src/block/noekeon_simd/noekeon_simd.cpp +++ b/src/block/noekeon_simd/noekeon_simd.cpp @@ -65,7 +65,7 @@ namespace Botan { */ void Noekeon_SIMD::encrypt_n(const byte in[], byte out[], size_t blocks) const { - const SecureVector<u32bit>& EK = this->get_EK(); + const secure_vector<u32bit>& EK = this->get_EK(); SIMD_32 K0 = SIMD_32(EK[0]); SIMD_32 K1 = SIMD_32(EK[1]); @@ -122,7 +122,7 @@ void Noekeon_SIMD::encrypt_n(const byte in[], byte out[], size_t blocks) const */ void Noekeon_SIMD::decrypt_n(const byte in[], byte out[], size_t blocks) const { - const SecureVector<u32bit>& DK = this->get_DK(); + const secure_vector<u32bit>& DK = this->get_DK(); SIMD_32 K0 = SIMD_32(DK[0]); SIMD_32 K1 = SIMD_32(DK[1]); diff --git a/src/block/rc2/rc2.cpp b/src/block/rc2/rc2.cpp index 97ca5d577..548c2f095 100644 --- a/src/block/rc2/rc2.cpp +++ b/src/block/rc2/rc2.cpp @@ -124,8 +124,8 @@ void RC2::key_schedule(const byte key[], size_t length) 0xC5, 0xF3, 0xDB, 0x47, 0xE5, 0xA5, 0x9C, 0x77, 0x0A, 0xA6, 0x20, 0x68, 0xFE, 0x7F, 0xC1, 0xAD }; - SecureVector<byte> L(128); - L.copy(key, length); + secure_vector<byte> L(128); + copy_mem(&L[0], key, length); for(size_t i = length; i != 128; ++i) L[i] = TABLE[(L[i-1] + L[i-length]) % 256]; @@ -135,6 +135,7 @@ void RC2::key_schedule(const byte key[], size_t length) for(s32bit i = 127-length; i >= 0; --i) L[i] = TABLE[L[i+1] ^ L[i+length]]; + K.resize(64); load_le<u16bit>(&K[0], &L[0], 64); } diff --git a/src/block/rc2/rc2.h b/src/block/rc2/rc2.h index 1ebad1e73..223c48792 100644 --- a/src/block/rc2/rc2.h +++ b/src/block/rc2/rc2.h @@ -28,15 +28,13 @@ class BOTAN_DLL RC2 : public Block_Cipher_Fixed_Params<8, 1, 32> */ static byte EKB_code(size_t bits); - void clear() { zeroise(K); } + void clear() { K.clear(); } std::string name() const { return "RC2"; } BlockCipher* clone() const { return new RC2; } - - RC2() : K(64) {} private: void key_schedule(const byte[], size_t); - SecureVector<u16bit> K; + secure_vector<u16bit> K; }; } diff --git a/src/block/rc5/rc5.cpp b/src/block/rc5/rc5.cpp index cfcc4cb64..fe558076a 100644 --- a/src/block/rc5/rc5.cpp +++ b/src/block/rc5/rc5.cpp @@ -18,8 +18,6 @@ namespace Botan { */ void RC5::encrypt_n(const byte in[], byte out[], size_t blocks) const { - const size_t rounds = (S.size() - 2) / 2; - for(size_t i = 0; i != blocks; ++i) { u32bit A = load_le<u32bit>(in, 0); @@ -53,8 +51,6 @@ void RC5::encrypt_n(const byte in[], byte out[], size_t blocks) const */ void RC5::decrypt_n(const byte in[], byte out[], size_t blocks) const { - const size_t rounds = (S.size() - 2) / 2; - for(size_t i = 0; i != blocks; ++i) { u32bit A = load_le<u32bit>(in, 0); @@ -88,6 +84,8 @@ void RC5::decrypt_n(const byte in[], byte out[], size_t blocks) const */ void RC5::key_schedule(const byte key[], size_t length) { + S.resize(2*rounds + 2); + const size_t WORD_KEYLENGTH = (((length - 1) / 4) + 1); const size_t MIX_ROUNDS = 3 * std::max(WORD_KEYLENGTH, S.size()); @@ -95,7 +93,7 @@ void RC5::key_schedule(const byte key[], size_t length) for(size_t i = 1; i != S.size(); ++i) S[i] = S[i-1] + 0x9E3779B9; - SecureVector<u32bit> K(8); + secure_vector<u32bit> K(8); for(s32bit i = length-1; i >= 0; --i) K[i/4] = (K[i/4] << 8) + key[i]; @@ -116,19 +114,17 @@ void RC5::key_schedule(const byte key[], size_t length) */ std::string RC5::name() const { - return "RC5(" + to_string(get_rounds()) + ")"; + return "RC5(" + std::to_string(rounds) + ")"; } /* * RC5 Constructor */ -RC5::RC5(size_t rounds) +RC5::RC5(size_t r) : rounds(r) { if(rounds < 8 || rounds > 32 || (rounds % 4 != 0)) throw Invalid_Argument("RC5: Invalid number of rounds " + - to_string(rounds)); - - S.resize(2*rounds + 2); + std::to_string(rounds)); } } diff --git a/src/block/rc5/rc5.h b/src/block/rc5/rc5.h index c69705471..2279260a3 100644 --- a/src/block/rc5/rc5.h +++ b/src/block/rc5/rc5.h @@ -21,9 +21,9 @@ class BOTAN_DLL RC5 : public Block_Cipher_Fixed_Params<8, 1, 32> void encrypt_n(const byte in[], byte out[], size_t blocks) const; void decrypt_n(const byte in[], byte out[], size_t blocks) const; - void clear() { zeroise(S); } + void clear() { S.clear(); } std::string name() const; - BlockCipher* clone() const { return new RC5(get_rounds()); } + BlockCipher* clone() const { return new RC5(rounds); } /** * @param rounds the number of RC5 rounds to run. Must be between @@ -31,11 +31,10 @@ class BOTAN_DLL RC5 : public Block_Cipher_Fixed_Params<8, 1, 32> */ RC5(size_t rounds); private: - size_t get_rounds() const { return (S.size() - 2) / 2; } - void key_schedule(const byte[], size_t); - SecureVector<u32bit> S; + size_t rounds; + secure_vector<u32bit> S; }; } diff --git a/src/block/rc6/rc6.cpp b/src/block/rc6/rc6.cpp index 53ca5a7a2..5a6c1091d 100644 --- a/src/block/rc6/rc6.cpp +++ b/src/block/rc6/rc6.cpp @@ -113,6 +113,8 @@ void RC6::decrypt_n(const byte in[], byte out[], size_t blocks) const */ void RC6::key_schedule(const byte key[], size_t length) { + S.resize(44); + const size_t WORD_KEYLENGTH = (((length - 1) / 4) + 1); const size_t MIX_ROUNDS = 3 * std::max(WORD_KEYLENGTH, S.size()); @@ -120,7 +122,7 @@ void RC6::key_schedule(const byte key[], size_t length) for(size_t i = 1; i != S.size(); ++i) S[i] = S[i-1] + 0x9E3779B9; - SecureVector<u32bit> K(8); + secure_vector<u32bit> K(8); for(s32bit i = length-1; i >= 0; --i) K[i/4] = (K[i/4] << 8) + key[i]; diff --git a/src/block/rc6/rc6.h b/src/block/rc6/rc6.h index af7b62316..e30a267e6 100644 --- a/src/block/rc6/rc6.h +++ b/src/block/rc6/rc6.h @@ -21,15 +21,13 @@ class BOTAN_DLL RC6 : public Block_Cipher_Fixed_Params<16, 1, 32> void encrypt_n(const byte in[], byte out[], size_t blocks) const; void decrypt_n(const byte in[], byte out[], size_t blocks) const; - void clear() { zeroise(S); } + void clear() { S.clear(); } std::string name() const { return "RC6"; } BlockCipher* clone() const { return new RC6; } - - RC6() : S(44) {} private: void key_schedule(const byte[], size_t); - SecureVector<u32bit> S; + secure_vector<u32bit> S; }; } diff --git a/src/block/safer/safer_sk.cpp b/src/block/safer/safer_sk.cpp index a3a6cefd8..1b79b3c2c 100644 --- a/src/block/safer/safer_sk.cpp +++ b/src/block/safer/safer_sk.cpp @@ -90,8 +90,6 @@ const byte LOG[512] = { */ void SAFER_SK::encrypt_n(const byte in[], byte out[], size_t blocks) const { - const size_t rounds = get_rounds(); - for(size_t i = 0; i != blocks; ++i) { byte A = in[0], B = in[1], C = in[2], D = in[3], @@ -128,8 +126,6 @@ void SAFER_SK::encrypt_n(const byte in[], byte out[], size_t blocks) const */ void SAFER_SK::decrypt_n(const byte in[], byte out[], size_t blocks) const { - const size_t rounds = get_rounds(); - for(size_t i = 0; i != blocks; ++i) { byte A = in[0], B = in[1], C = in[2], D = in[3], @@ -208,7 +204,9 @@ void SAFER_SK::key_schedule(const byte key[], size_t) 0x07, 0x08, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x11, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }; - SecureVector<byte> KB(18); + EK.resize(16 * rounds + 8); + + secure_vector<byte> KB(18); for(size_t i = 0; i != 8; ++i) { @@ -216,7 +214,7 @@ void SAFER_SK::key_schedule(const byte key[], size_t) KB[17] ^= KB[i+9] = EK[i] = key[i+8]; } - for(size_t i = 0; i != get_rounds(); ++i) + for(size_t i = 0; i != rounds; ++i) { for(size_t j = 0; j != 18; ++j) KB[j] = rotate_left(KB[j], 6); @@ -230,7 +228,7 @@ void SAFER_SK::key_schedule(const byte key[], size_t) */ std::string SAFER_SK::name() const { - return "SAFER-SK(" + to_string(get_rounds()) + ")"; + return "SAFER-SK(" + std::to_string(rounds) + ")"; } /* @@ -238,18 +236,16 @@ std::string SAFER_SK::name() const */ BlockCipher* SAFER_SK::clone() const { - return new SAFER_SK(get_rounds()); + return new SAFER_SK(rounds); } /* * SAFER-SK Constructor */ -SAFER_SK::SAFER_SK(size_t rounds) +SAFER_SK::SAFER_SK(size_t r) : rounds(r) { if(rounds > 13 || rounds == 0) throw Invalid_Argument(name() + ": Invalid number of rounds"); - - EK.resize(16 * rounds + 8); } } diff --git a/src/block/safer/safer_sk.h b/src/block/safer/safer_sk.h index 564ea5c50..dfe226652 100644 --- a/src/block/safer/safer_sk.h +++ b/src/block/safer/safer_sk.h @@ -21,7 +21,7 @@ class BOTAN_DLL SAFER_SK : public Block_Cipher_Fixed_Params<8, 16> void encrypt_n(const byte in[], byte out[], size_t blocks) const; void decrypt_n(const byte in[], byte out[], size_t blocks) const; - void clear() { zeroise(EK); } + void clear() { EK.clear(); } std::string name() const; BlockCipher* clone() const; @@ -31,10 +31,10 @@ class BOTAN_DLL SAFER_SK : public Block_Cipher_Fixed_Params<8, 16> */ SAFER_SK(size_t rounds); private: - size_t get_rounds() const { return (EK.size() - 8) / 16; } void key_schedule(const byte[], size_t); - SecureVector<byte> EK; + size_t rounds; + secure_vector<byte> EK; }; } diff --git a/src/block/seed/seed.cpp b/src/block/seed/seed.cpp index 408220013..fb8708214 100644 --- a/src/block/seed/seed.cpp +++ b/src/block/seed/seed.cpp @@ -111,13 +111,15 @@ void SEED::key_schedule(const byte key[], size_t) 0x779B99E3, 0xEF3733C6, 0xDE6E678D, 0xBCDCCF1B }; - SecureVector<u32bit> WK(4); + secure_vector<u32bit> WK(4); for(size_t i = 0; i != 4; ++i) WK[i] = load_be<u32bit>(key, i); G_FUNC G; + K.resize(32); + for(size_t i = 0; i != 16; i += 2) { K[2*i ] = G(WK[0] + WK[2] - RC[i]); diff --git a/src/block/seed/seed.h b/src/block/seed/seed.h index 979312930..95dab758d 100644 --- a/src/block/seed/seed.h +++ b/src/block/seed/seed.h @@ -21,11 +21,9 @@ class BOTAN_DLL SEED : public Block_Cipher_Fixed_Params<16, 16> void encrypt_n(const byte in[], byte out[], size_t blocks) const; void decrypt_n(const byte in[], byte out[], size_t blocks) const; - void clear() { zeroise(K); } + void clear() { K.clear(); } std::string name() const { return "SEED"; } BlockCipher* clone() const { return new SEED; } - - SEED() : K(32) {} private: void key_schedule(const byte[], size_t); @@ -37,7 +35,7 @@ class BOTAN_DLL SEED : public Block_Cipher_Fixed_Params<16, 16> static const u32bit S0[256], S1[256], S2[256], S3[256]; }; - SecureVector<u32bit> K; + secure_vector<u32bit> K; }; } diff --git a/src/block/serpent/serpent.cpp b/src/block/serpent/serpent.cpp index b3cf0f6c9..0f0a4fd63 100644 --- a/src/block/serpent/serpent.cpp +++ b/src/block/serpent/serpent.cpp @@ -358,7 +358,7 @@ void Serpent::key_schedule(const byte key[], size_t length) { const u32bit PHI = 0x9E3779B9; - SecureVector<u32bit> W(140); + secure_vector<u32bit> W(140); for(size_t i = 0; i != length / 4; ++i) W[i] = load_le<u32bit>(key, i); @@ -387,7 +387,8 @@ void Serpent::key_schedule(const byte key[], size_t length) SBoxE8(W[120],W[121],W[122],W[123]); SBoxE7(W[124],W[125],W[126],W[127]); SBoxE6(W[128],W[129],W[130],W[131]); SBoxE5(W[132],W[133],W[134],W[135]); SBoxE4(W[136],W[137],W[138],W[139]); - round_key.copy(&W[8], 132); + + round_key.assign(&W[8], &W[140]); } } diff --git a/src/block/serpent/serpent.h b/src/block/serpent/serpent.h index df3f039aa..9e5abcf35 100644 --- a/src/block/serpent/serpent.h +++ b/src/block/serpent/serpent.h @@ -21,17 +21,15 @@ class BOTAN_DLL Serpent : public Block_Cipher_Fixed_Params<16, 16, 32, 8> void encrypt_n(const byte in[], byte out[], size_t blocks) const; void decrypt_n(const byte in[], byte out[], size_t blocks) const; - void clear() { zeroise(round_key); } + void clear() { round_key.clear(); } std::string name() const { return "Serpent"; } BlockCipher* clone() const { return new Serpent; } - - Serpent() : round_key(132) {} protected: /** * For use by subclasses using SIMD, asm, etc * @return const reference to the key schedule */ - const SecureVector<u32bit>& get_round_keys() const + const secure_vector<u32bit>& get_round_keys() const { return round_key; } /** @@ -45,7 +43,7 @@ class BOTAN_DLL Serpent : public Block_Cipher_Fixed_Params<16, 16, 32, 8> private: void key_schedule(const byte key[], size_t length); - SecureVector<u32bit> round_key; + secure_vector<u32bit> round_key; }; } diff --git a/src/block/serpent_x86_32/serp_x86_32.cpp b/src/block/serpent_x86_32/serp_x86_32.cpp index 4cefe1d65..9566ed8a6 100644 --- a/src/block/serpent_x86_32/serp_x86_32.cpp +++ b/src/block/serpent_x86_32/serp_x86_32.cpp @@ -72,7 +72,7 @@ void Serpent_X86_32::decrypt_n(const byte in[], byte out[], size_t blocks) const */ void Serpent_X86_32::key_schedule(const byte key[], size_t length) { - SecureVector<u32bit> W(140); + secure_vector<u32bit> W(140); for(size_t i = 0; i != length / 4; ++i) W[i] = load_le<u32bit>(key, i); W[length / 4] |= u32bit(1) << ((length%4)*8); diff --git a/src/block/skipjack/skipjack.cpp b/src/block/skipjack/skipjack.cpp index b73972b59..fb9916092 100644 --- a/src/block/skipjack/skipjack.cpp +++ b/src/block/skipjack/skipjack.cpp @@ -183,6 +183,7 @@ void Skipjack::key_schedule(const byte key[], size_t) 0x5E, 0x6C, 0xA9, 0x13, 0x57, 0x25, 0xB5, 0xE3, 0xBD, 0xA8, 0x3A, 0x01, 0x05, 0x59, 0x2A, 0x46 }; + FTAB.resize(256*10); for(size_t i = 0; i != 10; ++i) for(size_t j = 0; j != 256; ++j) FTAB[256*i+j] = F[j ^ key[9-i]]; @@ -193,7 +194,7 @@ void Skipjack::key_schedule(const byte key[], size_t) */ void Skipjack::clear() { - zeroise(FTAB); + FTAB.clear(); } } diff --git a/src/block/skipjack/skipjack.h b/src/block/skipjack/skipjack.h index 051d35351..60a55c8a5 100644 --- a/src/block/skipjack/skipjack.h +++ b/src/block/skipjack/skipjack.h @@ -24,12 +24,10 @@ class BOTAN_DLL Skipjack : public Block_Cipher_Fixed_Params<8, 10> void clear(); std::string name() const { return "Skipjack"; } BlockCipher* clone() const { return new Skipjack; } - - Skipjack() : FTAB(2560) {} private: void key_schedule(const byte[], size_t); - SecureVector<byte> FTAB; + secure_vector<byte> FTAB; }; } diff --git a/src/block/square/square.cpp b/src/block/square/square.cpp index cd1865582..c319dab16 100644 --- a/src/block/square/square.cpp +++ b/src/block/square/square.cpp @@ -142,7 +142,7 @@ void Square::decrypt_n(const byte in[], byte out[], size_t blocks) const */ void Square::key_schedule(const byte key[], size_t) { - SecureVector<u32bit> XEK(36), XDK(36); + secure_vector<u32bit> XEK(36), XDK(36); for(size_t i = 0; i != 4; ++i) XEK[i] = load_be<u32bit>(key, i); @@ -160,6 +160,12 @@ void Square::key_schedule(const byte key[], size_t) transform(&XEK[4*i]); } + EK.assign(&XEK[4], &XEK[36]); + DK.assign(&XDK[4], &XDK[36]); + + ME.resize(32); + MD.resize(32); + for(size_t i = 0; i != 4; ++i) for(size_t j = 0; j != 4; ++j) { @@ -168,9 +174,6 @@ void Square::key_schedule(const byte key[], size_t) MD[4*i+j ] = get_byte(j, XDK[i ]); MD[4*i+j+16] = get_byte(j, XEK[i ]); } - - EK.copy(&XEK[4], 28); - DK.copy(&XDK[4], 28); } /* @@ -209,10 +212,10 @@ void Square::transform(u32bit round_key[4]) */ void Square::clear() { - zeroise(EK); - zeroise(DK); - zeroise(ME); - zeroise(MD); + EK.clear(); + DK.clear(); + ME.clear(); + MD.clear(); } } diff --git a/src/block/square/square.h b/src/block/square/square.h index 5147c0383..618dbf6d9 100644 --- a/src/block/square/square.h +++ b/src/block/square/square.h @@ -24,8 +24,6 @@ class BOTAN_DLL Square : public Block_Cipher_Fixed_Params<16, 16> void clear(); std::string name() const { return "Square"; } BlockCipher* clone() const { return new Square; } - - Square() : EK(28), DK(28), ME(32), MD(32) {} private: void key_schedule(const byte[], size_t); @@ -45,8 +43,8 @@ class BOTAN_DLL Square : public Block_Cipher_Fixed_Params<16, 16> static const u32bit TD2[256]; static const u32bit TD3[256]; - SecureVector<u32bit> EK, DK; - SecureVector<byte> ME, MD; + secure_vector<u32bit> EK, DK; + secure_vector<byte> ME, MD; }; } diff --git a/src/block/tea/tea.cpp b/src/block/tea/tea.cpp index 4ef995a7c..e45f7cb48 100644 --- a/src/block/tea/tea.cpp +++ b/src/block/tea/tea.cpp @@ -65,6 +65,7 @@ void TEA::decrypt_n(const byte in[], byte out[], size_t blocks) const */ void TEA::key_schedule(const byte key[], size_t) { + K.resize(4); for(size_t i = 0; i != 4; ++i) K[i] = load_be<u32bit>(key, i); } diff --git a/src/block/tea/tea.h b/src/block/tea/tea.h index 0290b112f..d2f81da17 100644 --- a/src/block/tea/tea.h +++ b/src/block/tea/tea.h @@ -21,14 +21,12 @@ class BOTAN_DLL TEA : public Block_Cipher_Fixed_Params<8, 16> void encrypt_n(const byte in[], byte out[], size_t blocks) const; void decrypt_n(const byte in[], byte out[], size_t blocks) const; - void clear() { zeroise(K); } + void clear() { K.clear(); } std::string name() const { return "TEA"; } BlockCipher* clone() const { return new TEA; } - - TEA() : K(4) {} private: void key_schedule(const byte[], size_t); - SecureVector<u32bit> K; + secure_vector<u32bit> K; }; } diff --git a/src/block/twofish/twofish.cpp b/src/block/twofish/twofish.cpp index c0735e202..eb5b279b9 100644 --- a/src/block/twofish/twofish.cpp +++ b/src/block/twofish/twofish.cpp @@ -121,7 +121,10 @@ void Twofish::decrypt_n(const byte in[], byte out[], size_t blocks) const */ void Twofish::key_schedule(const byte key[], size_t length) { - SecureVector<byte> S(16); + SB.resize(1024); + RK.resize(40); + + secure_vector<byte> S(16); for(size_t i = 0; i != length; ++i) rs_mul(&S[4*(i/8)], key[i], i); @@ -235,8 +238,8 @@ void Twofish::rs_mul(byte S[4], byte key, size_t offset) */ void Twofish::clear() { - zeroise(SB); - zeroise(RK); + SB.clear(); + RK.clear(); } } diff --git a/src/block/twofish/twofish.h b/src/block/twofish/twofish.h index 7594bdcfd..3d8e47498 100644 --- a/src/block/twofish/twofish.h +++ b/src/block/twofish/twofish.h @@ -24,8 +24,6 @@ class BOTAN_DLL Twofish : public Block_Cipher_Fixed_Params<16, 16, 32, 8> void clear(); std::string name() const { return "Twofish"; } BlockCipher* clone() const { return new Twofish; } - - Twofish() : SB(1024), RK(40) {} private: void key_schedule(const byte[], size_t); @@ -41,7 +39,7 @@ class BOTAN_DLL Twofish : public Block_Cipher_Fixed_Params<16, 16, 32, 8> static const byte EXP_TO_POLY[255]; static const byte POLY_TO_EXP[255]; - SecureVector<u32bit> SB, RK; + secure_vector<u32bit> SB, RK; }; } diff --git a/src/block/xtea/xtea.cpp b/src/block/xtea/xtea.cpp index 597eedd07..b0c976b36 100644 --- a/src/block/xtea/xtea.cpp +++ b/src/block/xtea/xtea.cpp @@ -123,7 +123,9 @@ void XTEA::decrypt_n(const byte in[], byte out[], size_t blocks) const */ void XTEA::key_schedule(const byte key[], size_t) { - SecureVector<u32bit> UK(4); + EK.resize(64); + + secure_vector<u32bit> UK(4); for(size_t i = 0; i != 4; ++i) UK[i] = load_be<u32bit>(key, i); diff --git a/src/block/xtea/xtea.h b/src/block/xtea/xtea.h index 985e9d6d1..1d86bf5ce 100644 --- a/src/block/xtea/xtea.h +++ b/src/block/xtea/xtea.h @@ -21,20 +21,18 @@ class BOTAN_DLL XTEA : public Block_Cipher_Fixed_Params<8, 16> void encrypt_n(const byte in[], byte out[], size_t blocks) const; void decrypt_n(const byte in[], byte out[], size_t blocks) const; - void clear() { zeroise(EK); } + void clear() { EK.clear(); } std::string name() const { return "XTEA"; } BlockCipher* clone() const { return new XTEA; } - - XTEA() : EK(64) {} protected: /** * @return const reference to the key schedule */ - const SecureVector<u32bit>& get_EK() const { return EK; } + const secure_vector<u32bit>& get_EK() const { return EK; } private: void key_schedule(const byte[], size_t); - SecureVector<u32bit> EK; + secure_vector<u32bit> EK; }; } diff --git a/src/build-data/buildh.in b/src/build-data/buildh.in index b3e6f8197..4668811bc 100644 --- a/src/build-data/buildh.in +++ b/src/build-data/buildh.in @@ -26,7 +26,7 @@ #endif /* Chunk sizes */ -#define BOTAN_DEFAULT_BUFFER_SIZE 4096 +#define BOTAN_DEFAULT_BUFFER_SIZE 1024 #define BOTAN_MEM_POOL_CHUNK_SIZE 64*1024 #define BOTAN_BLOCK_CIPHER_PAR_MULT 4 diff --git a/src/build-data/cc/clang.txt b/src/build-data/cc/clang.txt index e5d52db3d..0a692e9aa 100644 --- a/src/build-data/cc/clang.txt +++ b/src/build-data/cc/clang.txt @@ -10,7 +10,7 @@ add_include_dir_option -I add_lib_dir_option -L add_lib_option -l -lang_flags "-D_REENTRANT -ansi -Wno-long-long" +lang_flags "-D_REENTRANT -std=c++0x" warning_flags "-W -Wall" makefile_style unix @@ -36,18 +36,10 @@ westmere -> "-march=corei7 -maes" </mach_opt> <mach_abi_linking> +all -> "-pthread" + x86_64 -> "-m64" -mips64 -> "-mabi=64" -s390 -> "-m31" -s390x -> "-m64" -sparc32 -> "-m32 -mno-app-regs" -sparc64 -> "-m64 -mno-app-regs" ppc64 -> "-m64" -# This should probably be used on most/all targets, but the docs are incomplete -openbsd -> "-pthread" -freebsd -> "-pthread" -dragonfly -> "-pthread" -netbsd -> "-pthread -D_NETBSD_SOURCE" -qnx -> "-fexceptions -D_QNX_SOURCE" +netbsd -> "-D_NETBSD_SOURCE" </mach_abi_linking> diff --git a/src/build-data/cc/compaq.txt b/src/build-data/cc/compaq.txt deleted file mode 100644 index 7e7f1ea56..000000000 --- a/src/build-data/cc/compaq.txt +++ /dev/null @@ -1,26 +0,0 @@ -macro_name COMPAQ - -binary_name cxx - -compile_option "-c " -output_to_option "-o " -add_include_dir_option -I -add_lib_dir_option -L -add_lib_option -l - -# -O3 and up seem to be unhappy with Botan -lib_opt_flags "-O2" -check_opt_flags "-O2" -debug_flags -g -no_debug_flags "" -lang_flags "-std ansi -D__USE_STD_IOSTREAM" - -makefile_style unix - -<so_link_flags> -default -> "$(CXX) -shared -soname $(SONAME)" -</so_link_flags> - -<mach_opt> -alpha -> "-arch=SUBMODEL" alpha- -</mach_opt> diff --git a/src/build-data/cc/gcc.txt b/src/build-data/cc/gcc.txt index 3de85099c..ccbba33fa 100644 --- a/src/build-data/cc/gcc.txt +++ b/src/build-data/cc/gcc.txt @@ -1,8 +1,6 @@ macro_name GCC -binary_name g++ - -has_tr1 yes +binary_name g++-4.8.0-r187608 compile_option "-c " output_to_option "-o " @@ -10,10 +8,10 @@ add_include_dir_option -I add_lib_dir_option -L add_lib_option -l -lang_flags "-D_REENTRANT -Wno-long-long" +lang_flags "-D_REENTRANT -std=c++0x" warning_flags "-W -Wall" -maintainer_warning_flags "-Werror -Weffc++ -Wall -Wextra -Wstrict-aliasing -Wstrict-overflow=5 -Wcast-align -Wmissing-declarations -Wpointer-arith -Wcast-qual -Wold-style-cast" +maintainer_warning_flags "-Werror -Wall -Wextra -Wstrict-aliasing -Wstrict-overflow=5 -Wcast-align -Wmissing-declarations -Wpointer-arith -Wcast-qual -Wold-style-cast -Wzero-as-null-pointer-constant" lib_opt_flags "-O3" check_opt_flags "-O2" @@ -90,18 +88,16 @@ x86_64 -> "-march=SUBMODEL -momit-leaf-frame-pointer" # The 'linking' bit means "use this for both compiling *and* linking" <mach_abi_linking> -x86_64 -> "-m64" +all -> "-pthread" + mips64 -> "-mabi=64" s390 -> "-m31" s390x -> "-m64" sparc32 -> "-m32 -mno-app-regs" sparc64 -> "-m64 -mno-app-regs" ppc64 -> "-m64" +x86_64 -> "-m64" -# This should probably be used on most/all targets, but the docs are unclear -openbsd -> "-pthread" -freebsd -> "-pthread" -dragonfly -> "-pthread" -netbsd -> "-pthread -D_NETBSD_SOURCE" -qnx -> "-fexceptions -D_QNX_SOURCE" +netbsd -> "-D_NETBSD_SOURCE" +qnx -> "-fexceptions -D_QNX_SOURCE" </mach_abi_linking> diff --git a/src/build-data/cc/icc.txt b/src/build-data/cc/icc.txt index 28c1a2816..e11875cb1 100644 --- a/src/build-data/cc/icc.txt +++ b/src/build-data/cc/icc.txt @@ -2,8 +2,6 @@ macro_name INTEL binary_name icpc -has_tr1 yes - compile_option "-c " output_to_option "-o " add_include_dir_option -I @@ -14,7 +12,7 @@ lib_opt_flags "-O2 -ip -unroll" check_opt_flags "-O2" debug_flags -g no_debug_flags "-fomit-frame-pointer" -lang_flags "" +lang_flags "-std=c++0x" warning_flags "-w1" shared_flags "-fPIC" diff --git a/src/build-data/cc/kai.txt b/src/build-data/cc/kai.txt deleted file mode 100644 index 2d9c0cd65..000000000 --- a/src/build-data/cc/kai.txt +++ /dev/null @@ -1,27 +0,0 @@ -macro_name KAI - -binary_name KCC - -compile_option "-c " -output_to_option "-o " -add_include_dir_option -I -add_lib_dir_option -L -add_lib_option -l - -ar_command "KCC -o" - -lib_opt_flags "+K3 --inline_auto_space_time=65 --abstract_pointer" -check_opt_flags "+K3" -lang_flags "-D__KAI_STRICT" -debug_flags -g -no_debug_flags "" - -makefile_style unix - -<so_link_flags> -default -> "$(CXX) --soname $(SONAME)" -</so_link_flags> - -<mach_abi_linking> -all -> "--one_per" -</mach_abi_linking> diff --git a/src/build-data/cc/mipspro.txt b/src/build-data/cc/mipspro.txt deleted file mode 100644 index 28b47b30d..000000000 --- a/src/build-data/cc/mipspro.txt +++ /dev/null @@ -1,39 +0,0 @@ -macro_name MIPSPRO - -binary_name CC - -compile_option "-c " -output_to_option "-o " -add_include_dir_option -I -add_lib_dir_option -L -add_lib_option -l - -lib_opt_flags "-O3 -OPT:alias=TYPED" -check_opt_flags "-O3 -OPT:alias=TYPED" -debug_flags "-g3" -no_debug_flags "" -shared_flags "-KPIC" -lang_flags "-ansi -LANG:ansi-for-init-scope=ON" -# Disabled, because, while my code is fine, it warns about a lot of it's own -# headers <g> -#warning_flags "-fullwarn" - -makefile_style unix - -<so_link_flags> -default -> "$(CXX) -shared -Wl,-soname,$(SONAME)" -</so_link_flags> - -<mach_opt> -mips32 -> "-mips1" -mips64 -> "-mips3" - -mips64-r5000 -> "-mips4 -r5000" -mips64-r8000 -> "-mips4 -r8000" -mips64-r10000 -> "-mips4 -r10000" -</mach_opt> - -<mach_abi_linking> -mips32 -> "-n32" -mips64 -> "-64" -</mach_abi_linking> diff --git a/src/build-data/cc/sgipro64.txt b/src/build-data/cc/sgipro64.txt deleted file mode 100644 index e6a58f16d..000000000 --- a/src/build-data/cc/sgipro64.txt +++ /dev/null @@ -1,27 +0,0 @@ -macro_name SGI_PRO64 - -binary_name sgiCC - -compile_option "-c " -output_to_option "-o " -add_include_dir_option -I -add_lib_dir_option -L -add_lib_option -l - -lib_opt_flags "-O3 -OPT:alias=TYPED" -check_opt_flags "-O3 -OPT:alias=TYPED" -debug_flags "-g3" -no_debug_flags "" -shared_flags "-KPIC" -lang_flags "-ansi -LANG:ansi-for-init-scope=ON" -warning_flags "-Wall -W" - -makefile_style unix - -<so_link_flags> -default -> "$(CXX) -shared -Wl,-soname,$(SONAME)" -</so_link_flags> - -<mach_opt> - -</mach_opt> diff --git a/src/build-data/os/windows.txt b/src/build-data/os/windows.txt index 2f344e33c..30a6b77f8 100644 --- a/src/build-data/os/windows.txt +++ b/src/build-data/os/windows.txt @@ -11,10 +11,11 @@ install_cmd_data "copy" install_cmd_exec "copy" <target_features> -win32_virtual_lock -win32_get_systemtime gmtime_s loadlibrary +win32_get_systemtime +win32_query_perf_counter +win32_virtual_lock </target_features> <aliases> diff --git a/src/cert/cvc/asn1_eac_tm.cpp b/src/cert/cvc/asn1_eac_tm.cpp index db5d2fbaf..a3a4d043d 100644 --- a/src/cert/cvc/asn1_eac_tm.cpp +++ b/src/cert/cvc/asn1_eac_tm.cpp @@ -1,7 +1,7 @@ /* * EAC Time Types * (C) 2007 FlexSecure GmbH -* 2008 Jack Lloyd +* 2008-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -12,17 +12,17 @@ #include <botan/charset.h> #include <botan/parsing.h> #include <botan/internal/rounding.h> -#include <botan/time.h> +#include <botan/calendar.h> namespace Botan { namespace { -SecureVector<byte> enc_two_digit(u32bit in) +secure_vector<byte> enc_two_digit(u32bit in) { - SecureVector<byte> result; + secure_vector<byte> result; in %= 100; - if (in < 10) + if(in < 10) result.push_back(0x00); else { @@ -51,9 +51,10 @@ u32bit dec_two_digit(byte b1, byte b2) /* * Create an EAC_Time */ -EAC_Time::EAC_Time(u64bit timer, ASN1_Tag t) : tag(t) +EAC_Time::EAC_Time(const std::chrono::system_clock::time_point& time, + ASN1_Tag t) : tag(t) { - calendar_point cal = calendar_value(timer); + calendar_point cal = calendar_value(time); year = cal.year; month = cal.month; @@ -67,6 +68,7 @@ EAC_Time::EAC_Time(const std::string& t_spec, ASN1_Tag t) : tag(t) { set_to(t_spec); } + /* * Create an EAC_Time */ @@ -80,7 +82,7 @@ EAC_Time::EAC_Time(u32bit y, u32bit m, u32bit d, ASN1_Tag t) : */ void EAC_Time::set_to(const std::string& time_str) { - if (time_str == "") + if(time_str == "") { year = month = day = 0; return; @@ -89,28 +91,28 @@ void EAC_Time::set_to(const std::string& time_str) std::vector<std::string> params; std::string current; - for (u32bit j = 0; j != time_str.size(); ++j) + for(u32bit j = 0; j != time_str.size(); ++j) { - if (Charset::is_digit(time_str[j])) + if(Charset::is_digit(time_str[j])) current += time_str[j]; else { - if (current != "") + if(current != "") params.push_back(current); current.clear(); } } - if (current != "") + if(current != "") params.push_back(current); - if (params.size() != 3) + if(params.size() != 3) throw Invalid_Argument("Invalid time specification " + time_str); year = to_u32bit(params[0]); month = to_u32bit(params[1]); day = to_u32bit(params[2]); - if (!passes_sanity_check()) + if(!passes_sanity_check()) throw Invalid_Argument("Invalid time specification " + time_str); } @@ -129,15 +131,10 @@ void EAC_Time::encode_into(DER_Encoder& der) const */ std::string EAC_Time::as_string() const { - if (time_is_set() == false) + if(time_is_set() == false) throw Invalid_State("EAC_Time::as_string: No time set"); - std::string asn1rep; - asn1rep = to_string(year, 2); - - asn1rep += to_string(month, 2) + to_string(day, 2); - - return asn1rep; + return std::to_string(year * 10000 + month * 100 + day); } /* @@ -153,15 +150,14 @@ bool EAC_Time::time_is_set() const */ std::string EAC_Time::readable_string() const { - if (time_is_set() == false) + if(time_is_set() == false) throw Invalid_State("EAC_Time::readable_string: No time set"); - std::string readable; - readable += to_string(year, 2) + "/"; - readable += to_string(month, 2) + "/"; - readable += to_string(day, 2) + " "; + std::string output(11, 0); - return readable; + std::sprintf(&output[0], "%04d/%02d/%02d", year, month, day); + + return output; } /* @@ -169,11 +165,11 @@ std::string EAC_Time::readable_string() const */ bool EAC_Time::passes_sanity_check() const { - if (year < 2000 || year > 2099) + if(year < 2000 || year > 2099) return false; - if (month == 0 || month > 12) + if(month == 0 || month > 12) return false; - if (day == 0 || day > 31) + if(day == 0 || day > 31) return false; return true; @@ -182,11 +178,11 @@ bool EAC_Time::passes_sanity_check() const /* * modification functions */ - void EAC_Time::add_years(u32bit years) { year += years; } + void EAC_Time::add_months(u32bit months) { year += months/12; @@ -198,23 +194,22 @@ void EAC_Time::add_months(u32bit months) } } - /* * Compare this time against another */ s32bit EAC_Time::cmp(const EAC_Time& other) const { - if (time_is_set() == false) + if(time_is_set() == false) throw Invalid_State("EAC_Time::cmp: No time set"); const s32bit EARLIER = -1, LATER = 1, SAME_TIME = 0; - if (year < other.year) return EARLIER; - if (year > other.year) return LATER; - if (month < other.month) return EARLIER; - if (month > other.month) return LATER; - if (day < other.day) return EARLIER; - if (day > other.day) return LATER; + if(year < other.year) return EARLIER; + if(year > other.year) return LATER; + if(month < other.month) return EARLIER; + if(month > other.month) return LATER; + if(day < other.day) return EARLIER; + if(day > other.day) return LATER; return SAME_TIME; } @@ -283,61 +278,16 @@ void EAC_Time::decode_from(BER_Decoder& source) } -u32bit EAC_Time::get_year() const - { - return year; - } - -u32bit EAC_Time::get_month() const - { - return month; - } - -u32bit EAC_Time::get_day() const - { - return day; - } - /* * make the value an octet string for encoding */ -SecureVector<byte> EAC_Time::encoded_eac_time() const +secure_vector<byte> EAC_Time::encoded_eac_time() const { - SecureVector<byte> result; + secure_vector<byte> result; result += enc_two_digit(year); result += enc_two_digit(month); result += enc_two_digit(day); return result; } -ASN1_Ced::ASN1_Ced(std::string const& str) : - EAC_Time(str, ASN1_Tag(37)) - {} - -ASN1_Ced::ASN1_Ced(u64bit val) : - EAC_Time(val, ASN1_Tag(37)) - {} - -ASN1_Ced::ASN1_Ced(EAC_Time const& other) : - EAC_Time(other.get_year(), - other.get_month(), - other.get_day(), - ASN1_Tag(37)) - {} - -ASN1_Cex::ASN1_Cex(std::string const& str) : - EAC_Time(str, ASN1_Tag(36)) - {} - -ASN1_Cex::ASN1_Cex(u64bit val) : - EAC_Time(val, ASN1_Tag(36)) - {} - -ASN1_Cex::ASN1_Cex(EAC_Time const& other) : - EAC_Time(other.get_year(), - other.get_month(), - other.get_day(), - ASN1_Tag(36)) - {} - } diff --git a/src/cert/cvc/cvc_ado.cpp b/src/cert/cvc/cvc_ado.cpp index 38f51e8dc..f224d15b9 100644 --- a/src/cert/cvc/cvc_ado.cpp +++ b/src/cert/cvc/cvc_ado.cpp @@ -26,7 +26,7 @@ EAC1_1_ADO::EAC1_1_ADO(const std::string& in) void EAC1_1_ADO::force_decode() { - SecureVector<byte> inner_cert; + secure_vector<byte> inner_cert; BER_Decoder(tbs_bits) .start_cons(ASN1_Tag(33)) .raw_bytes(inner_cert) @@ -34,7 +34,7 @@ void EAC1_1_ADO::force_decode() .decode(m_car) .verify_end(); - SecureVector<byte> req_bits = DER_Encoder() + secure_vector<byte> req_bits = DER_Encoder() .start_cons(ASN1_Tag(33), APPLICATION) .raw_bytes(inner_cert) .end_cons() @@ -45,11 +45,11 @@ void EAC1_1_ADO::force_decode() sig_algo = m_req.sig_algo; } -MemoryVector<byte> EAC1_1_ADO::make_signed(PK_Signer& signer, - const MemoryRegion<byte>& tbs_bits, +std::vector<byte> EAC1_1_ADO::make_signed(PK_Signer& signer, + const secure_vector<byte>& tbs_bits, RandomNumberGenerator& rng) { - SecureVector<byte> concat_sig = signer.sign_message(tbs_bits, rng); + secure_vector<byte> concat_sig = signer.sign_message(tbs_bits, rng); return DER_Encoder() .start_cons(ASN1_Tag(7), APPLICATION) @@ -65,11 +65,11 @@ ASN1_Car EAC1_1_ADO::get_car() const } void EAC1_1_ADO::decode_info(DataSource& source, - SecureVector<byte> & res_tbs_bits, + secure_vector<byte> & res_tbs_bits, ECDSA_Signature & res_sig) { - SecureVector<byte> concat_sig; - SecureVector<byte> cert_inner_bits; + secure_vector<byte> concat_sig; + secure_vector<byte> cert_inner_bits; ASN1_Car car; BER_Decoder(source) @@ -81,7 +81,7 @@ void EAC1_1_ADO::decode_info(DataSource& source, .decode(concat_sig, OCTET_STRING, ASN1_Tag(55), APPLICATION) .end_cons(); - SecureVector<byte> enc_cert = DER_Encoder() + secure_vector<byte> enc_cert = DER_Encoder() .start_cons(ASN1_Tag(33), APPLICATION) .raw_bytes(cert_inner_bits) .end_cons() @@ -97,7 +97,7 @@ void EAC1_1_ADO::encode(Pipe& out, X509_Encoding encoding) const if(encoding == PEM) throw Invalid_Argument("EAC1_1_ADO::encode() cannot PEM encode an EAC object"); - SecureVector<byte> concat_sig( + secure_vector<byte> concat_sig( EAC1_1_obj<EAC1_1_ADO>::m_sig.get_concatenation()); out.write(DER_Encoder() @@ -108,7 +108,7 @@ void EAC1_1_ADO::encode(Pipe& out, X509_Encoding encoding) const .get_contents()); } -SecureVector<byte> EAC1_1_ADO::tbs_data() const +secure_vector<byte> EAC1_1_ADO::tbs_data() const { return tbs_bits; } diff --git a/src/cert/cvc/cvc_ado.h b/src/cert/cvc/cvc_ado.h index 65a39fd91..81b89ea00 100644 --- a/src/cert/cvc/cvc_ado.h +++ b/src/cert/cvc/cvc_ado.h @@ -43,9 +43,9 @@ class BOTAN_DLL EAC1_1_ADO : public EAC1_1_obj<EAC1_1_ADO> * @param tbs_bits the TBS data to sign * @param rng a random number generator */ - static MemoryVector<byte> make_signed( + static std::vector<byte> make_signed( PK_Signer& signer, - const MemoryRegion<byte>& tbs_bits, + const secure_vector<byte>& tbs_bits, RandomNumberGenerator& rng); /** @@ -73,7 +73,7 @@ class BOTAN_DLL EAC1_1_ADO : public EAC1_1_obj<EAC1_1_ADO> * Get the TBS data of this CVC ADO request. * @result the TBS data */ - SecureVector<byte> tbs_data() const; + secure_vector<byte> tbs_data() const; virtual ~EAC1_1_ADO() {} private: @@ -82,7 +82,7 @@ class BOTAN_DLL EAC1_1_ADO : public EAC1_1_obj<EAC1_1_ADO> void force_decode(); static void decode_info(DataSource& source, - SecureVector<byte> & res_tbs_bits, + secure_vector<byte> & res_tbs_bits, ECDSA_Signature & res_sig); }; diff --git a/src/cert/cvc/cvc_cert.cpp b/src/cert/cvc/cvc_cert.cpp index 54f72ecfc..12558bb80 100644 --- a/src/cert/cvc/cvc_cert.cpp +++ b/src/cert/cvc/cvc_cert.cpp @@ -33,8 +33,8 @@ u32bit EAC1_1_CVC::get_chat_value() const */ void EAC1_1_CVC::force_decode() { - SecureVector<byte> enc_pk; - SecureVector<byte> enc_chat_val; + secure_vector<byte> enc_pk; + secure_vector<byte> enc_chat_val; size_t cpi; BER_Decoder tbs_cert(tbs_bits); tbs_cert.decode(cpi, ASN1_Tag(41), APPLICATION) @@ -88,7 +88,7 @@ bool EAC1_1_CVC::operator==(EAC1_1_CVC const& rhs) const && get_concat_sig() == rhs.get_concat_sig()); } -ECDSA_PublicKey* decode_eac1_1_key(const MemoryRegion<byte>&, +ECDSA_PublicKey* decode_eac1_1_key(const secure_vector<byte>&, AlgorithmIdentifier&) { throw Internal_Error("decode_eac1_1_key: Unimplemented"); @@ -96,7 +96,7 @@ ECDSA_PublicKey* decode_eac1_1_key(const MemoryRegion<byte>&, } EAC1_1_CVC make_cvc_cert(PK_Signer& signer, - MemoryRegion<byte> const& public_key, + secure_vector<byte> const& public_key, ASN1_Car const& car, ASN1_Chr const& chr, byte holder_auth_templ, @@ -105,12 +105,12 @@ EAC1_1_CVC make_cvc_cert(PK_Signer& signer, RandomNumberGenerator& rng) { OID chat_oid(OIDS::lookup("CertificateHolderAuthorizationTemplate")); - MemoryVector<byte> enc_chat_val; + std::vector<byte> enc_chat_val; enc_chat_val.push_back(holder_auth_templ); - MemoryVector<byte> enc_cpi; + std::vector<byte> enc_cpi; enc_cpi.push_back(0x00); - MemoryVector<byte> tbs = DER_Encoder() + std::vector<byte> tbs = DER_Encoder() .encode(enc_cpi, OCTET_STRING, ASN1_Tag(41), APPLICATION) // cpi .encode(car) .raw_bytes(public_key) @@ -123,7 +123,7 @@ EAC1_1_CVC make_cvc_cert(PK_Signer& signer, .encode(cex) .get_contents(); - MemoryVector<byte> signed_cert = + std::vector<byte> signed_cert = EAC1_1_CVC::make_signed(signer, EAC1_1_CVC::build_cert_body(tbs), rng); diff --git a/src/cert/cvc/cvc_cert.h b/src/cert/cvc/cvc_cert.h index 69d0d824a..20370e64b 100644 --- a/src/cert/cvc/cvc_cert.h +++ b/src/cert/cvc/cvc_cert.h @@ -96,7 +96,7 @@ inline bool operator!=(EAC1_1_CVC const& lhs, EAC1_1_CVC const& rhs) * @param rng a random number generator */ EAC1_1_CVC BOTAN_DLL make_cvc_cert(PK_Signer& signer, - const MemoryRegion<byte>& public_key, + const secure_vector<byte>& public_key, ASN1_Car const& car, ASN1_Chr const& chr, byte holder_auth_templ, @@ -107,7 +107,7 @@ EAC1_1_CVC BOTAN_DLL make_cvc_cert(PK_Signer& signer, /** * Decode an EAC encoding ECDSA key */ -BOTAN_DLL ECDSA_PublicKey* decode_eac1_1_key(const MemoryRegion<byte>& enc_key, +BOTAN_DLL ECDSA_PublicKey* decode_eac1_1_key(const secure_vector<byte>& enc_key, AlgorithmIdentifier& sig_algo); } diff --git a/src/cert/cvc/cvc_gen_cert.h b/src/cert/cvc/cvc_gen_cert.h index ad61b85bf..a272e316f 100644 --- a/src/cert/cvc/cvc_gen_cert.h +++ b/src/cert/cvc/cvc_gen_cert.h @@ -56,14 +56,14 @@ class EAC1_1_gen_CVC : public EAC1_1_obj<Derived> // CRTP continuation from EAC1 * Get the to-be-signed (TBS) data of this object. * @result the TBS data of this object */ - SecureVector<byte> tbs_data() const; + secure_vector<byte> tbs_data() const; /** * Build the DER encoded certifcate body of an object * @param tbs the data to be signed * @result the correctly encoded body of the object */ - static SecureVector<byte> build_cert_body(MemoryRegion<byte> const& tbs); + static secure_vector<byte> build_cert_body(secure_vector<byte> const& tbs); /** * Create a signed generalized CVC object. @@ -72,9 +72,9 @@ class EAC1_1_gen_CVC : public EAC1_1_obj<Derived> // CRTP continuation from EAC1 * @param rng a random number generator * @result the DER encoded signed generalized CVC object */ - static MemoryVector<byte> make_signed( + static std::vector<byte> make_signed( PK_Signer& signer, - const MemoryRegion<byte>& tbs_bits, + const secure_vector<byte>& tbs_bits, RandomNumberGenerator& rng); EAC1_1_gen_CVC() { m_pk = 0; } @@ -88,7 +88,7 @@ class EAC1_1_gen_CVC : public EAC1_1_obj<Derived> // CRTP continuation from EAC1 bool self_signed; static void decode_info(DataSource& source, - SecureVector<byte> & res_tbs_bits, + secure_vector<byte> & res_tbs_bits, ECDSA_Signature & res_sig); }; @@ -104,12 +104,12 @@ template<typename Derived> bool EAC1_1_gen_CVC<Derived>::is_self_signed() const } template<typename Derived> -MemoryVector<byte> EAC1_1_gen_CVC<Derived>::make_signed( +std::vector<byte> EAC1_1_gen_CVC<Derived>::make_signed( PK_Signer& signer, - const MemoryRegion<byte>& tbs_bits, + const secure_vector<byte>& tbs_bits, RandomNumberGenerator& rng) // static { - SecureVector<byte> concat_sig = signer.sign_message(tbs_bits, rng); + secure_vector<byte> concat_sig = signer.sign_message(tbs_bits, rng); return DER_Encoder() .start_cons(ASN1_Tag(33), APPLICATION) @@ -125,7 +125,7 @@ Public_Key* EAC1_1_gen_CVC<Derived>::subject_public_key() const return new ECDSA_PublicKey(*m_pk); } -template<typename Derived> SecureVector<byte> EAC1_1_gen_CVC<Derived>::build_cert_body(MemoryRegion<byte> const& tbs) +template<typename Derived> secure_vector<byte> EAC1_1_gen_CVC<Derived>::build_cert_body(secure_vector<byte> const& tbs) { return DER_Encoder() .start_cons(ASN1_Tag(78), APPLICATION) @@ -133,15 +133,15 @@ template<typename Derived> SecureVector<byte> EAC1_1_gen_CVC<Derived>::build_cer .end_cons().get_contents(); } -template<typename Derived> SecureVector<byte> EAC1_1_gen_CVC<Derived>::tbs_data() const +template<typename Derived> secure_vector<byte> EAC1_1_gen_CVC<Derived>::tbs_data() const { return build_cert_body(EAC1_1_obj<Derived>::tbs_bits); } template<typename Derived> void EAC1_1_gen_CVC<Derived>::encode(Pipe& out, X509_Encoding encoding) const { - SecureVector<byte> concat_sig(EAC1_1_obj<Derived>::m_sig.get_concatenation()); - SecureVector<byte> der = DER_Encoder() + secure_vector<byte> concat_sig(EAC1_1_obj<Derived>::m_sig.get_concatenation()); + secure_vector<byte> der = DER_Encoder() .start_cons(ASN1_Tag(33), APPLICATION) .start_cons(ASN1_Tag(78), APPLICATION) .raw_bytes(EAC1_1_obj<Derived>::tbs_bits) @@ -159,10 +159,10 @@ template<typename Derived> void EAC1_1_gen_CVC<Derived>::encode(Pipe& out, X509_ template<typename Derived> void EAC1_1_gen_CVC<Derived>::decode_info( DataSource& source, - SecureVector<byte> & res_tbs_bits, + secure_vector<byte> & res_tbs_bits, ECDSA_Signature & res_sig) { - SecureVector<byte> concat_sig; + secure_vector<byte> concat_sig; BER_Decoder(source) .start_cons(ASN1_Tag(33)) .start_cons(ASN1_Tag(78)) diff --git a/src/cert/cvc/cvc_req.cpp b/src/cert/cvc/cvc_req.cpp index ad9e2f4ca..bd7dee3fa 100644 --- a/src/cert/cvc/cvc_req.cpp +++ b/src/cert/cvc/cvc_req.cpp @@ -19,7 +19,7 @@ bool EAC1_1_Req::operator==(EAC1_1_Req const& rhs) const void EAC1_1_Req::force_decode() { - SecureVector<byte> enc_pk; + secure_vector<byte> enc_pk; BER_Decoder tbs_cert(tbs_bits); size_t cpi; tbs_cert.decode(cpi, ASN1_Tag(41), APPLICATION) diff --git a/src/cert/cvc/cvc_req.h b/src/cert/cvc/cvc_req.h index 1e8cea7f8..ac4e22453 100644 --- a/src/cert/cvc/cvc_req.h +++ b/src/cert/cvc/cvc_req.h @@ -35,7 +35,7 @@ class BOTAN_DLL EAC1_1_Req : public EAC1_1_gen_CVC<EAC1_1_Req> EAC1_1_Req(DataSource& source); /** - * Construct a CVC request from a DER encoded CVC reqeust file. + * Construct a CVC request from a DER encoded CVC request file. * @param str the path to the DER encoded file */ EAC1_1_Req(const std::string& str); diff --git a/src/cert/cvc/cvc_self.cpp b/src/cert/cvc/cvc_self.cpp index 662a1d2be..e692bc9b8 100644 --- a/src/cert/cvc/cvc_self.cpp +++ b/src/cert/cvc/cvc_self.cpp @@ -8,7 +8,6 @@ #include <botan/cvc_self.h> #include <botan/ecc_key.h> #include <botan/point_gfp.h> -#include <botan/time.h> #include <botan/oids.h> #include <sstream> #include <memory> @@ -35,7 +34,7 @@ void encode_eac_bigint(DER_Encoder& der, const BigInt& x, ASN1_Tag tag) der.encode(BigInt::encode_1363(x, x.bytes()), OCTET_STRING, tag); } -MemoryVector<byte> eac_1_1_encoding(const EC_PublicKey* key, +std::vector<byte> eac_1_1_encoding(const EC_PublicKey* key, const OID& sig_algo) { if(key->domain_format() == EC_DOMPAR_ENC_OID) @@ -107,7 +106,7 @@ EAC1_1_CVC create_self_signed_cert(Private_Key const& key, PK_Signer signer(*priv_key, padding_and_hash); - MemoryVector<byte> enc_public_key = eac_1_1_encoding(priv_key, sig_algo.oid); + std::vector<byte> enc_public_key = eac_1_1_encoding(priv_key, sig_algo.oid); return make_cvc_cert(signer, enc_public_key, @@ -134,17 +133,17 @@ EAC1_1_Req create_cvc_req(Private_Key const& key, PK_Signer signer(*priv_key, padding_and_hash); - MemoryVector<byte> enc_public_key = eac_1_1_encoding(priv_key, sig_algo.oid); + std::vector<byte> enc_public_key = eac_1_1_encoding(priv_key, sig_algo.oid); - MemoryVector<byte> enc_cpi; + std::vector<byte> enc_cpi; enc_cpi.push_back(0x00); - MemoryVector<byte> tbs = DER_Encoder() + std::vector<byte> tbs = DER_Encoder() .encode(enc_cpi, OCTET_STRING, ASN1_Tag(41), APPLICATION) .raw_bytes(enc_public_key) .encode(chr) .get_contents(); - MemoryVector<byte> signed_cert = + std::vector<byte> signed_cert = EAC1_1_gen_CVC<EAC1_1_Req>::make_signed(signer, EAC1_1_gen_CVC<EAC1_1_Req>::build_cert_body(tbs), rng); @@ -164,12 +163,13 @@ EAC1_1_ADO create_ado_req(Private_Key const& key, { throw Invalid_Argument("CVC_EAC::create_self_signed_cert(): unsupported key type"); } + std::string padding_and_hash = padding_and_hash_from_oid(req.signature_algorithm().oid); PK_Signer signer(*priv_key, padding_and_hash); - SecureVector<byte> tbs_bits = req.BER_encode(); + secure_vector<byte> tbs_bits = req.BER_encode(); tbs_bits += DER_Encoder().encode(car).get_contents(); - MemoryVector<byte> signed_cert = + std::vector<byte> signed_cert = EAC1_1_ADO::make_signed(signer, tbs_bits, rng); DataSource_Memory source(signed_cert); @@ -193,9 +193,8 @@ EAC1_1_CVC create_cvca(Private_Key const& key, } EAC1_1_CVC_Options opts; opts.car = car; - const u64bit current_time = system_time(); - opts.ced = ASN1_Ced(current_time); + opts.ced = ASN1_Ced(std::chrono::system_clock::now()); opts.cex = ASN1_Cex(opts.ced); opts.cex.add_months(cvca_validity_months); opts.holder_auth_templ = (CVCA | (iris * IRIS) | (fingerpr * FINGERPRINT)); @@ -210,12 +209,12 @@ EAC1_1_CVC link_cvca(EAC1_1_CVC const& signer, EAC1_1_CVC const& signee, RandomNumberGenerator& rng) { - ECDSA_PrivateKey const* priv_key = dynamic_cast<ECDSA_PrivateKey const*>(&key); + const ECDSA_PrivateKey* priv_key = dynamic_cast<ECDSA_PrivateKey const*>(&key); + if (priv_key == 0) - { - throw Invalid_Argument("CVC_EAC::create_self_signed_cert(): unsupported key type"); - } - ASN1_Ced ced(system_time()); + throw Invalid_Argument("link_cvca(): unsupported key type"); + + ASN1_Ced ced(std::chrono::system_clock::now()); ASN1_Cex cex(signee.get_cex()); if (*static_cast<EAC_Time*>(&ced) > *static_cast<EAC_Time*>(&cex)) { @@ -232,11 +231,11 @@ EAC1_1_CVC link_cvca(EAC1_1_CVC const& signer, AlgorithmIdentifier sig_algo = signer.signature_algorithm(); std::string padding_and_hash = padding_and_hash_from_oid(sig_algo.oid); PK_Signer pk_signer(*priv_key, padding_and_hash); - std::auto_ptr<Public_Key> pk(signee.subject_public_key()); + std::unique_ptr<Public_Key> pk(signee.subject_public_key()); ECDSA_PublicKey* subj_pk = dynamic_cast<ECDSA_PublicKey*>(pk.get()); subj_pk->set_parameter_encoding(EC_DOMPAR_ENC_EXPLICIT); - MemoryVector<byte> enc_public_key = eac_1_1_encoding(priv_key, sig_algo.oid); + std::vector<byte> enc_public_key = eac_1_1_encoding(priv_key, sig_algo.oid); return make_cvc_cert(pk_signer, enc_public_key, signer.get_car(), @@ -262,13 +261,19 @@ EAC1_1_CVC sign_request(EAC1_1_CVC const& signer_cert, throw Invalid_Argument("CVC_EAC::create_self_signed_cert(): unsupported key type"); } std::string chr_str = signee.get_chr().value(); - chr_str += to_string(seqnr, seqnr_len); + + std::string seqnr_string = std::to_string(seqnr); + + while(seqnr_string.size() < seqnr_len) + seqnr_string = '0' + seqnr_string; + + chr_str += seqnr_string; ASN1_Chr chr(chr_str); std::string padding_and_hash = padding_and_hash_from_oid(signee.signature_algorithm().oid); PK_Signer pk_signer(*priv_key, padding_and_hash); - std::auto_ptr<Public_Key> pk(signee.subject_public_key()); + std::unique_ptr<Public_Key> pk(signee.subject_public_key()); ECDSA_PublicKey* subj_pk = dynamic_cast<ECDSA_PublicKey*>(pk.get()); - std::auto_ptr<Public_Key> signer_pk(signer_cert.subject_public_key()); + std::unique_ptr<Public_Key> signer_pk(signer_cert.subject_public_key()); // for the case that the domain parameters are not set... // (we use those from the signer because they must fit) @@ -277,8 +282,9 @@ EAC1_1_CVC sign_request(EAC1_1_CVC const& signer_cert, subj_pk->set_parameter_encoding(EC_DOMPAR_ENC_IMPLICITCA); AlgorithmIdentifier sig_algo(signer_cert.signature_algorithm()); - const u64bit current_time = system_time(); - ASN1_Ced ced(current_time); + + ASN1_Ced ced(std::chrono::system_clock::now()); + u32bit chat_val; u32bit chat_low = signer_cert.get_chat_value() & 0x3; // take the chat rights from signer ASN1_Cex cex(ced); @@ -303,7 +309,7 @@ EAC1_1_CVC sign_request(EAC1_1_CVC const& signer_cert, // (IS cannot sign certificates) } - MemoryVector<byte> enc_public_key = eac_1_1_encoding(priv_key, sig_algo.oid); + std::vector<byte> enc_public_key = eac_1_1_encoding(priv_key, sig_algo.oid); return make_cvc_cert(pk_signer, enc_public_key, ASN1_Car(signer_cert.get_chr().iso_8859()), diff --git a/src/cert/cvc/eac_asn_obj.h b/src/cert/cvc/eac_asn_obj.h index d0bab6fdd..9937abb01 100644 --- a/src/cert/cvc/eac_asn_obj.h +++ b/src/cert/cvc/eac_asn_obj.h @@ -56,7 +56,6 @@ class BOTAN_DLL EAC_Time : public ASN1_Object * e.g. "2007 08 01" */ void set_to(const std::string& str); - //void set_to(const std::string&, ASN1_Tag); /** * Add the specified number of years to this. @@ -74,28 +73,32 @@ class BOTAN_DLL EAC_Time : public ASN1_Object * Get the year value of this objects. * @return year value */ - u32bit get_year() const; + u32bit get_year() const { return year; } /** * Get the month value of this objects. * @return month value */ - u32bit get_month() const; + u32bit get_month() const { return month; } /** * Get the day value of this objects. * @return day value */ - u32bit get_day() const; + u32bit get_day() const { return day; } - EAC_Time(u64bit, ASN1_Tag t = ASN1_Tag(0)); - //EAC_Time(const std::string& = ""); - EAC_Time(const std::string&, ASN1_Tag = ASN1_Tag(0)); - EAC_Time(u32bit year, u32bit month, u32bit day, ASN1_Tag = ASN1_Tag(0)); + EAC_Time(const std::chrono::system_clock::time_point& time, + ASN1_Tag tag = ASN1_Tag(0)); + + EAC_Time(const std::string& yyyy_mm_dd, + ASN1_Tag tag = ASN1_Tag(0)); + + EAC_Time(u32bit year, u32bit month, u32bit day, + ASN1_Tag tag = ASN1_Tag(0)); virtual ~EAC_Time() {} private: - SecureVector<byte> encoded_eac_time() const; + secure_vector<byte> encoded_eac_time() const; bool passes_sanity_check() const; u32bit year, month, day; ASN1_Tag tag; @@ -113,25 +116,25 @@ class BOTAN_DLL ASN1_Ced : public EAC_Time * @param str a string in the format "yyyy mm dd", * e.g. "2007 08 01" */ - ASN1_Ced(std::string const& str = ""); + ASN1_Ced(const std::string& str = "") : + EAC_Time(str, ASN1_Tag(37)) {} /** - * Construct a CED from a timer value. - * @param time the number of seconds elapsed midnight, 1st - * January 1970 GMT (or 7pm, 31st December 1969 EST) up to the - * desired date + * Construct a CED from a time point */ - ASN1_Ced(u64bit time); + ASN1_Ced(const std::chrono::system_clock::time_point& time) : + EAC_Time(time, ASN1_Tag(37)) {} /** * Copy constructor (for general EAC_Time objects). * @param other the object to copy from */ - ASN1_Ced(EAC_Time const& other); - //ASN1_Ced(ASN1_Cex const& cex); + ASN1_Ced(const EAC_Time& other) : + EAC_Time(other.get_year(), other.get_month(), other.get_day(), + ASN1_Tag(37)) + {} }; - /** * This class represents CVC CEXs. Only limited sanity checks of * the inputted date value are performed. @@ -140,27 +143,20 @@ class BOTAN_DLL ASN1_Cex : public EAC_Time { public: /** - * Construct a CED from a string value. + * Construct a CEX from a string value. * @param str a string in the format "yyyy mm dd", * e.g. "2007 08 01" */ - ASN1_Cex(std::string const& str=""); + ASN1_Cex(const std::string& str = "") : + EAC_Time(str, ASN1_Tag(36)) {} - /** - * Construct a CED from a timer value. - * @param time the number of seconds elapsed - * midnight, 1st - * January 1970 GMT (or 7pm, 31st December 1969 EST) - * up to the desired date - */ - ASN1_Cex(u64bit time); + ASN1_Cex(const std::chrono::system_clock::time_point& time) : + EAC_Time(time, ASN1_Tag(36)) {} - /** - * Copy constructor (for general EAC_Time objects). - * @param other the object to copy from - */ - ASN1_Cex(EAC_Time const& other); - //ASN1_Cex(ASN1_Ced const& ced); + ASN1_Cex(const EAC_Time& other) : + EAC_Time(other.get_year(), other.get_month(), other.get_day(), + ASN1_Tag(36)) + {} }; /** diff --git a/src/cert/cvc/eac_obj.h b/src/cert/cvc/eac_obj.h index eb6db3369..39f34b874 100644 --- a/src/cert/cvc/eac_obj.h +++ b/src/cert/cvc/eac_obj.h @@ -24,7 +24,7 @@ class EAC1_1_obj : public EAC_Signed_Object * Return the signature as a concatenation of the encoded parts. * @result the concatenated signature */ - SecureVector<byte> get_concat_sig() const + secure_vector<byte> get_concat_sig() const { return m_sig.get_concatenation(); } bool check_signature(class Public_Key& key) const diff --git a/src/cert/cvc/ecdsa_sig.cpp b/src/cert/cvc/ecdsa_sig.cpp index e8fd7f051..91166ad79 100644 --- a/src/cert/cvc/ecdsa_sig.cpp +++ b/src/cert/cvc/ecdsa_sig.cpp @@ -10,7 +10,7 @@ namespace Botan { -ECDSA_Signature::ECDSA_Signature(const MemoryRegion<byte>& ber) +ECDSA_Signature::ECDSA_Signature(const secure_vector<byte>& ber) { BER_Decoder(ber) .start_cons(SEQUENCE) @@ -20,7 +20,7 @@ ECDSA_Signature::ECDSA_Signature(const MemoryRegion<byte>& ber) .verify_end(); } -MemoryVector<byte> ECDSA_Signature::DER_encode() const +std::vector<byte> ECDSA_Signature::DER_encode() const { return DER_Encoder() .start_cons(SEQUENCE) @@ -30,20 +30,20 @@ MemoryVector<byte> ECDSA_Signature::DER_encode() const .get_contents(); } -MemoryVector<byte> ECDSA_Signature::get_concatenation() const +std::vector<byte> ECDSA_Signature::get_concatenation() const { // use the larger const size_t enc_len = m_r > m_s ? m_r.bytes() : m_s.bytes(); - SecureVector<byte> sv_r = BigInt::encode_1363(m_r, enc_len); - SecureVector<byte> sv_s = BigInt::encode_1363(m_s, enc_len); + secure_vector<byte> sv_r = BigInt::encode_1363(m_r, enc_len); + secure_vector<byte> sv_s = BigInt::encode_1363(m_s, enc_len); - SecureVector<byte> result(sv_r); + secure_vector<byte> result(sv_r); result += sv_s; return result; } -ECDSA_Signature decode_concatenation(const MemoryRegion<byte>& concat) +ECDSA_Signature decode_concatenation(const secure_vector<byte>& concat) { if(concat.size() % 2 != 0) throw Invalid_Argument("Erroneous length of signature"); diff --git a/src/cert/cvc/ecdsa_sig.h b/src/cert/cvc/ecdsa_sig.h index a92052470..a92d5078c 100644 --- a/src/cert/cvc/ecdsa_sig.h +++ b/src/cert/cvc/ecdsa_sig.h @@ -27,7 +27,7 @@ class BOTAN_DLL ECDSA_Signature ECDSA_Signature(const BigInt& r, const BigInt& s) : m_r(r), m_s(s) {} - ECDSA_Signature(const MemoryRegion<byte>& ber); + ECDSA_Signature(const secure_vector<byte>& ber); const BigInt& get_r() const { return m_r; } const BigInt& get_s() const { return m_s; } @@ -35,9 +35,9 @@ class BOTAN_DLL ECDSA_Signature /** * return the r||s */ - MemoryVector<byte> get_concatenation() const; + std::vector<byte> get_concatenation() const; - MemoryVector<byte> DER_encode() const; + std::vector<byte> DER_encode() const; bool operator==(const ECDSA_Signature& other) const { @@ -54,7 +54,7 @@ inline bool operator!=(const ECDSA_Signature& lhs, const ECDSA_Signature& rhs) return !(lhs == rhs); } -ECDSA_Signature decode_concatenation(const MemoryRegion<byte>& concatenation); +ECDSA_Signature decode_concatenation(const secure_vector<byte>& concatenation); } diff --git a/src/cert/cvc/info.txt b/src/cert/cvc/info.txt index 33a872053..3cf759188 100644 --- a/src/cert/cvc/info.txt +++ b/src/cert/cvc/info.txt @@ -1,5 +1,4 @@ define CARD_VERIFIABLE_CERTIFICATES - load_on request <header:public> diff --git a/src/cert/cvc/signed_obj.cpp b/src/cert/cvc/signed_obj.cpp index d6aa2f02b..4f04cd72e 100644 --- a/src/cert/cvc/signed_obj.cpp +++ b/src/cert/cvc/signed_obj.cpp @@ -16,7 +16,7 @@ namespace Botan { /* * Return a BER encoded X.509 object */ -SecureVector<byte> EAC_Signed_Object::BER_encode() const +secure_vector<byte> EAC_Signed_Object::BER_encode() const { Pipe ber; ber.start_msg(); @@ -46,7 +46,7 @@ AlgorithmIdentifier EAC_Signed_Object::signature_algorithm() const } bool EAC_Signed_Object::check_signature(Public_Key& pub_key, - const MemoryRegion<byte>& sig) const + const secure_vector<byte>& sig) const { try { @@ -62,7 +62,7 @@ bool EAC_Signed_Object::check_signature(Public_Key& pub_key, Signature_Format format = (pub_key.message_parts() >= 2) ? DER_SEQUENCE : IEEE_1363; - SecureVector<byte> to_sign = tbs_data(); + secure_vector<byte> to_sign = tbs_data(); PK_Verifier verifier(pub_key, padding, format); return verifier.verify_message(to_sign, sig); diff --git a/src/cert/cvc/signed_obj.h b/src/cert/cvc/signed_obj.h index 20f0e7b14..45bd2858e 100644 --- a/src/cert/cvc/signed_obj.h +++ b/src/cert/cvc/signed_obj.h @@ -26,7 +26,7 @@ class BOTAN_DLL EAC_Signed_Object * Get the TBS (to-be-signed) data in this object. * @return DER encoded TBS data of this object */ - virtual SecureVector<byte> tbs_data() const = 0; + virtual secure_vector<byte> tbs_data() const = 0; /** * Get the signature of this object as a concatenation, i.e. if the @@ -39,7 +39,7 @@ class BOTAN_DLL EAC_Signed_Object NOTE: this is here only because abstract signature objects have not yet been introduced */ - virtual SecureVector<byte> get_concat_sig() const = 0; + virtual secure_vector<byte> get_concat_sig() const = 0; /** * Get the signature algorithm identifier used to sign this object. @@ -55,7 +55,7 @@ class BOTAN_DLL EAC_Signed_Object * associated with this public key */ bool check_signature(class Public_Key& key, - const MemoryRegion<byte>& sig) const; + const secure_vector<byte>& sig) const; /** * Write this object DER encoded into a specified pipe. @@ -69,7 +69,7 @@ class BOTAN_DLL EAC_Signed_Object * BER encode this object. * @return result containing the BER representation of this object. */ - SecureVector<byte> BER_encode() const; + secure_vector<byte> BER_encode() const; /** * PEM encode this object. @@ -83,7 +83,7 @@ class BOTAN_DLL EAC_Signed_Object EAC_Signed_Object() {} AlgorithmIdentifier sig_algo; - SecureVector<byte> tbs_bits; + secure_vector<byte> tbs_bits; std::string PEM_label_pref; std::vector<std::string> PEM_labels_allowed; private: diff --git a/src/cert/x509/certstor.cpp b/src/cert/x509/certstor.cpp index de27361ed..293072785 100644 --- a/src/cert/x509/certstor.cpp +++ b/src/cert/x509/certstor.cpp @@ -32,7 +32,7 @@ void Certificate_Store_In_Memory::add_certificate(const X509_Certificate& cert) std::vector<X509_Certificate> Certificate_Store_In_Memory::find_cert_by_subject_and_key_id( const X509_DN& subject_dn, - const MemoryRegion<byte>& key_id) const + const std::vector<byte>& key_id) const { std::vector<X509_Certificate> result; @@ -41,7 +41,7 @@ Certificate_Store_In_Memory::find_cert_by_subject_and_key_id( // Only compare key ids if set in both call and in the cert if(key_id.size()) { - MemoryVector<byte> skid = certs[i].subject_key_id(); + std::vector<byte> skid = certs[i].subject_key_id(); if(skid.size() && skid != key_id) // no match continue; @@ -76,7 +76,7 @@ void Certificate_Store_In_Memory::add_crl(const X509_CRL& crl) std::vector<X509_CRL> Certificate_Store_In_Memory::find_crl_by_issuer_and_key_id( const X509_DN& issuer_dn, - const MemoryRegion<byte>& key_id) const + const std::vector<byte>& key_id) const { std::vector<X509_CRL> result; @@ -85,7 +85,7 @@ Certificate_Store_In_Memory::find_crl_by_issuer_and_key_id( // Only compare key ids if set in both call and in the CRL if(key_id.size()) { - MemoryVector<byte> akid = crls[i].authority_key_id(); + std::vector<byte> akid = crls[i].authority_key_id(); if(akid.size() && akid != key_id) // no match continue; diff --git a/src/cert/x509/certstor.h b/src/cert/x509/certstor.h index e2727c569..584259f8c 100644 --- a/src/cert/x509/certstor.h +++ b/src/cert/x509/certstor.h @@ -39,7 +39,7 @@ class BOTAN_DLL Certificate_Store virtual std::vector<X509_Certificate> find_cert_by_subject_and_key_id( const X509_DN& subject_dn, - const MemoryRegion<byte>& key_id) const = 0; + const std::vector<byte>& key_id) const = 0; /** * Find CRLs by the DN and key id of the issuer @@ -47,7 +47,7 @@ class BOTAN_DLL Certificate_Store virtual std::vector<X509_CRL> find_crl_by_issuer_and_key_id( const X509_DN& issuer_dn, - const MemoryRegion<byte>& key_id) const = 0; + const std::vector<byte>& key_id) const = 0; }; /** @@ -62,11 +62,11 @@ class BOTAN_DLL Certificate_Store_In_Memory : public Certificate_Store std::vector<X509_Certificate> find_cert_by_subject_and_key_id( const X509_DN& subject_dn, - const MemoryRegion<byte>& key_id) const; + const std::vector<byte>& key_id) const; std::vector<X509_CRL> find_crl_by_issuer_and_key_id( const X509_DN& issuer_dn, - const MemoryRegion<byte>& key_id) const; + const std::vector<byte>& key_id) const; Certificate_Store_In_Memory() {} private: diff --git a/src/cert/x509/crl_ent.cpp b/src/cert/x509/crl_ent.cpp index d566637f6..a5663e6bb 100644 --- a/src/cert/x509/crl_ent.cpp +++ b/src/cert/x509/crl_ent.cpp @@ -11,7 +11,6 @@ #include <botan/ber_dec.h> #include <botan/bigint.h> #include <botan/oids.h> -#include <botan/time.h> namespace Botan { @@ -31,7 +30,7 @@ CRL_Entry::CRL_Entry(const X509_Certificate& cert, CRL_Code why) : throw_on_unknown_critical(false) { serial = cert.serial_number(); - time = X509_Time(system_time()); + time = X509_Time(std::chrono::system_clock::now()); reason = why; } diff --git a/src/cert/x509/crl_ent.h b/src/cert/x509/crl_ent.h index ae9535484..769519f78 100644 --- a/src/cert/x509/crl_ent.h +++ b/src/cert/x509/crl_ent.h @@ -45,7 +45,7 @@ class BOTAN_DLL CRL_Entry : public ASN1_Object * Get the serial number of the certificate associated with this entry. * @return certificate's serial number */ - MemoryVector<byte> serial_number() const { return serial; } + std::vector<byte> serial_number() const { return serial; } /** * Get the revocation date of the certificate associated with this entry @@ -74,7 +74,7 @@ class BOTAN_DLL CRL_Entry : public ASN1_Object private: bool throw_on_unknown_critical; - MemoryVector<byte> serial; + std::vector<byte> serial; X509_Time time; CRL_Code reason; }; diff --git a/src/cert/x509/pkcs10.cpp b/src/cert/x509/pkcs10.cpp index 784318d3d..c67f74142 100644 --- a/src/cert/x509/pkcs10.cpp +++ b/src/cert/x509/pkcs10.cpp @@ -35,6 +35,15 @@ PKCS10_Request::PKCS10_Request(const std::string& in) : } /* +* PKCS10_Request Constructor +*/ +PKCS10_Request::PKCS10_Request(const std::vector<byte>& in) : + X509_Object(in, "CERTIFICATE REQUEST/NEW CERTIFICATE REQUEST") + { + do_decode(); + } + +/* * Deocde the CertificateRequestInfo */ void PKCS10_Request::force_decode() @@ -45,7 +54,7 @@ void PKCS10_Request::force_decode() cert_req_info.decode(version); if(version != 0) throw Decoding_Error("Unknown version code in PKCS #10 request: " + - to_string(version)); + std::to_string(version)); X509_DN dn_subject; cert_req_info.decode(dn_subject); @@ -59,7 +68,7 @@ void PKCS10_Request::force_decode() info.add("X509.Certificate.public_key", PEM_Code::encode( - ASN1::put_in_sequence(public_key.value), + ASN1::put_in_sequence(unlock(public_key.value)), "PUBLIC KEY" ) ); @@ -136,10 +145,10 @@ X509_DN PKCS10_Request::subject_dn() const /* * Return the public key of the requestor */ -MemoryVector<byte> PKCS10_Request::raw_public_key() const +std::vector<byte> PKCS10_Request::raw_public_key() const { DataSource_Memory source(info.get1("X509.Certificate.public_key")); - return PEM_Code::decode_check_label(source, "PUBLIC KEY"); + return unlock(PEM_Code::decode_check_label(source, "PUBLIC KEY")); } /* diff --git a/src/cert/x509/pkcs10.h b/src/cert/x509/pkcs10.h index 065dfbdc0..974ea0070 100644 --- a/src/cert/x509/pkcs10.h +++ b/src/cert/x509/pkcs10.h @@ -33,7 +33,7 @@ class BOTAN_DLL PKCS10_Request : public X509_Object * Get the raw DER encoded public key. * @return raw DER encoded public key */ - MemoryVector<byte> raw_public_key() const; + std::vector<byte> raw_public_key() const; /** * Get the subject DN. @@ -91,6 +91,12 @@ class BOTAN_DLL PKCS10_Request : public X509_Object * encoded request file */ PKCS10_Request(const std::string& filename); + + /** + * Create a PKCS#10 Request from binary data. + * @param vec a std::vector containing the DER value + */ + PKCS10_Request(const std::vector<byte>& vec); private: void force_decode(); void handle_attribute(const Attribute&); diff --git a/src/cert/x509/x509_ca.cpp b/src/cert/x509/x509_ca.cpp index 77e066533..9633d1466 100644 --- a/src/cert/x509/x509_ca.cpp +++ b/src/cert/x509/x509_ca.cpp @@ -57,8 +57,8 @@ X509_Certificate X509_CA::sign_request(const PKCS10_Request& req, constraints = Key_Constraints(KEY_CERT_SIGN | CRL_SIGN); else { - std::auto_ptr<Public_Key> key(req.subject_public_key()); - constraints = find_constraints(*key, req.constraints()); + std::unique_ptr<Public_Key> key(req.subject_public_key()); + constraints = X509::find_constraints(*key, req.constraints()); } Extensions extensions; @@ -91,7 +91,7 @@ X509_Certificate X509_CA::sign_request(const PKCS10_Request& req, X509_Certificate X509_CA::make_cert(PK_Signer* signer, RandomNumberGenerator& rng, const AlgorithmIdentifier& sig_algo, - const MemoryRegion<byte>& pub_key, + const std::vector<byte>& pub_key, const X509_Time& not_before, const X509_Time& not_after, const X509_DN& issuer_dn, @@ -103,35 +103,35 @@ X509_Certificate X509_CA::make_cert(PK_Signer* signer, BigInt serial_no(rng, SERIAL_BITS); - DataSource_Memory source(X509_Object::make_signed(signer, rng, sig_algo, - DER_Encoder().start_cons(SEQUENCE) - .start_explicit(0) - .encode(X509_CERT_VERSION-1) - .end_explicit() + const std::vector<byte> cert = X509_Object::make_signed( + signer, rng, sig_algo, + DER_Encoder().start_cons(SEQUENCE) + .start_explicit(0) + .encode(X509_CERT_VERSION-1) + .end_explicit() - .encode(serial_no) + .encode(serial_no) - .encode(sig_algo) - .encode(issuer_dn) + .encode(sig_algo) + .encode(issuer_dn) - .start_cons(SEQUENCE) - .encode(not_before) - .encode(not_after) - .end_cons() + .start_cons(SEQUENCE) + .encode(not_before) + .encode(not_after) + .end_cons() - .encode(subject_dn) - .raw_bytes(pub_key) + .encode(subject_dn) + .raw_bytes(pub_key) - .start_explicit(3) - .start_cons(SEQUENCE) - .encode(extensions) - .end_cons() - .end_explicit() - .end_cons() - .get_contents() - )); + .start_explicit(3) + .start_cons(SEQUENCE) + .encode(extensions) + .end_cons() + .end_explicit() + .end_cons() + .get_contents()); - return X509_Certificate(source); + return X509_Certificate(cert); } /* @@ -173,36 +173,37 @@ X509_CRL X509_CA::make_crl(const std::vector<CRL_Entry>& revoked, next_update = timespec_to_u32bit("7d"); // Totally stupid: ties encoding logic to the return of std::time!! - const u64bit current_time = system_time(); + auto current_time = std::chrono::system_clock::now(); + auto expire_time = current_time + std::chrono::seconds(next_update); Extensions extensions; extensions.add( new Cert_Extension::Authority_Key_ID(cert.subject_key_id())); extensions.add(new Cert_Extension::CRL_Number(crl_number)); - DataSource_Memory source(X509_Object::make_signed(signer, rng, ca_sig_algo, - DER_Encoder().start_cons(SEQUENCE) - .encode(X509_CRL_VERSION-1) - .encode(ca_sig_algo) - .encode(cert.issuer_dn()) - .encode(X509_Time(current_time)) - .encode(X509_Time(current_time + next_update)) - .encode_if(revoked.size() > 0, - DER_Encoder() - .start_cons(SEQUENCE) - .encode_list(revoked) - .end_cons() - ) - .start_explicit(0) - .start_cons(SEQUENCE) - .encode(extensions) - .end_cons() - .end_explicit() - .end_cons() - .get_contents() - )); + const std::vector<byte> crl = X509_Object::make_signed( + signer, rng, ca_sig_algo, + DER_Encoder().start_cons(SEQUENCE) + .encode(X509_CRL_VERSION-1) + .encode(ca_sig_algo) + .encode(cert.issuer_dn()) + .encode(X509_Time(current_time)) + .encode(X509_Time(expire_time)) + .encode_if(revoked.size() > 0, + DER_Encoder() + .start_cons(SEQUENCE) + .encode_list(revoked) + .end_cons() + ) + .start_explicit(0) + .start_cons(SEQUENCE) + .encode(extensions) + .end_cons() + .end_explicit() + .end_cons() + .get_contents()); - return X509_CRL(source); + return X509_CRL(crl); } /* diff --git a/src/cert/x509/x509_ca.h b/src/cert/x509/x509_ca.h index 97be6a415..d37b02eaf 100644 --- a/src/cert/x509/x509_ca.h +++ b/src/cert/x509/x509_ca.h @@ -82,7 +82,7 @@ class BOTAN_DLL X509_CA static X509_Certificate make_cert(PK_Signer* signer, RandomNumberGenerator& rng, const AlgorithmIdentifier& sig_algo, - const MemoryRegion<byte>& pub_key, + const std::vector<byte>& pub_key, const X509_Time& not_before, const X509_Time& not_after, const X509_DN& issuer_dn, @@ -99,11 +99,11 @@ class BOTAN_DLL X509_CA const Private_Key& key, const std::string& hash_fn); + X509_CA(const X509_CA&) = delete; + X509_CA& operator=(const X509_CA&) = delete; + ~X509_CA(); private: - X509_CA(const X509_CA&) {} - X509_CA& operator=(const X509_CA&) { return (*this); } - X509_CRL make_crl(const std::vector<CRL_Entry>& entries, u32bit crl_number, u32bit next_update, RandomNumberGenerator& rng) const; diff --git a/src/cert/x509/x509_crl.cpp b/src/cert/x509/x509_crl.cpp index 9c6b891c7..1d6393470 100644 --- a/src/cert/x509/x509_crl.cpp +++ b/src/cert/x509/x509_crl.cpp @@ -33,6 +33,12 @@ X509_CRL::X509_CRL(const std::string& in, bool touc) : do_decode(); } +X509_CRL::X509_CRL(const std::vector<byte>& in, bool touc) : + X509_Object(in, "CRL/X509 CRL"), throw_on_unknown_critical(touc) + { + do_decode(); + } + /** * Check if this particular certificate is listed in the CRL */ @@ -82,7 +88,7 @@ void X509_CRL::force_decode() if(version != 0 && version != 1) throw X509_CRL_Error("Unknown X.509 CRL version " + - to_string(version+1)); + std::to_string(version+1)); AlgorithmIdentifier sig_algo_inner; tbs_crl.decode(sig_algo_inner); @@ -153,7 +159,7 @@ X509_DN X509_CRL::issuer_dn() const /* * Return the key identifier of the issuer */ -MemoryVector<byte> X509_CRL::authority_key_id() const +std::vector<byte> X509_CRL::authority_key_id() const { return info.get1_memvec("X509v3.AuthorityKeyIdentifier"); } diff --git a/src/cert/x509/x509_crl.h b/src/cert/x509/x509_crl.h index 55eb8424b..3e45df121 100644 --- a/src/cert/x509/x509_crl.h +++ b/src/cert/x509/x509_crl.h @@ -52,7 +52,7 @@ class BOTAN_DLL X509_CRL : public X509_Object * Get the AuthorityKeyIdentifier of this CRL. * @return this CRLs AuthorityKeyIdentifier */ - MemoryVector<byte> authority_key_id() const; + std::vector<byte> authority_key_id() const; /** * Get the serial number of this CRL. @@ -88,6 +88,16 @@ class BOTAN_DLL X509_CRL : public X509_Object */ X509_CRL(const std::string& filename, bool throw_on_unknown_critical = false); + + /** + * Construct a CRL from a binary vector + * @param vec the binary (DER) representation of the CRL + * @param throw_on_unknown_critical should we throw an exception + * if an unknown CRL extension marked as critical is encountered. + */ + X509_CRL(const std::vector<byte>& vec, + bool throw_on_unknown_critical = false); + private: void force_decode(); diff --git a/src/cert/x509/x509_ext.cpp b/src/cert/x509/x509_ext.cpp index 6e0befaf3..919fb790a 100644 --- a/src/cert/x509/x509_ext.cpp +++ b/src/cert/x509/x509_ext.cpp @@ -36,7 +36,7 @@ Certificate_Extension* Extensions::get_extension(const OID& oid) X509_EXTENSION("X509v3.CertificatePolicies", Certificate_Policies); X509_EXTENSION("X509v3.ReasonCode", CRL_ReasonCode); - return 0; + return nullptr; } /* @@ -114,7 +114,7 @@ void Extensions::decode_from(BER_Decoder& from_source) while(sequence.more_items()) { OID oid; - MemoryVector<byte> value; + std::vector<byte> value; bool critical; sequence.start_cons(SEQUENCE) @@ -176,7 +176,7 @@ size_t Basic_Constraints::get_path_limit() const /* * Encode the extension */ -MemoryVector<byte> Basic_Constraints::encode_inner() const +std::vector<byte> Basic_Constraints::encode_inner() const { return DER_Encoder() .start_cons(SEQUENCE) @@ -186,13 +186,13 @@ MemoryVector<byte> Basic_Constraints::encode_inner() const .encode_optional(path_limit, NO_CERT_PATH_LIMIT) ) .end_cons() - .get_contents(); + .get_contents_unlocked(); } /* * Decode the extension */ -void Basic_Constraints::decode_inner(const MemoryRegion<byte>& in) +void Basic_Constraints::decode_inner(const std::vector<byte>& in) { BER_Decoder(in) .start_cons(SEQUENCE) @@ -217,14 +217,14 @@ void Basic_Constraints::contents_to(Data_Store& subject, Data_Store&) const /* * Encode the extension */ -MemoryVector<byte> Key_Usage::encode_inner() const +std::vector<byte> Key_Usage::encode_inner() const { if(constraints == NO_CONSTRAINTS) throw Encoding_Error("Cannot encode zero usage constraints"); const size_t unused_bits = low_bit(constraints) - 1; - MemoryVector<byte> der; + std::vector<byte> der; der.push_back(BIT_STRING); der.push_back(2 + ((unused_bits < 8) ? 1 : 0)); der.push_back(unused_bits % 8); @@ -238,7 +238,7 @@ MemoryVector<byte> Key_Usage::encode_inner() const /* * Decode the extension */ -void Key_Usage::decode_inner(const MemoryRegion<byte>& in) +void Key_Usage::decode_inner(const std::vector<byte>& in) { BER_Decoder ber(in); @@ -274,15 +274,15 @@ void Key_Usage::contents_to(Data_Store& subject, Data_Store&) const /* * Encode the extension */ -MemoryVector<byte> Subject_Key_ID::encode_inner() const +std::vector<byte> Subject_Key_ID::encode_inner() const { - return DER_Encoder().encode(key_id, OCTET_STRING).get_contents(); + return DER_Encoder().encode(key_id, OCTET_STRING).get_contents_unlocked(); } /* * Decode the extension */ -void Subject_Key_ID::decode_inner(const MemoryRegion<byte>& in) +void Subject_Key_ID::decode_inner(const std::vector<byte>& in) { BER_Decoder(in).decode(key_id, OCTET_STRING).verify_end(); } @@ -298,28 +298,28 @@ void Subject_Key_ID::contents_to(Data_Store& subject, Data_Store&) const /* * Subject_Key_ID Constructor */ -Subject_Key_ID::Subject_Key_ID(const MemoryRegion<byte>& pub_key) +Subject_Key_ID::Subject_Key_ID(const std::vector<byte>& pub_key) { SHA_160 hash; - key_id = hash.process(pub_key); + key_id = unlock(hash.process(pub_key)); } /* * Encode the extension */ -MemoryVector<byte> Authority_Key_ID::encode_inner() const +std::vector<byte> Authority_Key_ID::encode_inner() const { return DER_Encoder() .start_cons(SEQUENCE) .encode(key_id, OCTET_STRING, ASN1_Tag(0), CONTEXT_SPECIFIC) .end_cons() - .get_contents(); + .get_contents_unlocked(); } /* * Decode the extension */ -void Authority_Key_ID::decode_inner(const MemoryRegion<byte>& in) +void Authority_Key_ID::decode_inner(const std::vector<byte>& in) { BER_Decoder(in) .start_cons(SEQUENCE) @@ -338,15 +338,15 @@ void Authority_Key_ID::contents_to(Data_Store&, Data_Store& issuer) const /* * Encode the extension */ -MemoryVector<byte> Alternative_Name::encode_inner() const +std::vector<byte> Alternative_Name::encode_inner() const { - return DER_Encoder().encode(alt_name).get_contents(); + return DER_Encoder().encode(alt_name).get_contents_unlocked(); } /* * Decode the extension */ -void Alternative_Name::decode_inner(const MemoryRegion<byte>& in) +void Alternative_Name::decode_inner(const std::vector<byte>& in) { BER_Decoder(in).decode(alt_name); } @@ -404,19 +404,19 @@ Issuer_Alternative_Name::Issuer_Alternative_Name(const AlternativeName& name) : /* * Encode the extension */ -MemoryVector<byte> Extended_Key_Usage::encode_inner() const +std::vector<byte> Extended_Key_Usage::encode_inner() const { return DER_Encoder() .start_cons(SEQUENCE) .encode_list(oids) .end_cons() - .get_contents(); + .get_contents_unlocked(); } /* * Decode the extension */ -void Extended_Key_Usage::decode_inner(const MemoryRegion<byte>& in) +void Extended_Key_Usage::decode_inner(const std::vector<byte>& in) { BER_Decoder(in) .start_cons(SEQUENCE) @@ -467,7 +467,7 @@ class Policy_Information : public ASN1_Object /* * Encode the extension */ -MemoryVector<byte> Certificate_Policies::encode_inner() const +std::vector<byte> Certificate_Policies::encode_inner() const { std::vector<Policy_Information> policies; @@ -478,13 +478,13 @@ MemoryVector<byte> Certificate_Policies::encode_inner() const .start_cons(SEQUENCE) .encode_list(policies) .end_cons() - .get_contents(); + .get_contents_unlocked(); } /* * Decode the extension */ -void Certificate_Policies::decode_inner(const MemoryRegion<byte>& in) +void Certificate_Policies::decode_inner(const std::vector<byte>& in) { std::vector<Policy_Information> policies; @@ -530,15 +530,15 @@ CRL_Number* CRL_Number::copy() const /* * Encode the extension */ -MemoryVector<byte> CRL_Number::encode_inner() const +std::vector<byte> CRL_Number::encode_inner() const { - return DER_Encoder().encode(crl_number).get_contents(); + return DER_Encoder().encode(crl_number).get_contents_unlocked(); } /* * Decode the extension */ -void CRL_Number::decode_inner(const MemoryRegion<byte>& in) +void CRL_Number::decode_inner(const std::vector<byte>& in) { BER_Decoder(in).decode(crl_number); } @@ -554,17 +554,17 @@ void CRL_Number::contents_to(Data_Store& info, Data_Store&) const /* * Encode the extension */ -MemoryVector<byte> CRL_ReasonCode::encode_inner() const +std::vector<byte> CRL_ReasonCode::encode_inner() const { return DER_Encoder() .encode(static_cast<size_t>(reason), ENUMERATED, UNIVERSAL) - .get_contents(); + .get_contents_unlocked(); } /* * Decode the extension */ -void CRL_ReasonCode::decode_inner(const MemoryRegion<byte>& in) +void CRL_ReasonCode::decode_inner(const std::vector<byte>& in) { size_t reason_code = 0; BER_Decoder(in).decode(reason_code, ENUMERATED, UNIVERSAL); diff --git a/src/cert/x509/x509_ext.h b/src/cert/x509/x509_ext.h index 714e29562..1e5d1adbb 100644 --- a/src/cert/x509/x509_ext.h +++ b/src/cert/x509/x509_ext.h @@ -56,8 +56,8 @@ class BOTAN_DLL Certificate_Extension protected: friend class Extensions; virtual bool should_encode() const { return true; } - virtual MemoryVector<byte> encode_inner() const = 0; - virtual void decode_inner(const MemoryRegion<byte>&) = 0; + virtual std::vector<byte> encode_inner() const = 0; + virtual void decode_inner(const std::vector<byte>&) = 0; }; /** @@ -107,8 +107,8 @@ class BOTAN_DLL Basic_Constraints : public Certificate_Extension std::string config_id() const { return "basic_constraints"; } std::string oid_name() const { return "X509v3.BasicConstraints"; } - MemoryVector<byte> encode_inner() const; - void decode_inner(const MemoryRegion<byte>&); + std::vector<byte> encode_inner() const; + void decode_inner(const std::vector<byte>&); void contents_to(Data_Store&, Data_Store&) const; bool is_ca; @@ -131,8 +131,8 @@ class BOTAN_DLL Key_Usage : public Certificate_Extension std::string oid_name() const { return "X509v3.KeyUsage"; } bool should_encode() const { return (constraints != NO_CONSTRAINTS); } - MemoryVector<byte> encode_inner() const; - void decode_inner(const MemoryRegion<byte>&); + std::vector<byte> encode_inner() const; + void decode_inner(const std::vector<byte>&); void contents_to(Data_Store&, Data_Store&) const; Key_Constraints constraints; @@ -147,19 +147,19 @@ class BOTAN_DLL Subject_Key_ID : public Certificate_Extension Subject_Key_ID* copy() const { return new Subject_Key_ID(key_id); } Subject_Key_ID() {} - Subject_Key_ID(const MemoryRegion<byte>&); + Subject_Key_ID(const std::vector<byte>&); - MemoryVector<byte> get_key_id() const { return key_id; } + std::vector<byte> get_key_id() const { return key_id; } private: std::string config_id() const { return "subject_key_id"; } std::string oid_name() const { return "X509v3.SubjectKeyIdentifier"; } bool should_encode() const { return (key_id.size() > 0); } - MemoryVector<byte> encode_inner() const; - void decode_inner(const MemoryRegion<byte>&); + std::vector<byte> encode_inner() const; + void decode_inner(const std::vector<byte>&); void contents_to(Data_Store&, Data_Store&) const; - MemoryVector<byte> key_id; + std::vector<byte> key_id; }; /** @@ -171,19 +171,19 @@ class BOTAN_DLL Authority_Key_ID : public Certificate_Extension Authority_Key_ID* copy() const { return new Authority_Key_ID(key_id); } Authority_Key_ID() {} - Authority_Key_ID(const MemoryRegion<byte>& k) : key_id(k) {} + Authority_Key_ID(const std::vector<byte>& k) : key_id(k) {} - MemoryVector<byte> get_key_id() const { return key_id; } + std::vector<byte> get_key_id() const { return key_id; } private: std::string config_id() const { return "authority_key_id"; } std::string oid_name() const { return "X509v3.AuthorityKeyIdentifier"; } bool should_encode() const { return (key_id.size() > 0); } - MemoryVector<byte> encode_inner() const; - void decode_inner(const MemoryRegion<byte>&); + std::vector<byte> encode_inner() const; + void decode_inner(const std::vector<byte>&); void contents_to(Data_Store&, Data_Store&) const; - MemoryVector<byte> key_id; + std::vector<byte> key_id; }; /** @@ -204,8 +204,8 @@ class BOTAN_DLL Alternative_Name : public Certificate_Extension std::string oid_name() const { return oid_name_str; } bool should_encode() const { return alt_name.has_items(); } - MemoryVector<byte> encode_inner() const; - void decode_inner(const MemoryRegion<byte>&); + std::vector<byte> encode_inner() const; + void decode_inner(const std::vector<byte>&); void contents_to(Data_Store&, Data_Store&) const; std::string config_name_str, oid_name_str; @@ -253,8 +253,8 @@ class BOTAN_DLL Extended_Key_Usage : public Certificate_Extension std::string oid_name() const { return "X509v3.ExtendedKeyUsage"; } bool should_encode() const { return (oids.size() > 0); } - MemoryVector<byte> encode_inner() const; - void decode_inner(const MemoryRegion<byte>&); + std::vector<byte> encode_inner() const; + void decode_inner(const std::vector<byte>&); void contents_to(Data_Store&, Data_Store&) const; std::vector<OID> oids; @@ -278,8 +278,8 @@ class BOTAN_DLL Certificate_Policies : public Certificate_Extension std::string oid_name() const { return "X509v3.CertificatePolicies"; } bool should_encode() const { return (oids.size() > 0); } - MemoryVector<byte> encode_inner() const; - void decode_inner(const MemoryRegion<byte>&); + std::vector<byte> encode_inner() const; + void decode_inner(const std::vector<byte>&); void contents_to(Data_Store&, Data_Store&) const; std::vector<OID> oids; @@ -302,8 +302,8 @@ class BOTAN_DLL CRL_Number : public Certificate_Extension std::string oid_name() const { return "X509v3.CRLNumber"; } bool should_encode() const { return has_value; } - MemoryVector<byte> encode_inner() const; - void decode_inner(const MemoryRegion<byte>&); + std::vector<byte> encode_inner() const; + void decode_inner(const std::vector<byte>&); void contents_to(Data_Store&, Data_Store&) const; bool has_value; @@ -326,8 +326,8 @@ class BOTAN_DLL CRL_ReasonCode : public Certificate_Extension std::string oid_name() const { return "X509v3.ReasonCode"; } bool should_encode() const { return (reason != UNSPECIFIED); } - MemoryVector<byte> encode_inner() const; - void decode_inner(const MemoryRegion<byte>&); + std::vector<byte> encode_inner() const; + void decode_inner(const std::vector<byte>&); void contents_to(Data_Store&, Data_Store&) const; CRL_Code reason; diff --git a/src/cert/x509/x509_obj.cpp b/src/cert/x509/x509_obj.cpp index 670bd8da6..af8be0384 100644 --- a/src/cert/x509/x509_obj.cpp +++ b/src/cert/x509/x509_obj.cpp @@ -16,8 +16,6 @@ #include <algorithm> #include <memory> -#include <stdio.h> - namespace Botan { /* @@ -29,7 +27,7 @@ X509_Object::X509_Object(DataSource& stream, const std::string& labels) } /* -* Createa a generic X.509 object +* Create a generic X.509 object */ X509_Object::X509_Object(const std::string& file, const std::string& labels) { @@ -38,6 +36,15 @@ X509_Object::X509_Object(const std::string& file, const std::string& labels) } /* +* Create a generic X.509 object +*/ +X509_Object::X509_Object(const std::vector<byte>& vec, const std::string& labels) + { + DataSource_Memory stream(&vec[0], vec.size()); + init(stream, labels); + } + +/* * Read a PEM or BER X.509 object */ void X509_Object::init(DataSource& in, const std::string& labels) @@ -99,7 +106,7 @@ void X509_Object::encode(Pipe& out, X509_Encoding encoding) const /* * Return a BER encoded X.509 object */ -MemoryVector<byte> X509_Object::BER_encode() const +std::vector<byte> X509_Object::BER_encode() const { return DER_Encoder() .start_cons(SEQUENCE) @@ -109,7 +116,7 @@ MemoryVector<byte> X509_Object::BER_encode() const .encode(sig_algo) .encode(sig, BIT_STRING) .end_cons() - .get_contents(); + .get_contents_unlocked(); } /* @@ -123,7 +130,7 @@ std::string X509_Object::PEM_encode() const /* * Return the TBS data */ -MemoryVector<byte> X509_Object::tbs_data() const +std::vector<byte> X509_Object::tbs_data() const { return ASN1::put_in_sequence(tbs_bits); } @@ -131,7 +138,7 @@ MemoryVector<byte> X509_Object::tbs_data() const /* * Return the signature of this object */ -MemoryVector<byte> X509_Object::signature() const +std::vector<byte> X509_Object::signature() const { return sig; } @@ -170,7 +177,7 @@ std::string X509_Object::hash_used_for_signature() const */ bool X509_Object::check_signature(const Public_Key* pub_key) const { - std::auto_ptr<const Public_Key> key(pub_key); + std::unique_ptr<Public_Key> key(pub_key); return check_signature(*key); } @@ -196,7 +203,6 @@ bool X509_Object::check_signature(const Public_Key& pub_key) const } catch(std::exception& e) { - printf("Failure during validation %s\n", e.what()); return false; } } @@ -204,10 +210,10 @@ bool X509_Object::check_signature(const Public_Key& pub_key) const /* * Apply the X.509 SIGNED macro */ -MemoryVector<byte> X509_Object::make_signed(PK_Signer* signer, +std::vector<byte> X509_Object::make_signed(PK_Signer* signer, RandomNumberGenerator& rng, const AlgorithmIdentifier& algo, - const MemoryRegion<byte>& tbs_bits) + const secure_vector<byte>& tbs_bits) { return DER_Encoder() .start_cons(SEQUENCE) @@ -215,7 +221,7 @@ MemoryVector<byte> X509_Object::make_signed(PK_Signer* signer, .encode(algo) .encode(signer->sign_message(tbs_bits, rng), BIT_STRING) .end_cons() - .get_contents(); + .get_contents_unlocked(); } /* diff --git a/src/cert/x509/x509_obj.h b/src/cert/x509/x509_obj.h index e46e72ce3..e91389acf 100644 --- a/src/cert/x509/x509_obj.h +++ b/src/cert/x509/x509_obj.h @@ -27,12 +27,12 @@ class BOTAN_DLL X509_Object * The underlying data that is to be or was signed * @return data that is or was signed */ - MemoryVector<byte> tbs_data() const; + std::vector<byte> tbs_data() const; /** * @return signature on tbs_data() */ - MemoryVector<byte> signature() const; + std::vector<byte> signature() const; /** * @return signature algorithm that was used to generate signature @@ -52,10 +52,10 @@ class BOTAN_DLL X509_Object * @param tbs the tbs bits to be signed * @return signed X509 object */ - static MemoryVector<byte> make_signed(class PK_Signer* signer, - RandomNumberGenerator& rng, - const AlgorithmIdentifier& alg_id, - const MemoryRegion<byte>& tbs); + static std::vector<byte> make_signed(class PK_Signer* signer, + RandomNumberGenerator& rng, + const AlgorithmIdentifier& alg_id, + const secure_vector<byte>& tbs); /** * Check the signature on this data @@ -75,7 +75,7 @@ class BOTAN_DLL X509_Object /** * @return BER encoding of this */ - MemoryVector<byte> BER_encode() const; + std::vector<byte> BER_encode() const; /** * @return PEM encoding of this @@ -95,15 +95,17 @@ class BOTAN_DLL X509_Object protected: X509_Object(DataSource& src, const std::string& pem_labels); X509_Object(const std::string& file, const std::string& pem_labels); + X509_Object(const std::vector<byte>& vec, const std::string& labels); void do_decode(); X509_Object() {} AlgorithmIdentifier sig_algo; - MemoryVector<byte> tbs_bits, sig; + std::vector<byte> tbs_bits, sig; private: virtual void force_decode() = 0; void init(DataSource&, const std::string&); void decode_info(DataSource&); + std::vector<std::string> PEM_labels_allowed; std::string PEM_label_pref; }; diff --git a/src/cert/x509/x509cert.cpp b/src/cert/x509/x509cert.cpp index 52115a1a8..d757c2b58 100644 --- a/src/cert/x509/x509cert.cpp +++ b/src/cert/x509/x509cert.cpp @@ -30,12 +30,8 @@ std::vector<std::string> lookup_oids(const std::vector<std::string>& in) { std::vector<std::string> out; - std::vector<std::string>::const_iterator i = in.begin(); - while(i != in.end()) - { + for(auto i = in.begin(); i != in.end(); ++i) out.push_back(OIDS::lookup(OID(*i))); - ++i; - } return out; } @@ -62,6 +58,16 @@ X509_Certificate::X509_Certificate(const std::string& in) : } /* +* X509_Certificate Constructor +*/ +X509_Certificate::X509_Certificate(const std::vector<byte>& in) : + X509_Object(in, "CERTIFICATE/X509 CERTIFICATE") + { + self_signed = false; + do_decode(); + } + +/* * Decode the TBSCertificate data */ void X509_Certificate::force_decode() @@ -87,7 +93,7 @@ void X509_Certificate::force_decode() .decode(dn_subject); if(version > 2) - throw Decoding_Error("Unknown X.509 cert version " + Botan::to_string(version)); + throw Decoding_Error("Unknown X.509 cert version " + std::to_string(version)); if(sig_algo != sig_algo_inner) throw Decoding_Error("Algorithm identifier mismatch"); @@ -101,7 +107,7 @@ void X509_Certificate::force_decode() throw BER_Bad_Tag("X509_Certificate: Unexpected tag for public key", public_key.type_tag, public_key.class_tag); - MemoryVector<byte> v2_issuer_key_id, v2_subject_key_id; + std::vector<byte> v2_issuer_key_id, v2_subject_key_id; tbs_cert.decode_optional_string(v2_issuer_key_id, BIT_STRING, 1); tbs_cert.decode_optional_string(v2_subject_key_id, BIT_STRING, 2); @@ -133,7 +139,7 @@ void X509_Certificate::force_decode() subject.add("X509.Certificate.public_key", PEM_Code::encode( - ASN1::put_in_sequence(public_key.value), + ASN1::put_in_sequence(unlock(public_key.value)), "PUBLIC KEY" ) ); @@ -253,7 +259,7 @@ std::vector<std::string> X509_Certificate::policies() const /* * Return the authority key id */ -MemoryVector<byte> X509_Certificate::authority_key_id() const +std::vector<byte> X509_Certificate::authority_key_id() const { return issuer.get1_memvec("X509v3.AuthorityKeyIdentifier"); } @@ -261,7 +267,7 @@ MemoryVector<byte> X509_Certificate::authority_key_id() const /* * Return the subject key id */ -MemoryVector<byte> X509_Certificate::subject_key_id() const +std::vector<byte> X509_Certificate::subject_key_id() const { return subject.get1_memvec("X509v3.SubjectKeyIdentifier"); } @@ -269,7 +275,7 @@ MemoryVector<byte> X509_Certificate::subject_key_id() const /* * Return the certificate serial number */ -MemoryVector<byte> X509_Certificate::serial_number() const +std::vector<byte> X509_Certificate::serial_number() const { return subject.get1_memvec("X509.Certificate.serial"); } @@ -290,6 +296,50 @@ X509_DN X509_Certificate::subject_dn() const return create_dn(subject); } +namespace { + +bool cert_subject_dns_match(const std::string& name, + const std::vector<std::string>& cert_names) + { + for(size_t i = 0; i != cert_names.size(); ++i) + { + const std::string cn = cert_names[i]; + + if(cn == name) + return true; + + /* + * Possible wildcard match. We only support the most basic form of + * cert wildcarding ala RFC 2595 + */ + if(cn.size() > 2 && cn[0] == '*' && cn[1] == '.' && name.size() > cn.size()) + { + const std::string base = cn.substr(1, std::string::npos); + + if(name.compare(name.size() - base.size(), base.size(), base) == 0) + return true; + } + } + + return false; + } + +} + +bool X509_Certificate::matches_dns_name(const std::string& name) const + { + if(name == "") + return false; + + if(cert_subject_dns_match(name, subject_info("DNS"))) + return true; + + if(cert_subject_dns_match(name, subject_info("Name"))) + return true; + + return false; + } + /* * Compare two certificates for equality */ @@ -302,6 +352,24 @@ bool X509_Certificate::operator==(const X509_Certificate& other) const subject == other.subject); } +bool X509_Certificate::operator<(const X509_Certificate& other) const + { + /* If signature values are not equal, sort by lexicographic ordering of that */ + if(sig != other.sig) + { + if(sig < other.sig) + return true; + return false; + } + + /* + * same signatures, highly unlikely case, revert to compare + * of entire contents + */ + + return to_string() < other.to_string(); + } + /* * X.509 Certificate Comparison */ @@ -323,7 +391,7 @@ std::string X509_Certificate::to_string() const "DNS", "URI", "PKIX.XMPPAddr", - 0 }; + nullptr }; std::ostringstream out; @@ -419,24 +487,15 @@ std::string X509_Certificate::to_string() const */ X509_DN create_dn(const Data_Store& info) { - class DN_Matcher : public Data_Store::Matcher + auto names = info.search_for( + [](const std::string& key, const std::string&) { - public: - bool operator()(const std::string& key, const std::string&) const - { - if(key.find("X520.") != std::string::npos) - return true; - return false; - } - }; - - std::multimap<std::string, std::string> names = - info.search_with(DN_Matcher()); + return (key.find("X520.") != std::string::npos); + }); X509_DN dn; - std::multimap<std::string, std::string>::iterator i; - for(i = names.begin(); i != names.end(); ++i) + for(auto i = names.begin(); i != names.end(); ++i) dn.add_attribute(i->first, i->second); return dn; @@ -447,32 +506,18 @@ X509_DN create_dn(const Data_Store& info) */ AlternativeName create_alt_name(const Data_Store& info) { - class AltName_Matcher : public Data_Store::Matcher + auto names = info.search_for( + [](const std::string& key, const std::string&) { - public: - bool operator()(const std::string& key, const std::string&) const - { - for(size_t i = 0; i != matches.size(); ++i) - if(key.compare(matches[i]) == 0) - return true; - return false; - } - - AltName_Matcher(const std::string& match_any_of) - { - matches = split_on(match_any_of, '/'); - } - private: - std::vector<std::string> matches; - }; - - std::multimap<std::string, std::string> names = - info.search_with(AltName_Matcher("RFC822/DNS/URI/IP")); + return (key == "RFC822" || + key == "DNS" || + key == "URI" || + key == "IP"); + }); AlternativeName alt_name; - std::multimap<std::string, std::string>::iterator i; - for(i = names.begin(); i != names.end(); ++i) + for(auto i = names.begin(); i != names.end(); ++i) alt_name.add_attribute(i->first, i->second); return alt_name; diff --git a/src/cert/x509/x509cert.h b/src/cert/x509/x509cert.h index 6a4fd6959..e204fb274 100644 --- a/src/cert/x509/x509cert.h +++ b/src/cert/x509/x509cert.h @@ -85,19 +85,19 @@ class BOTAN_DLL X509_Certificate : public X509_Object * Get the serial number of this certificate. * @return certificates serial number */ - MemoryVector<byte> serial_number() const; + std::vector<byte> serial_number() const; /** * Get the DER encoded AuthorityKeyIdentifier of this certificate. * @return DER encoded AuthorityKeyIdentifier */ - MemoryVector<byte> authority_key_id() const; + std::vector<byte> authority_key_id() const; /** * Get the DER encoded SubjectKeyIdentifier of this certificate. * @return DER encoded SubjectKeyIdentifier */ - MemoryVector<byte> subject_key_id() const; + std::vector<byte> subject_key_id() const; /** * Check whether this certificate is self signed. @@ -148,12 +148,24 @@ class BOTAN_DLL X509_Certificate : public X509_Object std::string to_string() const; /** + * Check if a certain DNS name matches up with the information in + * the cert + */ + bool matches_dns_name(const std::string& name) const; + + /** * Check to certificates for equality. * @return true both certificates are (binary) equal */ bool operator==(const X509_Certificate& other) const; /** + * Impose an arbitrary (but consistent) ordering + * @return true if this is less than other by some unspecified criteria + */ + bool operator<(const X509_Certificate& other) const; + + /** * Create a certificate from a data source providing the DER or * PEM encoded certificate. * @param source the data source @@ -166,6 +178,9 @@ class BOTAN_DLL X509_Certificate : public X509_Object * @param filename the name of the certificate file */ X509_Certificate(const std::string& filename); + + X509_Certificate(const std::vector<byte>& in); + private: void force_decode(); friend class X509_CA; diff --git a/src/cert/x509/x509opt.cpp b/src/cert/x509/x509opt.cpp index 345df1fe0..8a27fdbde 100644 --- a/src/cert/x509/x509opt.cpp +++ b/src/cert/x509/x509opt.cpp @@ -8,7 +8,7 @@ #include <botan/x509self.h> #include <botan/oids.h> #include <botan/parsing.h> -#include <botan/time.h> +#include <chrono> namespace Botan { @@ -78,16 +78,16 @@ void X509_Cert_Options::sanity_check() const * Initialize the certificate options */ X509_Cert_Options::X509_Cert_Options(const std::string& initial_opts, - u32bit expiration_time_in_seconds) + u32bit expiration_time) { is_CA = false; path_limit = 0; constraints = NO_CONSTRAINTS; - const u64bit now = system_time(); + auto now = std::chrono::system_clock::now(); start = X509_Time(now); - end = X509_Time(now + expiration_time_in_seconds); + end = X509_Time(now + std::chrono::seconds(expiration_time)); if(initial_opts == "") return; diff --git a/src/cert/x509/x509path.cpp b/src/cert/x509/x509path.cpp index fcf27841d..1d0667f85 100644 --- a/src/cert/x509/x509path.cpp +++ b/src/cert/x509/x509path.cpp @@ -9,8 +9,8 @@ #include <botan/parsing.h> #include <botan/pubkey.h> #include <botan/oids.h> -#include <botan/time.h> #include <algorithm> +#include <chrono> #include <memory> namespace Botan { diff --git a/src/cert/x509/x509path.h b/src/cert/x509/x509path.h index 18129a236..fc784d429 100644 --- a/src/cert/x509/x509path.h +++ b/src/cert/x509/x509path.h @@ -10,7 +10,12 @@ #include <botan/x509cert.h> #include <botan/certstor.h> +<<<<<<< variant A #include <set> +>>>>>>> variant B +#include <functional> +####### Ancestor +======= end namespace Botan { diff --git a/src/cert/x509/x509self.cpp b/src/cert/x509/x509self.cpp index a2f89159f..c13772382 100644 --- a/src/cert/x509/x509self.cpp +++ b/src/cert/x509/x509self.cpp @@ -53,8 +53,8 @@ X509_Certificate create_self_signed_cert(const X509_Cert_Options& opts, opts.sanity_check(); - MemoryVector<byte> pub_key = X509::BER_encode(key); - std::auto_ptr<PK_Signer> signer(choose_sig_format(key, hash_fn, sig_algo)); + std::vector<byte> pub_key = X509::BER_encode(key); + std::unique_ptr<PK_Signer> signer(choose_sig_format(key, hash_fn, sig_algo)); load_info(opts, subject_dn, subject_alt); Key_Constraints constraints; @@ -99,8 +99,8 @@ PKCS10_Request create_cert_req(const X509_Cert_Options& opts, opts.sanity_check(); - MemoryVector<byte> pub_key = X509::BER_encode(key); - std::auto_ptr<PK_Signer> signer(choose_sig_format(key, hash_fn, sig_algo)); + std::vector<byte> pub_key = X509::BER_encode(key); + std::unique_ptr<PK_Signer> signer(choose_sig_format(key, hash_fn, sig_algo)); load_info(opts, subject_dn, subject_alt); const size_t PKCS10_VERSION = 0; @@ -134,7 +134,7 @@ PKCS10_Request create_cert_req(const X509_Cert_Options& opts, tbs_req.encode( Attribute("PKCS9.ChallengePassword", - DER_Encoder().encode(challenge).get_contents() + DER_Encoder().encode(challenge).get_contents_unlocked() ) ); } @@ -145,20 +145,17 @@ PKCS10_Request create_cert_req(const X509_Cert_Options& opts, .start_cons(SEQUENCE) .encode(extensions) .end_cons() - .get_contents() + .get_contents_unlocked() ) ) .end_explicit() .end_cons(); - DataSource_Memory source( - X509_Object::make_signed(signer.get(), - rng, - sig_algo, - tbs_req.get_contents()) - ); + const std::vector<byte> req = + X509_Object::make_signed(signer.get(), rng, sig_algo, + tbs_req.get_contents()); - return PKCS10_Request(source); + return PKCS10_Request(req); } } diff --git a/src/cms/cms_algo.cpp b/src/cms/cms_algo.cpp index 3c245cc6f..6d768306b 100644 --- a/src/cms/cms_algo.cpp +++ b/src/cms/cms_algo.cpp @@ -23,10 +23,10 @@ namespace { /* * Wrap a key as specified in RFC 3217 */ -SecureVector<byte> do_rfc3217_wrap(RandomNumberGenerator& rng, +secure_vector<byte> do_rfc3217_wrap(RandomNumberGenerator& rng, const std::string& cipher_name, const SymmetricKey& kek, - const SecureVector<byte>& input) + const secure_vector<byte>& input) { class Flip_Bytes : public Filter { @@ -44,9 +44,9 @@ SecureVector<byte> do_rfc3217_wrap(RandomNumberGenerator& rng, buf.clear(); } - Flip_Bytes(const SecureVector<byte>& prefix) : buf(prefix) {} + Flip_Bytes(const secure_vector<byte>& prefix) : buf(prefix) {} private: - SecureVector<byte> buf; + secure_vector<byte> buf; }; Algorithm_Factory& af = global_state().algorithm_factory(); @@ -78,7 +78,7 @@ SecureVector<byte> do_rfc3217_wrap(RandomNumberGenerator& rng, /* * Wrap a CEK with a KEK */ -SecureVector<byte> CMS_Encoder::wrap_key(RandomNumberGenerator& rng, +secure_vector<byte> CMS_Encoder::wrap_key(RandomNumberGenerator& rng, const std::string& cipher, const SymmetricKey& cek, const SymmetricKey& kek) @@ -98,7 +98,7 @@ SecureVector<byte> CMS_Encoder::wrap_key(RandomNumberGenerator& rng, if(kek.length() != 16) throw Encoding_Error("CMS: 128-bit KEKs must be used with " + cipher); - SecureVector<byte> lcekpad; + secure_vector<byte> lcekpad; lcekpad.push_back(static_cast<byte>(cek.length())); lcekpad += cek.bits_of(); while(lcekpad.size() % 8) @@ -113,7 +113,7 @@ SecureVector<byte> CMS_Encoder::wrap_key(RandomNumberGenerator& rng, /* * Encode the parameters for an encryption algo */ -SecureVector<byte> CMS_Encoder::encode_params(const std::string& cipher, +secure_vector<byte> CMS_Encoder::encode_params(const std::string& cipher, const SymmetricKey& key, const InitializationVector& iv) { diff --git a/src/cms/cms_comp.cpp b/src/cms/cms_comp.cpp index 3d9108e13..8ff46acea 100644 --- a/src/cms/cms_comp.cpp +++ b/src/cms/cms_comp.cpp @@ -37,13 +37,13 @@ void CMS_Encoder::compress(const std::string& algo) Pipe pipe(compressor); pipe.process_msg(data); - SecureVector<byte> compressed = pipe.read_all(); + secure_vector<byte> compressed = pipe.read_all(); DER_Encoder encoder; encoder.start_cons(SEQUENCE). encode(static_cast<size_t>(0)). encode(AlgorithmIdentifier("Compression." + algo, - MemoryVector<byte>())). + std::vector<byte>())). raw_bytes(make_econtent(compressed, type)). end_cons(); diff --git a/src/cms/cms_dalg.cpp b/src/cms/cms_dalg.cpp index 2935f3070..96bdd5be3 100644 --- a/src/cms/cms_dalg.cpp +++ b/src/cms/cms_dalg.cpp @@ -20,7 +20,7 @@ namespace { /* * Compute the hash of some content */ -SecureVector<byte> hash_of(const SecureVector<byte>& content, +secure_vector<byte> hash_of(const secure_vector<byte>& content, const AlgorithmIdentifier& hash_algo, std::string& hash_name) { @@ -28,7 +28,7 @@ SecureVector<byte> hash_of(const SecureVector<byte>& content, Algorithm_Factory& af = global_state().algorithm_factory(); - std::auto_ptr<HashFunction> hash_fn(af.make_hash_function(hash_name)); + std::unique_ptr<HashFunction> hash_fn(af.make_hash_function(hash_name)); return hash_fn->process(content); } @@ -51,10 +51,11 @@ std::vector<X509_Certificate> get_cert(BER_Decoder& signer_info, iands.decode(issuer); iands.decode(serial); - found = store.get_certs(IandS_Match(issuer, BigInt::encode(serial))); + found = store.get_certs( + X509_Store_Search::by_issuer_and_serial(issuer, serial)); } else if(id.type_tag == 0 && id.class_tag == CONSTRUCTED) - found = store.get_certs(SKID_Match(id.value)); + found = store.get_certs(X509_Store_Search::by_skid(id.value)); else throw Decoding_Error("CMS: Unknown tag for cert identifier"); #endif @@ -105,11 +106,11 @@ void read_orig_info(BER_Decoder& info, X509_Store& store) /* * Decode any Attributes, and check type */ -SecureVector<byte> decode_attributes(BER_Decoder& ber, const OID& type, +secure_vector<byte> decode_attributes(BER_Decoder& ber, const OID& type, bool& bad_attributes) { BER_Object obj = ber.get_next_object(); - SecureVector<byte> digest; + secure_vector<byte> digest; bool got_digest = false; bool got_content_type = false; @@ -177,7 +178,7 @@ void CMS_Decoder::decode_layer() { size_t version; AlgorithmIdentifier hash_algo; - SecureVector<byte> digest; + secure_vector<byte> digest; BER_Decoder hash_info = decoder.start_cons(SEQUENCE); @@ -212,7 +213,7 @@ void CMS_Decoder::decode_layer() while(signer_infos.more_items()) { AlgorithmIdentifier sig_algo, hash_algo; - SecureVector<byte> signature, digest; + secure_vector<byte> signature, digest; size_t version; BER_Decoder signer_info = BER::get_subsequence(signer_infos); diff --git a/src/cms/cms_dec.h b/src/cms/cms_dec.h index 8aa5c0edb..8c2057c2a 100644 --- a/src/cms/cms_dec.h +++ b/src/cms/cms_dec.h @@ -52,7 +52,7 @@ class BOTAN_DLL CMS_Decoder std::vector<Private_Key*> keys; OID type, next_type; - SecureVector<byte> data; + secure_vector<byte> data; Status status; std::string info; }; diff --git a/src/cms/cms_ealg.cpp b/src/cms/cms_ealg.cpp index 4aee8afd8..4c3fd98fc 100644 --- a/src/cms/cms_ealg.cpp +++ b/src/cms/cms_ealg.cpp @@ -53,22 +53,22 @@ DER_Encoder& encode_si(DER_Encoder& der, const X509_Certificate& cert, /* * Compute the hash of some content */ -SecureVector<byte> hash_of(const SecureVector<byte>& content, +secure_vector<byte> hash_of(const secure_vector<byte>& content, const std::string& hash_name) { Algorithm_Factory& af = global_state().algorithm_factory(); - std::auto_ptr<HashFunction> hash_fn(af.make_hash_function(hash_name)); + std::unique_ptr<HashFunction> hash_fn(af.make_hash_function(hash_name)); return hash_fn->process(content); } /* * Encode Attributes containing info on content */ -SecureVector<byte> encode_attr(const SecureVector<byte>& data, +secure_vector<byte> encode_attr(const secure_vector<byte>& data, const std::string& type, const std::string& hash) { - SecureVector<byte> digest = hash_of(data, hash); + secure_vector<byte> digest = hash_of(data, hash); DER_Encoder encoder; encoder.encode(OIDS::lookup(type)); @@ -96,7 +96,7 @@ void CMS_Encoder::encrypt(RandomNumberGenerator& rng, { const std::string cipher = choose_algo(user_cipher, "TripleDES"); - std::auto_ptr<Public_Key> key(to.subject_public_key()); + std::unique_ptr<Public_Key> key(to.subject_public_key()); const std::string algo = key->algo_name(); Key_Constraints constraints = to.constraints(); @@ -198,7 +198,7 @@ void CMS_Encoder::encrypt(RandomNumberGenerator& rng, const std::string cipher = choose_algo(user_cipher, "TripleDES"); SymmetricKey cek = setup_key(rng, cipher); - SecureVector<byte> kek_id; // FIXME: ? + secure_vector<byte> kek_id; // FIXME: ? DER_Encoder encoder; @@ -244,7 +244,7 @@ void CMS_Encoder::encrypt(RandomNumberGenerator&, /* * Encrypt the content with the chosen key/cipher */ -SecureVector<byte> CMS_Encoder::do_encrypt(RandomNumberGenerator& rng, +secure_vector<byte> CMS_Encoder::do_encrypt(RandomNumberGenerator& rng, const SymmetricKey& key, const std::string& cipher_name) { @@ -297,9 +297,9 @@ void CMS_Encoder::sign(const X509_Certificate& cert, AlgorithmIdentifier sig_algo(OIDS::lookup(key.algo_name() + "/" + padding), AlgorithmIdentifier::USE_NULL_PARAM); - SecureVector<byte> signed_attr = encode_attr(data, type, hash); + secure_vector<byte> signed_attr = encode_attr(data, type, hash); signer.update(signed_attr); - SecureVector<byte> signature = signer.signature(rng); + secure_vector<byte> signature = signer.signature(rng); signed_attr[0] = 0xA0; const size_t SI_VERSION = cert.subject_key_id().size() ? 3 : 1; diff --git a/src/cms/cms_enc.cpp b/src/cms/cms_enc.cpp index 1a45a6a46..58d7cabb6 100644 --- a/src/cms/cms_enc.cpp +++ b/src/cms/cms_enc.cpp @@ -36,7 +36,7 @@ void CMS_Encoder::set_data(const std::string& str) /* * Finalize and return the CMS encoded data */ -SecureVector<byte> CMS_Encoder::get_contents() +secure_vector<byte> CMS_Encoder::get_contents() { DER_Encoder encoder; @@ -72,7 +72,7 @@ std::string CMS_Encoder::PEM_contents() /* * Make an EncapsulatedContentInfo */ -SecureVector<byte> CMS_Encoder::make_econtent(const SecureVector<byte>& data, +secure_vector<byte> CMS_Encoder::make_econtent(const secure_vector<byte>& data, const std::string& type) { return DER_Encoder().start_cons(SEQUENCE). diff --git a/src/cms/cms_enc.h b/src/cms/cms_enc.h index 5dca838dd..c86dbe58e 100644 --- a/src/cms/cms_enc.h +++ b/src/cms/cms_enc.h @@ -47,7 +47,7 @@ class BOTAN_DLL CMS_Encoder void compress(const std::string&); static bool can_compress_with(const std::string&); - SecureVector<byte> get_contents(); + secure_vector<byte> get_contents(); std::string PEM_contents(); void set_data(const std::string&); @@ -65,25 +65,25 @@ class BOTAN_DLL CMS_Encoder const X509_Certificate&, Public_Key*, const std::string&); - SecureVector<byte> do_encrypt(RandomNumberGenerator& rng, + secure_vector<byte> do_encrypt(RandomNumberGenerator& rng, const SymmetricKey&, const std::string&); - static SecureVector<byte> make_econtent(const SecureVector<byte>&, + static secure_vector<byte> make_econtent(const secure_vector<byte>&, const std::string&); static SymmetricKey setup_key(RandomNumberGenerator& rng, const std::string&); - static SecureVector<byte> wrap_key(RandomNumberGenerator& rng, + static secure_vector<byte> wrap_key(RandomNumberGenerator& rng, const std::string&, const SymmetricKey&, const SymmetricKey&); - static SecureVector<byte> encode_params(const std::string&, + static secure_vector<byte> encode_params(const std::string&, const SymmetricKey&, const InitializationVector&); - SecureVector<byte> data; + secure_vector<byte> data; std::string type; }; diff --git a/src/codec/base64/base64.cpp b/src/codec/base64/base64.cpp index 6a53a7a9a..719a3e8fa 100644 --- a/src/codec/base64/base64.cpp +++ b/src/codec/base64/base64.cpp @@ -92,11 +92,6 @@ std::string base64_encode(const byte input[], return output; } -std::string base64_encode(const MemoryRegion<byte>& input) - { - return base64_encode(&input[0], input.size()); - } - size_t base64_decode(byte output[], const char input[], size_t input_length, @@ -226,11 +221,11 @@ size_t base64_decode(byte output[], return base64_decode(output, &input[0], input.length(), ignore_ws); } -SecureVector<byte> base64_decode(const char input[], +secure_vector<byte> base64_decode(const char input[], size_t input_length, bool ignore_ws) { - SecureVector<byte> bin((round_up<size_t>(input_length, 4) * 3) / 4); + secure_vector<byte> bin((round_up<size_t>(input_length, 4) * 3) / 4); size_t written = base64_decode(&bin[0], input, @@ -241,7 +236,7 @@ SecureVector<byte> base64_decode(const char input[], return bin; } -SecureVector<byte> base64_decode(const std::string& input, +secure_vector<byte> base64_decode(const std::string& input, bool ignore_ws) { return base64_decode(&input[0], input.size(), ignore_ws); diff --git a/src/codec/base64/base64.h b/src/codec/base64/base64.h index 23a2558bd..9ea4143b7 100644 --- a/src/codec/base64/base64.h +++ b/src/codec/base64/base64.h @@ -46,7 +46,11 @@ std::string BOTAN_DLL base64_encode(const byte input[], * @param input some input * @return base64adecimal representation of input */ -std::string BOTAN_DLL base64_encode(const MemoryRegion<byte>& input); +template<typename Alloc> +std::string base64_encode(const std::vector<byte, Alloc>& input) + { + return base64_encode(&input[0], input.size()); + } /** * Perform base64 decoding @@ -104,7 +108,7 @@ size_t BOTAN_DLL base64_decode(byte output[], exception if whitespace is encountered * @return decoded base64 output */ -SecureVector<byte> BOTAN_DLL base64_decode(const char input[], +secure_vector<byte> BOTAN_DLL base64_decode(const char input[], size_t input_length, bool ignore_ws = true); @@ -115,7 +119,7 @@ SecureVector<byte> BOTAN_DLL base64_decode(const char input[], exception if whitespace is encountered * @return decoded base64 output */ -SecureVector<byte> BOTAN_DLL base64_decode(const std::string& input, +secure_vector<byte> BOTAN_DLL base64_decode(const std::string& input, bool ignore_ws = true); } diff --git a/src/codec/hex/hex.cpp b/src/codec/hex/hex.cpp index 41ba1298d..1fd32e2ed 100644 --- a/src/codec/hex/hex.cpp +++ b/src/codec/hex/hex.cpp @@ -34,12 +34,6 @@ void hex_encode(char output[], } } -std::string hex_encode(const MemoryRegion<byte>& input, - bool uppercase) - { - return hex_encode(&input[0], input.size(), uppercase); - } - std::string hex_encode(const byte input[], size_t input_length, bool uppercase) @@ -165,11 +159,11 @@ size_t hex_decode(byte output[], return hex_decode(output, &input[0], input.length(), ignore_ws); } -SecureVector<byte> hex_decode(const char input[], +secure_vector<byte> hex_decode(const char input[], size_t input_length, bool ignore_ws) { - SecureVector<byte> bin(1 + input_length / 2); + secure_vector<byte> bin(1 + input_length / 2); size_t written = hex_decode(&bin[0], input, @@ -180,7 +174,7 @@ SecureVector<byte> hex_decode(const char input[], return bin; } -SecureVector<byte> hex_decode(const std::string& input, +secure_vector<byte> hex_decode(const std::string& input, bool ignore_ws) { return hex_decode(&input[0], input.size(), ignore_ws); diff --git a/src/codec/hex/hex.h b/src/codec/hex/hex.h index 40930e808..bdb5e5365 100644 --- a/src/codec/hex/hex.h +++ b/src/codec/hex/hex.h @@ -42,8 +42,12 @@ std::string BOTAN_DLL hex_encode(const byte input[], * @param uppercase should output be upper or lower case? * @return hexadecimal representation of input */ -std::string BOTAN_DLL hex_encode(const MemoryRegion<byte>& input, - bool uppercase = true); +template<typename Alloc> +std::string hex_encode(const std::vector<byte, Alloc>& input, + bool uppercase = true) + { + return hex_encode(&input[0], input.size(), uppercase); + } /** * Perform hex decoding @@ -98,7 +102,7 @@ size_t BOTAN_DLL hex_decode(byte output[], exception if whitespace is encountered * @return decoded hex output */ -SecureVector<byte> BOTAN_DLL hex_decode(const char input[], +secure_vector<byte> BOTAN_DLL hex_decode(const char input[], size_t input_length, bool ignore_ws = true); @@ -109,8 +113,8 @@ SecureVector<byte> BOTAN_DLL hex_decode(const char input[], exception if whitespace is encountered * @return decoded hex output */ -SecureVector<byte> BOTAN_DLL hex_decode(const std::string& input, - bool ignore_ws = true); +secure_vector<byte> BOTAN_DLL hex_decode(const std::string& input, + bool ignore_ws = true); } diff --git a/src/codec/openpgp/openpgp.cpp b/src/codec/openpgp/openpgp.cpp index ab9673689..7bd811a2f 100644 --- a/src/codec/openpgp/openpgp.cpp +++ b/src/codec/openpgp/openpgp.cpp @@ -67,7 +67,7 @@ std::string PGP_encode(const byte input[], size_t length, /* * OpenPGP Base64 decoding */ -SecureVector<byte> PGP_decode(DataSource& source, +secure_vector<byte> PGP_decode(DataSource& source, std::string& label, std::map<std::string, std::string>& headers) { @@ -136,7 +136,7 @@ SecureVector<byte> PGP_decode(DataSource& source, } Pipe base64(new Base64_Decoder, - new Fork(0, + new Fork(nullptr, new Chain(new Hash_Filter(new CRC24), new Base64_Encoder) ) @@ -186,7 +186,7 @@ SecureVector<byte> PGP_decode(DataSource& source, /* * OpenPGP Base64 decoding */ -SecureVector<byte> PGP_decode(DataSource& source, std::string& label) +secure_vector<byte> PGP_decode(DataSource& source, std::string& label) { std::map<std::string, std::string> ignored; return PGP_decode(source, label, ignored); diff --git a/src/codec/openpgp/openpgp.h b/src/codec/openpgp/openpgp.h index 0cd77d53a..de56155f2 100644 --- a/src/codec/openpgp/openpgp.h +++ b/src/codec/openpgp/openpgp.h @@ -42,7 +42,7 @@ BOTAN_DLL std::string PGP_encode( * @param headers is set to any headers * @return decoded output as raw binary */ -BOTAN_DLL SecureVector<byte> PGP_decode( +BOTAN_DLL secure_vector<byte> PGP_decode( DataSource& source, std::string& label, std::map<std::string, std::string>& headers); @@ -52,7 +52,7 @@ BOTAN_DLL SecureVector<byte> PGP_decode( * @param label is set to the human-readable label * @return decoded output as raw binary */ -BOTAN_DLL SecureVector<byte> PGP_decode( +BOTAN_DLL secure_vector<byte> PGP_decode( DataSource& source, std::string& label); diff --git a/src/codec/pem/pem.cpp b/src/codec/pem/pem.cpp index 005ec7310..03ec33440 100644 --- a/src/codec/pem/pem.cpp +++ b/src/codec/pem/pem.cpp @@ -28,22 +28,13 @@ std::string encode(const byte der[], size_t length, const std::string& label, } /* -* PEM encode BER/DER-encoded objects -*/ -std::string encode(const MemoryRegion<byte>& data, const std::string& label, - size_t width) - { - return encode(&data[0], data.size(), label, width); - } - -/* * Decode PEM down to raw BER/DER */ -SecureVector<byte> decode_check_label(DataSource& source, +secure_vector<byte> decode_check_label(DataSource& source, const std::string& label_want) { std::string label_got; - SecureVector<byte> ber = decode(source, label_got); + secure_vector<byte> ber = decode(source, label_got); if(label_got != label_want) throw Decoding_Error("PEM: Label mismatch, wanted " + label_want + ", got " + label_got); @@ -53,7 +44,7 @@ SecureVector<byte> decode_check_label(DataSource& source, /* * Decode PEM down to raw BER/DER */ -SecureVector<byte> decode(DataSource& source, std::string& label) +secure_vector<byte> decode(DataSource& source, std::string& label) { const size_t RANDOM_CHAR_LIMIT = 8; @@ -110,6 +101,19 @@ SecureVector<byte> decode(DataSource& source, std::string& label) return base64.read_all(); } +secure_vector<byte> decode_check_label(const std::string& pem, + const std::string& label_want) + { + DataSource_Memory src(pem); + return decode_check_label(src, label_want); + } + +secure_vector<byte> decode(const std::string& pem, std::string& label) + { + DataSource_Memory src(pem); + return decode(src, label); + } + /* * Search for a PEM signature */ @@ -118,7 +122,7 @@ bool matches(DataSource& source, const std::string& extra, { const std::string PEM_HEADER = "-----BEGIN " + extra; - SecureVector<byte> search_buf(search_range); + secure_vector<byte> search_buf(search_range); size_t got = source.peek(&search_buf[0], search_buf.size(), 0); if(got < PEM_HEADER.length()) diff --git a/src/codec/pem/pem.h b/src/codec/pem/pem.h index d15bfe978..6c33c642d 100644 --- a/src/codec/pem/pem.h +++ b/src/codec/pem/pem.h @@ -14,18 +14,69 @@ namespace Botan { namespace PEM_Code { -/* -* PEM Encoding/Decoding +/** +* Encode some binary data in PEM format +*/ +BOTAN_DLL std::string encode(const byte data[], + size_t data_len, + const std::string& label, + size_t line_width = 64); + +/** +* Encode some binary data in PEM format +*/ +inline std::string encode(const std::vector<byte>& data, + const std::string& label, + size_t line_width = 64) + { + return encode(&data[0], data.size(), label, line_width); + } + +/** +* Encode some binary data in PEM format +*/ +inline std::string encode(const secure_vector<byte>& data, + const std::string& label, + size_t line_width = 64) + { + return encode(&data[0], data.size(), label, line_width); + } + +/** +* Decode PEM data +* @param label is set to the PEM label found for later inspection */ -BOTAN_DLL std::string encode(const byte[], size_t, - const std::string&, size_t = 64); -BOTAN_DLL std::string encode(const MemoryRegion<byte>&, - const std::string&, size_t = 64); +BOTAN_DLL secure_vector<byte> decode(DataSource& pem, + std::string& label); -BOTAN_DLL SecureVector<byte> decode(DataSource&, std::string&); -BOTAN_DLL SecureVector<byte> decode_check_label(DataSource&, - const std::string&); -BOTAN_DLL bool matches(DataSource&, const std::string& = "", +/** +* Decode PEM data +* @param label is set to the PEM label found for later inspection +*/ +BOTAN_DLL secure_vector<byte> decode(const std::string& pem, + std::string& label); + +/** +* Decode PEM data +* @param label is what we expect the label to be +*/ +BOTAN_DLL secure_vector<byte> decode_check_label( + DataSource& pem, + const std::string& label); + +/** +* Decode PEM data +* @param label is what we expect the label to be +*/ +BOTAN_DLL secure_vector<byte> decode_check_label( + const std::string& pem, + const std::string& label); + +/** +* Heuristic test for PEM data. +*/ +BOTAN_DLL bool matches(DataSource& source, + const std::string& extra = "", size_t search_range = 4096); } diff --git a/src/constructs/aont/package.cpp b/src/constructs/aont/package.cpp index 4d46f6b61..1adee90e8 100644 --- a/src/constructs/aont/package.cpp +++ b/src/constructs/aont/package.cpp @@ -37,7 +37,7 @@ void aont_package(RandomNumberGenerator& rng, // Set K0 (the all zero key) cipher->set_key(SymmetricKey(all_zeros)); - SecureVector<byte> buf(BLOCK_SIZE); + secure_vector<byte> buf(BLOCK_SIZE); const size_t blocks = (input_len + BLOCK_SIZE - 1) / BLOCK_SIZE; @@ -57,13 +57,13 @@ void aont_package(RandomNumberGenerator& rng, for(size_t j = 0; j != sizeof(i); ++j) buf[BLOCK_SIZE - 1 - j] ^= get_byte(sizeof(i)-1-j, i); - cipher->encrypt(buf); + cipher->encrypt(&buf[0]); - xor_buf(final_block, buf, BLOCK_SIZE); + xor_buf(&final_block[0], &buf[0], BLOCK_SIZE); } // XOR the random package key into the final block - xor_buf(final_block, package_key.begin(), BLOCK_SIZE); + xor_buf(&final_block[0], package_key.begin(), BLOCK_SIZE); } void aont_unpackage(BlockCipher* cipher, @@ -83,8 +83,8 @@ void aont_unpackage(BlockCipher* cipher, cipher->set_key(SymmetricKey(all_zeros)); - SecureVector<byte> package_key(BLOCK_SIZE); - SecureVector<byte> buf(BLOCK_SIZE); + secure_vector<byte> package_key(BLOCK_SIZE); + secure_vector<byte> buf(BLOCK_SIZE); // Copy the package key (masked with the block hashes) copy_mem(&package_key[0], @@ -105,9 +105,9 @@ void aont_unpackage(BlockCipher* cipher, for(size_t j = 0; j != sizeof(i); ++j) buf[BLOCK_SIZE - 1 - j] ^= get_byte(sizeof(i)-1-j, i); - cipher->encrypt(buf); + cipher->encrypt(&buf[0]); - xor_buf(&package_key[0], buf, BLOCK_SIZE); + xor_buf(&package_key[0], &buf[0], BLOCK_SIZE); } Pipe pipe(new StreamCipher_Filter(new CTR_BE(cipher), package_key)); diff --git a/src/constructs/cryptobox/cryptobox.cpp b/src/constructs/cryptobox/cryptobox.cpp index ab263c3e9..aa2369c6c 100644 --- a/src/constructs/cryptobox/cryptobox.cpp +++ b/src/constructs/cryptobox/cryptobox.cpp @@ -44,7 +44,7 @@ std::string encrypt(const byte input[], size_t input_len, const std::string& passphrase, RandomNumberGenerator& rng) { - SecureVector<byte> pbkdf_salt(PBKDF_SALT_LEN); + secure_vector<byte> pbkdf_salt(PBKDF_SALT_LEN); rng.randomize(&pbkdf_salt[0], pbkdf_salt.size()); PKCS5_PBKDF2 pbkdf(new HMAC(new SHA_512)); @@ -64,7 +64,7 @@ std::string encrypt(const byte input[], size_t input_len, Pipe pipe(get_cipher("Serpent/CTR-BE", cipher_key, iv, ENCRYPTION), new Fork( - 0, + nullptr, new MAC_Filter(new HMAC(new SHA_512), mac_key, MAC_OUTPUT_LEN))); @@ -79,10 +79,10 @@ std::string encrypt(const byte input[], size_t input_len, */ const size_t ciphertext_len = pipe.remaining(0); - SecureVector<byte> out_buf(VERSION_CODE_LEN + - PBKDF_SALT_LEN + - MAC_OUTPUT_LEN + - ciphertext_len); + std::vector<byte> out_buf(VERSION_CODE_LEN + + PBKDF_SALT_LEN + + MAC_OUTPUT_LEN + + ciphertext_len); for(size_t i = 0; i != VERSION_CODE_LEN; ++i) out_buf[i] = get_byte(i, CRYPTOBOX_VERSION_CODE); @@ -100,7 +100,7 @@ std::string decrypt(const byte input[], size_t input_len, const std::string& passphrase) { DataSource_Memory input_src(input, input_len); - SecureVector<byte> ciphertext = + secure_vector<byte> ciphertext = PEM_Code::decode_check_label(input_src, "BOTAN CRYPTOBOX MESSAGE"); diff --git a/src/constructs/fpe_fe1/fpe_fe1.cpp b/src/constructs/fpe_fe1/fpe_fe1.cpp index 91d328c17..b22d3a8df 100644 --- a/src/constructs/fpe_fe1/fpe_fe1.cpp +++ b/src/constructs/fpe_fe1/fpe_fe1.cpp @@ -84,7 +84,7 @@ class FPE_Encryptor public: FPE_Encryptor(const SymmetricKey& key, const BigInt& n, - const MemoryRegion<byte>& tweak); + const std::vector<byte>& tweak); ~FPE_Encryptor() { delete mac; } @@ -92,17 +92,17 @@ class FPE_Encryptor private: MessageAuthenticationCode* mac; - SecureVector<byte> mac_n_t; + std::vector<byte> mac_n_t; }; FPE_Encryptor::FPE_Encryptor(const SymmetricKey& key, const BigInt& n, - const MemoryRegion<byte>& tweak) + const std::vector<byte>& tweak) { mac = new HMAC(new SHA_256); mac->set_key(key); - SecureVector<byte> n_bin = BigInt::encode(n); + std::vector<byte> n_bin = BigInt::encode(n); if(n_bin.size() > MAX_N_BYTES) throw std::runtime_error("N is too large for FPE encryption"); @@ -113,12 +113,12 @@ FPE_Encryptor::FPE_Encryptor(const SymmetricKey& key, mac->update_be(static_cast<u32bit>(tweak.size())); mac->update(&tweak[0], tweak.size()); - mac_n_t = mac->final(); + mac_n_t = unlock(mac->final()); } BigInt FPE_Encryptor::operator()(size_t round_no, const BigInt& R) { - SecureVector<byte> r_bin = BigInt::encode(R); + secure_vector<byte> r_bin = BigInt::encode_locked(R); mac->update(mac_n_t); mac->update_be(static_cast<u32bit>(round_no)); @@ -126,7 +126,7 @@ BigInt FPE_Encryptor::operator()(size_t round_no, const BigInt& R) mac->update_be(static_cast<u32bit>(r_bin.size())); mac->update(&r_bin[0], r_bin.size()); - SecureVector<byte> X = mac->final(); + secure_vector<byte> X = mac->final(); return BigInt(&X[0], X.size()); } @@ -137,7 +137,7 @@ BigInt FPE_Encryptor::operator()(size_t round_no, const BigInt& R) */ BigInt fe1_encrypt(const BigInt& n, const BigInt& X0, const SymmetricKey& key, - const MemoryRegion<byte>& tweak) + const std::vector<byte>& tweak) { FPE_Encryptor F(key, n, tweak); @@ -165,7 +165,7 @@ BigInt fe1_encrypt(const BigInt& n, const BigInt& X0, */ BigInt fe1_decrypt(const BigInt& n, const BigInt& X0, const SymmetricKey& key, - const MemoryRegion<byte>& tweak) + const std::vector<byte>& tweak) { FPE_Encryptor F(key, n, tweak); diff --git a/src/constructs/fpe_fe1/fpe_fe1.h b/src/constructs/fpe_fe1/fpe_fe1.h index da9a6bcb6..66e7f1cfa 100644 --- a/src/constructs/fpe_fe1/fpe_fe1.h +++ b/src/constructs/fpe_fe1/fpe_fe1.h @@ -24,7 +24,7 @@ namespace FPE { */ BigInt BOTAN_DLL fe1_encrypt(const BigInt& n, const BigInt& X, const SymmetricKey& key, - const MemoryRegion<byte>& tweak); + const std::vector<byte>& tweak); /** * Decrypt X from and onto the group Z_n using key and tweak @@ -35,7 +35,7 @@ BigInt BOTAN_DLL fe1_encrypt(const BigInt& n, const BigInt& X, */ BigInt BOTAN_DLL fe1_decrypt(const BigInt& n, const BigInt& X, const SymmetricKey& key, - const MemoryRegion<byte>& tweak); + const std::vector<byte>& tweak); } diff --git a/src/constructs/rfc3394/rfc3394.cpp b/src/constructs/rfc3394/rfc3394.cpp index b000873fd..cfe95f40b 100644 --- a/src/constructs/rfc3394/rfc3394.cpp +++ b/src/constructs/rfc3394/rfc3394.cpp @@ -32,25 +32,25 @@ BlockCipher* make_aes(size_t keylength, } -SecureVector<byte> rfc3394_keywrap(const MemoryRegion<byte>& key, - const SymmetricKey& kek, - Algorithm_Factory& af) +secure_vector<byte> rfc3394_keywrap(const secure_vector<byte>& key, + const SymmetricKey& kek, + Algorithm_Factory& af) { if(key.size() % 8 != 0) throw std::invalid_argument("Bad input key size for NIST key wrap"); - std::auto_ptr<BlockCipher> aes(make_aes(kek.length(), af)); + std::unique_ptr<BlockCipher> aes(make_aes(kek.length(), af)); aes->set_key(kek); const size_t n = key.size() / 8; - SecureVector<byte> R((n + 1) * 8); - SecureVector<byte> A(16); + secure_vector<byte> R((n + 1) * 8); + secure_vector<byte> A(16); for(size_t i = 0; i != 8; ++i) A[i] = 0xA6; - copy_mem(&R[8], key.begin(), key.size()); + copy_mem(&R[8], &key[0], key.size()); for(size_t j = 0; j <= 5; ++j) { @@ -74,25 +74,25 @@ SecureVector<byte> rfc3394_keywrap(const MemoryRegion<byte>& key, return R; } -SecureVector<byte> rfc3394_keyunwrap(const MemoryRegion<byte>& key, +secure_vector<byte> rfc3394_keyunwrap(const secure_vector<byte>& key, const SymmetricKey& kek, Algorithm_Factory& af) { if(key.size() < 16 || key.size() % 8 != 0) throw std::invalid_argument("Bad input key size for NIST key unwrap"); - std::auto_ptr<BlockCipher> aes(make_aes(kek.length(), af)); + std::unique_ptr<BlockCipher> aes(make_aes(kek.length(), af)); aes->set_key(kek); const size_t n = (key.size() - 8) / 8; - SecureVector<byte> R(n * 8); - SecureVector<byte> A(16); + secure_vector<byte> R(n * 8); + secure_vector<byte> A(16); for(size_t i = 0; i != 8; ++i) A[i] = key[i]; - copy_mem(&R[0], key.begin() + 8, key.size() - 8); + copy_mem(&R[0], &key[8], key.size() - 8); for(size_t j = 0; j <= 5; ++j) { diff --git a/src/constructs/rfc3394/rfc3394.h b/src/constructs/rfc3394/rfc3394.h index 645586ee2..febd5207e 100644 --- a/src/constructs/rfc3394/rfc3394.h +++ b/src/constructs/rfc3394/rfc3394.h @@ -23,7 +23,7 @@ class Algorithm_Factory; * @param af an algorithm factory * @return key encrypted under kek */ -SecureVector<byte> BOTAN_DLL rfc3394_keywrap(const MemoryRegion<byte>& key, +secure_vector<byte> BOTAN_DLL rfc3394_keywrap(const secure_vector<byte>& key, const SymmetricKey& kek, Algorithm_Factory& af); @@ -36,7 +36,7 @@ SecureVector<byte> BOTAN_DLL rfc3394_keywrap(const MemoryRegion<byte>& key, * @param af an algorithm factory * @return key decrypted under kek */ -SecureVector<byte> BOTAN_DLL rfc3394_keyunwrap(const MemoryRegion<byte>& key, +secure_vector<byte> BOTAN_DLL rfc3394_keyunwrap(const secure_vector<byte>& key, const SymmetricKey& kek, Algorithm_Factory& af); diff --git a/src/constructs/srp6/srp6.cpp b/src/constructs/srp6/srp6.cpp index 287f0bdfb..f1927b648 100644 --- a/src/constructs/srp6/srp6.cpp +++ b/src/constructs/srp6/srp6.cpp @@ -1,6 +1,6 @@ /* -* SRP-6a -* (C) 2011 Jack Lloyd +* SRP-6a (RFC 5054 compatatible) +* (C) 2011,2012 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -20,7 +20,7 @@ BigInt hash_seq(const std::string& hash_id, const BigInt& in1, const BigInt& in2) { - std::auto_ptr<HashFunction> hash_fn( + std::unique_ptr<HashFunction> hash_fn( global_state().algorithm_factory().make_hash_function(hash_id)); hash_fn->update(BigInt::encode_1363(in1, pad_to)); @@ -29,54 +29,61 @@ BigInt hash_seq(const std::string& hash_id, return BigInt::decode(hash_fn->final()); } -BigInt hash_seq(const std::string& hash_id, - size_t pad_to, - const BigInt& in1, - const BigInt& in2, - const BigInt& in3) - { - std::auto_ptr<HashFunction> hash_fn( - global_state().algorithm_factory().make_hash_function(hash_id)); - - hash_fn->update(BigInt::encode_1363(in1, pad_to)); - hash_fn->update(BigInt::encode_1363(in2, pad_to)); - hash_fn->update(BigInt::encode_1363(in3, pad_to)); - - return BigInt::decode(hash_fn->final()); - } - BigInt compute_x(const std::string& hash_id, const std::string& identifier, const std::string& password, - const MemoryRegion<byte>& salt) + const std::vector<byte>& salt) { - std::auto_ptr<HashFunction> hash_fn( + std::unique_ptr<HashFunction> hash_fn( global_state().algorithm_factory().make_hash_function(hash_id)); hash_fn->update(identifier); hash_fn->update(":"); hash_fn->update(password); - SecureVector<byte> inner_h = hash_fn->final(); + secure_vector<byte> inner_h = hash_fn->final(); hash_fn->update(salt); hash_fn->update(inner_h); - SecureVector<byte> outer_h = hash_fn->final(); + secure_vector<byte> outer_h = hash_fn->final(); return BigInt::decode(outer_h); } } +std::string srp6_group_identifier(const BigInt& N, const BigInt& g) + { + /* + This function assumes that only one 'standard' SRP parameter set has + been defined for a particular bitsize. As of this writing that is the case. + */ + try + { + const std::string group_name = "modp/srp/" + std::to_string(N.bits()); + + DL_Group group(group_name); + + if(group.get_p() == N && group.get_g() == g) + return group_name; + + throw std::runtime_error("Unknown SRP params"); + } + catch(...) + { + throw Invalid_Argument("Bad SRP group parameters"); + } + } + std::pair<BigInt, SymmetricKey> -SRP6_Client_Session:: step1(const std::string& identifier, - const std::string& password, - const std::string& group_id, - const std::string& hash_id, - const MemoryRegion<byte>& salt, - const BigInt& B, - RandomNumberGenerator& rng) +srp6_client_agree(const std::string& identifier, + const std::string& password, + const std::string& group_id, + const std::string& hash_id, + const std::vector<byte>& salt, + const BigInt& B, + RandomNumberGenerator& rng) { DL_Group group(group_id); const BigInt& g = group.get_g(); @@ -89,7 +96,7 @@ SRP6_Client_Session:: step1(const std::string& identifier, BigInt k = hash_seq(hash_id, p_bytes, p, g); - BigInt a(rng, p.bits() - 1); + BigInt a(rng, 256); BigInt A = power_mod(g, a, p); @@ -104,11 +111,11 @@ SRP6_Client_Session:: step1(const std::string& identifier, return std::make_pair(A, Sk); } -BigInt SRP6_Client_Session::generate_verifier(const std::string& identifier, - const std::string& password, - const MemoryRegion<byte>& salt, - const std::string& group_id, - const std::string& hash_id) +BigInt generate_srp6_verifier(const std::string& identifier, + const std::string& password, + const std::vector<byte>& salt, + const std::string& group_id, + const std::string& hash_id) { const BigInt x = compute_x(hash_id, identifier, password, salt); @@ -129,7 +136,7 @@ BigInt SRP6_Server_Session::step1(const BigInt& v, BigInt k = hash_seq(hash_id, p_bytes, p, g); - BigInt b(rng, p.bits() - 1); + BigInt b(rng, 256); B = (v*k + power_mod(g, b, p)) % p; diff --git a/src/constructs/srp6/srp6.h b/src/constructs/srp6/srp6.h index 01bd2a4c7..b34253d7a 100644 --- a/src/constructs/srp6/srp6.h +++ b/src/constructs/srp6/srp6.h @@ -1,6 +1,6 @@ /* * SRP-6a (RFC 5054 compatatible) -* (C) 2011 Jack Lloyd +* (C) 2011,2012 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -17,44 +17,43 @@ namespace Botan { /** -* Represents a SRP-6a client session +* SRP6a Client side +* @param username the username we are attempting login for +* @param password the password we are attempting to use +* @param group_id specifies the shared SRP group +* @param hash_id specifies a secure hash function +* @param salt is the salt value sent by the server +* @param B is the server's public value +* @param rng is a random number generator +* +* @return (A,K) the client public key and the shared secret key */ -class BOTAN_DLL SRP6_Client_Session - { - public: +std::pair<BigInt,SymmetricKey> +BOTAN_DLL srp6_client_agree(const std::string& username, + const std::string& password, + const std::string& group_id, + const std::string& hash_id, + const std::vector<byte>& salt, + const BigInt& B, + RandomNumberGenerator& rng); - /** - * Client side step 1 - * @param username the username we are attempting login for - * @param password the password we are attempting to use - * @param group_id specifies the shared SRP group - * @param hash_id specifies a secure hash function - * @param salt is the salt value sent by the server - * @param B is the server's public value - * @param rng is a random number generator - * - * @return (A,K) the client public key and the shared secret key - */ - std::pair<BigInt,SymmetricKey> step1(const std::string& username, - const std::string& password, - const std::string& group_id, - const std::string& hash_id, - const MemoryRegion<byte>& salt, - const BigInt& B, - RandomNumberGenerator& rng); +/** +* Generate a new SRP-6 verifier +* @param identifier a username or other client identifier +* @param password the secret used to authenticate user +* @param salt a randomly chosen value, at least 128 bits long +*/ +BigInt BOTAN_DLL generate_srp6_verifier(const std::string& identifier, + const std::string& password, + const std::vector<byte>& salt, + const std::string& group_id, + const std::string& hash_id); - /** - * Generate a new SRP-6 verifier - * @param identifier a username or other client identifier - * @param password the secret used to authenticate user - * @param salt a randomly chosen value, at least 128 bits long - */ - static BigInt generate_verifier(const std::string& identifier, - const std::string& password, - const MemoryRegion<byte>& salt, - const std::string& group_id, - const std::string& hash_id); - }; +/** +* Return the group id for this SRP param set, or else thrown an +* exception +*/ +std::string BOTAN_DLL srp6_group_identifier(const BigInt& N, const BigInt& g); /** * Represents a SRP-6a server session diff --git a/src/constructs/srp6/srp6_files.cpp b/src/constructs/srp6/srp6_files.cpp index 2d685614f..4df2986f3 100644 --- a/src/constructs/srp6/srp6_files.cpp +++ b/src/constructs/srp6/srp6_files.cpp @@ -31,7 +31,7 @@ SRP6_Authenticator_File::SRP6_Authenticator_File(const std::string& filename) std::string username = parts[0]; BigInt v = BigInt::decode(base64_decode(parts[1])); - MemoryVector<byte> salt = base64_decode(parts[2]); + std::vector<byte> salt = unlock(base64_decode(parts[2])); BigInt group_id_idx = BigInt::decode(base64_decode(parts[3])); std::string group_id; @@ -51,7 +51,7 @@ SRP6_Authenticator_File::SRP6_Authenticator_File(const std::string& filename) bool SRP6_Authenticator_File::lookup_user(const std::string& username, BigInt& v, - MemoryVector<byte>& salt, + std::vector<byte>& salt, std::string& group_id) const { std::map<std::string, SRP6_Data>::const_iterator i = entries.find(username); diff --git a/src/constructs/srp6/srp6_files.h b/src/constructs/srp6/srp6_files.h index 1def0fd51..4e0d3ff02 100644 --- a/src/constructs/srp6/srp6_files.h +++ b/src/constructs/srp6/srp6_files.h @@ -17,7 +17,7 @@ namespace Botan { /** * A GnuTLS compatible SRP6 authenticator file */ -class SRP6_Authenticator_File +class BOTAN_DLL SRP6_Authenticator_File { public: /** @@ -28,7 +28,7 @@ class SRP6_Authenticator_File bool lookup_user(const std::string& username, BigInt& v, - MemoryVector<byte>& salt, + std::vector<byte>& salt, std::string& group_id) const; private: struct SRP6_Data @@ -36,12 +36,12 @@ class SRP6_Authenticator_File SRP6_Data() {} SRP6_Data(const BigInt& v, - const MemoryRegion<byte>& salt, + const std::vector<byte>& salt, const std::string& group_id) : v(v), salt(salt), group_id(group_id) {} BigInt v; - MemoryVector<byte> salt; + std::vector<byte> salt; std::string group_id; }; diff --git a/src/constructs/tss/tss.cpp b/src/constructs/tss/tss.cpp index d0a18f534..e002084a1 100644 --- a/src/constructs/tss/tss.cpp +++ b/src/constructs/tss/tss.cpp @@ -150,7 +150,7 @@ RTSS_Share::split(byte M, byte N, shares[i].contents.push_back(i+1); // secret = S || H(S) - SecureVector<byte> secret(S, S_len); + secure_vector<byte> secret(S, S + S_len); secret += hash.process(S, S_len); for(size_t i = 0; i != secret.size(); ++i) @@ -178,7 +178,7 @@ RTSS_Share::split(byte M, byte N, return shares; } -SecureVector<byte> +secure_vector<byte> RTSS_Share::reconstruct(const std::vector<RTSS_Share>& shares) { const size_t RTSS_HEADER_SIZE = 20; @@ -205,13 +205,13 @@ RTSS_Share::reconstruct(const std::vector<RTSS_Share>& shares) byte hash_id = shares[0].contents[16]; - std::auto_ptr<HashFunction> hash(get_rtss_hash_by_id(hash_id)); + std::unique_ptr<HashFunction> hash(get_rtss_hash_by_id(hash_id)); if(shares[0].size() != secret_len + hash->output_length() + RTSS_HEADER_SIZE + 1) throw Decoding_Error("Bad RTSS length field in header"); std::vector<byte> V(shares.size()); - SecureVector<byte> secret; + secure_vector<byte> secret; for(size_t i = RTSS_HEADER_SIZE + 1; i != shares[0].size(); ++i) { @@ -250,13 +250,13 @@ RTSS_Share::reconstruct(const std::vector<RTSS_Share>& shares) throw Decoding_Error("Bad length in RTSS output"); hash->update(&secret[0], secret_len); - SecureVector<byte> hash_check = hash->final(); + secure_vector<byte> hash_check = hash->final(); if(!same_mem(&hash_check[0], &secret[secret_len], hash->output_length())) throw Decoding_Error("RTSS hash check failed"); - return SecureVector<byte>(&secret[0], secret_len); + return secure_vector<byte>(&secret[0], &secret[secret_len]); } } diff --git a/src/constructs/tss/tss.h b/src/constructs/tss/tss.h index 297c65971..4664af317 100644 --- a/src/constructs/tss/tss.h +++ b/src/constructs/tss/tss.h @@ -38,7 +38,7 @@ class BOTAN_DLL RTSS_Share /** * @param shares the list of shares */ - static SecureVector<byte> + static secure_vector<byte> reconstruct(const std::vector<RTSS_Share>& shares); RTSS_Share() {} @@ -68,7 +68,7 @@ class BOTAN_DLL RTSS_Share */ bool initialized() const { return (contents.size() > 0); } private: - SecureVector<byte> contents; + secure_vector<byte> contents; }; } diff --git a/src/credentials/credentials_manager.cpp b/src/credentials/credentials_manager.cpp new file mode 100644 index 000000000..adb3a64fc --- /dev/null +++ b/src/credentials/credentials_manager.cpp @@ -0,0 +1,149 @@ +/* +* Credentials Manager +* (C) 2011,2012 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/credentials_manager.h> +#include <botan/x509stor.h> + +namespace Botan { + +std::string Credentials_Manager::psk_identity_hint(const std::string&, + const std::string&) + { + return ""; + } + +std::string Credentials_Manager::psk_identity(const std::string&, + const std::string&, + const std::string&) + { + return ""; + } + +SymmetricKey Credentials_Manager::psk(const std::string&, + const std::string&, + const std::string& identity) + { + throw Internal_Error("No PSK set for identity " + identity); + } + +bool Credentials_Manager::attempt_srp(const std::string&, + const std::string&) + { + return false; + } + +std::string Credentials_Manager::srp_identifier(const std::string&, + const std::string&) + { + return ""; + } + +std::string Credentials_Manager::srp_password(const std::string&, + const std::string&, + const std::string&) + { + return ""; + } + +bool Credentials_Manager::srp_verifier(const std::string&, + const std::string&, + const std::string&, + std::string&, + BigInt&, + std::vector<byte>&, + bool) + { + return false; + } + +std::vector<X509_Certificate> Credentials_Manager::cert_chain( + const std::vector<std::string>&, + const std::string&, + const std::string&) + { + return std::vector<X509_Certificate>(); + } + +std::vector<X509_Certificate> Credentials_Manager::cert_chain_single_type( + const std::string& cert_key_type, + const std::string& type, + const std::string& context) + { + std::vector<std::string> cert_types; + cert_types.push_back(cert_key_type); + return cert_chain(cert_types, type, context); + } + +Private_Key* Credentials_Manager::private_key_for(const X509_Certificate&, + const std::string&, + const std::string&) + { + return nullptr; + } + +std::vector<X509_Certificate> +Credentials_Manager::trusted_certificate_authorities( + const std::string&, + const std::string&) + { + return std::vector<X509_Certificate>(); + } + +void Credentials_Manager::verify_certificate_chain( + const std::string& type, + const std::string& purported_hostname, + const std::vector<X509_Certificate>& cert_chain) + { + if(cert_chain.empty()) + throw std::invalid_argument("Certificate chain was empty"); + + if(purported_hostname != "" && !cert_chain[0].matches_dns_name(purported_hostname)) + throw std::runtime_error("Certificate did not match hostname"); + +#if 1 + std::vector<X509_Certificate> CAs = trusted_certificate_authorities(type, purported_hostname); + + X509_Store store; + + for(size_t i = 0; i != CAs.size(); ++i) + store.add_cert(CAs[i], true); + for(size_t i = 0; i != cert_chain.size(); ++i) + store.add_cert(cert_chain[i]); + + X509_Code result = store.validate_cert(cert_chain[0], X509_Store::TLS_SERVER); + + if(CAs.empty()) + { + if(result == CERT_ISSUER_NOT_FOUND) + return; + if(result == CANNOT_ESTABLISH_TRUST) + return; + } + + if(result != VERIFIED) + throw std::runtime_error("Certificate did not validate, code " + + std::to_string(result)); +#else + + // New X.509 API + const Certificate_Store& CAs = + trusted_certificate_authorities(type, purported_hostname); + + Path_Validation_Result result = + x509_path_validate(cert_chain, + Path_Validation_Restrictions(), + store); + + if(!result.successful_validation()) + throw std::runtime_error("Certificate validation failure: " + result.as_string()); + + if(!CAs.certificate_known(result.trust_root()) + throw std::runtime_error("Certificate chain roots in unknown/untrusted CA"); +#endif + } + +} diff --git a/src/credentials/credentials_manager.h b/src/credentials/credentials_manager.h new file mode 100644 index 000000000..57ebd8b38 --- /dev/null +++ b/src/credentials/credentials_manager.h @@ -0,0 +1,153 @@ +/* +* Credentials Manager +* (C) 2011,2012 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_CREDENTIALS_MANAGER_H__ +#define BOTAN_CREDENTIALS_MANAGER_H__ + +#include <botan/x509cert.h> +#include <botan/symkey.h> +#include <string> + +namespace Botan { + +class BigInt; + +/** +* Interface for a credentials manager. +* +* A type is a fairly static value that represents the general nature +* of the transaction occuring. Currently used values are "tls-client" +* and "tls-server". Context represents a hostname, email address, +* username, or other identifier. +*/ +class BOTAN_DLL Credentials_Manager + { + public: + virtual ~Credentials_Manager() {} + + virtual std::string psk_identity_hint(const std::string& type, + const std::string& context); + + /** + * @param identity_hint was passed by the server (but may be empty) + * @return the PSK identity we want to use + */ + virtual std::string psk_identity(const std::string& type, + const std::string& context, + const std::string& identity_hint); + + /** + * @return the PSK used for identity, or throw an exception if no + * key exists + */ + virtual SymmetricKey psk(const std::string& type, + const std::string& context, + const std::string& identity); + + /** + * Return true if we should attempt SRP authentication + */ + virtual bool attempt_srp(const std::string& type, + const std::string& context); + + /** + * @return identifier for client-side SRP auth, if available + for this type/context. Should return empty string + if password auth not desired/available. + */ + virtual std::string srp_identifier(const std::string& type, + const std::string& context); + + /** + * @param identifier specifies what identifier we want the + * password for. This will be a value previously returned + * by srp_identifier. + * @return password for client-side SRP auth, if available + for this identifier/type/context. + */ + virtual std::string srp_password(const std::string& type, + const std::string& context, + const std::string& identifier); + + /** + * Retrieve SRP verifier parameters + */ + virtual bool srp_verifier(const std::string& type, + const std::string& context, + const std::string& identifier, + std::string& group_name, + BigInt& verifier, + std::vector<byte>& salt, + bool generate_fake_on_unknown); + + /** + * Return a cert chain we can use, ordered from leaf to root, + * or else an empty vector. + * + * It is assumed that the caller can get the private key of the + * leaf with private_key_for + * + * @param cert_key_types specifies the key types desired ("RSA", + * "DSA", "ECDSA", etc), or empty if there + * is no preference by the caller. + */ + virtual std::vector<X509_Certificate> cert_chain( + const std::vector<std::string>& cert_key_types, + const std::string& type, + const std::string& context); + + /** + * Return a cert chain we can use, ordered from leaf to root, + * or else an empty vector. + * + * It is assumed that the caller can get the private key of the + * leaf with private_key_for + * + * @param cert_key_type specifies the type of key requested + * ("RSA", "DSA", "ECDSA", etc) + */ + std::vector<X509_Certificate> cert_chain_single_type( + const std::string& cert_key_type, + const std::string& type, + const std::string& context); + + /** + * Return a list of the certificates of CAs that we trust in this + * type/context. + */ + virtual std::vector<X509_Certificate> trusted_certificate_authorities( + const std::string& type, + const std::string& context); + + /** + * Check the certificate chain is valid up to a trusted root, and + * optionally (if hostname != "") that the hostname given is + * consistent with the leaf certificate. + * + * This function should throw an exception derived from + * std::exception with an informative what() result if the + * certificate chain cannot be verified. + */ + virtual void verify_certificate_chain( + const std::string& type, + const std::string& hostname, + const std::vector<X509_Certificate>& cert_chain); + + /** + * @return private key associated with this certificate if we should + * use it with this context. cert was returned by cert_chain + * @note this object should retain ownership of the returned key; + * it should not be deleted by the caller. + */ + virtual Private_Key* private_key_for(const X509_Certificate& cert, + const std::string& type, + const std::string& context); + }; + +} + +#endif diff --git a/src/credentials/info.txt b/src/credentials/info.txt new file mode 100644 index 000000000..689c4f1ae --- /dev/null +++ b/src/credentials/info.txt @@ -0,0 +1,6 @@ +define CREDENTIALS_MANAGER + +<requires> +x509cert +x509store +</requires> diff --git a/src/engine/asm_engine/asm_engine.cpp b/src/engine/asm_engine/asm_engine.cpp index 6d475136f..a43a3302d 100644 --- a/src/engine/asm_engine/asm_engine.cpp +++ b/src/engine/asm_engine/asm_engine.cpp @@ -40,7 +40,7 @@ Assembler_Engine::find_block_cipher(const SCAN_Name& request, #endif } - return 0; + return nullptr; } HashFunction* @@ -66,7 +66,7 @@ Assembler_Engine::find_hash(const SCAN_Name& request, #endif } - return 0; + return nullptr; } } diff --git a/src/engine/asm_engine/asm_engine.h b/src/engine/asm_engine/asm_engine.h index bd82566d3..40fe5342f 100644 --- a/src/engine/asm_engine/asm_engine.h +++ b/src/engine/asm_engine/asm_engine.h @@ -23,7 +23,7 @@ class Assembler_Engine : public Engine BlockCipher* find_block_cipher(const SCAN_Name&, Algorithm_Factory&) const; - HashFunction* find_hash(const SCAN_Name& reqeust, + HashFunction* find_hash(const SCAN_Name& request, Algorithm_Factory&) const; }; diff --git a/src/engine/core_engine/core_engine.h b/src/engine/core_engine/core_engine.h index 5386991c3..983b75290 100644 --- a/src/engine/core_engine/core_engine.h +++ b/src/engine/core_engine/core_engine.h @@ -44,10 +44,10 @@ class Core_Engine : public Engine StreamCipher* find_stream_cipher(const SCAN_Name&, Algorithm_Factory&) const; - HashFunction* find_hash(const SCAN_Name& reqeust, + HashFunction* find_hash(const SCAN_Name& request, Algorithm_Factory&) const; - MessageAuthenticationCode* find_mac(const SCAN_Name& reqeust, + MessageAuthenticationCode* find_mac(const SCAN_Name& request, Algorithm_Factory&) const; PBKDF* find_pbkdf(const SCAN_Name& algo_spec, diff --git a/src/engine/core_engine/core_modes.cpp b/src/engine/core_engine/core_modes.cpp index 8a929e880..ffd8aa04f 100644 --- a/src/engine/core_engine/core_modes.cpp +++ b/src/engine/core_engine/core_modes.cpp @@ -111,7 +111,7 @@ Keyed_Filter* get_cipher_mode(const BlockCipher* block_cipher, else return new CTS_Decryption(block_cipher->clone()); #else - return 0; + return nullptr; #endif } @@ -123,7 +123,7 @@ Keyed_Filter* get_cipher_mode(const BlockCipher* block_cipher, return new CBC_Decryption(block_cipher->clone(), get_bc_pad(padding, "PKCS7")); #else - return 0; + return nullptr; #endif } @@ -149,7 +149,7 @@ Keyed_Filter* get_cipher_mode(const BlockCipher* block_cipher, else if(algo_info.size() == 2) bits = to_u32bit(algo_info[1]); else - return 0; + return nullptr; #if defined(BOTAN_HAS_CFB) if(mode_name == "CFB") @@ -172,7 +172,7 @@ Keyed_Filter* get_cipher_mode(const BlockCipher* block_cipher, #endif } - return 0; + return nullptr; } /* @@ -195,10 +195,10 @@ Keyed_Filter* Core_Engine::get_cipher(const std::string& algo_spec, const BlockCipher* block_cipher = af.prototype_block_cipher(cipher_name); if(!block_cipher) - return 0; + return nullptr; if(algo_parts.size() >= 4) - return 0; // 4 part mode, not something we know about + return nullptr; // 4 part mode, not something we know about if(algo_parts.size() < 2) throw Lookup_Error("Cipher specification '" + algo_spec + @@ -213,7 +213,7 @@ Keyed_Filter* Core_Engine::get_cipher(const std::string& algo_spec, padding = (mode == "CBC") ? "PKCS7" : "NoPadding"; if(mode == "ECB" && padding == "CTS") - return 0; + return nullptr; else if((mode != "CBC" && mode != "ECB") && padding != "NoPadding") throw Invalid_Algorithm_Name(algo_spec); diff --git a/src/engine/core_engine/def_pk_ops.cpp b/src/engine/core_engine/def_pk_ops.cpp index db418d5bc..23ba7722c 100644 --- a/src/engine/core_engine/def_pk_ops.cpp +++ b/src/engine/core_engine/def_pk_ops.cpp @@ -58,7 +58,7 @@ Core_Engine::get_encryption_op(const Public_Key& key) const return new ElGamal_Encryption_Operation(*s); #endif - return 0; + return nullptr; } PK_Ops::Decryption* @@ -74,7 +74,7 @@ Core_Engine::get_decryption_op(const Private_Key& key) const return new ElGamal_Decryption_Operation(*s); #endif - return 0; + return nullptr; } PK_Ops::Key_Agreement* @@ -90,7 +90,7 @@ Core_Engine::get_key_agreement_op(const Private_Key& key) const return new ECDH_KA_Operation(*ecdh); #endif - return 0; + return nullptr; } PK_Ops::Signature* @@ -127,7 +127,7 @@ Core_Engine::get_signature_op(const Private_Key& key) const return new NR_Signature_Operation(*s); #endif - return 0; + return nullptr; } PK_Ops::Verification* @@ -164,7 +164,7 @@ Core_Engine::get_verify_op(const Public_Key& key) const return new NR_Verification_Operation(*s); #endif - return 0; + return nullptr; } } diff --git a/src/engine/core_engine/lookup_block.cpp b/src/engine/core_engine/lookup_block.cpp index c27a13237..a02c75daa 100644 --- a/src/engine/core_engine/lookup_block.cpp +++ b/src/engine/core_engine/lookup_block.cpp @@ -135,8 +135,12 @@ BlockCipher* Core_Engine::find_block_cipher(const SCAN_Name& request, #endif #if defined(BOTAN_HAS_CAMELLIA) - if(request.algo_name() == "Camellia") - return new Camellia; + if(request.algo_name() == "Camellia-128") + return new Camellia_128; + if(request.algo_name() == "Camellia-192") + return new Camellia_192; + if(request.algo_name() == "Camellia-256") + return new Camellia_256; #endif #if defined(BOTAN_HAS_CAST) @@ -273,13 +277,13 @@ BlockCipher* Core_Engine::find_block_cipher(const SCAN_Name& request, af.prototype_stream_cipher(request.arg(1)); if(!hash || !stream_cipher) - return 0; + return nullptr; return new Lion(hash->clone(), stream_cipher->clone(), block_size); } #endif - return 0; + return nullptr; } } diff --git a/src/engine/core_engine/lookup_hash.cpp b/src/engine/core_engine/lookup_hash.cpp index f94a97864..9958d18b9 100644 --- a/src/engine/core_engine/lookup_hash.cpp +++ b/src/engine/core_engine/lookup_hash.cpp @@ -218,7 +218,7 @@ HashFunction* Core_Engine::find_hash(const SCAN_Name& request, { const HashFunction* hash = af.prototype_hash_function(request.arg(i)); if(!hash) - return 0; + return nullptr; hash_prototypes.push_back(hash); } @@ -232,7 +232,7 @@ HashFunction* Core_Engine::find_hash(const SCAN_Name& request, #endif - return 0; + return nullptr; } } diff --git a/src/engine/core_engine/lookup_mac.cpp b/src/engine/core_engine/lookup_mac.cpp index 9f322b399..32275b559 100644 --- a/src/engine/core_engine/lookup_mac.cpp +++ b/src/engine/core_engine/lookup_mac.cpp @@ -64,7 +64,7 @@ Core_Engine::find_mac(const SCAN_Name& request, return new ANSI_X919_MAC(af.make_block_cipher("DES")); #endif - return 0; + return nullptr; } } diff --git a/src/engine/core_engine/lookup_pbkdf.cpp b/src/engine/core_engine/lookup_pbkdf.cpp index 9e9255f0a..2419f4373 100644 --- a/src/engine/core_engine/lookup_pbkdf.cpp +++ b/src/engine/core_engine/lookup_pbkdf.cpp @@ -46,7 +46,7 @@ PBKDF* Core_Engine::find_pbkdf(const SCAN_Name& algo_spec, return new OpenPGP_S2K(af.make_hash_function(algo_spec.arg(0))); #endif - return 0; + return nullptr; } } diff --git a/src/engine/core_engine/lookup_stream.cpp b/src/engine/core_engine/lookup_stream.cpp index 5b4859c1a..50e246756 100644 --- a/src/engine/core_engine/lookup_stream.cpp +++ b/src/engine/core_engine/lookup_stream.cpp @@ -55,7 +55,7 @@ Core_Engine::find_stream_cipher(const SCAN_Name& request, return new WiderWake_41_BE; #endif - return 0; + return nullptr; } } diff --git a/src/engine/dyn_engine/dyn_engine.cpp b/src/engine/dyn_engine/dyn_engine.cpp index b76544d0f..078ec4b83 100644 --- a/src/engine/dyn_engine/dyn_engine.cpp +++ b/src/engine/dyn_engine/dyn_engine.cpp @@ -21,7 +21,7 @@ extern "C" { Dynamically_Loaded_Engine::Dynamically_Loaded_Engine( const std::string& library_path) : - engine(0) + engine(nullptr) { lib = new Dynamically_Loaded_Library(library_path); @@ -35,7 +35,7 @@ Dynamically_Loaded_Engine::Dynamically_Loaded_Engine( if(mod_version != 20101003) throw std::runtime_error("Incompatible version in " + library_path + " of " + - to_string(mod_version)); + std::to_string(mod_version)); creator_func creator = lib->resolve<creator_func>("create_engine"); @@ -49,7 +49,7 @@ Dynamically_Loaded_Engine::Dynamically_Loaded_Engine( catch(...) { delete lib; - lib = 0; + lib = nullptr; throw; } } diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index 80712a2f8..d4f6885bc 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -13,79 +13,79 @@ BlockCipher* Engine::find_block_cipher(const SCAN_Name&, Algorithm_Factory&) const { - return 0; + return nullptr; } StreamCipher* Engine::find_stream_cipher(const SCAN_Name&, Algorithm_Factory&) const { - return 0; + return nullptr; } HashFunction* Engine::find_hash(const SCAN_Name&, Algorithm_Factory&) const { - return 0; + return nullptr; } MessageAuthenticationCode* Engine::find_mac(const SCAN_Name&, Algorithm_Factory&) const { - return 0; + return nullptr; } PBKDF* Engine::find_pbkdf(const SCAN_Name&, Algorithm_Factory&) const { - return 0; + return nullptr; } Modular_Exponentiator* Engine::mod_exp(const BigInt&, Power_Mod::Usage_Hints) const { - return 0; + return nullptr; } Keyed_Filter* Engine::get_cipher(const std::string&, Cipher_Dir, Algorithm_Factory&) { - return 0; + return nullptr; } PK_Ops::Key_Agreement* Engine::get_key_agreement_op(const Private_Key&) const { - return 0; + return nullptr; } PK_Ops::Signature* Engine::get_signature_op(const Private_Key&) const { - return 0; + return nullptr; } PK_Ops::Verification* Engine::get_verify_op(const Public_Key&) const { - return 0; + return nullptr; } PK_Ops::Encryption* Engine::get_encryption_op(const Public_Key&) const { - return 0; + return nullptr; } PK_Ops::Decryption* Engine::get_decryption_op(const Private_Key&) const { - return 0; + return nullptr; } } diff --git a/src/engine/gnump/gmp_wrap.h b/src/engine/gnump/gmp_wrap.h index fc7aa856e..0a786f3ee 100644 --- a/src/engine/gnump/gmp_wrap.h +++ b/src/engine/gnump/gmp_wrap.h @@ -25,7 +25,7 @@ class GMP_MPZ void encode(byte[], size_t) const; size_t bytes() const; - SecureVector<byte> to_bytes() const + secure_vector<byte> to_bytes() const { return BigInt::encode(to_bigint()); } GMP_MPZ& operator=(const GMP_MPZ&); diff --git a/src/engine/gnump/gnump_pk.cpp b/src/engine/gnump/gnump_pk.cpp index 25735fe55..b2a2f9352 100644 --- a/src/engine/gnump/gnump_pk.cpp +++ b/src/engine/gnump/gnump_pk.cpp @@ -38,7 +38,7 @@ class GMP_DH_KA_Operation : public PK_Ops::Key_Agreement GMP_DH_KA_Operation(const DH_PrivateKey& dh) : x(dh.get_x()), p(dh.group_p()) {} - SecureVector<byte> agree(const byte w[], size_t w_len) + secure_vector<byte> agree(const byte w[], size_t w_len) { GMP_MPZ z(w, w_len); mpz_powm(z.value, z.value, x.value, p.value); @@ -66,14 +66,14 @@ class GMP_DSA_Signature_Operation : public PK_Ops::Signature size_t message_part_size() const { return (q_bits + 7) / 8; } size_t max_input_bits() const { return q_bits; } - SecureVector<byte> sign(const byte msg[], size_t msg_len, + secure_vector<byte> sign(const byte msg[], size_t msg_len, RandomNumberGenerator& rng); private: const GMP_MPZ x, p, q, g; size_t q_bits; }; -SecureVector<byte> +secure_vector<byte> GMP_DSA_Signature_Operation::sign(const byte msg[], size_t msg_len, RandomNumberGenerator& rng) { @@ -104,7 +104,7 @@ GMP_DSA_Signature_Operation::sign(const byte msg[], size_t msg_len, if(mpz_cmp_ui(r.value, 0) == 0 || mpz_cmp_ui(s.value, 0) == 0) throw Internal_Error("GMP_DSA_Op::sign: r or s was zero"); - SecureVector<byte> output(2*q_bytes); + secure_vector<byte> output(2*q_bytes); r.encode(output, q_bytes); s.encode(output + q_bytes, q_bytes); return output; @@ -192,7 +192,7 @@ class GMP_RSA_Private_Operation : public PK_Ops::Signature, size_t max_input_bits() const { return (n_bits - 1); } - SecureVector<byte> sign(const byte msg[], size_t msg_len, + secure_vector<byte> sign(const byte msg[], size_t msg_len, RandomNumberGenerator&) { BigInt m(msg, msg_len); @@ -200,7 +200,7 @@ class GMP_RSA_Private_Operation : public PK_Ops::Signature, return BigInt::encode_1363(x, (n_bits + 7) / 8); } - SecureVector<byte> decrypt(const byte msg[], size_t msg_len) + secure_vector<byte> decrypt(const byte msg[], size_t msg_len) { BigInt m(msg, msg_len); return BigInt::encode(private_op(m)); @@ -238,14 +238,14 @@ class GMP_RSA_Public_Operation : public PK_Ops::Verification, size_t max_input_bits() const { return (n.bits() - 1); } bool with_recovery() const { return true; } - SecureVector<byte> encrypt(const byte msg[], size_t msg_len, + secure_vector<byte> encrypt(const byte msg[], size_t msg_len, RandomNumberGenerator&) { BigInt m(msg, msg_len); return BigInt::encode_1363(public_op(m), n.bytes()); } - SecureVector<byte> verify_mr(const byte msg[], size_t msg_len) + secure_vector<byte> verify_mr(const byte msg[], size_t msg_len) { BigInt m(msg, msg_len); return BigInt::encode(public_op(m)); diff --git a/src/engine/openssl/bn_wrap.cpp b/src/engine/openssl/bn_wrap.cpp index 779956824..0ac31f61b 100644 --- a/src/engine/openssl/bn_wrap.cpp +++ b/src/engine/openssl/bn_wrap.cpp @@ -15,7 +15,7 @@ namespace Botan { OSSL_BN::OSSL_BN(const BigInt& in) { value = BN_new(); - SecureVector<byte> encoding = BigInt::encode(in); + secure_vector<byte> encoding = BigInt::encode(in); if(in != 0) BN_bin2bn(encoding, encoding.size(), value); } @@ -75,7 +75,7 @@ size_t OSSL_BN::bytes() const */ BigInt OSSL_BN::to_bigint() const { - SecureVector<byte> out(bytes()); + secure_vector<byte> out(bytes()); BN_bn2bin(value, out); return BigInt::decode(out); } diff --git a/src/engine/openssl/bn_wrap.h b/src/engine/openssl/bn_wrap.h index c5c07a35c..177dbd8c7 100644 --- a/src/engine/openssl/bn_wrap.h +++ b/src/engine/openssl/bn_wrap.h @@ -25,7 +25,7 @@ class OSSL_BN void encode(byte[], size_t) const; size_t bytes() const; - SecureVector<byte> to_bytes() const + secure_vector<byte> to_bytes() const { return BigInt::encode(to_bigint()); } OSSL_BN& operator=(const OSSL_BN&); diff --git a/src/engine/openssl/ossl_arc4.cpp b/src/engine/openssl/ossl_arc4.cpp index 0b1f7f1f3..6469d263a 100644 --- a/src/engine/openssl/ossl_arc4.cpp +++ b/src/engine/openssl/ossl_arc4.cpp @@ -46,7 +46,7 @@ std::string ARC4_OpenSSL::name() const { if(SKIP == 0) return "ARC4"; if(SKIP == 256) return "MARK-4"; - else return "RC4_skip(" + to_string(SKIP) + ")"; + else return "RC4_skip(" + std::to_string(SKIP) + ")"; } /* @@ -71,7 +71,7 @@ void ARC4_OpenSSL::cipher(const byte in[], byte out[], size_t length) } /** -* Look for an OpenSSL-suported stream cipher (ARC4) +* Look for an OpenSSL-supported stream cipher (ARC4) */ StreamCipher* OpenSSL_Engine::find_stream_cipher(const SCAN_Name& request, diff --git a/src/engine/openssl/ossl_bc.cpp b/src/engine/openssl/ossl_bc.cpp index 36f78205f..d419f56be 100644 --- a/src/engine/openssl/ossl_bc.cpp +++ b/src/engine/openssl/ossl_bc.cpp @@ -123,7 +123,7 @@ void EVP_BlockCipher::decrypt_n(const byte in[], byte out[], */ void EVP_BlockCipher::key_schedule(const byte key[], size_t length) { - SecureVector<byte> full_key(key, length); + secure_vector<byte> full_key(key, length); if(cipher_name == "TripleDES" && length == 16) { diff --git a/src/engine/openssl/ossl_pk.cpp b/src/engine/openssl/ossl_pk.cpp index 23ae6b25d..2557ec297 100644 --- a/src/engine/openssl/ossl_pk.cpp +++ b/src/engine/openssl/ossl_pk.cpp @@ -36,7 +36,7 @@ class OSSL_DH_KA_Operation : public PK_Ops::Key_Agreement OSSL_DH_KA_Operation(const DH_PrivateKey& dh) : x(dh.get_x()), p(dh.group_p()) {} - SecureVector<byte> agree(const byte w[], size_t w_len) + secure_vector<byte> agree(const byte w[], size_t w_len) { OSSL_BN i(w, w_len), r; BN_mod_exp(r.value, i.value, x.value, p.value, ctx.value); @@ -65,7 +65,7 @@ class OSSL_DSA_Signature_Operation : public PK_Ops::Signature size_t message_part_size() const { return (q_bits + 7) / 8; } size_t max_input_bits() const { return q_bits; } - SecureVector<byte> sign(const byte msg[], size_t msg_len, + secure_vector<byte> sign(const byte msg[], size_t msg_len, RandomNumberGenerator& rng); private: const OSSL_BN x, p, q, g; @@ -73,7 +73,7 @@ class OSSL_DSA_Signature_Operation : public PK_Ops::Signature size_t q_bits; }; -SecureVector<byte> +secure_vector<byte> OSSL_DSA_Signature_Operation::sign(const byte msg[], size_t msg_len, RandomNumberGenerator& rng) { @@ -103,7 +103,7 @@ OSSL_DSA_Signature_Operation::sign(const byte msg[], size_t msg_len, if(BN_is_zero(r.value) || BN_is_zero(s.value)) throw Internal_Error("OpenSSL_DSA_Op::sign: r or s was zero"); - SecureVector<byte> output(2*q_bytes); + secure_vector<byte> output(2*q_bytes); r.encode(output, q_bytes); s.encode(output + q_bytes, q_bytes); return output; @@ -191,7 +191,7 @@ class OSSL_RSA_Private_Operation : public PK_Ops::Signature, size_t max_input_bits() const { return (n_bits - 1); } - SecureVector<byte> sign(const byte msg[], size_t msg_len, + secure_vector<byte> sign(const byte msg[], size_t msg_len, RandomNumberGenerator&) { BigInt m(msg, msg_len); @@ -199,7 +199,7 @@ class OSSL_RSA_Private_Operation : public PK_Ops::Signature, return BigInt::encode_1363(x, (n_bits + 7) / 8); } - SecureVector<byte> decrypt(const byte msg[], size_t msg_len) + secure_vector<byte> decrypt(const byte msg[], size_t msg_len) { BigInt m(msg, msg_len); return BigInt::encode(private_op(m)); @@ -237,14 +237,14 @@ class OSSL_RSA_Public_Operation : public PK_Ops::Verification, size_t max_input_bits() const { return (n.bits() - 1); } bool with_recovery() const { return true; } - SecureVector<byte> encrypt(const byte msg[], size_t msg_len, + secure_vector<byte> encrypt(const byte msg[], size_t msg_len, RandomNumberGenerator&) { BigInt m(msg, msg_len); return BigInt::encode_1363(public_op(m), n.bytes()); } - SecureVector<byte> verify_mr(const byte msg[], size_t msg_len) + secure_vector<byte> verify_mr(const byte msg[], size_t msg_len) { BigInt m(msg, msg_len); return BigInt::encode(public_op(m)); diff --git a/src/engine/simd_engine/simd_engine.cpp b/src/engine/simd_engine/simd_engine.cpp index f9a731a82..70529f1fd 100644 --- a/src/engine/simd_engine/simd_engine.cpp +++ b/src/engine/simd_engine/simd_engine.cpp @@ -68,7 +68,7 @@ SIMD_Engine::find_block_cipher(const SCAN_Name& request, return new XTEA_SIMD; #endif - return 0; + return nullptr; } HashFunction* @@ -80,7 +80,7 @@ SIMD_Engine::find_hash(const SCAN_Name& request, return new SHA_160_SSE2; #endif - return 0; + return nullptr; } } diff --git a/src/engine/simd_engine/simd_engine.h b/src/engine/simd_engine/simd_engine.h index 73f7d2233..66c8886f1 100644 --- a/src/engine/simd_engine/simd_engine.h +++ b/src/engine/simd_engine/simd_engine.h @@ -23,7 +23,7 @@ class SIMD_Engine : public Engine BlockCipher* find_block_cipher(const SCAN_Name&, Algorithm_Factory&) const; - HashFunction* find_hash(const SCAN_Name& reqeust, + HashFunction* find_hash(const SCAN_Name& request, Algorithm_Factory&) const; }; diff --git a/src/entropy/cryptoapi_rng/es_capi.cpp b/src/entropy/cryptoapi_rng/es_capi.cpp index c9069ce65..a706b4d5c 100644 --- a/src/entropy/cryptoapi_rng/es_capi.cpp +++ b/src/entropy/cryptoapi_rng/es_capi.cpp @@ -55,7 +55,7 @@ class CSP_Handle */ void Win32_CAPI_EntropySource::poll(Entropy_Accumulator& accum) { - MemoryRegion<byte>& io_buffer = accum.get_io_buffer(32); + secure_vector<byte>& io_buffer = accum.get_io_buffer(32); for(size_t i = 0; i != prov_types.size(); ++i) { diff --git a/src/entropy/dev_random/dev_random.cpp b/src/entropy/dev_random/dev_random.cpp index 9e4f0b373..3090f9510 100644 --- a/src/entropy/dev_random/dev_random.cpp +++ b/src/entropy/dev_random/dev_random.cpp @@ -45,7 +45,7 @@ size_t Device_EntropySource::Device_Reader::get(byte out[], size_t length, timeout.tv_sec = (ms_wait_time / 1000); timeout.tv_usec = (ms_wait_time % 1000) * 1000; - if(::select(fd + 1, &read_set, 0, 0, &timeout) < 0) + if(::select(fd + 1, &read_set, nullptr, nullptr, &timeout) < 0) return 0; if(!(FD_ISSET(fd, &read_set))) @@ -111,7 +111,7 @@ void Device_EntropySource::poll(Entropy_Accumulator& accum) accum.desired_remaining_bits() / ENTROPY_BITS_PER_BYTE, 32); const size_t read_wait_ms = std::max<size_t>(go_get, 100); - MemoryRegion<byte>& io_buffer = accum.get_io_buffer(go_get); + secure_vector<byte>& io_buffer = accum.get_io_buffer(go_get); for(size_t i = 0; i != devices.size(); ++i) { diff --git a/src/entropy/egd/es_egd.cpp b/src/entropy/egd/es_egd.cpp index e0ebf9509..d8dbecd44 100644 --- a/src/entropy/egd/es_egd.cpp +++ b/src/entropy/egd/es_egd.cpp @@ -139,7 +139,7 @@ void EGD_EntropySource::poll(Entropy_Accumulator& accum) { size_t go_get = std::min<size_t>(accum.desired_remaining_bits() / 8, 32); - MemoryRegion<byte>& io_buffer = accum.get_io_buffer(go_get); + secure_vector<byte>& io_buffer = accum.get_io_buffer(go_get); for(size_t i = 0; i != sockets.size(); ++i) { diff --git a/src/entropy/entropy_src.h b/src/entropy/entropy_src.h index 3f15b5907..e130574f4 100644 --- a/src/entropy/entropy_src.h +++ b/src/entropy/entropy_src.h @@ -35,7 +35,7 @@ class BOTAN_DLL Entropy_Accumulator * @param size requested size for the I/O buffer * @return cached I/O buffer for repeated polls */ - MemoryRegion<byte>& get_io_buffer(size_t size) + secure_vector<byte>& get_io_buffer(size_t size) { io_buffer.resize(size); return io_buffer; } /** @@ -87,7 +87,7 @@ class BOTAN_DLL Entropy_Accumulator private: virtual void add_bytes(const byte bytes[], size_t length) = 0; - SecureVector<byte> io_buffer; + secure_vector<byte> io_buffer; size_t entropy_goal; double collected_bits; }; diff --git a/src/entropy/hres_timer/hres_timer.cpp b/src/entropy/hres_timer/hres_timer.cpp index dd1fc6f7c..c6b31d996 100644 --- a/src/entropy/hres_timer/hres_timer.cpp +++ b/src/entropy/hres_timer/hres_timer.cpp @@ -7,9 +7,8 @@ #include <botan/internal/hres_timer.h> #include <botan/cpuid.h> -#include <botan/time.h> -#if defined(BOTAN_TARGET_OS_IS_WINDOWS) +#if defined(BOTAN_TARGET_OS_HAS_QUERY_PERF_COUNTER) #include <windows.h> #endif @@ -20,8 +19,7 @@ namespace Botan { */ void High_Resolution_Timestamp::poll(Entropy_Accumulator& accum) { - // If Windows, grab the Performance Counter (usually TSC or PIT) -#if defined(BOTAN_TARGET_OS_IS_WINDOWS) +#if defined(BOTAN_TARGET_OS_HAS_QUERY_PERF_COUNTER) { LARGE_INTEGER tv; ::QueryPerformanceCounter(&tv); diff --git a/src/entropy/proc_walk/es_ftw.cpp b/src/entropy/proc_walk/es_ftw.cpp index 8b4408aee..7d72e7752 100644 --- a/src/entropy/proc_walk/es_ftw.cpp +++ b/src/entropy/proc_walk/es_ftw.cpp @@ -42,7 +42,7 @@ class Directory_Walker : public File_Descriptor_Source { public: Directory_Walker(const std::string& root) : - m_cur_dir(std::make_pair<DIR*, std::string>(0, "")) + m_cur_dir(std::make_pair<DIR*, std::string>(nullptr, "")) { if(DIR* root_dir = ::opendir(root.c_str())) m_cur_dir = std::make_pair(root_dir, root); @@ -71,15 +71,13 @@ std::pair<struct dirent*, std::string> Directory_Walker::get_next_dirent() { while(m_cur_dir.first) { - struct dirent* dir = ::readdir(m_cur_dir.first); - - if(dir) - return std::make_pair<struct dirent*, std::string>(dir, m_cur_dir.second); + if(struct dirent* dir = ::readdir(m_cur_dir.first)) + return std::make_pair(dir, m_cur_dir.second); ::closedir(m_cur_dir.first); - m_cur_dir = std::make_pair<DIR*, std::string>(0, ""); + m_cur_dir = std::make_pair<DIR*, std::string>(nullptr, ""); - while(!m_dirlist.empty() && m_cur_dir.first == 0) + while(!m_dirlist.empty() && !m_cur_dir.first) { const std::string next_dir_name = m_dirlist[0]; m_dirlist.pop_front(); @@ -89,7 +87,7 @@ std::pair<struct dirent*, std::string> Directory_Walker::get_next_dirent() } } - return std::make_pair<struct dirent*, std::string>(0, ""); // nothing left + return std::make_pair<struct dirent*, std::string>(nullptr, ""); // nothing left } int Directory_Walker::next_fd() @@ -133,9 +131,8 @@ int Directory_Walker::next_fd() /** * FTW_EntropySource Constructor */ -FTW_EntropySource::FTW_EntropySource(const std::string& p) : path(p) +FTW_EntropySource::FTW_EntropySource(const std::string& p) : path(p), dir(nullptr) { - dir = 0; } /** @@ -144,6 +141,7 @@ FTW_EntropySource::FTW_EntropySource(const std::string& p) : path(p) FTW_EntropySource::~FTW_EntropySource() { delete dir; + dir = nullptr; } void FTW_EntropySource::poll(Entropy_Accumulator& accum) @@ -153,7 +151,7 @@ void FTW_EntropySource::poll(Entropy_Accumulator& accum) if(!dir) dir = new Directory_Walker(path); - MemoryRegion<byte>& io_buffer = accum.get_io_buffer(4096); + secure_vector<byte>& io_buffer = accum.get_io_buffer(4096); for(size_t i = 0; i != MAX_FILES_READ_PER_POLL; ++i) { @@ -163,7 +161,7 @@ void FTW_EntropySource::poll(Entropy_Accumulator& accum) if(fd == -1) { delete dir; - dir = 0; + dir = nullptr; break; } diff --git a/src/entropy/rdrand/info.txt b/src/entropy/rdrand/info.txt new file mode 100644 index 000000000..4b9362d61 --- /dev/null +++ b/src/entropy/rdrand/info.txt @@ -0,0 +1,20 @@ +define ENTROPY_SRC_RDRAND + +<source> +rdrand.cpp +</source> + +<header:internal> +rdrand.h +</header:internal> + +<arch> +x86 +x86_64 +</arch> + +<cc> +gcc +clang +icc +</cc> diff --git a/src/entropy/rdrand/rdrand.cpp b/src/entropy/rdrand/rdrand.cpp new file mode 100644 index 000000000..51b2bd5f6 --- /dev/null +++ b/src/entropy/rdrand/rdrand.cpp @@ -0,0 +1,60 @@ +/* +* Entropy Source Using Intel's rdrand instruction +* (C) 2012 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/internal/rdrand.h> +#include <botan/cpuid.h> + +#if !defined(BOTAN_USE_GCC_INLINE_ASM) + #include <immintrin.h> +#endif + +namespace Botan { + +/* +* Get the timestamp +*/ +void Intel_Rdrand::poll(Entropy_Accumulator& accum) + { + if(!CPUID::has_rdrand()) + return; + + /* + * Put an upper bound on the total entropy we're willing to claim + * for any one polling of rdrand to prevent it from swamping our + * poll. Internally, the rdrand system is a DRGB that reseeds at a + * somewhat unpredictable rate (the current conditions are + * documented, but that might not be true for different + * implementations, eg on Haswell or a future AMD chip, so I don't + * want to assume). This limit ensures we're going to poll at least + * one other source so we have some diversity in our inputs. + */ + + const size_t POLL_UPPER_BOUND = 96; + const size_t RDRAND_POLLS = 32; + const double ENTROPY_PER_POLL = + static_cast<double>(POLL_UPPER_BOUND) / (RDRAND_POLLS * 4); + + for(size_t i = 0; i != RDRAND_POLLS; ++i) + { + unsigned int r; + +#if BOTAN_USE_GCC_INLINE_ASM + int cf = 0; + + // Encoding of rdrand %eax + asm(".byte 0x0F, 0xC7, 0xF0; adcl $0,%1" : + "=a" (r), "=r" (cf) : "0" (r), "1" (cf) : "cc"); +#else + int cf = _rdrand32_step(&r); +#endif + + if(cf == 1) + accum.add(r, ENTROPY_PER_POLL); + } + } + +} diff --git a/src/entropy/rdrand/rdrand.h b/src/entropy/rdrand/rdrand.h new file mode 100644 index 000000000..d7629d37f --- /dev/null +++ b/src/entropy/rdrand/rdrand.h @@ -0,0 +1,28 @@ +/* +* Entropy Source Using Intel's rdrand instruction +* (C) 2012 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_ENTROPY_SRC_RDRAND_H__ +#define BOTAN_ENTROPY_SRC_RDRAND_H__ + +#include <botan/entropy_src.h> + +namespace Botan { + +/** +* Entropy source using the rdrand instruction first introduced on +* Intel's Ivy Bridge architecture. +*/ +class Intel_Rdrand : public EntropySource + { + public: + std::string name() const { return "Intel Rdrand"; } + void poll(Entropy_Accumulator& accum); + }; + +} + +#endif diff --git a/src/entropy/unix_procs/es_unix.cpp b/src/entropy/unix_procs/es_unix.cpp index b989e0213..f72a691d2 100644 --- a/src/entropy/unix_procs/es_unix.cpp +++ b/src/entropy/unix_procs/es_unix.cpp @@ -68,7 +68,7 @@ void Unix_EntropySource::poll(Entropy_Accumulator& accum) "/etc/passwd", ".", "..", - 0 }; + nullptr }; for(size_t i = 0; stat_targets[i]; i++) { @@ -93,7 +93,7 @@ void Unix_EntropySource::poll(Entropy_Accumulator& accum) const size_t MINIMAL_WORKING = 16; - MemoryRegion<byte>& io_buffer = accum.get_io_buffer(DEFAULT_BUFFERSIZE); + secure_vector<byte>& io_buffer = accum.get_io_buffer(DEFAULT_BUFFERSIZE); for(size_t i = 0; i != sources.size(); i++) { diff --git a/src/entropy/unix_procs/unix_cmd.cpp b/src/entropy/unix_procs/unix_cmd.cpp index 930444075..823da2717 100644 --- a/src/entropy/unix_procs/unix_cmd.cpp +++ b/src/entropy/unix_procs/unix_cmd.cpp @@ -29,10 +29,10 @@ void do_exec(const std::vector<std::string>& arg_list, { const size_t args = arg_list.size() - 1; - const char* arg1 = (args >= 1) ? arg_list[1].c_str() : 0; - const char* arg2 = (args >= 2) ? arg_list[2].c_str() : 0; - const char* arg3 = (args >= 3) ? arg_list[3].c_str() : 0; - const char* arg4 = (args >= 4) ? arg_list[4].c_str() : 0; + const char* arg1 = (args >= 1) ? arg_list[1].c_str() : nullptr; + const char* arg2 = (args >= 2) ? arg_list[2].c_str() : nullptr; + const char* arg3 = (args >= 3) ? arg_list[3].c_str() : nullptr; + const char* arg4 = (args >= 4) ? arg_list[4].c_str() : nullptr; for(size_t j = 0; j != paths.size(); j++) { @@ -74,7 +74,7 @@ size_t DataSource_Command::read(byte buf[], size_t length) tv.tv_usec = MAX_BLOCK_USECS; ssize_t got = 0; - if(::select(pipe->fd + 1, &set, 0, 0, &tv) == 1) + if(::select(pipe->fd + 1, &set, nullptr, nullptr, &tv) == 1) { if(FD_ISSET(pipe->fd, &set)) got = ::read(pipe->fd, buf, length); @@ -182,7 +182,7 @@ void DataSource_Command::shutdown_pipe() { if(pipe) { - pid_t reaped = waitpid(pipe->pid, 0, WNOHANG); + pid_t reaped = waitpid(pipe->pid, nullptr, WNOHANG); if(reaped == 0) { @@ -191,21 +191,21 @@ void DataSource_Command::shutdown_pipe() struct ::timeval tv; tv.tv_sec = 0; tv.tv_usec = KILL_WAIT; - select(0, 0, 0, 0, &tv); + select(0, nullptr, nullptr, nullptr, &tv); - reaped = ::waitpid(pipe->pid, 0, WNOHANG); + reaped = ::waitpid(pipe->pid, nullptr, WNOHANG); if(reaped == 0) { ::kill(pipe->pid, SIGKILL); do - reaped = ::waitpid(pipe->pid, 0, 0); + reaped = ::waitpid(pipe->pid, nullptr, 0); while(reaped == -1); } } delete pipe; - pipe = 0; + pipe = nullptr; } } @@ -223,7 +223,7 @@ DataSource_Command::DataSource_Command(const std::string& prog_and_args, if(arg_list.size() > 5) throw Invalid_Argument("DataSource_Command: Too many args"); - pipe = 0; + pipe = nullptr; create_pipe(paths); } diff --git a/src/filters/algo_filt.cpp b/src/filters/algo_filt.cpp index 337733b5f..dbc46c7e6 100644 --- a/src/filters/algo_filt.cpp +++ b/src/filters/algo_filt.cpp @@ -92,7 +92,7 @@ Hash_Filter::Hash_Filter(const std::string& algo_spec, */ void Hash_Filter::end_msg() { - SecureVector<byte> output = hash->final(); + secure_vector<byte> output = hash->final(); if(OUTPUT_LENGTH) send(output, std::min<size_t>(OUTPUT_LENGTH, output.size())); else @@ -125,7 +125,7 @@ MAC_Filter::MAC_Filter(const std::string& mac_name, const SymmetricKey& key, */ void MAC_Filter::end_msg() { - SecureVector<byte> output = mac->final(); + secure_vector<byte> output = mac->final(); if(OUTPUT_LENGTH) send(output, std::min<size_t>(OUTPUT_LENGTH, output.size())); else diff --git a/src/filters/basefilt.h b/src/filters/basefilt.h index adde3dd54..5252be973 100644 --- a/src/filters/basefilt.h +++ b/src/filters/basefilt.h @@ -39,7 +39,8 @@ class BOTAN_DLL Chain : public Fanout_Filter * Construct a chain of up to four filters. The filters are set * up in the same order as the arguments. */ - Chain(Filter* = 0, Filter* = 0, Filter* = 0, Filter* = 0); + Chain(Filter* = nullptr, Filter* = nullptr, + Filter* = nullptr, Filter* = nullptr); /** * Construct a chain from range of filters @@ -65,7 +66,7 @@ class BOTAN_DLL Fork : public Fanout_Filter /** * Construct a Fork filter with up to four forks. */ - Fork(Filter*, Filter*, Filter* = 0, Filter* = 0); + Fork(Filter*, Filter*, Filter* = nullptr, Filter* = nullptr); /** * Construct a Fork from range of filters diff --git a/src/filters/buf_filt.h b/src/filters/buf_filt.h index 87180e3e1..9a3fc9a2b 100644 --- a/src/filters/buf_filt.h +++ b/src/filters/buf_filt.h @@ -27,6 +27,12 @@ class BOTAN_DLL Buffered_Filter */ void write(const byte in[], size_t length); + template<typename Alloc> + void write(const std::vector<byte, Alloc>& in, size_t length) + { + write(&in[0], length); + } + /** * Finish a message, emitting to buffered_block and buffered_final * Will throw an exception if less than final_minimum bytes were @@ -78,7 +84,7 @@ class BOTAN_DLL Buffered_Filter private: size_t main_block_mod, final_minimum; - SecureVector<byte> buffer; + secure_vector<byte> buffer; size_t buffer_pos; }; diff --git a/src/filters/bzip2/bzip2.cpp b/src/filters/bzip2/bzip2.cpp index a291c1173..18a53558c 100644 --- a/src/filters/bzip2/bzip2.cpp +++ b/src/filters/bzip2/bzip2.cpp @@ -48,7 +48,7 @@ void* bzip_malloc(void* info_ptr, int n, int size) void bzip_free(void* info_ptr, void* ptr) { Bzip_Alloc_Info* info = static_cast<Bzip_Alloc_Info*>(info_ptr); - std::map<void*, size_t>::const_iterator i = info->current_allocs.find(ptr); + auto i = info->current_allocs.find(ptr); if(i == info->current_allocs.end()) throw Invalid_Argument("bzip_free: Got pointer not allocated by us"); info->alloc->deallocate(ptr, i->second); diff --git a/src/filters/bzip2/bzip2.h b/src/filters/bzip2/bzip2.h index b3b222eb2..2505cf54e 100644 --- a/src/filters/bzip2/bzip2.h +++ b/src/filters/bzip2/bzip2.h @@ -33,7 +33,7 @@ class BOTAN_DLL Bzip_Compression : public Filter void clear(); const size_t level; - SecureVector<byte> buffer; + secure_vector<byte> buffer; class Bzip_Stream* bz; }; @@ -55,7 +55,7 @@ class BOTAN_DLL Bzip_Decompression : public Filter void clear(); const bool small_mem; - SecureVector<byte> buffer; + secure_vector<byte> buffer; class Bzip_Stream* bz; bool no_writes; }; diff --git a/src/filters/codec_filt/b64_filt.cpp b/src/filters/codec_filt/b64_filt.cpp index 9341571d4..b804b33c7 100644 --- a/src/filters/codec_filt/b64_filt.cpp +++ b/src/filters/codec_filt/b64_filt.cpp @@ -79,7 +79,7 @@ void Base64_Encoder::do_output(const byte input[], size_t length) */ void Base64_Encoder::write(const byte input[], size_t length) { - in.copy(position, input, length); + buffer_insert(in, position, input, length); if(position + length >= in.size()) { encode_and_send(&in[0], in.size()); @@ -91,7 +91,7 @@ void Base64_Encoder::write(const byte input[], size_t length) input += in.size(); length -= in.size(); } - in.copy(input, length); + copy_mem(&in[0], input, length); position = 0; } position += length; diff --git a/src/filters/codec_filt/b64_filt.h b/src/filters/codec_filt/b64_filt.h index afff53f30..dcb3cdbd5 100644 --- a/src/filters/codec_filt/b64_filt.h +++ b/src/filters/codec_filt/b64_filt.h @@ -47,7 +47,7 @@ class BOTAN_DLL Base64_Encoder : public Filter const size_t line_length; const bool trailing_newline; - MemoryVector<byte> in, out; + std::vector<byte> in, out; size_t position, out_position; }; @@ -79,7 +79,7 @@ class BOTAN_DLL Base64_Decoder : public Filter Base64_Decoder(Decoder_Checking checking = NONE); private: const Decoder_Checking checking; - MemoryVector<byte> in, out; + std::vector<byte> in, out; size_t position; }; diff --git a/src/filters/codec_filt/hex_filt.cpp b/src/filters/codec_filt/hex_filt.cpp index 3d56beec4..e85bdb17e 100644 --- a/src/filters/codec_filt/hex_filt.cpp +++ b/src/filters/codec_filt/hex_filt.cpp @@ -75,7 +75,7 @@ void Hex_Encoder::encode_and_send(const byte block[], size_t length) */ void Hex_Encoder::write(const byte input[], size_t length) { - in.copy(position, input, length); + buffer_insert(in, position, input, length); if(position + length >= in.size()) { encode_and_send(&in[0], in.size()); @@ -87,7 +87,7 @@ void Hex_Encoder::write(const byte input[], size_t length) input += in.size(); length -= in.size(); } - in.copy(input, length); + copy_mem(&in[0], input, length); position = 0; } position += length; diff --git a/src/filters/codec_filt/hex_filt.h b/src/filters/codec_filt/hex_filt.h index 0dc38c804..dbe6b9bae 100644 --- a/src/filters/codec_filt/hex_filt.h +++ b/src/filters/codec_filt/hex_filt.h @@ -49,7 +49,7 @@ class BOTAN_DLL Hex_Encoder : public Filter const Case casing; const size_t line_length; - MemoryVector<byte> in, out; + std::vector<byte> in, out; size_t position, counter; }; @@ -72,7 +72,7 @@ class BOTAN_DLL Hex_Decoder : public Filter Hex_Decoder(Decoder_Checking checking = NONE); private: const Decoder_Checking checking; - MemoryVector<byte> in, out; + std::vector<byte> in, out; size_t position; }; diff --git a/src/filters/data_snk.cpp b/src/filters/data_snk.cpp index d651dcba7..2903e5e1f 100644 --- a/src/filters/data_snk.cpp +++ b/src/filters/data_snk.cpp @@ -29,7 +29,7 @@ void DataSink_Stream::write(const byte out[], size_t length) DataSink_Stream::DataSink_Stream(std::ostream& out, const std::string& name) : identifier(name), - sink_p(0), + sink_p(nullptr), sink(out) { } diff --git a/src/filters/data_snk.h b/src/filters/data_snk.h index e31cb9d28..6b9da0b4d 100644 --- a/src/filters/data_snk.h +++ b/src/filters/data_snk.h @@ -22,9 +22,9 @@ class BOTAN_DLL DataSink : public Filter bool attachable() { return false; } DataSink() {} virtual ~DataSink() {} - private: - DataSink& operator=(const DataSink&) { return (*this); } - DataSink(const DataSink&); + + DataSink& operator=(const DataSink&) = delete; + DataSink(const DataSink&) = delete; }; /** diff --git a/src/filters/data_src.cpp b/src/filters/data_src.cpp index da67baa98..cc100ab13 100644 --- a/src/filters/data_src.cpp +++ b/src/filters/data_src.cpp @@ -77,26 +77,10 @@ bool DataSource_Memory::end_of_data() const /* * DataSource_Memory Constructor */ -DataSource_Memory::DataSource_Memory(const byte in[], size_t length) : - source(in, length) - { - offset = 0; - } - -/* -* DataSource_Memory Constructor -*/ -DataSource_Memory::DataSource_Memory(const MemoryRegion<byte>& in) : - source(in) - { - offset = 0; - } - -/* -* DataSource_Memory Constructor -*/ DataSource_Memory::DataSource_Memory(const std::string& in) : - source(reinterpret_cast<const byte*>(in.data()), in.length()) + source(reinterpret_cast<const byte*>(in.data()), + reinterpret_cast<const byte*>(in.data()) + in.length()), + offset(0) { offset = 0; } @@ -127,7 +111,7 @@ size_t DataSource_Stream::peek(byte out[], size_t length, size_t offset) const if(offset) { - SecureVector<byte> buf(offset); + secure_vector<byte> buf(offset); source.read(reinterpret_cast<char*>(&buf[0]), buf.size()); if(source.bad()) throw Stream_IO_Error("DataSource_Stream::peek: Source failure"); @@ -190,7 +174,7 @@ DataSource_Stream::DataSource_Stream(const std::string& path, DataSource_Stream::DataSource_Stream(std::istream& in, const std::string& name) : identifier(name), - source_p(0), + source_p(nullptr), source(in), total_read(0) { diff --git a/src/filters/data_src.h b/src/filters/data_src.h index a274de8e2..62bdacd33 100644 --- a/src/filters/data_src.h +++ b/src/filters/data_src.h @@ -81,9 +81,8 @@ class BOTAN_DLL DataSource DataSource() {} virtual ~DataSource() {} - private: - DataSource& operator=(const DataSource&) { return (*this); } - DataSource(const DataSource&); + DataSource& operator=(const DataSource&) = delete; + DataSource(const DataSource&) = delete; }; /** @@ -107,15 +106,24 @@ class BOTAN_DLL DataSource_Memory : public DataSource * @param in the byte array to read from * @param length the length of the byte array */ - DataSource_Memory(const byte in[], size_t length); + DataSource_Memory(const byte in[], size_t length) : + source(in, in + length), offset(0) {} + + /** + * Construct a memory source that reads from a secure_vector + * @param in the MemoryRegion to read from + */ + DataSource_Memory(const secure_vector<byte>& in) : + source(in), offset(0) {} /** - * Construct a memory source that reads from a MemoryRegion + * Construct a memory source that reads from a std::vector * @param in the MemoryRegion to read from */ - DataSource_Memory(const MemoryRegion<byte>& in); + DataSource_Memory(const std::vector<byte>& in) : + source(&in[0], &in[in.size()]), offset(0) {} private: - SecureVector<byte> source; + secure_vector<byte> source; size_t offset; }; diff --git a/src/filters/fd_unix/fd_unix.cpp b/src/filters/fd_unix/fd_unix.cpp index 3a9253b5e..dc6fbe696 100644 --- a/src/filters/fd_unix/fd_unix.cpp +++ b/src/filters/fd_unix/fd_unix.cpp @@ -16,7 +16,7 @@ namespace Botan { */ int operator<<(int fd, Pipe& pipe) { - SecureVector<byte> buffer(DEFAULT_BUFFERSIZE); + secure_vector<byte> buffer(DEFAULT_BUFFERSIZE); while(pipe.remaining()) { size_t got = pipe.read(&buffer[0], buffer.size()); @@ -38,7 +38,7 @@ int operator<<(int fd, Pipe& pipe) */ int operator>>(int fd, Pipe& pipe) { - SecureVector<byte> buffer(DEFAULT_BUFFERSIZE); + secure_vector<byte> buffer(DEFAULT_BUFFERSIZE); while(true) { ssize_t ret = read(fd, &buffer[0], buffer.size()); diff --git a/src/filters/filter.cpp b/src/filters/filter.cpp index c33f25814..9432f0304 100644 --- a/src/filters/filter.cpp +++ b/src/filters/filter.cpp @@ -96,7 +96,7 @@ Filter* Filter::get_next() const { if(port_num < next.size()) return next[port_num]; - return 0; + return nullptr; } /* @@ -104,7 +104,7 @@ Filter* Filter::get_next() const */ void Filter::set_next(Filter* filters[], size_t size) { - while(size && filters && filters[size-1] == 0) + while(size && filters && filters[size-1] == nullptr) --size; next.clear(); diff --git a/src/filters/filter.h b/src/filters/filter.h index 962b2816e..581d95c58 100644 --- a/src/filters/filter.h +++ b/src/filters/filter.h @@ -10,6 +10,7 @@ #include <botan/secmem.h> #include <vector> +#include <string> namespace Botan { @@ -65,22 +66,33 @@ class BOTAN_DLL Filter /** * @param in some input for the filter */ - void send(const MemoryRegion<byte>& in) { send(&in[0], in.size()); } + void send(const secure_vector<byte>& in) { send(&in[0], in.size()); } + + /** + * @param in some input for the filter + */ + void send(const std::vector<byte>& in) { send(&in[0], in.size()); } + + /** + * @param in some input for the filter + * @param length the number of bytes of in to send + */ + void send(const secure_vector<byte>& in, size_t length) + { + send(&in[0], length); + } /** * @param in some input for the filter * @param length the number of bytes of in to send */ - void send(const MemoryRegion<byte>& in, size_t length) + void send(const std::vector<byte>& in, size_t length) { send(&in[0], length); } Filter(); private: - Filter(const Filter&) {} - Filter& operator=(const Filter&) { return (*this); } - /** * Start a new message in *this and all following filters. Only for * internal use, not intended for use in client applications. @@ -96,6 +108,9 @@ class BOTAN_DLL Filter friend class Pipe; friend class Fanout_Filter; + Filter(const Filter&) = delete; + Filter& operator=(const Filter&) = delete; + size_t total_ports() const; size_t current_port() const { return port_num; } @@ -120,7 +135,7 @@ class BOTAN_DLL Filter void set_next(Filter* filters[], size_t count); Filter* get_next() const; - SecureVector<byte> write_queue; + secure_vector<byte> write_queue; std::vector<Filter*> next; size_t port_num, filter_owns; diff --git a/src/filters/filters.h b/src/filters/filters.h index b409e78f5..08b505bc0 100644 --- a/src/filters/filters.h +++ b/src/filters/filters.h @@ -94,7 +94,7 @@ class BOTAN_DLL StreamCipher_Filter : public Keyed_Filter ~StreamCipher_Filter() { delete cipher; } private: - SecureVector<byte> buffer; + secure_vector<byte> buffer; StreamCipher* cipher; }; diff --git a/src/filters/modes/cbc/cbc.cpp b/src/filters/modes/cbc/cbc.cpp index b464d075f..00518fc86 100644 --- a/src/filters/modes/cbc/cbc.cpp +++ b/src/filters/modes/cbc/cbc.cpp @@ -65,9 +65,9 @@ void CBC_Encryption::buffered_block(const byte input[], size_t length) for(size_t i = 0; i != blocks; ++i) { - xor_buf(state, input + i * cipher->block_size(), state.size()); + xor_buf(&state[0], input + i * cipher->block_size(), state.size()); cipher->encrypt(state); - send(state, state.size()); + send(state); } } @@ -91,13 +91,13 @@ void CBC_Encryption::end_msg() { size_t last_block = current_position() % cipher->block_size(); - SecureVector<byte> padding(cipher->block_size()); - padder->pad(padding, padding.size(), last_block); + std::vector<byte> padding(cipher->block_size()); + padder->pad(&padding[0], padding.size(), last_block); size_t pad_bytes = padder->pad_bytes(cipher->block_size(), last_block); if(pad_bytes) - Buffered_Filter::write(padding, pad_bytes); + Buffered_Filter::write(&padding[0], pad_bytes); Buffered_Filter::end_msg(); } @@ -170,7 +170,7 @@ void CBC_Decryption::buffered_block(const byte input[], size_t length) cipher->decrypt_n(input, &temp[0], to_proc); - xor_buf(temp, state, cipher->block_size()); + xor_buf(&temp[0], &state[0], cipher->block_size()); for(size_t i = 1; i < to_proc; ++i) xor_buf(&temp[i * cipher->block_size()], @@ -202,9 +202,9 @@ void CBC_Decryption::buffered_final(const byte input[], size_t length) input += extra_blocks * cipher->block_size(); - cipher->decrypt(input, temp); - xor_buf(temp, state, cipher->block_size()); - send(temp, padder->unpad(temp, cipher->block_size())); + cipher->decrypt(&input[0], &temp[0]); + xor_buf(&temp[0], &state[0], cipher->block_size()); + send(&temp[0], padder->unpad(&temp[0], cipher->block_size())); copy_mem(&state[0], input, state.size()); // save for IV chaining } diff --git a/src/filters/modes/cbc/cbc.h b/src/filters/modes/cbc/cbc.h index d828f53a6..4fd0f7d66 100644 --- a/src/filters/modes/cbc/cbc.h +++ b/src/filters/modes/cbc/cbc.h @@ -52,7 +52,7 @@ class BOTAN_DLL CBC_Encryption : public Keyed_Filter, BlockCipher* cipher; const BlockCipherModePaddingMethod* padder; - SecureVector<byte> state; + secure_vector<byte> state; }; /** @@ -92,7 +92,7 @@ class BOTAN_DLL CBC_Decryption : public Keyed_Filter, BlockCipher* cipher; const BlockCipherModePaddingMethod* padder; - SecureVector<byte> state, temp; + secure_vector<byte> state, temp; }; } diff --git a/src/filters/modes/cfb/cfb.cpp b/src/filters/modes/cfb/cfb.cpp index 8f7471c98..2b7cca84a 100644 --- a/src/filters/modes/cfb/cfb.cpp +++ b/src/filters/modes/cfb/cfb.cpp @@ -26,7 +26,7 @@ CFB_Encryption::CFB_Encryption(BlockCipher* ciph, size_t fback_bits) if(feedback == 0 || fback_bits % 8 != 0 || feedback > cipher->block_size()) throw Invalid_Argument("CFB_Encryption: Invalid feedback size " + - to_string(fback_bits)); + std::to_string(fback_bits)); } /* @@ -46,7 +46,7 @@ CFB_Encryption::CFB_Encryption(BlockCipher* ciph, if(feedback == 0 || fback_bits % 8 != 0 || feedback > cipher->block_size()) throw Invalid_Argument("CFB_Encryption: Invalid feedback size " + - to_string(fback_bits)); + std::to_string(fback_bits)); set_key(key); set_iv(iv); @@ -61,7 +61,7 @@ void CFB_Encryption::set_iv(const InitializationVector& iv) zeroise(buffer); position = 0; - cipher->encrypt(state, buffer); + cipher->encrypt(&state[0], &buffer[0]); } /* @@ -82,7 +82,10 @@ void CFB_Encryption::write(const byte input[], size_t length) { for(size_t j = 0; j != cipher->block_size() - feedback; ++j) state[j] = state[j + feedback]; - state.copy(cipher->block_size() - feedback, buffer, feedback); + + buffer_insert(state, cipher->block_size() - feedback, + &buffer[0], feedback); + cipher->encrypt(state, buffer); position = 0; } @@ -103,7 +106,7 @@ CFB_Decryption::CFB_Decryption(BlockCipher* ciph, size_t fback_bits) if(feedback == 0 || fback_bits % 8 != 0 || feedback > cipher->block_size()) throw Invalid_Argument("CFB_Decryption: Invalid feedback size " + - to_string(fback_bits)); + std::to_string(fback_bits)); } /* @@ -123,7 +126,7 @@ CFB_Decryption::CFB_Decryption(BlockCipher* ciph, if(feedback == 0 || fback_bits % 8 != 0 || feedback > cipher->block_size()) throw Invalid_Argument("CFB_Decryption: Invalid feedback size " + - to_string(fback_bits)); + std::to_string(fback_bits)); set_key(key); set_iv(iv); @@ -151,7 +154,7 @@ void CFB_Decryption::write(const byte input[], size_t length) size_t xored = std::min(feedback - position, length); xor_buf(&buffer[position], input, xored); send(&buffer[position], xored); - buffer.copy(position, input, xored); + buffer_insert(buffer, position, input, xored); input += xored; length -= xored; position += xored; @@ -159,7 +162,10 @@ void CFB_Decryption::write(const byte input[], size_t length) { for(size_t j = 0; j != cipher->block_size() - feedback; ++j) state[j] = state[j + feedback]; - state.copy(cipher->block_size() - feedback, buffer, feedback); + + buffer_insert(state, cipher->block_size() - feedback, + &buffer[0], feedback); + cipher->encrypt(state, buffer); position = 0; } diff --git a/src/filters/modes/cfb/cfb.h b/src/filters/modes/cfb/cfb.h index 64eb1e832..212ac76da 100644 --- a/src/filters/modes/cfb/cfb.h +++ b/src/filters/modes/cfb/cfb.h @@ -43,7 +43,7 @@ class BOTAN_DLL CFB_Encryption : public Keyed_Filter void write(const byte[], size_t); BlockCipher* cipher; - SecureVector<byte> buffer, state; + secure_vector<byte> buffer, state; size_t position, feedback; }; @@ -77,7 +77,7 @@ class BOTAN_DLL CFB_Decryption : public Keyed_Filter void write(const byte[], size_t); BlockCipher* cipher; - SecureVector<byte> buffer, state; + secure_vector<byte> buffer, state; size_t position, feedback; }; diff --git a/src/filters/modes/cts/cts.cpp b/src/filters/modes/cts/cts.cpp index c654c8719..f77a28dd5 100644 --- a/src/filters/modes/cts/cts.cpp +++ b/src/filters/modes/cts/cts.cpp @@ -56,7 +56,7 @@ void CTS_Encryption::set_iv(const InitializationVector& iv) */ void CTS_Encryption::encrypt(const byte block[]) { - xor_buf(state, block, cipher->block_size()); + xor_buf(&state[0], &block[0], cipher->block_size()); cipher->encrypt(state); send(state, cipher->block_size()); } @@ -67,7 +67,7 @@ void CTS_Encryption::encrypt(const byte block[]) void CTS_Encryption::write(const byte input[], size_t length) { size_t copied = std::min<size_t>(buffer.size() - position, length); - buffer.copy(position, input, copied); + buffer_insert(buffer, position, input, copied); length -= copied; input += copied; position += copied; @@ -91,7 +91,7 @@ void CTS_Encryption::write(const byte input[], size_t length) copy_mem(&buffer[0], &buffer[cipher->block_size()], cipher->block_size()); position = cipher->block_size(); } - buffer.copy(position, input, length); + buffer_insert(buffer, position, input, length); position += length; } @@ -105,7 +105,7 @@ void CTS_Encryption::end_msg() xor_buf(state, buffer, cipher->block_size()); cipher->encrypt(state); - SecureVector<byte> cn = state; + secure_vector<byte> cn = state; clear_mem(&buffer[position], buffer.size() - position); encrypt(&buffer[cipher->block_size()]); send(cn, position - cipher->block_size()); @@ -161,7 +161,7 @@ void CTS_Decryption::decrypt(const byte block[]) cipher->decrypt(block, &temp[0]); xor_buf(temp, state, cipher->block_size()); send(temp, cipher->block_size()); - state.copy(block, cipher->block_size()); + copy_mem(&state[0], block, cipher->block_size()); } /* @@ -170,14 +170,14 @@ void CTS_Decryption::decrypt(const byte block[]) void CTS_Decryption::write(const byte input[], size_t length) { size_t copied = std::min<size_t>(buffer.size() - position, length); - buffer.copy(position, input, copied); + buffer_insert(buffer, position, input, copied); length -= copied; input += copied; position += copied; if(length == 0) return; - decrypt(buffer); + decrypt(&buffer[0]); if(length > cipher->block_size()) { decrypt(&buffer[cipher->block_size()]); @@ -194,7 +194,7 @@ void CTS_Decryption::write(const byte input[], size_t length) copy_mem(&buffer[0], &buffer[cipher->block_size()], cipher->block_size()); position = cipher->block_size(); } - buffer.copy(position, input, length); + buffer_insert(buffer, position, input, length); position += length; } @@ -203,17 +203,17 @@ void CTS_Decryption::write(const byte input[], size_t length) */ void CTS_Decryption::end_msg() { - cipher->decrypt(buffer, temp); - xor_buf(temp, &buffer[cipher->block_size()], position - cipher->block_size()); + cipher->decrypt(&buffer[0], &temp[0]); + xor_buf(&temp[0], &buffer[cipher->block_size()], position - cipher->block_size()); - SecureVector<byte> xn = temp; + secure_vector<byte> xn = temp; copy_mem(&buffer[position], &xn[position - cipher->block_size()], buffer.size() - position); - cipher->decrypt(&buffer[cipher->block_size()], temp); - xor_buf(temp, state, cipher->block_size()); + cipher->decrypt(&buffer[cipher->block_size()], &temp[0]); + xor_buf(&temp[0], &state[0], cipher->block_size()); send(temp, cipher->block_size()); send(xn, position - cipher->block_size()); } diff --git a/src/filters/modes/cts/cts.h b/src/filters/modes/cts/cts.h index 8e19073f4..ac296316f 100644 --- a/src/filters/modes/cts/cts.h +++ b/src/filters/modes/cts/cts.h @@ -44,7 +44,7 @@ class BOTAN_DLL CTS_Encryption : public Keyed_Filter void encrypt(const byte[]); BlockCipher* cipher; - SecureVector<byte> buffer, state; + secure_vector<byte> buffer, state; size_t position; }; @@ -79,7 +79,7 @@ class BOTAN_DLL CTS_Decryption : public Keyed_Filter void decrypt(const byte[]); BlockCipher* cipher; - SecureVector<byte> buffer, state, temp; + secure_vector<byte> buffer, state, temp; size_t position; }; diff --git a/src/filters/modes/eax/eax.cpp b/src/filters/modes/eax/eax.cpp index 6d6d9ec18..e67f03f68 100644 --- a/src/filters/modes/eax/eax.cpp +++ b/src/filters/modes/eax/eax.cpp @@ -19,7 +19,7 @@ namespace { /* * EAX MAC-based PRF */ -SecureVector<byte> eax_prf(byte tag, size_t BLOCK_SIZE, +secure_vector<byte> eax_prf(byte tag, size_t BLOCK_SIZE, MessageAuthenticationCode* mac, const byte in[], size_t length) { @@ -45,7 +45,7 @@ EAX_Base::EAX_Base(BlockCipher* cipher, size_t tag_size) : ctr = new CTR_BE(cipher); // takes ownership if(tag_size % 8 != 0 || TAG_SIZE == 0 || TAG_SIZE > cmac->output_length()) - throw Invalid_Argument(name() + ": Bad tag size " + to_string(tag_size)); + throw Invalid_Argument(name() + ": Bad tag size " + std::to_string(tag_size)); } /* @@ -70,7 +70,7 @@ void EAX_Base::set_key(const SymmetricKey& key) ctr->set_key(key); cmac->set_key(key); - header_mac = eax_prf(1, BLOCK_SIZE, cmac, 0, 0); + header_mac = eax_prf(1, BLOCK_SIZE, cmac, nullptr, 0); } /* @@ -131,7 +131,7 @@ void EAX_Encryption::write(const byte input[], size_t length) */ void EAX_Encryption::end_msg() { - SecureVector<byte> data_mac = cmac->final(); + secure_vector<byte> data_mac = cmac->final(); xor_buf(data_mac, nonce_mac, data_mac.size()); xor_buf(data_mac, header_mac, data_mac.size()); diff --git a/src/filters/modes/eax/eax.h b/src/filters/modes/eax/eax.h index e8efb9398..d78287521 100644 --- a/src/filters/modes/eax/eax.h +++ b/src/filters/modes/eax/eax.h @@ -81,17 +81,17 @@ class BOTAN_DLL EAX_Base : public Keyed_Filter /** * The MAC of the nonce */ - SecureVector<byte> nonce_mac; + secure_vector<byte> nonce_mac; /** * The MAC of the header */ - SecureVector<byte> header_mac; + secure_vector<byte> header_mac; /** * A buffer for CTR mode encryption */ - SecureVector<byte> ctr_buf; + secure_vector<byte> ctr_buf; }; /** @@ -151,7 +151,7 @@ class BOTAN_DLL EAX_Decryption : public EAX_Base void do_write(const byte[], size_t); void end_msg(); - SecureVector<byte> queue; + secure_vector<byte> queue; size_t queue_start, queue_end; }; diff --git a/src/filters/modes/eax/eax_dec.cpp b/src/filters/modes/eax/eax_dec.cpp index 72e2249ac..a2675cac0 100644 --- a/src/filters/modes/eax/eax_dec.cpp +++ b/src/filters/modes/eax/eax_dec.cpp @@ -47,7 +47,7 @@ void EAX_Decryption::write(const byte input[], size_t length) { const size_t copied = std::min<size_t>(length, queue.size() - queue_end); - queue.copy(queue_end, input, copied); + buffer_insert(queue, queue_end, input, copied); input += copied; length -= copied; queue_end += copied; @@ -62,9 +62,9 @@ void EAX_Decryption::write(const byte input[], size_t length) if(queue_start + TAG_SIZE == queue_end && queue_start >= queue.size() / 2) { - SecureVector<byte> queue_data(TAG_SIZE); - queue_data.copy(&queue[queue_start], TAG_SIZE); - queue.copy(&queue_data[0], TAG_SIZE); + secure_vector<byte> queue_data(TAG_SIZE); + copy_mem(&queue_data[0], &queue[queue_start], TAG_SIZE); + copy_mem(&queue[0], &queue_data[0], TAG_SIZE); queue_start = 0; queue_end = TAG_SIZE; } @@ -100,7 +100,7 @@ void EAX_Decryption::end_msg() if((queue_end - queue_start) != TAG_SIZE) throw Decoding_Error(name() + ": Message authentication failure"); - SecureVector<byte> data_mac = cmac->final(); + secure_vector<byte> data_mac = cmac->final(); for(size_t j = 0; j != TAG_SIZE; ++j) if(queue[queue_start+j] != (data_mac[j] ^ nonce_mac[j] ^ header_mac[j])) diff --git a/src/filters/modes/ecb/ecb.cpp b/src/filters/modes/ecb/ecb.cpp index 9115d6362..d36d2350b 100644 --- a/src/filters/modes/ecb/ecb.cpp +++ b/src/filters/modes/ecb/ecb.cpp @@ -70,8 +70,8 @@ void ECB_Encryption::end_msg() { size_t last_block = current_position() % cipher->block_size(); - SecureVector<byte> padding(cipher->block_size()); - padder->pad(padding, padding.size(), last_block); + secure_vector<byte> padding(cipher->block_size()); + padder->pad(&padding[0], padding.size(), last_block); size_t pad_bytes = padder->pad_bytes(cipher->block_size(), last_block); @@ -203,8 +203,8 @@ void ECB_Decryption::buffered_final(const byte input[], size_t length) input += extra_blocks * cipher->block_size(); - cipher->decrypt(input, temp); - send(temp, padder->unpad(temp, cipher->block_size())); + cipher->decrypt(input, &temp[0]); + send(&temp[0], padder->unpad(&temp[0], cipher->block_size())); } } diff --git a/src/filters/modes/ecb/ecb.h b/src/filters/modes/ecb/ecb.h index 94cff1f52..e6476ab5d 100644 --- a/src/filters/modes/ecb/ecb.h +++ b/src/filters/modes/ecb/ecb.h @@ -46,7 +46,7 @@ class BOTAN_DLL ECB_Encryption : public Keyed_Filter, BlockCipher* cipher; BlockCipherModePaddingMethod* padder; - SecureVector<byte> temp; + secure_vector<byte> temp; }; /** @@ -80,7 +80,7 @@ class BOTAN_DLL ECB_Decryption : public Keyed_Filter, BlockCipher* cipher; BlockCipherModePaddingMethod* padder; - SecureVector<byte> temp; + secure_vector<byte> temp; }; } diff --git a/src/filters/modes/xts/xts.cpp b/src/filters/modes/xts/xts.cpp index 2d2957088..e29ef6b98 100644 --- a/src/filters/modes/xts/xts.cpp +++ b/src/filters/modes/xts/xts.cpp @@ -92,14 +92,14 @@ void XTS_Encryption::set_iv(const InitializationVector& iv) const size_t blocks_in_tweak = tweak.size() / cipher->block_size(); - tweak.copy(iv.begin(), iv.length()); + tweak.assign(iv.begin(), iv.end()); cipher2->encrypt(tweak); for(size_t i = 1; i < blocks_in_tweak; ++i) { - tweak.copy(i*cipher->block_size(), - &tweak[(i-1)*cipher->block_size()], - cipher->block_size()); + buffer_insert(tweak, i*cipher->block_size(), + &tweak[(i-1)*cipher->block_size()], + cipher->block_size()); poly_double(&tweak[i*cipher->block_size()], cipher->block_size()); } @@ -136,7 +136,7 @@ void XTS_Encryption::buffered_block(const byte input[], size_t length) const size_t blocks_in_tweak = tweak.size() / cipher->block_size(); size_t blocks = length / cipher->block_size(); - SecureVector<byte> temp(tweak.size()); + secure_vector<byte> temp(tweak.size()); while(blocks) { @@ -151,13 +151,15 @@ void XTS_Encryption::buffered_block(const byte input[], size_t length) send(temp, to_proc_bytes); - tweak.copy(&tweak[(to_proc-1)*cipher->block_size()], - cipher->block_size()); + copy_mem(&tweak[0], + &tweak[(to_proc-1)*cipher->block_size()], + cipher->block_size()); + poly_double(&tweak[0], cipher->block_size()); for(size_t i = 1; i < blocks_in_tweak; ++i) { - tweak.copy(i*cipher->block_size(), + buffer_insert(tweak, i*cipher->block_size(), &tweak[(i-1)*cipher->block_size()], cipher->block_size()); @@ -192,7 +194,7 @@ void XTS_Encryption::buffered_final(const byte input[], size_t length) input += leftover_blocks; length -= leftover_blocks; - SecureVector<byte> temp(input, length); + secure_vector<byte> temp(input, input + length); xor_buf(temp, tweak, cipher->block_size()); cipher->encrypt(temp); @@ -264,12 +266,12 @@ void XTS_Decryption::set_iv(const InitializationVector& iv) const size_t blocks_in_tweak = tweak.size() / cipher->block_size(); - tweak.copy(iv.begin(), iv.length()); + tweak.assign(iv.begin(), iv.end()); cipher2->encrypt(tweak); for(size_t i = 1; i < blocks_in_tweak; ++i) { - tweak.copy(i*cipher->block_size(), + buffer_insert(tweak, i*cipher->block_size(), &tweak[(i-1)*cipher->block_size()], cipher->block_size()); @@ -309,7 +311,7 @@ void XTS_Decryption::buffered_block(const byte input[], size_t input_length) const size_t blocks_in_tweak = tweak.size() / cipher->block_size(); size_t blocks = input_length / cipher->block_size(); - SecureVector<byte> temp(tweak.size()); + secure_vector<byte> temp(tweak.size()); while(blocks) { @@ -324,15 +326,17 @@ void XTS_Decryption::buffered_block(const byte input[], size_t input_length) send(temp, to_proc_bytes); - tweak.copy(&tweak[(to_proc-1)*cipher->block_size()], - cipher->block_size()); + copy_mem(&tweak[0], + &tweak[(to_proc-1)*cipher->block_size()], + cipher->block_size()); + poly_double(&tweak[0], cipher->block_size()); for(size_t i = 1; i < blocks_in_tweak; ++i) { - tweak.copy(i*cipher->block_size(), - &tweak[(i-1)*cipher->block_size()], - cipher->block_size()); + buffer_insert(tweak, i*cipher->block_size(), + &tweak[(i-1)*cipher->block_size()], + cipher->block_size()); poly_double(&tweak[i*cipher->block_size()], cipher->block_size()); } @@ -361,8 +365,8 @@ void XTS_Decryption::buffered_final(const byte input[], size_t length) input += leftover_blocks; length -= leftover_blocks; - SecureVector<byte> temp(input, length); - SecureVector<byte> tweak_copy(&tweak[0], cipher->block_size()); + secure_vector<byte> temp(input, input + length); + secure_vector<byte> tweak_copy(&tweak[0], &tweak[cipher->block_size()]); poly_double(&tweak_copy[0], cipher->block_size()); diff --git a/src/filters/modes/xts/xts.h b/src/filters/modes/xts/xts.h index 52db9bcfc..d4801cd37 100644 --- a/src/filters/modes/xts/xts.h +++ b/src/filters/modes/xts/xts.h @@ -48,7 +48,7 @@ class BOTAN_DLL XTS_Encryption : public Keyed_Filter, BlockCipher* cipher; BlockCipher* cipher2; - SecureVector<byte> tweak; + secure_vector<byte> tweak; }; /** @@ -85,7 +85,7 @@ class BOTAN_DLL XTS_Decryption : public Keyed_Filter, BlockCipher* cipher; BlockCipher* cipher2; - SecureVector<byte> tweak; + secure_vector<byte> tweak; }; } diff --git a/src/filters/out_buf.cpp b/src/filters/out_buf.cpp index 7b79b4b70..b1dc8ff7f 100644 --- a/src/filters/out_buf.cpp +++ b/src/filters/out_buf.cpp @@ -69,7 +69,7 @@ void Output_Buffers::retire() if(buffers[i] && buffers[i]->size() == 0) { delete buffers[i]; - buffers[i] = 0; + buffers[i] = nullptr; } while(buffers.size() && !buffers[0]) @@ -85,7 +85,7 @@ void Output_Buffers::retire() SecureQueue* Output_Buffers::get(Pipe::message_id msg) const { if(msg < offset) - return 0; + return nullptr; BOTAN_ASSERT(msg < message_count(), "Message number out of range"); diff --git a/src/filters/pipe.cpp b/src/filters/pipe.cpp index 3c3b5e6a4..e3c2f53b6 100644 --- a/src/filters/pipe.cpp +++ b/src/filters/pipe.cpp @@ -43,11 +43,12 @@ Pipe::Pipe(Filter* f1, Filter* f2, Filter* f3, Filter* f4) /* * Pipe Constructor */ -Pipe::Pipe(Filter* filter_array[], size_t count) +Pipe::Pipe(std::initializer_list<Filter*> args) { init(); - for(size_t j = 0; j != count; ++j) - append(filter_array[j]); + + for(auto i = args.begin(); i != args.end(); ++i) + append(*i); } /* @@ -65,7 +66,7 @@ Pipe::~Pipe() void Pipe::init() { outputs = new Output_Buffers; - pipe = 0; + pipe = nullptr; default_read = 0; inside_msg = false; } @@ -75,10 +76,8 @@ void Pipe::init() */ void Pipe::reset() { - if(inside_msg) - throw Invalid_State("Pipe cannot be reset while it is processing"); destruct(pipe); - pipe = 0; + pipe = nullptr; inside_msg = false; } @@ -125,7 +124,12 @@ void Pipe::process_msg(const byte input[], size_t length) /* * Process a full message at once */ -void Pipe::process_msg(const MemoryRegion<byte>& input) +void Pipe::process_msg(const secure_vector<byte>& input) + { + process_msg(&input[0], input.size()); + } + +void Pipe::process_msg(const std::vector<byte>& input) { process_msg(&input[0], input.size()); } @@ -155,7 +159,7 @@ void Pipe::start_msg() { if(inside_msg) throw Invalid_State("Pipe::start_msg: Message was already started"); - if(pipe == 0) + if(pipe == nullptr) pipe = new Null_Filter; find_endpoints(pipe); pipe->new_msg(); @@ -174,7 +178,7 @@ void Pipe::end_msg() if(dynamic_cast<Null_Filter*>(pipe)) { delete pipe; - pipe = 0; + pipe = nullptr; } inside_msg = false; @@ -206,7 +210,7 @@ void Pipe::clear_endpoints(Filter* f) for(size_t j = 0; j != f->total_ports(); ++j) { if(f->next[j] && dynamic_cast<SecureQueue*>(f->next[j])) - f->next[j] = 0; + f->next[j] = nullptr; clear_endpoints(f->next[j]); } } diff --git a/src/filters/pipe.h b/src/filters/pipe.h index e5cb5f445..3236e7c36 100644 --- a/src/filters/pipe.h +++ b/src/filters/pipe.h @@ -11,6 +11,7 @@ #include <botan/data_src.h> #include <botan/filter.h> #include <botan/exceptn.h> +#include <initializer_list> #include <iosfwd> namespace Botan { @@ -42,7 +43,7 @@ class BOTAN_DLL Pipe : public DataSource */ Invalid_Message_Number(const std::string& where, message_id msg) : Invalid_Argument("Pipe::" + where + ": Invalid message number " + - to_string(msg)) + std::to_string(msg)) {} }; @@ -65,9 +66,17 @@ class BOTAN_DLL Pipe : public DataSource /** * Write input to the pipe, i.e. to its first filter. - * @param in the MemoryRegion containing the data to write + * @param in the secure_vector containing the data to write */ - void write(const MemoryRegion<byte>& in); + void write(const secure_vector<byte>& in) + { write(&in[0], in.size()); } + + /** + * Write input to the pipe, i.e. to its first filter. + * @param in the std::vector containing the data to write + */ + void write(const std::vector<byte>& in) + { write(&in[0], in.size()); } /** * Write input to the pipe, i.e. to its first filter. @@ -96,9 +105,15 @@ class BOTAN_DLL Pipe : public DataSource /** * Perform start_msg(), write() and end_msg() sequentially. - * @param in the MemoryRegion containing the data to write + * @param in the secure_vector containing the data to write + */ + void process_msg(const secure_vector<byte>& in); + + /** + * Perform start_msg(), write() and end_msg() sequentially. + * @param in the secure_vector containing the data to write */ - void process_msg(const MemoryRegion<byte>& in); + void process_msg(const std::vector<byte>& in); /** * Perform start_msg(), write() and end_msg() sequentially. @@ -156,9 +171,9 @@ class BOTAN_DLL Pipe : public DataSource /** * Read the full contents of the pipe. * @param msg the number identifying the message to read from - * @return SecureVector holding the contents of the pipe + * @return secure_vector holding the contents of the pipe */ - SecureVector<byte> read_all(message_id msg = DEFAULT_MESSAGE); + secure_vector<byte> read_all(message_id msg = DEFAULT_MESSAGE); /** * Read the full contents of the pipe. @@ -261,18 +276,20 @@ class BOTAN_DLL Pipe : public DataSource * Construct a Pipe of up to four filters. The filters are set up * in the same order as the arguments. */ - Pipe(Filter* = 0, Filter* = 0, Filter* = 0, Filter* = 0); + Pipe(Filter* = nullptr, Filter* = nullptr, + Filter* = nullptr, Filter* = nullptr); /** - * Construct a Pipe from range of filters passed as an array + * Construct a Pipe from a list of filters * @param filters the set of filters to use - * @param count the number of elements in filters */ - Pipe(Filter* filters[], size_t count); + Pipe(std::initializer_list<Filter*> filters); + + Pipe(const Pipe&) = delete; + Pipe& operator=(const Pipe&) = delete; + ~Pipe(); private: - Pipe(const Pipe&) : DataSource() {} - Pipe& operator=(const Pipe&) { return (*this); } void init(); void destruct(Filter*); void find_endpoints(Filter*); diff --git a/src/filters/pipe_io.cpp b/src/filters/pipe_io.cpp index 9dd0ad0bb..a549eaee8 100644 --- a/src/filters/pipe_io.cpp +++ b/src/filters/pipe_io.cpp @@ -15,7 +15,7 @@ namespace Botan { */ std::ostream& operator<<(std::ostream& stream, Pipe& pipe) { - SecureVector<byte> buffer(DEFAULT_BUFFERSIZE); + secure_vector<byte> buffer(DEFAULT_BUFFERSIZE); while(stream.good() && pipe.remaining()) { size_t got = pipe.read(&buffer[0], buffer.size()); @@ -31,7 +31,7 @@ std::ostream& operator<<(std::ostream& stream, Pipe& pipe) */ std::istream& operator>>(std::istream& stream, Pipe& pipe) { - SecureVector<byte> buffer(DEFAULT_BUFFERSIZE); + secure_vector<byte> buffer(DEFAULT_BUFFERSIZE); while(stream.good()) { stream.read(reinterpret_cast<char*>(&buffer[0]), buffer.size()); diff --git a/src/filters/pipe_rw.cpp b/src/filters/pipe_rw.cpp index 90af9ed34..8a713ea8d 100644 --- a/src/filters/pipe_rw.cpp +++ b/src/filters/pipe_rw.cpp @@ -39,14 +39,6 @@ void Pipe::write(const byte input[], size_t length) } /* -* Write into a Pipe -*/ -void Pipe::write(const MemoryRegion<byte>& input) - { - write(&input[0], input.size()); - } - -/* * Write a string into a Pipe */ void Pipe::write(const std::string& str) @@ -67,7 +59,7 @@ void Pipe::write(byte input) */ void Pipe::write(DataSource& source) { - SecureVector<byte> buffer(DEFAULT_BUFFERSIZE); + secure_vector<byte> buffer(DEFAULT_BUFFERSIZE); while(!source.end_of_data()) { size_t got = source.read(&buffer[0], buffer.size()); @@ -102,10 +94,10 @@ size_t Pipe::read(byte& out, message_id msg) /* * Return all data in the pipe */ -SecureVector<byte> Pipe::read_all(message_id msg) +secure_vector<byte> Pipe::read_all(message_id msg) { msg = ((msg != DEFAULT_MESSAGE) ? msg : default_msg()); - SecureVector<byte> buffer(remaining(msg)); + secure_vector<byte> buffer(remaining(msg)); size_t got = read(&buffer[0], buffer.size(), msg); buffer.resize(got); return buffer; @@ -117,7 +109,7 @@ SecureVector<byte> Pipe::read_all(message_id msg) std::string Pipe::read_all_as_string(message_id msg) { msg = ((msg != DEFAULT_MESSAGE) ? msg : default_msg()); - SecureVector<byte> buffer(DEFAULT_BUFFERSIZE); + secure_vector<byte> buffer(DEFAULT_BUFFERSIZE); std::string str; str.reserve(remaining(msg)); diff --git a/src/filters/pk_filts/pk_filts.cpp b/src/filters/pk_filts/pk_filts.cpp index d843d711c..45fcc18b8 100644 --- a/src/filters/pk_filts/pk_filts.cpp +++ b/src/filters/pk_filts/pk_filts.cpp @@ -83,14 +83,13 @@ void PK_Verifier_Filter::end_msg() */ void PK_Verifier_Filter::set_signature(const byte sig[], size_t length) { - signature.resize(length); - copy_mem(&signature[0], sig, length); + signature.assign(sig, sig + length); } /* * Set the signature to check */ -void PK_Verifier_Filter::set_signature(const MemoryRegion<byte>& sig) +void PK_Verifier_Filter::set_signature(const secure_vector<byte>& sig) { signature = sig; } @@ -100,7 +99,7 @@ void PK_Verifier_Filter::set_signature(const MemoryRegion<byte>& sig) */ PK_Verifier_Filter::PK_Verifier_Filter(PK_Verifier* v, const byte sig[], size_t length) : - verifier(v), signature(sig, length) + verifier(v), signature(sig, sig + length) { } @@ -108,7 +107,7 @@ PK_Verifier_Filter::PK_Verifier_Filter(PK_Verifier* v, const byte sig[], * PK_Verifier_Filter Constructor */ PK_Verifier_Filter::PK_Verifier_Filter(PK_Verifier* v, - const MemoryRegion<byte>& sig) : + const secure_vector<byte>& sig) : verifier(v), signature(sig) { } diff --git a/src/filters/pk_filts/pk_filts.h b/src/filters/pk_filts/pk_filts.h index dd67e389b..cc1c2220d 100644 --- a/src/filters/pk_filts/pk_filts.h +++ b/src/filters/pk_filts/pk_filts.h @@ -28,7 +28,7 @@ class BOTAN_DLL PK_Encryptor_Filter : public Filter private: PK_Encryptor* cipher; RandomNumberGenerator& rng; - SecureVector<byte> buffer; + secure_vector<byte> buffer; }; /** @@ -43,7 +43,7 @@ class BOTAN_DLL PK_Decryptor_Filter : public Filter ~PK_Decryptor_Filter() { delete cipher; } private: PK_Decryptor* cipher; - SecureVector<byte> buffer; + secure_vector<byte> buffer; }; /** @@ -75,15 +75,15 @@ class BOTAN_DLL PK_Verifier_Filter : public Filter void end_msg(); void set_signature(const byte[], size_t); - void set_signature(const MemoryRegion<byte>&); + void set_signature(const secure_vector<byte>&); PK_Verifier_Filter(PK_Verifier* v) : verifier(v) {} PK_Verifier_Filter(PK_Verifier*, const byte[], size_t); - PK_Verifier_Filter(PK_Verifier*, const MemoryRegion<byte>&); + PK_Verifier_Filter(PK_Verifier*, const secure_vector<byte>&); ~PK_Verifier_Filter() { delete verifier; } private: PK_Verifier* verifier; - SecureVector<byte> signature; + secure_vector<byte> signature; }; } diff --git a/src/filters/secqueue.cpp b/src/filters/secqueue.cpp index 8dc95ea99..811a7ef57 100644 --- a/src/filters/secqueue.cpp +++ b/src/filters/secqueue.cpp @@ -17,9 +17,9 @@ class SecureQueueNode { public: SecureQueueNode() : buffer(DEFAULT_BUFFERSIZE) - { next = 0; start = end = 0; } + { next = nullptr; start = end = 0; } - ~SecureQueueNode() { next = 0; start = end = 0; } + ~SecureQueueNode() { next = nullptr; start = end = 0; } size_t write(const byte input[], size_t length) { @@ -50,7 +50,7 @@ class SecureQueueNode private: friend class SecureQueue; SecureQueueNode* next; - SecureVector<byte> buffer; + secure_vector<byte> buffer; size_t start, end; }; @@ -59,7 +59,7 @@ class SecureQueueNode */ SecureQueue::SecureQueue() { - set_next(0, 0); + set_next(nullptr, 0); head = tail = new SecureQueueNode; } @@ -69,7 +69,7 @@ SecureQueue::SecureQueue() SecureQueue::SecureQueue(const SecureQueue& input) : Fanout_Filter(), DataSource() { - set_next(0, 0); + set_next(nullptr, 0); head = tail = new SecureQueueNode; SecureQueueNode* temp = input.head; @@ -92,7 +92,7 @@ void SecureQueue::destroy() delete temp; temp = holder; } - head = tail = 0; + head = tail = nullptr; } /* @@ -208,4 +208,9 @@ bool SecureQueue::end_of_data() const return (size() == 0); } +bool SecureQueue::empty() const + { + return (size() == 0); + } + } diff --git a/src/filters/secqueue.h b/src/filters/secqueue.h index 632ae857d..e773b69bc 100644 --- a/src/filters/secqueue.h +++ b/src/filters/secqueue.h @@ -28,6 +28,8 @@ class BOTAN_DLL SecureQueue : public Fanout_Filter, public DataSource bool end_of_data() const; + bool empty() const; + /** * @return number of bytes available in the queue */ diff --git a/src/filters/zlib/zlib.cpp b/src/filters/zlib/zlib.cpp index 0f88b5558..169146826 100644 --- a/src/filters/zlib/zlib.cpp +++ b/src/filters/zlib/zlib.cpp @@ -47,7 +47,7 @@ void* zlib_malloc(void* info_ptr, unsigned int n, unsigned int size) void zlib_free(void* info_ptr, void* ptr) { Zlib_Alloc_Info* info = static_cast<Zlib_Alloc_Info*>(info_ptr); - std::map<void*, size_t>::const_iterator i = info->current_allocs.find(ptr); + auto i = info->current_allocs.find(ptr); if(i == info->current_allocs.end()) throw Invalid_Argument("zlib_free: Got pointer not allocated by us"); info->alloc->deallocate(ptr, i->second); @@ -91,10 +91,12 @@ class Zlib_Stream /* * Zlib_Compression Constructor */ -Zlib_Compression::Zlib_Compression(size_t l) : - level((l >= 9) ? 9 : l), buffer(DEFAULT_BUFFERSIZE) +Zlib_Compression::Zlib_Compression(size_t l, bool raw_deflate) : + level((l >= 9) ? 9 : l), + raw_deflate(raw_deflate), + buffer(DEFAULT_BUFFERSIZE), + zlib(0) { - zlib = 0; } /* @@ -104,7 +106,17 @@ void Zlib_Compression::start_msg() { clear(); zlib = new Zlib_Stream; - if(deflateInit(&(zlib->stream), level) != Z_OK) + + int res = deflateInit2(&(zlib->stream), + level, + Z_DEFLATED, + (raw_deflate ? -15 : 15), + 8, + Z_DEFAULT_STRATEGY); + + if(res == Z_STREAM_ERROR) + throw Invalid_Argument("Bad setting in deflateInit2"); + else if(res != Z_OK) throw Memory_Exhaustion(); } @@ -185,10 +197,12 @@ void Zlib_Compression::clear() /* * Zlib_Decompression Constructor */ -Zlib_Decompression::Zlib_Decompression() : buffer(DEFAULT_BUFFERSIZE) +Zlib_Decompression::Zlib_Decompression(bool raw_deflate) : + raw_deflate(raw_deflate), + buffer(DEFAULT_BUFFERSIZE), + zlib(0), + no_writes(true) { - zlib = 0; - no_writes = true; } /* @@ -198,7 +212,8 @@ void Zlib_Decompression::start_msg() { clear(); zlib = new Zlib_Stream; - if(inflateInit(&(zlib->stream)) != Z_OK) + + if(inflateInit2(&(zlib->stream), (raw_deflate ? -15 : 15)) != Z_OK) throw Memory_Exhaustion(); } diff --git a/src/filters/zlib/zlib.h b/src/filters/zlib/zlib.h index 77ec5eecc..c4d21a250 100644 --- a/src/filters/zlib/zlib.h +++ b/src/filters/zlib/zlib.h @@ -31,16 +31,21 @@ class BOTAN_DLL Zlib_Compression : public Filter void flush(); /** - @param level how much effort to use on compressing (0 to 9); - higher levels are slower but tend to give better compression + * @param level how much effort to use on compressing (0 to 9); + * higher levels are slower but tend to give better + * compression + * @param raw_deflate if true no zlib header/trailer will be used */ - Zlib_Compression(size_t level = 6); + Zlib_Compression(size_t level = 6, + bool raw_deflate = false); ~Zlib_Compression() { clear(); } private: void clear(); const size_t level; - SecureVector<byte> buffer; + const bool raw_deflate; + + secure_vector<byte> buffer; class Zlib_Stream* zlib; }; @@ -56,11 +61,14 @@ class BOTAN_DLL Zlib_Decompression : public Filter void start_msg(); void end_msg(); - Zlib_Decompression(); + Zlib_Decompression(bool raw_deflate = false); ~Zlib_Decompression() { clear(); } private: void clear(); - SecureVector<byte> buffer; + + const bool raw_deflate; + + secure_vector<byte> buffer; class Zlib_Stream* zlib; bool no_writes; }; diff --git a/src/hash/bmw_512/bmw_512.h b/src/hash/bmw_512/bmw_512.h index 474b607bb..b9ea63578 100644 --- a/src/hash/bmw_512/bmw_512.h +++ b/src/hash/bmw_512/bmw_512.h @@ -30,7 +30,7 @@ class BOTAN_DLL BMW_512 : public MDx_HashFunction void compress_n(const byte input[], size_t blocks); void copy_out(byte output[]); - SecureVector<u64bit> H, M, Q; + secure_vector<u64bit> H, M, Q; }; } diff --git a/src/hash/comb4p/comb4p.cpp b/src/hash/comb4p/comb4p.cpp index 1ea64a5cb..7aec5972e 100644 --- a/src/hash/comb4p/comb4p.cpp +++ b/src/hash/comb4p/comb4p.cpp @@ -13,8 +13,8 @@ namespace Botan { namespace { -void comb4p_round(MemoryRegion<byte>& out, - const MemoryRegion<byte>& in, +void comb4p_round(secure_vector<byte>& out, + const secure_vector<byte>& in, byte round_no, HashFunction* h1, HashFunction* h2) @@ -25,7 +25,7 @@ void comb4p_round(MemoryRegion<byte>& out, h1->update(&in[0], in.size()); h2->update(&in[0], in.size()); - SecureVector<byte> h_buf = h1->final(); + secure_vector<byte> h_buf = h1->final(); xor_buf(&out[0], &h_buf[0], std::min(out.size(), h_buf.size())); h_buf = h2->final(); @@ -78,8 +78,8 @@ void Comb4P::add_data(const byte input[], size_t length) void Comb4P::final_result(byte out[]) { - SecureVector<byte> h1 = hash1->final(); - SecureVector<byte> h2 = hash2->final(); + secure_vector<byte> h1 = hash1->final(); + secure_vector<byte> h2 = hash2->final(); // First round xor_buf(&h1[0], &h2[0], std::min(h1.size(), h2.size())); diff --git a/src/hash/gost_3411/gost_3411.cpp b/src/hash/gost_3411/gost_3411.cpp index c0f39da47..eb889c0a5 100644 --- a/src/hash/gost_3411/gost_3411.cpp +++ b/src/hash/gost_3411/gost_3411.cpp @@ -43,7 +43,7 @@ void GOST_34_11::add_data(const byte input[], size_t length) if(position) { - buffer.copy(position, input, length); + buffer_insert(buffer, position, input, length); if(position + length >= hash_block_size()) { @@ -60,7 +60,7 @@ void GOST_34_11::add_data(const byte input[], size_t length) if(full_blocks) compress_n(input, full_blocks); - buffer.copy(position, input + full_blocks * hash_block_size(), remaining); + buffer_insert(buffer, position, input + full_blocks * hash_block_size(), remaining); position += remaining; } @@ -210,7 +210,7 @@ void GOST_34_11::compress_n(const byte input[], size_t blocks) S2[30] = S[ 2] ^ S[ 4] ^ S[ 8] ^ S[14] ^ S[16] ^ S[18] ^ S[22] ^ S[24] ^ S[28] ^ S[30]; S2[31] = S[ 3] ^ S[ 5] ^ S[ 9] ^ S[15] ^ S[17] ^ S[19] ^ S[23] ^ S[25] ^ S[29] ^ S[31]; - hash.copy(S2, 32); + copy_mem(&hash[0], &S2[0], 32); } } @@ -225,11 +225,11 @@ void GOST_34_11::final_result(byte out[]) compress_n(&buffer[0], 1); } - SecureVector<byte> length_buf(32); + secure_vector<byte> length_buf(32); const u64bit bit_count = count * 8; store_le(bit_count, &length_buf[0]); - SecureVector<byte> sum_buf = sum; + secure_vector<byte> sum_buf = sum; compress_n(&length_buf[0], 1); compress_n(&sum_buf[0], 1); diff --git a/src/hash/gost_3411/gost_3411.h b/src/hash/gost_3411/gost_3411.h index fbbcb7a89..5437ca4d8 100644 --- a/src/hash/gost_3411/gost_3411.h +++ b/src/hash/gost_3411/gost_3411.h @@ -34,7 +34,7 @@ class BOTAN_DLL GOST_34_11 : public HashFunction void final_result(byte[]); GOST_28147_89 cipher; - SecureVector<byte> buffer, sum, hash; + secure_vector<byte> buffer, sum, hash; size_t position; u64bit count; }; diff --git a/src/hash/has160/has160.h b/src/hash/has160/has160.h index d32361601..9947d9580 100644 --- a/src/hash/has160/has160.h +++ b/src/hash/has160/has160.h @@ -31,7 +31,7 @@ class BOTAN_DLL HAS_160 : public MDx_HashFunction void compress_n(const byte[], size_t blocks); void copy_out(byte[]); - SecureVector<u32bit> X, digest; + secure_vector<u32bit> X, digest; }; } diff --git a/src/hash/keccak/keccak.cpp b/src/hash/keccak/keccak.cpp index 922167b61..e34c0fd43 100644 --- a/src/hash/keccak/keccak.cpp +++ b/src/hash/keccak/keccak.cpp @@ -112,12 +112,12 @@ Keccak_1600::Keccak_1600(size_t output_bits) : if(output_bits != 224 && output_bits != 256 && output_bits != 384 && output_bits != 512) throw Invalid_Argument("Keccak_1600: Invalid output length " + - to_string(output_bits)); + std::to_string(output_bits)); } std::string Keccak_1600::name() const { - return "Keccak-1600(" + to_string(output_bits) + ")"; + return "Keccak-1600(" + std::to_string(output_bits) + ")"; } HashFunction* Keccak_1600::clone() const @@ -178,12 +178,12 @@ void Keccak_1600::add_data(const byte input[], size_t length) void Keccak_1600::final_result(byte output[]) { - MemoryVector<byte> padding(bitrate / 8 - S_pos); + std::vector<byte> padding(bitrate / 8 - S_pos); padding[0] = 0x01; padding[padding.size()-1] |= 0x80; - add_data(padding, padding.size()); + add_data(&padding[0], padding.size()); /* * We never have to run the permutation again because we only support diff --git a/src/hash/keccak/keccak.h b/src/hash/keccak/keccak.h index 17ae632ba..e91a04d32 100644 --- a/src/hash/keccak/keccak.h +++ b/src/hash/keccak/keccak.h @@ -38,7 +38,7 @@ class BOTAN_DLL Keccak_1600 : public HashFunction void final_result(byte out[]); size_t output_bits, bitrate; - SecureVector<u64bit> S; + secure_vector<u64bit> S; size_t S_pos; }; diff --git a/src/hash/md2/md2.cpp b/src/hash/md2/md2.cpp index 761528dc6..8f6a90208 100644 --- a/src/hash/md2/md2.cpp +++ b/src/hash/md2/md2.cpp @@ -39,7 +39,7 @@ void MD2::hash(const byte input[]) 0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, 0xDB, 0x99, 0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14 }; - X.copy(16, input, hash_block_size()); + buffer_insert(X, 16, input, hash_block_size()); xor_buf(&X[32], &X[0], &X[16], hash_block_size()); byte T = 0; @@ -66,7 +66,7 @@ void MD2::hash(const byte input[]) */ void MD2::add_data(const byte input[], size_t length) { - buffer.copy(position, input, length); + buffer_insert(buffer, position, input, length); if(position + length >= hash_block_size()) { @@ -79,7 +79,7 @@ void MD2::add_data(const byte input[], size_t length) input += hash_block_size(); length -= hash_block_size(); } - buffer.copy(input, length); + copy_mem(&buffer[0], input, length); position = 0; } position += length; diff --git a/src/hash/md2/md2.h b/src/hash/md2/md2.h index 84e0323f7..032d8a8e0 100644 --- a/src/hash/md2/md2.h +++ b/src/hash/md2/md2.h @@ -32,7 +32,7 @@ class BOTAN_DLL MD2 : public HashFunction void hash(const byte[]); void final_result(byte[]); - SecureVector<byte> X, checksum, buffer; + secure_vector<byte> X, checksum, buffer; size_t position; }; diff --git a/src/hash/md4/md4.h b/src/hash/md4/md4.h index d37dbe3b2..750be0fe7 100644 --- a/src/hash/md4/md4.h +++ b/src/hash/md4/md4.h @@ -33,12 +33,12 @@ class BOTAN_DLL MD4 : public MDx_HashFunction /** * The message buffer, exposed for use by subclasses (x86 asm) */ - SecureVector<u32bit> M; + secure_vector<u32bit> M; /** * The digest value, exposed for use by subclasses (x86 asm) */ - SecureVector<u32bit> digest; + secure_vector<u32bit> digest; }; } diff --git a/src/hash/md5/md5.h b/src/hash/md5/md5.h index 92c023c92..bc90df0af 100644 --- a/src/hash/md5/md5.h +++ b/src/hash/md5/md5.h @@ -33,12 +33,12 @@ class BOTAN_DLL MD5 : public MDx_HashFunction /** * The message buffer, exposed for use by subclasses (x86 asm) */ - SecureVector<u32bit> M; + secure_vector<u32bit> M; /** * The digest value, exposed for use by subclasses (x86 asm) */ - SecureVector<u32bit> digest; + secure_vector<u32bit> digest; }; } diff --git a/src/hash/mdx_hash/mdx_hash.cpp b/src/hash/mdx_hash/mdx_hash.cpp index 7bfcf6592..81042c1fa 100644 --- a/src/hash/mdx_hash/mdx_hash.cpp +++ b/src/hash/mdx_hash/mdx_hash.cpp @@ -44,7 +44,7 @@ void MDx_HashFunction::add_data(const byte input[], size_t length) if(position) { - buffer.copy(position, input, length); + buffer_insert(buffer, position, input, length); if(position + length >= buffer.size()) { @@ -61,7 +61,7 @@ void MDx_HashFunction::add_data(const byte input[], size_t length) if(full_blocks) compress_n(input, full_blocks); - buffer.copy(position, input + full_blocks * buffer.size(), remaining); + buffer_insert(buffer, position, input + full_blocks * buffer.size(), remaining); position += remaining; } diff --git a/src/hash/mdx_hash/mdx_hash.h b/src/hash/mdx_hash/mdx_hash.h index ed3381605..14d3c27a0 100644 --- a/src/hash/mdx_hash/mdx_hash.h +++ b/src/hash/mdx_hash/mdx_hash.h @@ -55,7 +55,7 @@ class BOTAN_DLL MDx_HashFunction : public HashFunction */ virtual void write_count(byte out[]); private: - SecureVector<byte> buffer; + secure_vector<byte> buffer; u64bit count; size_t position; diff --git a/src/hash/par_hash/par_hash.cpp b/src/hash/par_hash/par_hash.cpp index 328be6a11..df47780ef 100644 --- a/src/hash/par_hash/par_hash.cpp +++ b/src/hash/par_hash/par_hash.cpp @@ -1,11 +1,12 @@ /* * Parallel -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ #include <botan/par_hash.h> +#include <botan/parsing.h> namespace Botan { @@ -14,20 +15,21 @@ namespace Botan { */ void Parallel::add_data(const byte input[], size_t length) { - for(size_t i = 0; i != hashes.size(); ++i) - hashes[i]->update(input, length); + for(auto hash : hashes) + hash->update(input, length); } /* * Finalize the hash */ -void Parallel::final_result(byte hash[]) +void Parallel::final_result(byte out[]) { - size_t offset = 0; - for(size_t i = 0; i != hashes.size(); ++i) + u32bit offset = 0; + + for(auto hash : hashes) { - hashes[i]->final(hash + offset); - offset += hashes[i]->output_length(); + hash->final(out + offset); + offset += hash->output_length(); } } @@ -37,8 +39,9 @@ void Parallel::final_result(byte hash[]) size_t Parallel::output_length() const { size_t sum = 0; - for(size_t i = 0; i != hashes.size(); ++i) - sum += hashes[i]->output_length(); + + for(auto hash : hashes) + sum += hash->output_length(); return sum; } @@ -47,14 +50,12 @@ size_t Parallel::output_length() const */ std::string Parallel::name() const { - std::string hash_names; - for(size_t i = 0; i != hashes.size(); ++i) - { - if(i) - hash_names += ','; - hash_names += hashes[i]->name(); - } - return "Parallel(" + hash_names + ")"; + std::vector<std::string> names; + + for(auto hash : hashes) + names.push_back(hash->name()); + + return "Parallel(" + string_join(names, ',') + ")"; } /* @@ -63,8 +64,10 @@ std::string Parallel::name() const HashFunction* Parallel::clone() const { std::vector<HashFunction*> hash_copies; - for(size_t i = 0; i != hashes.size(); ++i) - hash_copies.push_back(hashes[i]->clone()); + + for(auto hash : hashes) + hash_copies.push_back(hash->clone()); + return new Parallel(hash_copies); } @@ -73,8 +76,8 @@ HashFunction* Parallel::clone() const */ void Parallel::clear() { - for(size_t i = 0; i != hashes.size(); ++i) - hashes[i]->clear(); + for(auto hash : hashes) + hash->clear(); } /* @@ -90,8 +93,8 @@ Parallel::Parallel(const std::vector<HashFunction*>& hash_in) : */ Parallel::~Parallel() { - for(size_t i = 0; i != hashes.size(); ++i) - delete hashes[i]; + for(auto hash : hashes) + delete hash; } } diff --git a/src/hash/rmd128/rmd128.h b/src/hash/rmd128/rmd128.h index d64cf3c84..e37666a27 100644 --- a/src/hash/rmd128/rmd128.h +++ b/src/hash/rmd128/rmd128.h @@ -30,7 +30,7 @@ class BOTAN_DLL RIPEMD_128 : public MDx_HashFunction void compress_n(const byte[], size_t blocks); void copy_out(byte[]); - SecureVector<u32bit> M, digest; + secure_vector<u32bit> M, digest; }; } diff --git a/src/hash/rmd160/rmd160.h b/src/hash/rmd160/rmd160.h index 5df4ad490..0e43fed9a 100644 --- a/src/hash/rmd160/rmd160.h +++ b/src/hash/rmd160/rmd160.h @@ -30,7 +30,7 @@ class BOTAN_DLL RIPEMD_160 : public MDx_HashFunction void compress_n(const byte[], size_t blocks); void copy_out(byte[]); - SecureVector<u32bit> M, digest; + secure_vector<u32bit> M, digest; }; } diff --git a/src/hash/sha1/sha160.h b/src/hash/sha1/sha160.h index c3b264861..e2a81808d 100644 --- a/src/hash/sha1/sha160.h +++ b/src/hash/sha1/sha160.h @@ -47,12 +47,12 @@ class BOTAN_DLL SHA_160 : public MDx_HashFunction /** * The digest value, exposed for use by subclasses (asm, SSE2) */ - SecureVector<u32bit> digest; + secure_vector<u32bit> digest; /** * The message buffer, exposed for use by subclasses (asm, SSE2) */ - SecureVector<u32bit> W; + secure_vector<u32bit> W; }; } diff --git a/src/hash/sha2_32/sha2_32.cpp b/src/hash/sha2_32/sha2_32.cpp index 6dd780e64..cffc8bd2a 100644 --- a/src/hash/sha2_32/sha2_32.cpp +++ b/src/hash/sha2_32/sha2_32.cpp @@ -50,7 +50,7 @@ inline u32bit sigma(u32bit X, u32bit rot1, u32bit rot2, u32bit shift) /* * SHA-224 / SHA-256 compression function */ -void compress(MemoryRegion<u32bit>& digest, +void compress(secure_vector<u32bit>& digest, const byte input[], size_t blocks) { u32bit A = digest[0], B = digest[1], C = digest[2], diff --git a/src/hash/sha2_32/sha2_32.h b/src/hash/sha2_32/sha2_32.h index 807b979d1..ccb8e07f2 100644 --- a/src/hash/sha2_32/sha2_32.h +++ b/src/hash/sha2_32/sha2_32.h @@ -31,7 +31,7 @@ class BOTAN_DLL SHA_224 : public MDx_HashFunction void compress_n(const byte[], size_t blocks); void copy_out(byte[]); - SecureVector<u32bit> digest; + secure_vector<u32bit> digest; }; /** @@ -52,7 +52,7 @@ class BOTAN_DLL SHA_256 : public MDx_HashFunction void compress_n(const byte[], size_t blocks); void copy_out(byte[]); - SecureVector<u32bit> digest; + secure_vector<u32bit> digest; }; } diff --git a/src/hash/sha2_64/sha2_64.cpp b/src/hash/sha2_64/sha2_64.cpp index 3026c3a39..8dcb4684e 100644 --- a/src/hash/sha2_64/sha2_64.cpp +++ b/src/hash/sha2_64/sha2_64.cpp @@ -49,7 +49,7 @@ inline u64bit sigma(u64bit X, u32bit rot1, u32bit rot2, u32bit shift) /* * SHA-{384,512} Compression Function */ -void compress(MemoryRegion<u64bit>& digest, +void compress(secure_vector<u64bit>& digest, const byte input[], size_t blocks) { u64bit A = digest[0], B = digest[1], C = digest[2], diff --git a/src/hash/sha2_64/sha2_64.h b/src/hash/sha2_64/sha2_64.h index 124d4bbfb..58b154170 100644 --- a/src/hash/sha2_64/sha2_64.h +++ b/src/hash/sha2_64/sha2_64.h @@ -30,7 +30,7 @@ class BOTAN_DLL SHA_384 : public MDx_HashFunction void compress_n(const byte[], size_t blocks); void copy_out(byte[]); - SecureVector<u64bit> digest; + secure_vector<u64bit> digest; }; /** @@ -51,7 +51,7 @@ class BOTAN_DLL SHA_512 : public MDx_HashFunction void compress_n(const byte[], size_t blocks); void copy_out(byte[]); - SecureVector<u64bit> digest; + secure_vector<u64bit> digest; }; } diff --git a/src/hash/skein/skein_512.cpp b/src/hash/skein/skein_512.cpp index 571bf9c0b..28c2aa38b 100644 --- a/src/hash/skein/skein_512.cpp +++ b/src/hash/skein/skein_512.cpp @@ -27,8 +27,8 @@ enum type_code { SKEIN_OUTPUT = 63 }; -void ubi_512(MemoryRegion<u64bit>& H, - MemoryRegion<u64bit>& T, +void ubi_512(secure_vector<u64bit>& H, + secure_vector<u64bit>& T, const byte msg[], size_t msg_len) { do @@ -125,7 +125,7 @@ void ubi_512(MemoryRegion<u64bit>& H, } while(msg_len); } -void reset_tweak(MemoryRegion<u64bit>& T, +void reset_tweak(secure_vector<u64bit>& T, type_code type, bool final) { T[0] = 0; @@ -135,8 +135,8 @@ void reset_tweak(MemoryRegion<u64bit>& T, (static_cast<u64bit>(final) << 63); } -void initial_block(MemoryRegion<u64bit>& H, - MemoryRegion<u64bit>& T, +void initial_block(secure_vector<u64bit>& H, + secure_vector<u64bit>& T, size_t output_bits, const std::string& personalization) { @@ -185,8 +185,9 @@ Skein_512::Skein_512(size_t arg_output_bits, std::string Skein_512::name() const { if(personalization != "") - return "Skein-512(" + to_string(output_bits) + "," + personalization + ")"; - return "Skein-512(" + to_string(output_bits) + ")"; + return "Skein-512(" + std::to_string(output_bits) + "," + + personalization + ")"; + return "Skein-512(" + std::to_string(output_bits) + ")"; } HashFunction* Skein_512::clone() const @@ -209,7 +210,7 @@ void Skein_512::add_data(const byte input[], size_t length) if(buf_pos) { - buffer.copy(buf_pos, input, length); + buffer_insert(buffer, buf_pos, input, length); if(buf_pos + length > 64) { ubi_512(H, T, &buffer[0], buffer.size()); @@ -227,7 +228,7 @@ void Skein_512::add_data(const byte input[], size_t length) length -= full_blocks * 64; - buffer.copy(buf_pos, input + full_blocks * 64, length); + buffer_insert(buffer, buf_pos, input + full_blocks * 64, length); buf_pos += length; } @@ -244,13 +245,13 @@ void Skein_512::final_result(byte out[]) size_t out_bytes = output_bits / 8; - SecureVector<u64bit> H_out(9); + secure_vector<u64bit> H_out(9); while(out_bytes) { const size_t to_proc = std::min<size_t>(out_bytes, 64); - H_out.copy(&H[0], 8); + copy_mem(&H_out[0], &H[0], 8); reset_tweak(T, SKEIN_OUTPUT, true); ubi_512(H_out, T, counter, sizeof(counter)); diff --git a/src/hash/skein/skein_512.h b/src/hash/skein/skein_512.h index 8605e5991..e0abc06ae 100644 --- a/src/hash/skein/skein_512.h +++ b/src/hash/skein/skein_512.h @@ -41,9 +41,9 @@ class BOTAN_DLL Skein_512 : public HashFunction std::string personalization; size_t output_bits; - SecureVector<u64bit> H; - SecureVector<u64bit> T; - SecureVector<byte> buffer; + secure_vector<u64bit> H; + secure_vector<u64bit> T; + secure_vector<byte> buffer; size_t buf_pos; }; diff --git a/src/hash/tiger/tiger.cpp b/src/hash/tiger/tiger.cpp index 6f40f84c8..57250d6f5 100644 --- a/src/hash/tiger/tiger.cpp +++ b/src/hash/tiger/tiger.cpp @@ -17,7 +17,7 @@ namespace { /* * Tiger Mixing Function */ -inline void mix(MemoryRegion<u64bit>& X) +inline void mix(secure_vector<u64bit>& X) { X[0] -= X[7] ^ 0xA5A5A5A5A5A5A5A5; X[1] ^= X[0]; @@ -83,7 +83,7 @@ void Tiger::copy_out(byte output[]) * Tiger Pass */ void Tiger::pass(u64bit& A, u64bit& B, u64bit& C, - const MemoryRegion<u64bit>& X, + const secure_vector<u64bit>& X, byte mul) { C ^= X[0]; @@ -160,7 +160,8 @@ void Tiger::clear() */ std::string Tiger::name() const { - return "Tiger(" + to_string(output_length()) + "," + to_string(passes) + ")"; + return "Tiger(" + std::to_string(output_length()) + "," + + std::to_string(passes) + ")"; } /* @@ -175,11 +176,11 @@ Tiger::Tiger(size_t hash_len, size_t passes) : { if(output_length() != 16 && output_length() != 20 && output_length() != 24) throw Invalid_Argument("Tiger: Illegal hash output size: " + - to_string(output_length())); + std::to_string(output_length())); if(passes < 3) throw Invalid_Argument("Tiger: Invalid number of passes: " - + to_string(passes)); + + std::to_string(passes)); clear(); } diff --git a/src/hash/tiger/tiger.h b/src/hash/tiger/tiger.h index 09c9947fb..70c70958b 100644 --- a/src/hash/tiger/tiger.h +++ b/src/hash/tiger/tiger.h @@ -38,7 +38,7 @@ class BOTAN_DLL Tiger : public MDx_HashFunction void copy_out(byte[]); static void pass(u64bit& A, u64bit& B, u64bit& C, - const MemoryRegion<u64bit>& M, + const secure_vector<u64bit>& M, byte mul); static const u64bit SBOX1[256]; @@ -46,7 +46,7 @@ class BOTAN_DLL Tiger : public MDx_HashFunction static const u64bit SBOX3[256]; static const u64bit SBOX4[256]; - SecureVector<u64bit> X, digest; + secure_vector<u64bit> X, digest; const size_t hash_len, passes; }; diff --git a/src/hash/whirlpool/whrlpool.h b/src/hash/whirlpool/whrlpool.h index ab7a78bc8..d4ad805e1 100644 --- a/src/hash/whirlpool/whrlpool.h +++ b/src/hash/whirlpool/whrlpool.h @@ -39,7 +39,7 @@ class BOTAN_DLL Whirlpool : public MDx_HashFunction static const u64bit C6[256]; static const u64bit C7[256]; - SecureVector<u64bit> M, digest; + secure_vector<u64bit> M, digest; }; } diff --git a/src/kdf/kdf.cpp b/src/kdf/kdf.cpp index 6281f753c..88cbd5b99 100644 --- a/src/kdf/kdf.cpp +++ b/src/kdf/kdf.cpp @@ -12,8 +12,8 @@ namespace Botan { /* * Derive a key */ -SecureVector<byte> KDF::derive_key(size_t key_len, - const MemoryRegion<byte>& secret, +secure_vector<byte> KDF::derive_key(size_t key_len, + const secure_vector<byte>& secret, const std::string& salt) const { return derive_key(key_len, &secret[0], secret.size(), @@ -24,8 +24,8 @@ SecureVector<byte> KDF::derive_key(size_t key_len, /* * Derive a key */ -SecureVector<byte> KDF::derive_key(size_t key_len, - const MemoryRegion<byte>& secret, +secure_vector<byte> KDF::derive_key(size_t key_len, + const secure_vector<byte>& secret, const byte salt[], size_t salt_len) const { return derive_key(key_len, &secret[0], secret.size(), @@ -35,18 +35,7 @@ SecureVector<byte> KDF::derive_key(size_t key_len, /* * Derive a key */ -SecureVector<byte> KDF::derive_key(size_t key_len, - const MemoryRegion<byte>& secret, - const MemoryRegion<byte>& salt) const - { - return derive_key(key_len, &secret[0], secret.size(), - &salt[0], salt.size()); - } - -/* -* Derive a key -*/ -SecureVector<byte> KDF::derive_key(size_t key_len, +secure_vector<byte> KDF::derive_key(size_t key_len, const byte secret[], size_t secret_len, const std::string& salt) const { @@ -58,7 +47,7 @@ SecureVector<byte> KDF::derive_key(size_t key_len, /* * Derive a key */ -SecureVector<byte> KDF::derive_key(size_t key_len, +secure_vector<byte> KDF::derive_key(size_t key_len, const byte secret[], size_t secret_len, const byte salt[], size_t salt_len) const { diff --git a/src/kdf/kdf.h b/src/kdf/kdf.h index 3ec912cfe..e158df0ae 100644 --- a/src/kdf/kdf.h +++ b/src/kdf/kdf.h @@ -26,8 +26,8 @@ class BOTAN_DLL KDF : public Algorithm * @param secret the secret input * @param salt a diversifier */ - SecureVector<byte> derive_key(size_t key_len, - const MemoryRegion<byte>& secret, + secure_vector<byte> derive_key(size_t key_len, + const secure_vector<byte>& secret, const std::string& salt = "") const; /** @@ -36,9 +36,15 @@ class BOTAN_DLL KDF : public Algorithm * @param secret the secret input * @param salt a diversifier */ - SecureVector<byte> derive_key(size_t key_len, - const MemoryRegion<byte>& secret, - const MemoryRegion<byte>& salt) const; + template<typename Alloc, typename Alloc2> + secure_vector<byte> derive_key(size_t key_len, + const std::vector<byte, Alloc>& secret, + const std::vector<byte, Alloc2>& salt) const + { + return derive_key(key_len, &secret[0], secret.size(), + &salt[0], salt.size()); + + } /** * Derive a key @@ -47,8 +53,8 @@ class BOTAN_DLL KDF : public Algorithm * @param salt a diversifier * @param salt_len size of salt in bytes */ - SecureVector<byte> derive_key(size_t key_len, - const MemoryRegion<byte>& secret, + secure_vector<byte> derive_key(size_t key_len, + const secure_vector<byte>& secret, const byte salt[], size_t salt_len) const; @@ -59,7 +65,7 @@ class BOTAN_DLL KDF : public Algorithm * @param secret_len size of secret in bytes * @param salt a diversifier */ - SecureVector<byte> derive_key(size_t key_len, + secure_vector<byte> derive_key(size_t key_len, const byte secret[], size_t secret_len, const std::string& salt = "") const; @@ -72,7 +78,7 @@ class BOTAN_DLL KDF : public Algorithm * @param salt a diversifier * @param salt_len size of salt in bytes */ - SecureVector<byte> derive_key(size_t key_len, + secure_vector<byte> derive_key(size_t key_len, const byte secret[], size_t secret_len, const byte salt[], @@ -82,7 +88,7 @@ class BOTAN_DLL KDF : public Algorithm virtual KDF* clone() const = 0; private: - virtual SecureVector<byte> + virtual secure_vector<byte> derive(size_t key_len, const byte secret[], size_t secret_len, const byte salt[], size_t salt_len) const = 0; diff --git a/src/kdf/kdf1/kdf1.cpp b/src/kdf/kdf1/kdf1.cpp index f3e4e208f..f00f71010 100644 --- a/src/kdf/kdf1/kdf1.cpp +++ b/src/kdf/kdf1/kdf1.cpp @@ -12,7 +12,7 @@ namespace Botan { /* * KDF1 Key Derivation Mechanism */ -SecureVector<byte> KDF1::derive(size_t, +secure_vector<byte> KDF1::derive(size_t, const byte secret[], size_t secret_len, const byte P[], size_t P_len) const { diff --git a/src/kdf/kdf1/kdf1.h b/src/kdf/kdf1/kdf1.h index f627235be..6a14d2995 100644 --- a/src/kdf/kdf1/kdf1.h +++ b/src/kdf/kdf1/kdf1.h @@ -19,7 +19,7 @@ namespace Botan { class BOTAN_DLL KDF1 : public KDF { public: - SecureVector<byte> derive(size_t, + secure_vector<byte> derive(size_t, const byte secret[], size_t secret_len, const byte P[], size_t P_len) const; diff --git a/src/kdf/kdf2/kdf2.cpp b/src/kdf/kdf2/kdf2.cpp index 51b9e41ea..39a929b58 100644 --- a/src/kdf/kdf2/kdf2.cpp +++ b/src/kdf/kdf2/kdf2.cpp @@ -12,11 +12,11 @@ namespace Botan { /* * KDF2 Key Derivation Mechanism */ -SecureVector<byte> KDF2::derive(size_t out_len, +secure_vector<byte> KDF2::derive(size_t out_len, const byte secret[], size_t secret_len, const byte P[], size_t P_len) const { - SecureVector<byte> output; + secure_vector<byte> output; u32bit counter = 1; while(out_len && counter) @@ -25,7 +25,7 @@ SecureVector<byte> KDF2::derive(size_t out_len, hash->update_be(counter); hash->update(P, P_len); - SecureVector<byte> hash_result = hash->final(); + secure_vector<byte> hash_result = hash->final(); size_t added = std::min(hash_result.size(), out_len); output += std::make_pair(&hash_result[0], added); diff --git a/src/kdf/kdf2/kdf2.h b/src/kdf/kdf2/kdf2.h index e85fe6d1c..e33939df9 100644 --- a/src/kdf/kdf2/kdf2.h +++ b/src/kdf/kdf2/kdf2.h @@ -19,7 +19,7 @@ namespace Botan { class BOTAN_DLL KDF2 : public KDF { public: - SecureVector<byte> derive(size_t, const byte[], size_t, + secure_vector<byte> derive(size_t, const byte[], size_t, const byte[], size_t) const; std::string name() const { return "KDF2(" + hash->name() + ")"; } diff --git a/src/kdf/mgf1/mgf1.cpp b/src/kdf/mgf1/mgf1.cpp index 7d949c2b8..e0433a02f 100644 --- a/src/kdf/mgf1/mgf1.cpp +++ b/src/kdf/mgf1/mgf1.cpp @@ -25,7 +25,7 @@ void MGF1::mask(const byte in[], size_t in_len, byte out[], { hash->update(in, in_len); hash->update_be(counter); - SecureVector<byte> buffer = hash->final(); + secure_vector<byte> buffer = hash->final(); size_t xored = std::min<size_t>(buffer.size(), out_len); xor_buf(out, &buffer[0], xored); diff --git a/src/kdf/prf_ssl3/prf_ssl3.cpp b/src/kdf/prf_ssl3/prf_ssl3.cpp index 72cf023e2..8475bf40a 100644 --- a/src/kdf/prf_ssl3/prf_ssl3.cpp +++ b/src/kdf/prf_ssl3/prf_ssl3.cpp @@ -33,11 +33,11 @@ OctetString next_hash(size_t where, size_t want, sha1.update(static_cast<byte>(ASCII_A_CHAR + where)); sha1.update(secret, secret_len); sha1.update(seed, seed_len); - SecureVector<byte> sha1_hash = sha1.final(); + secure_vector<byte> sha1_hash = sha1.final(); md5.update(secret, secret_len); md5.update(sha1_hash); - SecureVector<byte> md5_hash = md5.final(); + secure_vector<byte> md5_hash = md5.final(); return OctetString(&md5_hash[0], want); } @@ -47,7 +47,7 @@ OctetString next_hash(size_t where, size_t want, /* * SSL3 PRF */ -SecureVector<byte> SSL3_PRF::derive(size_t key_len, +secure_vector<byte> SSL3_PRF::derive(size_t key_len, const byte secret[], size_t secret_len, const byte seed[], size_t seed_len) const { diff --git a/src/kdf/prf_ssl3/prf_ssl3.h b/src/kdf/prf_ssl3/prf_ssl3.h index b07454be2..bae8badb8 100644 --- a/src/kdf/prf_ssl3/prf_ssl3.h +++ b/src/kdf/prf_ssl3/prf_ssl3.h @@ -18,7 +18,7 @@ namespace Botan { class BOTAN_DLL SSL3_PRF : public KDF { public: - SecureVector<byte> derive(size_t, const byte[], size_t, + secure_vector<byte> derive(size_t, const byte[], size_t, const byte[], size_t) const; std::string name() const { return "SSL3-PRF"; } diff --git a/src/kdf/prf_tls/info.txt b/src/kdf/prf_tls/info.txt index 9531a6a83..113c92251 100644 --- a/src/kdf/prf_tls/info.txt +++ b/src/kdf/prf_tls/info.txt @@ -1,4 +1,5 @@ define TLS_V10_PRF +define TLS_V12_PRF <requires> hmac diff --git a/src/kdf/prf_tls/prf_tls.cpp b/src/kdf/prf_tls/prf_tls.cpp index 2b57cdd25..006b418c9 100644 --- a/src/kdf/prf_tls/prf_tls.cpp +++ b/src/kdf/prf_tls/prf_tls.cpp @@ -18,14 +18,23 @@ namespace { /* * TLS PRF P_hash function */ -void P_hash(MemoryRegion<byte>& output, +void P_hash(secure_vector<byte>& output, MessageAuthenticationCode* mac, const byte secret[], size_t secret_len, const byte seed[], size_t seed_len) { - mac->set_key(secret, secret_len); + try + { + mac->set_key(secret, secret_len); + } + catch(Invalid_Key_Length) + { + throw Internal_Error("The premaster secret of " + + std::to_string(secret_len) + + " bytes is too long for the PRF"); + } - SecureVector<byte> A(seed, seed_len); + secure_vector<byte> A(seed, seed + seed_len); size_t offset = 0; @@ -38,7 +47,7 @@ void P_hash(MemoryRegion<byte>& output, mac->update(A); mac->update(seed, seed_len); - SecureVector<byte> block = mac->final(); + secure_vector<byte> block = mac->final(); xor_buf(&output[offset], &block[0], this_block_len); offset += this_block_len; @@ -65,11 +74,11 @@ TLS_PRF::~TLS_PRF() /* * TLS PRF */ -SecureVector<byte> TLS_PRF::derive(size_t key_len, +secure_vector<byte> TLS_PRF::derive(size_t key_len, const byte secret[], size_t secret_len, const byte seed[], size_t seed_len) const { - SecureVector<byte> output(key_len); + secure_vector<byte> output(key_len); size_t S1_len = (secret_len + 1) / 2, S2_len = (secret_len + 1) / 2; @@ -94,11 +103,11 @@ TLS_12_PRF::~TLS_12_PRF() delete hmac; } -SecureVector<byte> TLS_12_PRF::derive(size_t key_len, +secure_vector<byte> TLS_12_PRF::derive(size_t key_len, const byte secret[], size_t secret_len, const byte seed[], size_t seed_len) const { - SecureVector<byte> output(key_len); + secure_vector<byte> output(key_len); P_hash(output, hmac, secret, secret_len, seed, seed_len); diff --git a/src/kdf/prf_tls/prf_tls.h b/src/kdf/prf_tls/prf_tls.h index 5237f17c0..fce11eae0 100644 --- a/src/kdf/prf_tls/prf_tls.h +++ b/src/kdf/prf_tls/prf_tls.h @@ -20,7 +20,7 @@ namespace Botan { class BOTAN_DLL TLS_PRF : public KDF { public: - SecureVector<byte> derive(size_t key_len, + secure_vector<byte> derive(size_t key_len, const byte secret[], size_t secret_len, const byte seed[], size_t seed_len) const; @@ -40,7 +40,7 @@ class BOTAN_DLL TLS_PRF : public KDF class BOTAN_DLL TLS_12_PRF : public KDF { public: - SecureVector<byte> derive(size_t key_len, + secure_vector<byte> derive(size_t key_len, const byte secret[], size_t secret_len, const byte seed[], size_t seed_len) const; diff --git a/src/kdf/prf_x942/prf_x942.cpp b/src/kdf/prf_x942/prf_x942.cpp index fc31effe4..149be163f 100644 --- a/src/kdf/prf_x942/prf_x942.cpp +++ b/src/kdf/prf_x942/prf_x942.cpp @@ -20,11 +20,11 @@ namespace { /* * Encode an integer as an OCTET STRING */ -MemoryVector<byte> encode_x942_int(u32bit n) +std::vector<byte> encode_x942_int(u32bit n) { byte n_buf[4] = { 0 }; store_be(n, n_buf); - return DER_Encoder().encode(n_buf, 4, OCTET_STRING).get_contents(); + return DER_Encoder().encode(n_buf, 4, OCTET_STRING).get_contents_unlocked(); } } @@ -32,14 +32,14 @@ MemoryVector<byte> encode_x942_int(u32bit n) /* * X9.42 PRF */ -SecureVector<byte> X942_PRF::derive(size_t key_len, +secure_vector<byte> X942_PRF::derive(size_t key_len, const byte secret[], size_t secret_len, const byte salt[], size_t salt_len) const { SHA_160 hash; const OID kek_algo(key_wrap_oid); - SecureVector<byte> key; + secure_vector<byte> key; u32bit counter = 1; while(key.size() != key_len && counter) @@ -68,7 +68,7 @@ SecureVector<byte> X942_PRF::derive(size_t key_len, .end_cons().get_contents() ); - SecureVector<byte> digest = hash.final(); + secure_vector<byte> digest = hash.final(); const size_t needed = std::min(digest.size(), key_len - key.size()); key += std::make_pair(&digest[0], needed); diff --git a/src/kdf/prf_x942/prf_x942.h b/src/kdf/prf_x942/prf_x942.h index e6093eda6..f86b1bdd5 100644 --- a/src/kdf/prf_x942/prf_x942.h +++ b/src/kdf/prf_x942/prf_x942.h @@ -18,7 +18,7 @@ namespace Botan { class BOTAN_DLL X942_PRF : public KDF { public: - SecureVector<byte> derive(size_t, const byte[], size_t, + secure_vector<byte> derive(size_t, const byte[], size_t, const byte[], size_t) const; std::string name() const { return "X942_PRF(" + key_wrap_oid + ")"; } diff --git a/src/libstate/get_enc.cpp b/src/libstate/get_enc.cpp index 6a87268e8..00297464b 100644 --- a/src/libstate/get_enc.cpp +++ b/src/libstate/get_enc.cpp @@ -96,7 +96,11 @@ EMSA* get_emsa(const std::string& algo_spec) #if defined(BOTAN_HAS_EMSA1) if(request.algo_name() == "EMSA1" && request.arg_count() == 1) + { + if(request.arg(0) == "Raw") + return new EMSA_Raw; return new EMSA1(af.make_hash_function(request.arg(0))); + } #endif #if defined(BOTAN_HAS_EMSA1_BSI) @@ -147,7 +151,7 @@ EME* get_eme(const std::string& algo_spec) Algorithm_Factory& af = global_state().algorithm_factory(); if(request.algo_name() == "Raw") - return 0; // No padding + return nullptr; // No padding #if defined(BOTAN_HAS_EME_PKCS1v15) if(request.algo_name() == "PKCS1v15" && request.arg_count() == 0) @@ -178,7 +182,7 @@ KDF* get_kdf(const std::string& algo_spec) Algorithm_Factory& af = global_state().algorithm_factory(); if(request.algo_name() == "Raw") - return 0; // No KDF + return nullptr; // No KDF #if defined(BOTAN_HAS_KDF1) if(request.algo_name() == "KDF1" && request.arg_count() == 1) @@ -195,14 +199,24 @@ KDF* get_kdf(const std::string& algo_spec) return new X942_PRF(request.arg(0)); // OID #endif +#if defined(BOTAN_HAS_SSL_V3_PRF) + if(request.algo_name() == "SSL3-PRF" && request.arg_count() == 0) + return new SSL3_PRF; +#endif + #if defined(BOTAN_HAS_TLS_V10_PRF) if(request.algo_name() == "TLS-PRF" && request.arg_count() == 0) return new TLS_PRF; #endif -#if defined(BOTAN_HAS_SSL_V3_PRF) - if(request.algo_name() == "SSL3-PRF" && request.arg_count() == 0) - return new SSL3_PRF; +#if defined(BOTAN_HAS_TLS_V10_PRF) + if(request.algo_name() == "TLS-PRF" && request.arg_count() == 0) + return new TLS_PRF; +#endif + +#if defined(BOTAN_HAS_TLS_V12_PRF) + if(request.algo_name() == "TLS-12-PRF" && request.arg_count() == 1) + return new TLS_12_PRF(af.make_mac("HMAC(" + request.arg(0) + ")")); #endif throw Algorithm_Not_Found(algo_spec); diff --git a/src/libstate/global_rng.cpp b/src/libstate/global_rng.cpp index e9ea530ac..65da38f5f 100644 --- a/src/libstate/global_rng.cpp +++ b/src/libstate/global_rng.cpp @@ -6,7 +6,6 @@ */ #include <botan/libstate.h> -#include <botan/internal/mutex.h> #if defined(BOTAN_HAS_RANDPOOL) #include <botan/randpool.h> @@ -24,6 +23,10 @@ #include <botan/internal/hres_timer.h> #endif +#if defined(BOTAN_HAS_ENTROPY_SRC_RDRAND) + #include <botan/internal/rdrand.h> +#endif + #if defined(BOTAN_HAS_ENTROPY_SRC_DEV_RANDOM) #include <botan/internal/dev_random.h> #endif @@ -65,6 +68,10 @@ void add_entropy_sources(RandomNumberGenerator* rng) rng->add_entropy_source(new High_Resolution_Timestamp); #endif +#if defined(BOTAN_HAS_ENTROPY_SRC_RDRAND) + rng->add_entropy_source(new Intel_Rdrand); +#endif + #if defined(BOTAN_HAS_ENTROPY_SRC_DEV_RANDOM) rng->add_entropy_source( new Device_EntropySource( @@ -107,62 +114,62 @@ class Serialized_PRNG : public RandomNumberGenerator public: void randomize(byte out[], size_t len) { - Mutex_Holder lock(mutex); + std::lock_guard<std::mutex> lock(mutex); rng->randomize(out, len); } bool is_seeded() const { - Mutex_Holder lock(mutex); + std::lock_guard<std::mutex> lock(mutex); return rng->is_seeded(); } void clear() { - Mutex_Holder lock(mutex); + std::lock_guard<std::mutex> lock(mutex); rng->clear(); } std::string name() const { - Mutex_Holder lock(mutex); + std::lock_guard<std::mutex> lock(mutex); return rng->name(); } void reseed(size_t poll_bits) { - Mutex_Holder lock(mutex); + std::lock_guard<std::mutex> lock(mutex); rng->reseed(poll_bits); } void add_entropy_source(EntropySource* es) { - Mutex_Holder lock(mutex); + std::lock_guard<std::mutex> lock(mutex); rng->add_entropy_source(es); } void add_entropy(const byte in[], size_t len) { - Mutex_Holder lock(mutex); + std::lock_guard<std::mutex> lock(mutex); rng->add_entropy(in, len); } // We do not own the mutex; Library_State does - Serialized_PRNG(RandomNumberGenerator* r, Mutex* m) : + Serialized_PRNG(RandomNumberGenerator* r, std::mutex& m) : mutex(m), rng(r) {} ~Serialized_PRNG() { delete rng; } private: - Mutex* mutex; + std::mutex& mutex; RandomNumberGenerator* rng; }; } RandomNumberGenerator* Library_State::make_global_rng(Algorithm_Factory& af, - Mutex* mutex) + std::mutex& mutex) { - RandomNumberGenerator* rng = 0; + RandomNumberGenerator* rng = nullptr; #if defined(BOTAN_HAS_HMAC_RNG) diff --git a/src/libstate/global_state.cpp b/src/libstate/global_state.cpp index 43c935ca3..6a846d9b0 100644 --- a/src/libstate/global_state.cpp +++ b/src/libstate/global_state.cpp @@ -22,7 +22,7 @@ namespace Global_State_Management { */ namespace { -Library_State* global_lib_state = 0; +Library_State* global_lib_state = nullptr; } @@ -37,7 +37,7 @@ Library_State& global_state() if(!global_lib_state) { global_lib_state = new Library_State; - global_lib_state->initialize(true); + global_lib_state->initialize(); } return (*global_lib_state); @@ -83,7 +83,7 @@ Library_State* swap_global_state(Library_State* new_state) */ bool global_state_exists() { - return (global_lib_state != 0); + return (global_lib_state != nullptr); } } diff --git a/src/libstate/info.txt b/src/libstate/info.txt index d48ad70d5..0e523e601 100644 --- a/src/libstate/info.txt +++ b/src/libstate/info.txt @@ -38,8 +38,6 @@ hmac_rng kdf mac mode_pad -mutex -noop_mutex pbkdf pk_pad pubkey @@ -47,5 +45,4 @@ rng sha2_32 sha2_64 stream -system_alloc </requires> diff --git a/src/libstate/init.cpp b/src/libstate/init.cpp index 7cdc615bd..2d724f366 100644 --- a/src/libstate/init.cpp +++ b/src/libstate/init.cpp @@ -1,12 +1,11 @@ /* * Default Initialization Function -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ #include <botan/init.h> -#include <botan/parsing.h> #include <botan/libstate.h> #include <botan/global_state.h> @@ -15,48 +14,20 @@ namespace Botan { /* * Library Initialization */ -void LibraryInitializer::initialize(const std::string& arg_string) +void LibraryInitializer::initialize(const std::string&) { - bool thread_safe = false; - - const std::vector<std::string> arg_list = split_on(arg_string, ' '); - for(size_t i = 0; i != arg_list.size(); ++i) - { - if(arg_list[i].size() == 0) - continue; - - std::string name, value; - - if(arg_list[i].find('=') == std::string::npos) - { - name = arg_list[i]; - value = "true"; - } - else - { - std::vector<std::string> name_and_value = split_on(arg_list[i], '='); - name = name_and_value[0]; - value = name_and_value[1]; - } - - bool is_on = - (value == "1" || value == "true" || value == "yes" || value == "on"); - - if(name == "thread_safe") - thread_safe = is_on; - } try { /* This two stage initialization process is because Library_State's constructor will implicitly refer to global state through the - allocators and so for, so global_state() has to be a valid + allocators and so forth, so global_state() has to be a valid reference before initialize() can be called. Yeah, gross. */ Global_State_Management::set_global_state(new Library_State); - global_state().initialize(thread_safe); + global_state().initialize(); } catch(...) { @@ -70,7 +41,7 @@ void LibraryInitializer::initialize(const std::string& arg_string) */ void LibraryInitializer::deinitialize() { - Global_State_Management::set_global_state(0); + Global_State_Management::set_global_state(nullptr); } } diff --git a/src/libstate/libstate.cpp b/src/libstate/libstate.cpp index 076b55fcf..78ff9135c 100644 --- a/src/libstate/libstate.cpp +++ b/src/libstate/libstate.cpp @@ -9,30 +9,14 @@ #include <botan/charset.h> #include <botan/engine.h> #include <botan/cpuid.h> -#include <botan/internal/defalloc.h> #include <botan/internal/core_engine.h> -#include <botan/internal/mutex.h> -#include <botan/internal/mux_noop.h> #include <botan/internal/stl_util.h> -#include <botan/internal/mlock.h> #include <algorithm> #if defined(BOTAN_HAS_SELFTESTS) #include <botan/selftest.h> #endif -#if defined(BOTAN_HAS_MUTEX_PTHREAD) - #include <botan/internal/mux_pthr.h> -#elif defined(BOTAN_HAS_MUTEX_WIN32) - #include <botan/internal/mux_win32.h> -#elif defined(BOTAN_HAS_MUTEX_QT) - #include <botan/internal/mux_qt.h> -#endif - -#if defined(BOTAN_HAS_ALLOC_MMAP) - #include <botan/internal/mmap_mem.h> -#endif - #if defined(BOTAN_HAS_ENGINE_ASSEMBLER) #include <botan/internal/asm_engine.h> #endif @@ -56,67 +40,12 @@ namespace Botan { /* -* Get a new mutex object -*/ -Mutex* Library_State::get_mutex() const - { - return mutex_factory->make(); - } - -/* -* Get an allocator by its name -*/ -Allocator* Library_State::get_allocator(const std::string& type) const - { - Mutex_Holder lock(allocator_lock); - - if(type != "") - return search_map<std::string, Allocator*>(alloc_factory, type, 0); - - if(!cached_default_allocator) - { - cached_default_allocator = - search_map<std::string, Allocator*>(alloc_factory, - default_allocator_name, 0); - } - - return cached_default_allocator; - } - -/* -* Create a new name to object mapping -*/ -void Library_State::add_allocator(Allocator* allocator) - { - Mutex_Holder lock(allocator_lock); - - allocator->init(); - - allocators.push_back(allocator); - alloc_factory[allocator->type()] = allocator; - } - -/* -* Set the default allocator type -*/ -void Library_State::set_default_allocator(const std::string& type) - { - Mutex_Holder lock(allocator_lock); - - if(type == "") - return; - - default_allocator_name = type; - cached_default_allocator = 0; - } - -/* * Get a configuration value */ std::string Library_State::get(const std::string& section, - const std::string& key) const + const std::string& key) { - Mutex_Holder lock(config_lock); + std::lock_guard<std::mutex> lock(config_lock); return search_map<std::string, std::string>(config, section + "/" + key, ""); @@ -126,9 +55,9 @@ std::string Library_State::get(const std::string& section, * See if a particular option has been set */ bool Library_State::is_set(const std::string& section, - const std::string& key) const + const std::string& key) { - Mutex_Holder lock(config_lock); + std::lock_guard<std::mutex> lock(config_lock); return config.count(section + "/" + key) != 0; } @@ -139,12 +68,11 @@ bool Library_State::is_set(const std::string& section, void Library_State::set(const std::string& section, const std::string& key, const std::string& value, bool overwrite) { - Mutex_Holder lock(config_lock); + std::lock_guard<std::mutex> lock(config_lock); std::string full_key = section + "/" + key; - std::map<std::string, std::string>::const_iterator i = - config.find(full_key); + auto i = config.find(full_key); if(overwrite || i == config.end() || i->second == "") config[full_key] = value; @@ -161,7 +89,7 @@ void Library_State::add_alias(const std::string& key, const std::string& value) /* * Dereference an alias to a fixed name */ -std::string Library_State::deref_alias(const std::string& key) const +std::string Library_State::deref_alias(const std::string& key) { std::string result = key; while(is_set("alias", result)) @@ -184,7 +112,7 @@ Algorithm_Factory& Library_State::algorithm_factory() const */ RandomNumberGenerator& Library_State::global_rng() { - Mutex_Holder lock(global_rng_lock); + std::lock_guard<std::mutex> lock(global_rng_lock); if(!global_rng_ptr) global_rng_ptr = make_global_rng(algorithm_factory(), @@ -196,46 +124,16 @@ RandomNumberGenerator& Library_State::global_rng() /* * Load a set of modules */ -void Library_State::initialize(bool thread_safe) +void Library_State::initialize() { CPUID::initialize(); - if(mutex_factory) + if(m_algorithm_factory) throw Invalid_State("Library_State has already been initialized"); - if(!thread_safe) - { - mutex_factory = new Noop_Mutex_Factory; - } - else - { -#if defined(BOTAN_HAS_MUTEX_PTHREAD) - mutex_factory = new Pthread_Mutex_Factory; -#elif defined(BOTAN_HAS_MUTEX_WIN32) - mutex_factory = new Win32_Mutex_Factory; -#elif defined(BOTAN_HAS_MUTEX_QT) - mutex_factory Qt_Mutex_Factory; -#else - throw Invalid_State("Could not find a thread-safe mutex object to use"); -#endif - } - - allocator_lock = get_mutex(); - config_lock = get_mutex(); - global_rng_lock = get_mutex(); - - default_allocator_name = has_mlock() ? "locking" : "malloc"; - - add_allocator(new Malloc_Allocator); - add_allocator(new Locking_Allocator(get_mutex())); - -#if defined(BOTAN_HAS_ALLOC_MMAP) - add_allocator(new MemoryMapping_Allocator(get_mutex())); -#endif - load_default_config(); - m_algorithm_factory = new Algorithm_Factory(*mutex_factory); + m_algorithm_factory = new Algorithm_Factory(); #if defined(BOTAN_HAS_ENGINE_GNU_MP) algorithm_factory().add_engine(new GMP_Engine); @@ -269,13 +167,9 @@ void Library_State::initialize(bool thread_safe) */ Library_State::Library_State() { - mutex_factory = 0; - allocator_lock = config_lock = 0; - cached_default_allocator = 0; - m_algorithm_factory = 0; + m_algorithm_factory = nullptr; - global_rng_lock = 0; - global_rng_ptr = 0; + global_rng_ptr = nullptr; } /* @@ -284,20 +178,10 @@ Library_State::Library_State() Library_State::~Library_State() { delete m_algorithm_factory; - delete global_rng_ptr; - - cached_default_allocator = 0; + m_algorithm_factory = nullptr; - for(size_t i = 0; i != allocators.size(); ++i) - { - allocators[i]->destroy(); - delete allocators[i]; - } - - delete global_rng_lock; - delete allocator_lock; - delete mutex_factory; - delete config_lock; + delete global_rng_ptr; + global_rng_ptr = nullptr; } } diff --git a/src/libstate/libstate.h b/src/libstate/libstate.h index aa957c8c9..b260a5bb9 100644 --- a/src/libstate/libstate.h +++ b/src/libstate/libstate.h @@ -9,20 +9,18 @@ #define BOTAN_LIB_STATE_H__ #include <botan/global_state.h> -#include <botan/allocate.h> #include <botan/algo_factory.h> #include <botan/rng.h> +#include <mutex> #include <string> #include <vector> #include <map> namespace Botan { -class Mutex; - -/** -* Global state container aka the buritto at the center of it all +/* +* Global State Container Base */ class BOTAN_DLL Library_State { @@ -30,10 +28,10 @@ class BOTAN_DLL Library_State Library_State(); ~Library_State(); - /** - * @param thread_safe should a mutex be used for serialization - */ - void initialize(bool thread_safe); + Library_State(const Library_State&) = delete; + Library_State& operator=(const Library_State&) = delete; + + void initialize(); /** * @return global Algorithm_Factory @@ -46,18 +44,6 @@ class BOTAN_DLL Library_State RandomNumberGenerator& global_rng(); /** - * @param name the name of the allocator - * @return allocator matching this name, or NULL - */ - Allocator* get_allocator(const std::string& name = "") const; - - /** - * Add a new allocator to the list of available ones - * @param alloc the allocator to add - */ - void add_allocator(Allocator* alloc); - - /** * Set the default allocator * @param name the name of the allocator to use as the default */ @@ -70,7 +56,7 @@ class BOTAN_DLL Library_State * @result the value of the parameter */ std::string get(const std::string& section, - const std::string& key) const; + const std::string& key); /** * Check whether a certain parameter is set or not. @@ -80,7 +66,7 @@ class BOTAN_DLL Library_State * false otherwise */ bool is_set(const std::string& section, - const std::string& key) const; + const std::string& key); /** * Set a configuration parameter. @@ -109,35 +95,19 @@ class BOTAN_DLL Library_State * @param alias the alias to resolve. * @return what the alias stands for */ - std::string deref_alias(const std::string& alias) const; - - /** - * @return newly created Mutex (free with delete) - */ - Mutex* get_mutex() const; + std::string deref_alias(const std::string&); private: static RandomNumberGenerator* make_global_rng(Algorithm_Factory& af, - Mutex* mutex); + std::mutex& mutex); void load_default_config(); - Library_State(const Library_State&) {} - Library_State& operator=(const Library_State&) { return (*this); } - - class Mutex_Factory* mutex_factory; - - Mutex* global_rng_lock; + std::mutex global_rng_lock; RandomNumberGenerator* global_rng_ptr; - Mutex* config_lock; + std::mutex config_lock; std::map<std::string, std::string> config; - Mutex* allocator_lock; - std::string default_allocator_name; - std::map<std::string, Allocator*> alloc_factory; - mutable Allocator* cached_default_allocator; - std::vector<Allocator*> allocators; - Algorithm_Factory* m_algorithm_factory; }; diff --git a/src/libstate/lookup.h b/src/libstate/lookup.h index e10c195b8..96364e1d9 100644 --- a/src/libstate/lookup.h +++ b/src/libstate/lookup.h @@ -235,7 +235,7 @@ BOTAN_DLL bool have_algorithm(const std::string& algo_spec); inline bool have_block_cipher(const std::string& algo_spec) { Algorithm_Factory& af = global_state().algorithm_factory(); - return (af.prototype_block_cipher(algo_spec) != 0); + return (af.prototype_block_cipher(algo_spec) != nullptr); } /** @@ -248,7 +248,7 @@ inline bool have_block_cipher(const std::string& algo_spec) inline bool have_stream_cipher(const std::string& algo_spec) { Algorithm_Factory& af = global_state().algorithm_factory(); - return (af.prototype_stream_cipher(algo_spec) != 0); + return (af.prototype_stream_cipher(algo_spec) != nullptr); } /** @@ -261,7 +261,7 @@ inline bool have_stream_cipher(const std::string& algo_spec) inline bool have_hash(const std::string& algo_spec) { Algorithm_Factory& af = global_state().algorithm_factory(); - return (af.prototype_hash_function(algo_spec) != 0); + return (af.prototype_hash_function(algo_spec) != nullptr); } /** @@ -274,7 +274,7 @@ inline bool have_hash(const std::string& algo_spec) inline bool have_mac(const std::string& algo_spec) { Algorithm_Factory& af = global_state().algorithm_factory(); - return (af.prototype_mac(algo_spec) != 0); + return (af.prototype_mac(algo_spec) != nullptr); } /* diff --git a/src/libstate/policy.cpp b/src/libstate/policy.cpp index 7abea7d4d..b1da22ce8 100644 --- a/src/libstate/policy.cpp +++ b/src/libstate/policy.cpp @@ -337,6 +337,15 @@ void set_default_dl_groups(Library_State& config) "NgRlEbmT//////////8=" "-----END X942 DH PARAMETERS-----"); + config.set("dl", "modp/srp/1536", + "-----BEGIN DH PARAMETERS-----" + "MIHHAoHBAJ3vPK+5OSd6sfEqhheke7vbpR30maxMgL7uqWFLGcxNX09fVW4ny95R" + "xqlL5GB6KRVYkDug0PhDgLZVu5oi6NzfAop87Gfw0IE0sci5eYkUm2CeC+O6tj1H" + "VIOB28Wx/HZOP0tT3Z2hFYv9PiucjPVu3wGVOTSWJ9sv1T0kt8SGZXcuQ31sf4zk" + "QnNK98y3roN8Jkrjqb64f4ov6bi1KS5aAh//XpFHnoznoowkQsbzFRgPk0maI03P" + "duP+0TX5uwIBAg==" + "-----END DH PARAMETERS-----"); + config.set("dl", "modp/ietf/2048", "-----BEGIN X942 DH PARAMETERS-----" "MIICDAKCAQEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb" @@ -388,6 +397,19 @@ void set_default_dl_groups(Library_State& config) "JcFokFSdaWV//////////w==" "-----END X942 DH PARAMETERS-----"); + config.set("dl", "modp/srp/3072", + "-----BEGIN DH PARAMETERS-----" + "MIIBiAKCAYEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb" + "IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft" + "awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT" + "mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh" + "fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq" + "5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM" + "fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq" + "ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqTrS" + "yv//////////AgEF" + "-----END DH PARAMETERS-----"); + config.set("dl", "modp/ietf/4096", "-----BEGIN X942 DH PARAMETERS-----" "MIIEDAKCAgEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb" @@ -414,6 +436,21 @@ void set_default_dl_groups(Library_State& config) "ydp1TEbH7uDDf9vuSFNgR6b6GuSaAxjM//////////8=" "-----END X942 DH PARAMETERS-----"); + config.set("dl", "modp/srp/4096", + "-----BEGIN DH PARAMETERS-----" + "MIICCAKCAgEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb" + "IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft" + "awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT" + "mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh" + "fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq" + "5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM" + "fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq" + "ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqSEI" + "ARpyPBKnh+bXiHGaEL26WyaZwycYavTiPBqUaDS2FQvaJYPpyirUTOjbu8LbBN6O" + "+S6O/BQfvsqmKHxZR05rwF2ZspZPoJDDoiM7oYZRW+ftH2EpcM7i16+4G912IXBI" + "HNAGkSfVsFqpk7TqmI2P3cGG/7fckKbAj030Nck0BjGZ//////////8CAQU=" + "-----END DH PARAMETERS-----"); + config.set("dl", "modp/ietf/6144", "-----BEGIN X942 DH PARAMETERS-----" "MIIGDAKCAwEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb" @@ -451,6 +488,27 @@ void set_default_dl_groups(Library_State& config) "jzbmIBJ//////////wIBAg==" "-----END X942 DH PARAMETERS-----"); + config.set("dl", "modp/srp/6144", + "-----BEGIN DH PARAMETERS-----" + "MIIDCAKCAwEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb" + "IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft" + "awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT" + "mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh" + "fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq" + "5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM" + "fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq" + "ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqSEI" + "ARpyPBKnh+bXiHGaEL26WyaZwycYavTiPBqUaDS2FQvaJYPpyirUTOjbu8LbBN6O" + "+S6O/BQfvsqmKHxZR05rwF2ZspZPoJDDoiM7oYZRW+ftH2EpcM7i16+4G912IXBI" + "HNAGkSfVsFqpk7TqmI2P3cGG/7fckKbAj030Nck0AoSSNsP6tNJ8cCbB1NyyYCZG" + "3sl1HnY9uje9+P+UBq2eUw7l2zgvQTABrrBqU+2QJ9gxF5cnsIZaiRjaPtvrz5sU" + "7UTObLrO1Lsb238UR+bMJUszIFFRK9evQm+49AE3jNK/WYPKAcZLkuzwMuoV0XId" + "A/SC185udP721V5wL0aYDIK1qEAxkAscnlnnyX++x+jzI6l6fjbMiL4PHUW3/1ha" + "xUvUB7IrQVSqzI9tfr9I4dgUzF7SD4A34KeXFe7ym+MoBqHVi7fF2nb1UKo9ih+/" + "8OsZzLGjE9Vc2lbJ7C7yljI4f+jXbjwEaAQ+j2Y/SGDuEr8tWwt0dNbmlPkebcxA" + "JP//////////AgEF" + "-----END DH PARAMETERS-----"); + config.set("dl", "modp/ietf/8192", "-----BEGIN X942 DH PARAMETERS-----" "MIIIDAKCBAEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb" @@ -498,6 +556,32 @@ void set_default_dl_groups(Library_State& config) "034BNyPKrHIjqzv01U8YKHE7K0pv5A+rdEBctziwZMBuzHbp7///////////AgEC" "-----END X942 DH PARAMETERS-----"); + config.set("dl", "modp/srp/8192", + "-----BEGIN DH PARAMETERS-----" + "MIIECAKCBAEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb" + "IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft" + "awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT" + "mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh" + "fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq" + "5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM" + "fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq" + "ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqSEI" + "ARpyPBKnh+bXiHGaEL26WyaZwycYavTiPBqUaDS2FQvaJYPpyirUTOjbu8LbBN6O" + "+S6O/BQfvsqmKHxZR05rwF2ZspZPoJDDoiM7oYZRW+ftH2EpcM7i16+4G912IXBI" + "HNAGkSfVsFqpk7TqmI2P3cGG/7fckKbAj030Nck0AoSSNsP6tNJ8cCbB1NyyYCZG" + "3sl1HnY9uje9+P+UBq2eUw7l2zgvQTABrrBqU+2QJ9gxF5cnsIZaiRjaPtvrz5sU" + "7UTObLrO1Lsb238UR+bMJUszIFFRK9evQm+49AE3jNK/WYPKAcZLkuzwMuoV0XId" + "A/SC185udP721V5wL0aYDIK1qEAxkAscnlnnyX++x+jzI6l6fjbMiL4PHUW3/1ha" + "xUvUB7IrQVSqzI9tfr9I4dgUzF7SD4A34KeXFe7ym+MoBqHVi7fF2nb1UKo9ih+/" + "8OsZzLGjE9Vc2lbJ7C7yljI4f+jXbjwEaAQ+j2Y/SGDuEr8tWwt0dNbmlPkebb4R" + "WXSjkm8S/uXkOHd8tqky34zYvsTQc7kxujvIMraNndMAdB+nv4r8R+0ldvaTa6Qk" + "ZjqrY5xa5PVoNCO0dCvxyXgjjxbL451lLeP9uL78hIrZIiIuBKQDfAcT61eoGiPw" + "xzRz/GRs6jBrS8vIhi+Dhd36nUt/osCH6HloMwPtW906Bis89bOieKZtKhP4P0T4" + "Ld8xDuB0q2o2RZfomaAlXcFk8xzFCEaFHfmrSBld7X6hsdUQvX7nTXP682vDHs+i" + "aDWQRvTrh5+SQAlDi0gcbNeImgAu1e44K8kZDab8Am5HlVjkR1Z36aqeMFDidlaU" + "38gfVuiAuW5xYMmA3Zjt09///////////wIBEw==" + "-----END DH PARAMETERS-----"); + config.set("dl", "dsa/jce/512", "-----BEGIN DSA PARAMETERS-----" "MIGdAkEA/KaCzo4Syrom78z3EQ5SbbB4sF7ey80etKII864WF64B81uRpH5t9jQT" diff --git a/src/mac/cbc_mac/cbc_mac.h b/src/mac/cbc_mac/cbc_mac.h index 5cc8adc67..be25718d9 100644 --- a/src/mac/cbc_mac/cbc_mac.h +++ b/src/mac/cbc_mac/cbc_mac.h @@ -40,7 +40,7 @@ class BOTAN_DLL CBC_MAC : public MessageAuthenticationCode void key_schedule(const byte[], size_t); BlockCipher* e; - SecureVector<byte> state; + secure_vector<byte> state; size_t position; }; diff --git a/src/mac/cmac/cmac.cpp b/src/mac/cmac/cmac.cpp index baf22f4e8..00120cf14 100644 --- a/src/mac/cmac/cmac.cpp +++ b/src/mac/cmac/cmac.cpp @@ -13,12 +13,12 @@ namespace Botan { /* * Perform CMAC's multiplication in GF(2^n) */ -SecureVector<byte> CMAC::poly_double(const MemoryRegion<byte>& in, +secure_vector<byte> CMAC::poly_double(const secure_vector<byte>& in, byte polynomial) { const byte poly_xor = (in[0] & 0x80) ? polynomial : 0; - SecureVector<byte> out = in; + secure_vector<byte> out = in; byte carry = 0; for(size_t i = out.size(); i != 0; --i) @@ -38,7 +38,7 @@ SecureVector<byte> CMAC::poly_double(const MemoryRegion<byte>& in, */ void CMAC::add_data(const byte input[], size_t length) { - buffer.copy(position, input, length); + buffer_insert(buffer, position, input, length); if(position + length > output_length()) { xor_buf(state, buffer, output_length()); @@ -52,7 +52,7 @@ void CMAC::add_data(const byte input[], size_t length) input += output_length(); length -= output_length(); } - buffer.copy(input, length); + copy_mem(&buffer[0], input, length); position = 0; } position += length; diff --git a/src/mac/cmac/cmac.h b/src/mac/cmac/cmac.h index 98634bdb7..b398f2563 100644 --- a/src/mac/cmac/cmac.h +++ b/src/mac/cmac/cmac.h @@ -35,8 +35,8 @@ class BOTAN_DLL CMAC : public MessageAuthenticationCode * @param in the input * @param polynomial the byte value of the polynomial */ - static SecureVector<byte> poly_double(const MemoryRegion<byte>& in, - byte polynomial); + static secure_vector<byte> poly_double(const secure_vector<byte>& in, + byte polynomial); /** * @param cipher the underlying block cipher to use @@ -49,7 +49,7 @@ class BOTAN_DLL CMAC : public MessageAuthenticationCode void key_schedule(const byte[], size_t); BlockCipher* e; - SecureVector<byte> buffer, state, B, P; + secure_vector<byte> buffer, state, B, P; size_t position; byte polynomial; }; diff --git a/src/mac/hmac/hmac.cpp b/src/mac/hmac/hmac.cpp index fc35e26ea..4b4ed2f70 100644 --- a/src/mac/hmac/hmac.cpp +++ b/src/mac/hmac/hmac.cpp @@ -37,12 +37,16 @@ void HMAC::final_result(byte mac[]) void HMAC::key_schedule(const byte key[], size_t length) { hash->clear(); + + i_key.resize(hash->hash_block_size()); + o_key.resize(hash->hash_block_size()); + std::fill(i_key.begin(), i_key.end(), 0x36); std::fill(o_key.begin(), o_key.end(), 0x5C); if(length > hash->hash_block_size()) { - SecureVector<byte> hmac_key = hash->process(key, length); + secure_vector<byte> hmac_key = hash->process(key, length); xor_buf(i_key, hmac_key, hmac_key.size()); xor_buf(o_key, hmac_key, hmac_key.size()); } @@ -61,8 +65,8 @@ void HMAC::key_schedule(const byte key[], size_t length) void HMAC::clear() { hash->clear(); - zeroise(i_key); - zeroise(o_key); + i_key.clear(); + o_key.clear(); } /* @@ -88,9 +92,6 @@ HMAC::HMAC(HashFunction* hash_in) : hash(hash_in) { if(hash->hash_block_size() == 0) throw Invalid_Argument("HMAC cannot be used with " + hash->name()); - - i_key.resize(hash->hash_block_size()); - o_key.resize(hash->hash_block_size()); } } diff --git a/src/mac/hmac/hmac.h b/src/mac/hmac/hmac.h index b76a058f4..cb5bd6917 100644 --- a/src/mac/hmac/hmac.h +++ b/src/mac/hmac/hmac.h @@ -27,7 +27,7 @@ class BOTAN_DLL HMAC : public MessageAuthenticationCode Key_Length_Specification key_spec() const { - return Key_Length_Specification(0, 2*hash->hash_block_size()); + return Key_Length_Specification(0, 512); } /** @@ -41,7 +41,7 @@ class BOTAN_DLL HMAC : public MessageAuthenticationCode void key_schedule(const byte[], size_t); HashFunction* hash; - SecureVector<byte> i_key, o_key; + secure_vector<byte> i_key, o_key; }; } diff --git a/src/mac/mac.cpp b/src/mac/mac.cpp index 2ef4ab64c..094aa1b4a 100644 --- a/src/mac/mac.cpp +++ b/src/mac/mac.cpp @@ -15,7 +15,7 @@ namespace Botan { */ bool MessageAuthenticationCode::verify_mac(const byte mac[], size_t length) { - SecureVector<byte> our_mac = final(); + secure_vector<byte> our_mac = final(); if(our_mac.size() != length) return false; diff --git a/src/mac/ssl3mac/ssl3_mac.cpp b/src/mac/ssl3mac/ssl3_mac.cpp index a07622eb3..8979d1291 100644 --- a/src/mac/ssl3mac/ssl3_mac.cpp +++ b/src/mac/ssl3mac/ssl3_mac.cpp @@ -35,11 +35,20 @@ void SSL3_MAC::final_result(byte mac[]) void SSL3_MAC::key_schedule(const byte key[], size_t length) { hash->clear(); + + // Quirk to deal with specification bug + const size_t inner_hash_length = + (hash->name() == "SHA-160") ? 60 : hash->hash_block_size(); + + i_key.resize(inner_hash_length); + o_key.resize(inner_hash_length); + std::fill(i_key.begin(), i_key.end(), 0x36); std::fill(o_key.begin(), o_key.end(), 0x5C); - i_key.copy(key, length); - o_key.copy(key, length); + copy_mem(&i_key[0], key, length); + copy_mem(&o_key[0], key, length); + hash->update(i_key); } @@ -49,8 +58,8 @@ void SSL3_MAC::key_schedule(const byte key[], size_t length) void SSL3_MAC::clear() { hash->clear(); - zeroise(i_key); - zeroise(o_key); + i_key.clear(); + o_key.clear(); } /* @@ -76,13 +85,6 @@ SSL3_MAC::SSL3_MAC(HashFunction* hash_in) : hash(hash_in) { if(hash->hash_block_size() == 0) throw Invalid_Argument("SSL3-MAC cannot be used with " + hash->name()); - - // Quirk to deal with specification bug - const size_t INNER_HASH_LENGTH = - (hash->name() == "SHA-160") ? 60 : hash->hash_block_size(); - - i_key.resize(INNER_HASH_LENGTH); - o_key.resize(INNER_HASH_LENGTH); } } diff --git a/src/mac/ssl3mac/ssl3_mac.h b/src/mac/ssl3mac/ssl3_mac.h index a85a78263..d23ac023c 100644 --- a/src/mac/ssl3mac/ssl3_mac.h +++ b/src/mac/ssl3mac/ssl3_mac.h @@ -41,7 +41,7 @@ class BOTAN_DLL SSL3_MAC : public MessageAuthenticationCode void key_schedule(const byte[], size_t); HashFunction* hash; - SecureVector<byte> i_key, o_key; + secure_vector<byte> i_key, o_key; }; } diff --git a/src/mac/x919_mac/x919_mac.cpp b/src/mac/x919_mac/x919_mac.cpp index fcbe77537..faf6138ef 100644 --- a/src/mac/x919_mac/x919_mac.cpp +++ b/src/mac/x919_mac/x919_mac.cpp @@ -44,7 +44,7 @@ void ANSI_X919_MAC::final_result(byte mac[]) { if(position) e->encrypt(state); - d->decrypt(state, mac); + d->decrypt(&state[0], mac); e->encrypt(mac); zeroise(state); position = 0; diff --git a/src/mac/x919_mac/x919_mac.h b/src/mac/x919_mac/x919_mac.h index 58a005e0b..4b5e63b33 100644 --- a/src/mac/x919_mac/x919_mac.h +++ b/src/mac/x919_mac/x919_mac.h @@ -41,7 +41,7 @@ class BOTAN_DLL ANSI_X919_MAC : public MessageAuthenticationCode BlockCipher* e; BlockCipher* d; - SecureVector<byte> state; + secure_vector<byte> state; size_t position; }; diff --git a/src/math/bigint/big_code.cpp b/src/math/bigint/big_code.cpp index 75a310a7c..a55ec662e 100644 --- a/src/math/bigint/big_code.cpp +++ b/src/math/bigint/big_code.cpp @@ -21,7 +21,7 @@ void BigInt::encode(byte output[], const BigInt& n, Base base) n.binary_encode(output); else if(base == Hexadecimal) { - SecureVector<byte> binary(n.encoded_size(Binary)); + secure_vector<byte> binary(n.encoded_size(Binary)); n.binary_encode(&binary[0]); hex_encode(reinterpret_cast<char*>(output), @@ -61,9 +61,23 @@ void BigInt::encode(byte output[], const BigInt& n, Base base) /* * Encode a BigInt */ -SecureVector<byte> BigInt::encode(const BigInt& n, Base base) +std::vector<byte> BigInt::encode(const BigInt& n, Base base) { - SecureVector<byte> output(n.encoded_size(base)); + std::vector<byte> output(n.encoded_size(base)); + encode(&output[0], n, base); + if(base != Binary) + for(size_t j = 0; j != output.size(); ++j) + if(output[j] == 0) + output[j] = '0'; + return output; + } + +/* +* Encode a BigInt +*/ +secure_vector<byte> BigInt::encode_locked(const BigInt& n, Base base) + { + secure_vector<byte> output(n.encoded_size(base)); encode(&output[0], n, base); if(base != Binary) for(size_t j = 0; j != output.size(); ++j) @@ -75,7 +89,7 @@ SecureVector<byte> BigInt::encode(const BigInt& n, Base base) /* * Encode a BigInt, with leading 0s if needed */ -SecureVector<byte> BigInt::encode_1363(const BigInt& n, size_t bytes) +secure_vector<byte> BigInt::encode_1363(const BigInt& n, size_t bytes) { const size_t n_bytes = n.bytes(); if(n_bytes > bytes) @@ -83,7 +97,7 @@ SecureVector<byte> BigInt::encode_1363(const BigInt& n, size_t bytes) const size_t leading_0s = bytes - n_bytes; - SecureVector<byte> output(bytes); + secure_vector<byte> output(bytes); encode(&output[leading_0s], n, Binary); return output; } @@ -91,14 +105,6 @@ SecureVector<byte> BigInt::encode_1363(const BigInt& n, size_t bytes) /* * Decode a BigInt */ -BigInt BigInt::decode(const MemoryRegion<byte>& buf, Base base) - { - return BigInt::decode(&buf[0], buf.size(), base); - } - -/* -* Decode a BigInt -*/ BigInt BigInt::decode(const byte buf[], size_t length, Base base) { BigInt r; @@ -106,12 +112,14 @@ BigInt BigInt::decode(const byte buf[], size_t length, Base base) r.binary_decode(buf, length); else if(base == Hexadecimal) { - SecureVector<byte> binary; + secure_vector<byte> binary; if(length % 2) { // Handle lack of leading 0 - const char buf0_with_leading_0[2] = { '0', buf[0] }; + const char buf0_with_leading_0[2] = + { '0', static_cast<char>(buf[0]) }; + binary = hex_decode(buf0_with_leading_0, 2); binary += hex_decode(reinterpret_cast<const char*>(&buf[1]), diff --git a/src/math/bigint/big_io.cpp b/src/math/bigint/big_io.cpp index 70e4a464a..130a98a3b 100644 --- a/src/math/bigint/big_io.cpp +++ b/src/math/bigint/big_io.cpp @@ -27,7 +27,7 @@ std::ostream& operator<<(std::ostream& stream, const BigInt& n) { if(n < 0) stream.write("-", 1); - SecureVector<byte> buffer = BigInt::encode(n, base); + const std::vector<byte> buffer = BigInt::encode(n, base); size_t skip = 0; while(buffer[skip] == '0' && skip < buffer.size()) ++skip; diff --git a/src/math/bigint/big_ops2.cpp b/src/math/bigint/big_ops2.cpp index ff5cc7922..ea2bdc961 100644 --- a/src/math/bigint/big_ops2.cpp +++ b/src/math/bigint/big_ops2.cpp @@ -23,15 +23,15 @@ BigInt& BigInt::operator+=(const BigInt& y) grow_to(reg_size); if(sign() == y.sign()) - bigint_add2(get_reg(), reg_size - 1, y.data(), y_sw); + bigint_add2(data(), reg_size - 1, y.data(), y_sw); else { s32bit relative_size = bigint_cmp(data(), x_sw, y.data(), y_sw); if(relative_size < 0) { - SecureVector<word> z(reg_size - 1); - bigint_sub3(z, y.data(), reg_size - 1, data(), x_sw); + secure_vector<word> z(reg_size - 1); + bigint_sub3(&z[0], y.data(), reg_size - 1, data(), x_sw); copy_mem(®[0], &z[0], z.size()); set_sign(y.sign()); } @@ -41,7 +41,7 @@ BigInt& BigInt::operator+=(const BigInt& y) set_sign(Positive); } else if(relative_size > 0) - bigint_sub2(get_reg(), x_sw, y.data(), y_sw); + bigint_sub2(data(), x_sw, y.data(), y_sw); } return (*this); @@ -62,9 +62,9 @@ BigInt& BigInt::operator-=(const BigInt& y) if(relative_size < 0) { if(sign() == y.sign()) - bigint_sub2_rev(get_reg(), y.data(), y_sw); + bigint_sub2_rev(data(), y.data(), y_sw); else - bigint_add2(get_reg(), reg_size - 1, y.data(), y_sw); + bigint_add2(data(), reg_size - 1, y.data(), y_sw); set_sign(y.reverse_sign()); } @@ -76,14 +76,14 @@ BigInt& BigInt::operator-=(const BigInt& y) set_sign(Positive); } else - bigint_shl1(get_reg(), x_sw, 0, 1); + bigint_shl1(data(), x_sw, 0, 1); } else if(relative_size > 0) { if(sign() == y.sign()) - bigint_sub2(get_reg(), x_sw, y.data(), y_sw); + bigint_sub2(data(), x_sw, y.data(), y_sw); else - bigint_add2(get_reg(), reg_size - 1, y.data(), y_sw); + bigint_add2(data(), reg_size - 1, y.data(), y_sw); } return (*this); @@ -105,22 +105,22 @@ BigInt& BigInt::operator*=(const BigInt& y) else if(x_sw == 1 && y_sw) { grow_to(y_sw + 2); - bigint_linmul3(get_reg(), y.data(), y_sw, word_at(0)); + bigint_linmul3(data(), y.data(), y_sw, word_at(0)); } else if(y_sw == 1 && x_sw) { grow_to(x_sw + 2); - bigint_linmul2(get_reg(), x_sw, y.word_at(0)); + bigint_linmul2(data(), x_sw, y.word_at(0)); } else { grow_to(size() + y.size()); - SecureVector<word> z(data(), x_sw); - SecureVector<word> workspace(size()); + secure_vector<word> z(data(), data() + x_sw); + secure_vector<word> workspace(size()); - bigint_mul(get_reg(), size(), workspace, - z, z.size(), x_sw, + bigint_mul(data(), size(), &workspace[0], + &z[0], z.size(), x_sw, y.data(), y.size(), y_sw); } @@ -159,7 +159,7 @@ word BigInt::operator%=(word mod) word result = (word_at(0) & (mod - 1)); clear(); grow_to(2); - get_reg()[0] = result; + reg[0] = result; return result; } @@ -171,9 +171,9 @@ word BigInt::operator%=(word mod) grow_to(2); if(remainder && sign() == BigInt::Negative) - get_reg()[0] = mod - remainder; + reg[0] = mod - remainder; else - get_reg()[0] = remainder; + reg[0] = remainder; set_sign(BigInt::Positive); @@ -192,7 +192,7 @@ BigInt& BigInt::operator<<=(size_t shift) words = sig_words(); grow_to(words + shift_words + (shift_bits ? 1 : 0)); - bigint_shl1(get_reg(), words, shift_words, shift_bits); + bigint_shl1(data(), words, shift_words, shift_bits); } return (*this); @@ -208,7 +208,7 @@ BigInt& BigInt::operator>>=(size_t shift) const size_t shift_words = shift / MP_WORD_BITS, shift_bits = shift % MP_WORD_BITS; - bigint_shr1(get_reg(), sig_words(), shift_words, shift_bits); + bigint_shr1(data(), sig_words(), shift_words, shift_bits); if(is_zero()) set_sign(Positive); diff --git a/src/math/bigint/big_ops3.cpp b/src/math/bigint/big_ops3.cpp index 52472bc52..a33b32bb7 100644 --- a/src/math/bigint/big_ops3.cpp +++ b/src/math/bigint/big_ops3.cpp @@ -23,20 +23,20 @@ BigInt operator+(const BigInt& x, const BigInt& y) BigInt z(x.sign(), std::max(x_sw, y_sw) + 1); if((x.sign() == y.sign())) - bigint_add3(z.get_reg(), x.data(), x_sw, y.data(), y_sw); + bigint_add3(z.data(), x.data(), x_sw, y.data(), y_sw); else { s32bit relative_size = bigint_cmp(x.data(), x_sw, y.data(), y_sw); if(relative_size < 0) { - bigint_sub3(z.get_reg(), y.data(), y_sw, x.data(), x_sw); + bigint_sub3(z.data(), y.data(), y_sw, x.data(), x_sw); z.set_sign(y.sign()); } else if(relative_size == 0) z.set_sign(BigInt::Positive); else if(relative_size > 0) - bigint_sub3(z.get_reg(), x.data(), x_sw, y.data(), y_sw); + bigint_sub3(z.data(), x.data(), x_sw, y.data(), y_sw); } return z; @@ -56,22 +56,22 @@ BigInt operator-(const BigInt& x, const BigInt& y) if(relative_size < 0) { if(x.sign() == y.sign()) - bigint_sub3(z.get_reg(), y.data(), y_sw, x.data(), x_sw); + bigint_sub3(z.data(), y.data(), y_sw, x.data(), x_sw); else - bigint_add3(z.get_reg(), x.data(), x_sw, y.data(), y_sw); + bigint_add3(z.data(), x.data(), x_sw, y.data(), y_sw); z.set_sign(y.reverse_sign()); } else if(relative_size == 0) { if(x.sign() != y.sign()) - bigint_shl2(z.get_reg(), x.data(), x_sw, 0, 1); + bigint_shl2(z.data(), x.data(), x_sw, 0, 1); } else if(relative_size > 0) { if(x.sign() == y.sign()) - bigint_sub3(z.get_reg(), x.data(), x_sw, y.data(), y_sw); + bigint_sub3(z.data(), x.data(), x_sw, y.data(), y_sw); else - bigint_add3(z.get_reg(), x.data(), x_sw, y.data(), y_sw); + bigint_add3(z.data(), x.data(), x_sw, y.data(), y_sw); z.set_sign(x.sign()); } return z; @@ -87,13 +87,13 @@ BigInt operator*(const BigInt& x, const BigInt& y) BigInt z(BigInt::Positive, x.size() + y.size()); if(x_sw == 1 && y_sw) - bigint_linmul3(z.get_reg(), y.data(), y_sw, x.word_at(0)); + bigint_linmul3(z.data(), y.data(), y_sw, x.word_at(0)); else if(y_sw == 1 && x_sw) - bigint_linmul3(z.get_reg(), x.data(), x_sw, y.word_at(0)); + bigint_linmul3(z.data(), x.data(), x_sw, y.word_at(0)); else if(x_sw && y_sw) { - SecureVector<word> workspace(z.size()); - bigint_mul(z.get_reg(), z.size(), workspace, + secure_vector<word> workspace(z.size()); + bigint_mul(z.data(), z.size(), &workspace[0], x.data(), x.size(), x_sw, y.data(), y.size(), y_sw); } @@ -164,7 +164,7 @@ BigInt operator<<(const BigInt& x, size_t shift) const size_t x_sw = x.sig_words(); BigInt y(x.sign(), x_sw + shift_words + (shift_bits ? 1 : 0)); - bigint_shl2(y.get_reg(), x.data(), x_sw, shift_words, shift_bits); + bigint_shl2(y.data(), x.data(), x_sw, shift_words, shift_bits); return y; } @@ -183,7 +183,7 @@ BigInt operator>>(const BigInt& x, size_t shift) x_sw = x.sig_words(); BigInt y(x.sign(), x_sw - shift_words); - bigint_shr2(y.get_reg(), x.data(), x_sw, shift_words, shift_bits); + bigint_shr2(y.data(), x.data(), x_sw, shift_words, shift_bits); return y; } diff --git a/src/math/bigint/big_rand.cpp b/src/math/bigint/big_rand.cpp index 7cddb2de0..a6776a296 100644 --- a/src/math/bigint/big_rand.cpp +++ b/src/math/bigint/big_rand.cpp @@ -35,7 +35,7 @@ void BigInt::randomize(RandomNumberGenerator& rng, clear(); else { - SecureVector<byte> array = rng.random_vec((bitsize + 7) / 8); + secure_vector<byte> array = rng.random_vec((bitsize + 7) / 8); if(bitsize % 8) array[0] &= 0xFF >> (8 - (bitsize % 8)); diff --git a/src/math/bigint/bigint.cpp b/src/math/bigint/bigint.cpp index e2e062f2d..224a27a48 100644 --- a/src/math/bigint/bigint.cpp +++ b/src/math/bigint/bigint.cpp @@ -40,23 +40,12 @@ BigInt::BigInt(Sign s, size_t size) } /* -* Construct a BigInt from a "raw" BigInt +* Copy constructor */ BigInt::BigInt(const BigInt& b) { - const size_t b_words = b.sig_words(); - - if(b_words) - { - reg.resize(round_up<size_t>(b_words, 8)); - reg.copy(b.data(), b_words); - set_sign(b.sign()); - } - else - { - reg.resize(2); - set_sign(Positive); - } + reg = b.get_reg(); + set_sign(b.sign()); } /* @@ -101,15 +90,6 @@ BigInt::BigInt(RandomNumberGenerator& rng, size_t bits) } /* -* Swap this BigInt with another -*/ -void BigInt::swap(BigInt& other) - { - reg.swap(other.reg); - std::swap(signedness, other.signedness); - } - -/* * Grow the internal storage */ void BigInt::grow_reg(size_t n) @@ -233,8 +213,7 @@ void BigInt::mask_bits(size_t n) const word mask = (static_cast<word>(1) << (n % MP_WORD_BITS)) - 1; if(top_word < size()) - for(size_t i = top_word + 1; i != size(); ++i) - reg[i] = 0; + clear_mem(®[top_word+1], size() - (top_word + 1)); reg[top_word] &= mask; } @@ -365,12 +344,4 @@ void BigInt::binary_decode(const byte buf[], size_t length) reg[length / WORD_BYTES] = (reg[length / WORD_BYTES] << 8) | buf[i]; } -/* -* Set this number to the value in buf -*/ -void BigInt::binary_decode(const MemoryRegion<byte>& buf) - { - binary_decode(buf, buf.size()); - } - } diff --git a/src/math/bigint/bigint.h b/src/math/bigint/bigint.h index 87c7cb766..98b98bd6f 100644 --- a/src/math/bigint/bigint.h +++ b/src/math/bigint/bigint.h @@ -314,22 +314,29 @@ class BOTAN_DLL BigInt * @result a pointer to the start of the internal register of * the integer value */ + word* data() { return ®[0]; } + + /** + * Return a pointer to the big integer word register + * @result a pointer to the start of the internal register of + * the integer value + */ const word* data() const { return ®[0]; } /** * return a reference to the internal register containing the value - * @result a reference to the word-array (SecureVector<word>) + * @result a reference to the word-array (secure_vector<word>) * with the internal register value (containing the integer * value) */ - SecureVector<word>& get_reg() { return reg; } + secure_vector<word>& get_reg() { return reg; } /** * return a const reference to the internal register containing the value - * @result a const reference to the word-array (SecureVector<word>) + * @result a const reference to the word-array (secure_vector<word>) * with the internal register value (containing the integer value) */ - const SecureVector<word>& get_reg() const { return reg; } + const secure_vector<word>& get_reg() const { return reg; } /** * Assign using a plain word array @@ -369,10 +376,13 @@ class BOTAN_DLL BigInt void binary_decode(const byte buf[], size_t length); /** - * Read integer value from a byte array (MemoryRegion<byte>) + * Read integer value from a byte array (secure_vector<byte>) * @param buf the array to load from */ - void binary_decode(const MemoryRegion<byte>& buf); + void binary_decode(const secure_vector<byte>& buf) + { + binary_decode(&buf[0], buf.size()); + } /** * @param base the base to measure the size for @@ -391,12 +401,21 @@ class BOTAN_DLL BigInt const BigInt& max); /** - * Encode the integer value from a BigInt to a SecureVector of bytes + * Encode the integer value from a BigInt to a std::vector of bytes + * @param n the BigInt to use as integer source + * @param base number-base of resulting byte array representation + * @result secure_vector of bytes containing the integer with given base + */ + static std::vector<byte> encode(const BigInt& n, Base base = Binary); + + /** + * Encode the integer value from a BigInt to a secure_vector of bytes * @param n the BigInt to use as integer source * @param base number-base of resulting byte array representation - * @result SecureVector of bytes containing the integer with given base + * @result secure_vector of bytes containing the integer with given base */ - static SecureVector<byte> encode(const BigInt& n, Base base = Binary); + static secure_vector<byte> encode_locked(const BigInt& n, + Base base = Binary); /** * Encode the integer value from a BigInt to a byte array @@ -423,22 +442,41 @@ class BOTAN_DLL BigInt * @param base number-base of the integer in buf * @result BigInt representing the integer in the byte array */ - static BigInt decode(const MemoryRegion<byte>& buf, - Base base = Binary); + static BigInt decode(const secure_vector<byte>& buf, + Base base = Binary) + { + return BigInt::decode(&buf[0], buf.size(), base); + } + + /** + * Create a BigInt from an integer in a byte array + * @param buf the binary value to load + * @param base number-base of the integer in buf + * @result BigInt representing the integer in the byte array + */ + static BigInt decode(const std::vector<byte>& buf, + Base base = Binary) + { + return BigInt::decode(&buf[0], buf.size(), base); + } /** * Encode a BigInt to a byte array according to IEEE 1363 * @param n the BigInt to encode - * @param bytes the length of the resulting SecureVector<byte> - * @result a SecureVector<byte> containing the encoded BigInt + * @param bytes the length of the resulting secure_vector<byte> + * @result a secure_vector<byte> containing the encoded BigInt */ - static SecureVector<byte> encode_1363(const BigInt& n, size_t bytes); + static secure_vector<byte> encode_1363(const BigInt& n, size_t bytes); /** * Swap this value with another * @param other BigInt to swap values with */ - void swap(BigInt& other); + void swap(BigInt& other) + { + reg.swap(other.reg); + std::swap(signedness, other.signedness); + } /** * Create empty BigInt @@ -500,8 +538,31 @@ class BOTAN_DLL BigInt */ BigInt(NumberType type, size_t n); + /** + * Move constructor + */ + BigInt(BigInt&& other) + { + this->swap(other); + } + + /** + * Move assignment + */ + BigInt& operator=(BigInt&& other) + { + if(this != &other) + this->swap(other); + + return (*this); + } + + /** + * Copy assignment + */ + BigInt& operator=(const BigInt&) = default; private: - SecureVector<word> reg; + secure_vector<word> reg; Sign signedness; }; diff --git a/src/math/ec_gfp/point_gfp.cpp b/src/math/ec_gfp/point_gfp.cpp index 7ac6b4141..599b6e842 100644 --- a/src/math/ec_gfp/point_gfp.cpp +++ b/src/math/ec_gfp/point_gfp.cpp @@ -45,7 +45,7 @@ void PointGFp::monty_mult(BigInt& z, const BigInt& x, const BigInt& y) const const size_t p_size = curve.get_p_words(); const word p_dash = curve.get_p_dash(); - SecureVector<word>& z_reg = z.get_reg(); + secure_vector<word>& z_reg = z.get_reg(); z_reg.resize(2*p_size+1); zeroise(z_reg); @@ -71,7 +71,7 @@ void PointGFp::monty_sqr(BigInt& z, const BigInt& x) const const size_t p_size = curve.get_p_words(); const word p_dash = curve.get_p_dash(); - SecureVector<word>& z_reg = z.get_reg(); + secure_vector<word>& z_reg = z.get_reg(); z_reg.resize(2*p_size+1); zeroise(z_reg); @@ -479,22 +479,22 @@ bool PointGFp::operator==(const PointGFp& other) const } // encoding and decoding -SecureVector<byte> EC2OSP(const PointGFp& point, byte format) +secure_vector<byte> EC2OSP(const PointGFp& point, byte format) { if(point.is_zero()) - return SecureVector<byte>(1); // single 0 byte + return secure_vector<byte>(1); // single 0 byte const size_t p_bytes = point.get_curve().get_p().bytes(); BigInt x = point.get_affine_x(); BigInt y = point.get_affine_y(); - SecureVector<byte> bX = BigInt::encode_1363(x, p_bytes); - SecureVector<byte> bY = BigInt::encode_1363(y, p_bytes); + secure_vector<byte> bX = BigInt::encode_1363(x, p_bytes); + secure_vector<byte> bY = BigInt::encode_1363(y, p_bytes); if(format == PointGFp::UNCOMPRESSED) { - SecureVector<byte> result; + secure_vector<byte> result; result.push_back(0x04); result += bX; @@ -504,7 +504,7 @@ SecureVector<byte> EC2OSP(const PointGFp& point, byte format) } else if(format == PointGFp::COMPRESSED) { - SecureVector<byte> result; + secure_vector<byte> result; result.push_back(0x02 | static_cast<byte>(y.get_bit(0))); result += bX; @@ -513,7 +513,7 @@ SecureVector<byte> EC2OSP(const PointGFp& point, byte format) } else if(format == PointGFp::HYBRID) { - SecureVector<byte> result; + secure_vector<byte> result; result.push_back(0x06 | static_cast<byte>(y.get_bit(0))); result += bX; @@ -591,7 +591,7 @@ PointGFp OS2ECP(const byte data[], size_t data_len, throw Illegal_Point("OS2ECP: Decoding error in hybrid format"); } else - throw Invalid_Argument("OS2ECP: Unknown format type"); + throw Invalid_Argument("OS2ECP: Unknown format type " + std::to_string(pc)); PointGFp result(curve, x, y); diff --git a/src/math/ec_gfp/point_gfp.h b/src/math/ec_gfp/point_gfp.h index b2b6fe2f0..017f66e1c 100644 --- a/src/math/ec_gfp/point_gfp.h +++ b/src/math/ec_gfp/point_gfp.h @@ -59,6 +59,34 @@ class BOTAN_DLL PointGFp PointGFp(const CurveGFp& curve); /** + * Copy constructor + */ + PointGFp(const PointGFp&) = default; + + /** + * Move Constructor + */ + PointGFp(PointGFp&& other) + { + this->swap(other); + } + + /** + * Standard Assignment + */ + PointGFp& operator=(const PointGFp&) = default; + + /** + * Move Assignment + */ + PointGFp& operator=(PointGFp&& other) + { + if(this != &other) + this->swap(other); + return (*this); + } + + /** * Construct a point from its affine coordinates * @param curve the base curve * @param x affine x coordinate @@ -66,9 +94,6 @@ class BOTAN_DLL PointGFp */ PointGFp(const CurveGFp& curve, const BigInt& x, const BigInt& y); - //PointGFp(const PointGFp& other) = default; - //PointGFp& operator=(const PointGFp& other) = default; - /** * += Operator * @param rhs the PointGFp to add to the local value @@ -220,7 +245,7 @@ class BOTAN_DLL PointGFp CurveGFp curve; BigInt coord_x, coord_y, coord_z; - mutable SecureVector<word> ws; // workspace for Montgomery + mutable secure_vector<word> ws; // workspace for Montgomery }; // relational operators @@ -253,12 +278,13 @@ inline PointGFp operator*(const PointGFp& point, const BigInt& scalar) } // encoding and decoding -SecureVector<byte> BOTAN_DLL EC2OSP(const PointGFp& point, byte format); +secure_vector<byte> BOTAN_DLL EC2OSP(const PointGFp& point, byte format); PointGFp BOTAN_DLL OS2ECP(const byte data[], size_t data_len, const CurveGFp& curve); -inline PointGFp OS2ECP(const MemoryRegion<byte>& data, const CurveGFp& curve) +template<typename Alloc> +PointGFp OS2ECP(const std::vector<byte, Alloc>& data, const CurveGFp& curve) { return OS2ECP(&data[0], data.size(), curve); } } diff --git a/src/math/numbertheory/dsa_gen.cpp b/src/math/numbertheory/dsa_gen.cpp index 670f103da..d30a08f1a 100644 --- a/src/math/numbertheory/dsa_gen.cpp +++ b/src/math/numbertheory/dsa_gen.cpp @@ -42,29 +42,29 @@ bool generate_dsa_primes(RandomNumberGenerator& rng, Algorithm_Factory& af, BigInt& p, BigInt& q, size_t pbits, size_t qbits, - const MemoryRegion<byte>& seed_c) + const std::vector<byte>& seed_c) { if(!fips186_3_valid_size(pbits, qbits)) throw Invalid_Argument( "FIPS 186-3 does not allow DSA domain parameters of " + - to_string(pbits) + "/" + to_string(qbits) + " bits long"); + std::to_string(pbits) + "/" + std::to_string(qbits) + " bits long"); if(seed_c.size() * 8 < qbits) throw Invalid_Argument( - "Generating a DSA parameter set with a " + to_string(qbits) + + "Generating a DSA parameter set with a " + std::to_string(qbits) + "long q requires a seed at least as many bits long"); - std::auto_ptr<HashFunction> hash( - af.make_hash_function("SHA-" + to_string(qbits))); + std::unique_ptr<HashFunction> hash( + af.make_hash_function("SHA-" + std::to_string(qbits))); const size_t HASH_SIZE = hash->output_length(); class Seed { public: - Seed(const MemoryRegion<byte>& s) : seed(s) {} + Seed(const std::vector<byte>& s) : seed(s) {} - operator MemoryRegion<byte>& () { return seed; } + operator std::vector<byte>& () { return seed; } Seed& operator++() { @@ -74,7 +74,7 @@ bool generate_dsa_primes(RandomNumberGenerator& rng, return (*this); } private: - SecureVector<byte> seed; + std::vector<byte> seed; }; Seed seed(seed_c); @@ -90,7 +90,7 @@ bool generate_dsa_primes(RandomNumberGenerator& rng, b = (pbits-1) % (HASH_SIZE * 8); BigInt X; - SecureVector<byte> V(HASH_SIZE * (n+1)); + std::vector<byte> V(HASH_SIZE * (n+1)); for(size_t j = 0; j != 4096; ++j) { @@ -116,14 +116,15 @@ bool generate_dsa_primes(RandomNumberGenerator& rng, /* * Generate DSA Primes */ -SecureVector<byte> generate_dsa_primes(RandomNumberGenerator& rng, - Algorithm_Factory& af, - BigInt& p, BigInt& q, - size_t pbits, size_t qbits) +std::vector<byte> generate_dsa_primes(RandomNumberGenerator& rng, + Algorithm_Factory& af, + BigInt& p, BigInt& q, + size_t pbits, size_t qbits) { while(true) { - SecureVector<byte> seed = rng.random_vec(qbits / 8); + std::vector<byte> seed(qbits / 8); + rng.randomize(&seed[0], seed.size()); if(generate_dsa_primes(rng, af, p, q, pbits, qbits, seed)) return seed; diff --git a/src/math/numbertheory/make_prm.cpp b/src/math/numbertheory/make_prm.cpp index 4fb3f908c..dc94420ab 100644 --- a/src/math/numbertheory/make_prm.cpp +++ b/src/math/numbertheory/make_prm.cpp @@ -20,7 +20,7 @@ BigInt random_prime(RandomNumberGenerator& rng, { if(bits <= 1) throw Invalid_Argument("random_prime: Can't make a prime of " + - to_string(bits) + " bits"); + std::to_string(bits) + " bits"); else if(bits == 2) return ((rng.next_byte() % 2) ? 2 : 3); else if(bits == 3) @@ -48,7 +48,7 @@ BigInt random_prime(RandomNumberGenerator& rng, p += (modulo - p % modulo) + equiv; const size_t sieve_size = std::min(bits / 2, PRIME_TABLE_SIZE); - SecureVector<size_t> sieve(sieve_size); + secure_vector<u16bit> sieve(sieve_size); for(size_t j = 0; j != sieve.size(); ++j) sieve[j] = p % PRIMES[j]; @@ -88,7 +88,7 @@ BigInt random_safe_prime(RandomNumberGenerator& rng, size_t bits) { if(bits <= 64) throw Invalid_Argument("random_safe_prime: Can't make a prime of " + - to_string(bits) + " bits"); + std::to_string(bits) + " bits"); BigInt p; do diff --git a/src/math/numbertheory/mp_numth.cpp b/src/math/numbertheory/mp_numth.cpp index 23623b5f0..b10fe2639 100644 --- a/src/math/numbertheory/mp_numth.cpp +++ b/src/math/numbertheory/mp_numth.cpp @@ -20,9 +20,9 @@ BigInt square(const BigInt& x) const size_t x_sw = x.sig_words(); BigInt z(BigInt::Positive, round_up<size_t>(2*x_sw, 16)); - SecureVector<word> workspace(z.size()); + secure_vector<word> workspace(z.size()); - bigint_sqr(z.get_reg(), z.size(), workspace, + bigint_sqr(z.data(), z.size(), &workspace[0], x.data(), x.size(), x_sw); return z; } @@ -44,13 +44,13 @@ BigInt mul_add(const BigInt& a, const BigInt& b, const BigInt& c) const size_t c_sw = c.sig_words(); BigInt r(sign, std::max(a.size() + b.size(), c_sw) + 1); - SecureVector<word> workspace(r.size()); + secure_vector<word> workspace(r.size()); - bigint_mul(r.get_reg(), r.size(), workspace, + bigint_mul(r.data(), r.size(), &workspace[0], a.data(), a.size(), a_sw, b.data(), b.size(), b_sw); const size_t r_size = std::max(r.sig_words(), c_sw); - bigint_add2(r.get_reg(), r_size, c.data(), c_sw); + bigint_add2(r.data(), r_size, c.data(), c_sw); return r; } diff --git a/src/math/numbertheory/numthry.cpp b/src/math/numbertheory/numthry.cpp index c7896c17a..18f6ce429 100644 --- a/src/math/numbertheory/numthry.cpp +++ b/src/math/numbertheory/numthry.cpp @@ -83,7 +83,7 @@ size_t miller_rabin_test_iterations(size_t bits, size_t level) { struct mapping { size_t bits; size_t verify_iter; size_t check_iter; }; - static const mapping tests[] = { + const mapping tests[] = { { 50, 55, 25 }, { 100, 38, 22 }, { 160, 32, 18 }, diff --git a/src/math/numbertheory/numthry.h b/src/math/numbertheory/numthry.h index 750fbc78e..d21635f34 100644 --- a/src/math/numbertheory/numthry.h +++ b/src/math/numbertheory/numthry.h @@ -189,7 +189,7 @@ class Algorithm_Factory; * @param qbits how long q will be in bits * @return random seed used to generate this parameter set */ -SecureVector<byte> BOTAN_DLL +std::vector<byte> BOTAN_DLL generate_dsa_primes(RandomNumberGenerator& rng, Algorithm_Factory& af, BigInt& p_out, BigInt& q_out, @@ -212,7 +212,7 @@ generate_dsa_primes(RandomNumberGenerator& rng, Algorithm_Factory& af, BigInt& p_out, BigInt& q_out, size_t pbits, size_t qbits, - const MemoryRegion<byte>& seed); + const std::vector<byte>& seed); /** * The size of the PRIMES[] array diff --git a/src/math/numbertheory/pow_mod.cpp b/src/math/numbertheory/pow_mod.cpp index bf6b29275..c7d7fe70e 100644 --- a/src/math/numbertheory/pow_mod.cpp +++ b/src/math/numbertheory/pow_mod.cpp @@ -16,7 +16,7 @@ namespace Botan { */ Power_Mod::Power_Mod(const BigInt& n, Usage_Hints hints) { - core = 0; + core = nullptr; set_modulus(n, hints); } @@ -25,7 +25,7 @@ Power_Mod::Power_Mod(const BigInt& n, Usage_Hints hints) */ Power_Mod::Power_Mod(const Power_Mod& other) { - core = 0; + core = nullptr; if(other.core) core = other.core->copy(); } @@ -36,7 +36,7 @@ Power_Mod::Power_Mod(const Power_Mod& other) Power_Mod& Power_Mod::operator=(const Power_Mod& other) { delete core; - core = 0; + core = nullptr; if(other.core) core = other.core->copy(); return (*this); @@ -56,7 +56,7 @@ Power_Mod::~Power_Mod() void Power_Mod::set_modulus(const BigInt& n, Usage_Hints hints) const { delete core; - core = 0; + core = nullptr; if(n != 0) { diff --git a/src/math/numbertheory/pow_mod.h b/src/math/numbertheory/pow_mod.h index 7ec237d72..9857c1833 100644 --- a/src/math/numbertheory/pow_mod.h +++ b/src/math/numbertheory/pow_mod.h @@ -61,7 +61,7 @@ class BOTAN_DLL Power_Mod Power_Mod(const BigInt& = 0, Usage_Hints = NO_HINTS); Power_Mod(const Power_Mod&); - ~Power_Mod(); + virtual ~Power_Mod(); private: mutable Modular_Exponentiator* core; Usage_Hints hints; diff --git a/src/math/numbertheory/powm_mnt.cpp b/src/math/numbertheory/powm_mnt.cpp index 8993f4ba9..0db5455a7 100644 --- a/src/math/numbertheory/powm_mnt.cpp +++ b/src/math/numbertheory/powm_mnt.cpp @@ -29,8 +29,8 @@ void Montgomery_Exponentiator::set_base(const BigInt& base) g.resize((1 << window_bits) - 1); - SecureVector<word> z(2 * (mod_words + 1)); - SecureVector<word> workspace(z.size()); + secure_vector<word> z(2 * (mod_words + 1)); + secure_vector<word> workspace(z.size()); g[0] = (base >= modulus) ? (base % modulus) : base; @@ -69,8 +69,8 @@ BigInt Montgomery_Exponentiator::execute() const const size_t exp_nibbles = (exp_bits + window_bits - 1) / window_bits; BigInt x = R_mod; - SecureVector<word> z(2 * (mod_words + 1)); - SecureVector<word> workspace(2 * (mod_words + 1)); + secure_vector<word> z(2 * (mod_words + 1)); + secure_vector<word> workspace(2 * (mod_words + 1)); for(size_t i = exp_nibbles; i > 0; --i) { diff --git a/src/mutex/info.txt b/src/mutex/info.txt deleted file mode 100644 index af4cf9bb3..000000000 --- a/src/mutex/info.txt +++ /dev/null @@ -1,5 +0,0 @@ -define MUTEX_WRAPPERS - -<header:internal> -mutex.h -</header:internal> diff --git a/src/mutex/mutex.h b/src/mutex/mutex.h deleted file mode 100644 index f209466d5..000000000 --- a/src/mutex/mutex.h +++ /dev/null @@ -1,71 +0,0 @@ -/* -* Mutex -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_MUTEX_H__ -#define BOTAN_MUTEX_H__ - -#include <botan/exceptn.h> - -namespace Botan { - -/** -* Mutex Base Class -*/ -class Mutex - { - public: - /** - * Lock the mutex - */ - virtual void lock() = 0; - - /** - * Unlock the mutex - */ - virtual void unlock() = 0; - virtual ~Mutex() {} - }; - -/** -* Mutex Factory -*/ -class Mutex_Factory - { - public: - /** - * @return newly allocated mutex - */ - virtual Mutex* make() = 0; - - virtual ~Mutex_Factory() {} - }; - -/** -* Mutex Holding Class for RAII -*/ -class Mutex_Holder - { - public: - /** - * Hold onto a mutex until we leave scope - * @param m the mutex to lock - */ - Mutex_Holder(Mutex* m) : mux(m) - { - if(!mux) - throw Invalid_Argument("Mutex_Holder: Argument was NULL"); - mux->lock(); - } - - ~Mutex_Holder() { mux->unlock(); } - private: - Mutex* mux; - }; - -} - -#endif diff --git a/src/mutex/noop_mutex/info.txt b/src/mutex/noop_mutex/info.txt deleted file mode 100644 index 16670b1dd..000000000 --- a/src/mutex/noop_mutex/info.txt +++ /dev/null @@ -1,9 +0,0 @@ -define MUTEX_NOOP - -<source> -mux_noop.cpp -</source> - -<header:internal> -mux_noop.h -</header:internal> diff --git a/src/mutex/noop_mutex/mux_noop.cpp b/src/mutex/noop_mutex/mux_noop.cpp deleted file mode 100644 index 18151274a..000000000 --- a/src/mutex/noop_mutex/mux_noop.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* -* No-Op Mutex Factory -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/internal/mux_noop.h> - -namespace Botan { - -/* -* No-Op Mutex Factory -*/ -Mutex* Noop_Mutex_Factory::make() - { - class Noop_Mutex : public Mutex - { - public: - class Mutex_State_Error : public Internal_Error - { - public: - Mutex_State_Error(const std::string& where) : - Internal_Error("Noop_Mutex::" + where + ": " + - "Mutex is already " + where + "ed") {} - }; - - void lock() - { - if(locked) - throw Mutex_State_Error("lock"); - locked = true; - } - - void unlock() - { - if(!locked) - throw Mutex_State_Error("unlock"); - locked = false; - } - - Noop_Mutex() { locked = false; } - private: - bool locked; - }; - - return new Noop_Mutex; - } - -} diff --git a/src/mutex/noop_mutex/mux_noop.h b/src/mutex/noop_mutex/mux_noop.h deleted file mode 100644 index 20989a635..000000000 --- a/src/mutex/noop_mutex/mux_noop.h +++ /dev/null @@ -1,26 +0,0 @@ -/* -* No-Op Mutex Factory -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_NOOP_MUTEX_FACTORY_H__ -#define BOTAN_NOOP_MUTEX_FACTORY_H__ - -#include <botan/internal/mutex.h> - -namespace Botan { - -/** -* No-Op Mutex Factory -*/ -class Noop_Mutex_Factory : public Mutex_Factory - { - public: - Mutex* make(); - }; - -} - -#endif diff --git a/src/mutex/pthreads/info.txt b/src/mutex/pthreads/info.txt deleted file mode 100644 index 1d826b61c..000000000 --- a/src/mutex/pthreads/info.txt +++ /dev/null @@ -1,29 +0,0 @@ -define MUTEX_PTHREAD - -<source> -mux_pthr.cpp -</source> - -<header:internal> -mux_pthr.h -</header:internal> - -<libs> -all!qnx,freebsd,dragonfly,openbsd,netbsd -> pthread -</libs> - -<os> -aix -cygwin -darwin -freebsd -dragonfly -hpux -irix -linux -netbsd -openbsd -qnx -solaris -tru64 -</os> diff --git a/src/mutex/pthreads/mux_pthr.cpp b/src/mutex/pthreads/mux_pthr.cpp deleted file mode 100644 index 165132239..000000000 --- a/src/mutex/pthreads/mux_pthr.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* -* Pthread Mutex -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/internal/mux_pthr.h> -#include <botan/exceptn.h> - -#ifndef _POSIX_C_SOURCE - #define _POSIX_C_SOURCE 199506 -#endif - -#include <pthread.h> - -namespace Botan { - -/* -* Pthread Mutex Factory -*/ -Mutex* Pthread_Mutex_Factory::make() - { - - class Pthread_Mutex : public Mutex - { - public: - void lock() - { - if(pthread_mutex_lock(&mutex) != 0) - throw Invalid_State("Pthread_Mutex::lock: Error occured"); - } - - void unlock() - { - if(pthread_mutex_unlock(&mutex) != 0) - throw Invalid_State("Pthread_Mutex::unlock: Error occured"); - } - - Pthread_Mutex() - { - if(pthread_mutex_init(&mutex, 0) != 0) - throw Invalid_State("Pthread_Mutex: initialization failed"); - } - - ~Pthread_Mutex() - { - if(pthread_mutex_destroy(&mutex) != 0) - throw Invalid_State("~Pthread_Mutex: mutex is still locked"); - } - private: - pthread_mutex_t mutex; - }; - - return new Pthread_Mutex(); - } - -} diff --git a/src/mutex/pthreads/mux_pthr.h b/src/mutex/pthreads/mux_pthr.h deleted file mode 100644 index 5cecd09ad..000000000 --- a/src/mutex/pthreads/mux_pthr.h +++ /dev/null @@ -1,26 +0,0 @@ -/* -* Pthread Mutex -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_MUTEX_PTHREAD_H__ -#define BOTAN_MUTEX_PTHREAD_H__ - -#include <botan/internal/mutex.h> - -namespace Botan { - -/** -* Pthread Mutex Factory -*/ -class Pthread_Mutex_Factory : public Mutex_Factory - { - public: - Mutex* make(); - }; - -} - -#endif diff --git a/src/mutex/qt_mutex/info.txt b/src/mutex/qt_mutex/info.txt deleted file mode 100644 index 7b014f886..000000000 --- a/src/mutex/qt_mutex/info.txt +++ /dev/null @@ -1,17 +0,0 @@ -define MUTEX_QT - -load_on request - -<source> -mux_qt.cpp -</source> - -<header:internal> -mux_qt.h -</header:internal> - -# I think we want to always use qt-mt, not qt -- not much point in supporting -# mutexes in a single threaded application, after all. -<libs> -all -> qt-mt -</libs> diff --git a/src/mutex/qt_mutex/mux_qt.cpp b/src/mutex/qt_mutex/mux_qt.cpp deleted file mode 100644 index da4e5ce5c..000000000 --- a/src/mutex/qt_mutex/mux_qt.cpp +++ /dev/null @@ -1,35 +0,0 @@ -/* -* Qt Thread Mutex -* (C) 2004-2007 Justin Karneges -* 2004-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/internal/mux_qt.h> -#include <qmutex.h> - -#if !defined(QT_THREAD_SUPPORT) - #error Your version of Qt does not support threads or mutexes -#endif - -namespace Botan { - -/* -* Qt Mutex Factory -*/ -Mutex* Qt_Mutex_Factory::make() - { - class Qt_Mutex : public Mutex - { - public: - void lock() { mutex.lock(); } - void unlock() { mutex.unlock(); } - private: - QMutex mutex; - }; - - return new Qt_Mutex(); - } - -} diff --git a/src/mutex/qt_mutex/mux_qt.h b/src/mutex/qt_mutex/mux_qt.h deleted file mode 100644 index 3805acc3b..000000000 --- a/src/mutex/qt_mutex/mux_qt.h +++ /dev/null @@ -1,27 +0,0 @@ -/* -* Qt Mutex -* (C) 2004-2007 Justin Karneges -* 2004-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_MUTEX_QT_H__ -#define BOTAN_MUTEX_QT_H__ - -#include <botan/internal/mutex.h> - -namespace Botan { - -/** -* Qt Mutex -*/ -class Qt_Mutex_Factory : public Mutex_Factory - { - public: - Mutex* make(); - }; - -} - -#endif diff --git a/src/mutex/win32_crit_section/info.txt b/src/mutex/win32_crit_section/info.txt deleted file mode 100644 index d90b8b64b..000000000 --- a/src/mutex/win32_crit_section/info.txt +++ /dev/null @@ -1,15 +0,0 @@ -define MUTEX_WIN32 - -<source> -mux_win32.cpp -</source> - -<header:internal> -mux_win32.h -</header:internal> - -<os> -cygwin -windows -mingw -</os> diff --git a/src/mutex/win32_crit_section/mux_win32.cpp b/src/mutex/win32_crit_section/mux_win32.cpp deleted file mode 100644 index fa6051798..000000000 --- a/src/mutex/win32_crit_section/mux_win32.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* -* Win32 Mutex -* (C) 2006 Luca Piccarreta -* 2006-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/internal/mux_win32.h> -#include <windows.h> - -namespace Botan { - -/* -* Win32 Mutex Factory -*/ -Mutex* Win32_Mutex_Factory::make() - { - class Win32_Mutex : public Mutex - { - public: - void lock() { EnterCriticalSection(&mutex); } - void unlock() { LeaveCriticalSection(&mutex); } - - Win32_Mutex() { InitializeCriticalSection(&mutex); } - ~Win32_Mutex() { DeleteCriticalSection(&mutex); } - private: - CRITICAL_SECTION mutex; - }; - - return new Win32_Mutex(); - } - -} diff --git a/src/mutex/win32_crit_section/mux_win32.h b/src/mutex/win32_crit_section/mux_win32.h deleted file mode 100644 index 2aa51e18b..000000000 --- a/src/mutex/win32_crit_section/mux_win32.h +++ /dev/null @@ -1,26 +0,0 @@ -/* -* Win32 Mutex -* (C) 2006 Luca Piccarreta -* 2006-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_MUTEX_WIN32_H__ -#define BOTAN_MUTEX_WIN32_H__ - -#include <botan/internal/mutex.h> - -namespace Botan { - -/** -* Win32 Mutex Factory -*/ -class Win32_Mutex_Factory : public Mutex_Factory - { - public: - Mutex* make(); - }; -} - -#endif diff --git a/src/passhash/bcrypt/bcrypt.cpp b/src/passhash/bcrypt/bcrypt.cpp index bb2e9095a..eeb99399f 100644 --- a/src/passhash/bcrypt/bcrypt.cpp +++ b/src/passhash/bcrypt/bcrypt.cpp @@ -54,7 +54,7 @@ std::string bcrypt_base64_encode(const byte input[], size_t length) return b64; } -MemoryVector<byte> bcrypt_base64_decode(std::string input) +std::vector<byte> bcrypt_base64_decode(std::string input) { const byte OPENBSD_BASE64_SUB[256] = { 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, @@ -84,11 +84,11 @@ MemoryVector<byte> bcrypt_base64_decode(std::string input) for(size_t i = 0; i != input.size(); ++i) input[i] = OPENBSD_BASE64_SUB[static_cast<byte>(input[i])]; - return base64_decode(input); + return unlock(base64_decode(input)); } std::string make_bcrypt(const std::string& pass, - const MemoryRegion<byte>& salt, + const std::vector<byte>& salt, u16bit work_factor) { const byte magic[24] = { @@ -97,14 +97,14 @@ std::string make_bcrypt(const std::string& pass, 0x63, 0x72, 0x79, 0x44, 0x6F, 0x75, 0x62, 0x74 }; - MemoryVector<byte> ctext(magic, 24); + std::vector<byte> ctext(magic, magic + sizeof(magic)); Blowfish blowfish; // Include the trailing NULL byte blowfish.eks_key_schedule(reinterpret_cast<const byte*>(pass.c_str()), pass.length() + 1, - salt, + &salt[0], work_factor); for(size_t i = 0; i != 64; ++i) @@ -112,8 +112,13 @@ std::string make_bcrypt(const std::string& pass, std::string salt_b64 = bcrypt_base64_encode(&salt[0], salt.size()); - return "$2a$" + to_string(work_factor, 2) + "$" + salt_b64.substr(0, 22) + - bcrypt_base64_encode(&ctext[0], ctext.size() - 1); + std::string work_factor_str = std::to_string(work_factor); + if(work_factor_str.length() == 1) + work_factor_str = "0" + work_factor_str; + + return "$2a$" + work_factor_str + + "$" + salt_b64.substr(0, 22) + + bcrypt_base64_encode(&ctext[0], ctext.size() - 1); } } @@ -122,7 +127,7 @@ std::string generate_bcrypt(const std::string& pass, RandomNumberGenerator& rng, u16bit work_factor) { - return make_bcrypt(pass, rng.random_vec(16), work_factor); + return make_bcrypt(pass, unlock(rng.random_vec(16)), work_factor); } bool check_bcrypt(const std::string& pass, const std::string& hash) @@ -136,7 +141,7 @@ bool check_bcrypt(const std::string& pass, const std::string& hash) const u16bit workfactor = to_u32bit(hash.substr(4, 2)); - MemoryVector<byte> salt = bcrypt_base64_decode(hash.substr(7, 22)); + std::vector<byte> salt = bcrypt_base64_decode(hash.substr(7, 22)); const std::string compare = make_bcrypt(pass, salt, workfactor); diff --git a/src/passhash/passhash9/passhash9.cpp b/src/passhash/passhash9/passhash9.cpp index e1e37da1e..af7ed761b 100644 --- a/src/passhash/passhash9/passhash9.cpp +++ b/src/passhash/passhash9/passhash9.cpp @@ -40,7 +40,7 @@ MessageAuthenticationCode* get_pbkdf_prf(byte alg_id) } catch(Algorithm_Not_Found) {} - return 0; + return nullptr; } } @@ -53,17 +53,18 @@ std::string generate_passhash9(const std::string& pass, MessageAuthenticationCode* prf = get_pbkdf_prf(alg_id); if(!prf) - throw Invalid_Argument("Passhash9: Algorithm id " + to_string(alg_id) + + throw Invalid_Argument("Passhash9: Algorithm id " + + std::to_string(alg_id) + " is not defined"); PKCS5_PBKDF2 kdf(prf); // takes ownership of pointer - SecureVector<byte> salt(SALT_BYTES); + secure_vector<byte> salt(SALT_BYTES); rng.randomize(&salt[0], salt.size()); const size_t kdf_iterations = WORK_FACTOR_SCALE * work_factor; - SecureVector<byte> pbkdf2_output = + secure_vector<byte> pbkdf2_output = kdf.derive_key(PASSHASH9_PBKDF_OUTPUT_LEN, pass, &salt[0], salt.size(), @@ -104,7 +105,7 @@ bool check_passhash9(const std::string& pass, const std::string& hash) pipe.write(hash.c_str() + MAGIC_PREFIX.size()); pipe.end_msg(); - SecureVector<byte> bin = pipe.read_all(); + secure_vector<byte> bin = pipe.read_all(); if(bin.size() != BINARY_LENGTH) return false; @@ -119,12 +120,12 @@ bool check_passhash9(const std::string& pass, const std::string& hash) MessageAuthenticationCode* pbkdf_prf = get_pbkdf_prf(alg_id); - if(pbkdf_prf == 0) + if(!pbkdf_prf) return false; // unknown algorithm, reject PKCS5_PBKDF2 kdf(pbkdf_prf); // takes ownership of pointer - SecureVector<byte> cmp = kdf.derive_key( + secure_vector<byte> cmp = kdf.derive_key( PASSHASH9_PBKDF_OUTPUT_LEN, pass, &bin[ALGID_BYTES + WORKFACTOR_BYTES], SALT_BYTES, diff --git a/src/pbe/pbe.h b/src/pbe/pbe.h index 9add98872..975f3e6c7 100644 --- a/src/pbe/pbe.h +++ b/src/pbe/pbe.h @@ -37,7 +37,7 @@ class BOTAN_DLL PBE : public Filter * DER encode the params (the number of iterations and the salt value) * @return encoded params */ - virtual MemoryVector<byte> encode_params() const = 0; + virtual std::vector<byte> encode_params() const = 0; /** * Decode params and use them inside this Filter. diff --git a/src/pbe/pbes1/pbes1.cpp b/src/pbe/pbes1/pbes1.cpp index ec5ebb253..0e5e8284c 100644 --- a/src/pbe/pbes1/pbes1.cpp +++ b/src/pbe/pbes1/pbes1.cpp @@ -65,7 +65,7 @@ void PBE_PKCS5v15::flush_pipe(bool safe_to_skip) if(safe_to_skip && pipe.remaining() < 64) return; - SecureVector<byte> buffer(DEFAULT_BUFFERSIZE); + secure_vector<byte> buffer(DEFAULT_BUFFERSIZE); while(pipe.remaining()) { size_t got = pipe.read(&buffer[0], buffer.size()); @@ -80,7 +80,7 @@ void PBE_PKCS5v15::set_key(const std::string& passphrase) { PKCS5_PBKDF1 pbkdf(hash_function->clone()); - SecureVector<byte> key_and_iv = pbkdf.derive_key(16, passphrase, + secure_vector<byte> key_and_iv = pbkdf.derive_key(16, passphrase, &salt[0], salt.size(), iterations).bits_of(); @@ -102,14 +102,14 @@ void PBE_PKCS5v15::new_params(RandomNumberGenerator& rng) /* * Encode PKCS#5 PBES1 parameters */ -MemoryVector<byte> PBE_PKCS5v15::encode_params() const +std::vector<byte> PBE_PKCS5v15::encode_params() const { return DER_Encoder() .start_cons(SEQUENCE) .encode(salt, OCTET_STRING) .encode(iterations) .end_cons() - .get_contents(); + .get_contents_unlocked(); } /* diff --git a/src/pbe/pbes1/pbes1.h b/src/pbe/pbes1/pbes1.h index e10cbbb53..bbdbd5b9d 100644 --- a/src/pbe/pbes1/pbes1.h +++ b/src/pbe/pbes1/pbes1.h @@ -40,7 +40,7 @@ class BOTAN_DLL PBE_PKCS5v15 : public PBE private: void set_key(const std::string&); void new_params(RandomNumberGenerator& rng); - MemoryVector<byte> encode_params() const; + std::vector<byte> encode_params() const; void decode_params(DataSource&); OID get_oid() const; @@ -50,7 +50,7 @@ class BOTAN_DLL PBE_PKCS5v15 : public PBE BlockCipher* block_cipher; HashFunction* hash_function; - SecureVector<byte> salt, key, iv; + secure_vector<byte> salt, key, iv; size_t iterations; Pipe pipe; }; diff --git a/src/pbe/pbes2/pbes2.cpp b/src/pbe/pbes2/pbes2.cpp index 85afe6ffe..752a4fb6d 100644 --- a/src/pbe/pbes2/pbes2.cpp +++ b/src/pbe/pbes2/pbes2.cpp @@ -72,7 +72,7 @@ void PBE_PKCS5v20::flush_pipe(bool safe_to_skip) if(safe_to_skip && pipe.remaining() < 64) return; - SecureVector<byte> buffer(DEFAULT_BUFFERSIZE); + secure_vector<byte> buffer(DEFAULT_BUFFERSIZE); while(pipe.remaining()) { size_t got = pipe.read(&buffer[0], buffer.size()); @@ -107,7 +107,7 @@ void PBE_PKCS5v20::new_params(RandomNumberGenerator& rng) /* * Encode PKCS#5 PBES2 parameters */ -MemoryVector<byte> PBE_PKCS5v20::encode_params() const +std::vector<byte> PBE_PKCS5v20::encode_params() const { return DER_Encoder() .start_cons(SEQUENCE) @@ -119,18 +119,18 @@ MemoryVector<byte> PBE_PKCS5v20::encode_params() const .encode(iterations) .encode(key_length) .end_cons() - .get_contents() + .get_contents_unlocked() ) ) .encode( AlgorithmIdentifier(block_cipher->name() + "/CBC", DER_Encoder() .encode(iv, OCTET_STRING) - .get_contents() + .get_contents_unlocked() ) ) .end_cons() - .get_contents(); + .get_contents_unlocked(); } /* @@ -228,8 +228,8 @@ PBE_PKCS5v20::PBE_PKCS5v20(BlockCipher* cipher, */ PBE_PKCS5v20::PBE_PKCS5v20(DataSource& params) : direction(DECRYPTION) { - hash_function = 0; - block_cipher = 0; + hash_function = nullptr; + block_cipher = nullptr; decode_params(params); } diff --git a/src/pbe/pbes2/pbes2.h b/src/pbe/pbes2/pbes2.h index 7b82980e5..5593c9091 100644 --- a/src/pbe/pbes2/pbes2.h +++ b/src/pbe/pbes2/pbes2.h @@ -49,7 +49,7 @@ class BOTAN_DLL PBE_PKCS5v20 : public PBE private: void set_key(const std::string&); void new_params(RandomNumberGenerator& rng); - MemoryVector<byte> encode_params() const; + std::vector<byte> encode_params() const; void decode_params(DataSource&); OID get_oid() const; @@ -58,7 +58,7 @@ class BOTAN_DLL PBE_PKCS5v20 : public PBE Cipher_Dir direction; BlockCipher* block_cipher; HashFunction* hash_function; - SecureVector<byte> salt, key, iv; + secure_vector<byte> salt, key, iv; size_t iterations, key_length; Pipe pipe; }; diff --git a/src/pbkdf/pbkdf1/pbkdf1.cpp b/src/pbkdf/pbkdf1/pbkdf1.cpp index 16de435e9..7f0939b8f 100644 --- a/src/pbkdf/pbkdf1/pbkdf1.cpp +++ b/src/pbkdf/pbkdf1/pbkdf1.cpp @@ -26,7 +26,7 @@ OctetString PKCS5_PBKDF1::derive_key(size_t key_len, hash->update(passphrase); hash->update(salt, salt_size); - SecureVector<byte> key = hash->final(); + secure_vector<byte> key = hash->final(); for(size_t j = 1; j != iterations; ++j) { diff --git a/src/pbkdf/pbkdf2/pbkdf2.cpp b/src/pbkdf/pbkdf2/pbkdf2.cpp index 7e4d1cd8a..699ce7c6b 100644 --- a/src/pbkdf/pbkdf2/pbkdf2.cpp +++ b/src/pbkdf/pbkdf2/pbkdf2.cpp @@ -30,14 +30,14 @@ OctetString PKCS5_PBKDF2::derive_key(size_t key_len, catch(Invalid_Key_Length) { throw Exception(name() + " cannot accept passphrases of length " + - to_string(passphrase.length())); + std::to_string(passphrase.length())); } - SecureVector<byte> key(key_len); + secure_vector<byte> key(key_len); byte* T = &key[0]; - SecureVector<byte> U(mac->output_length()); + secure_vector<byte> U(mac->output_length()); u32bit counter = 1; while(key_len) @@ -48,13 +48,13 @@ OctetString PKCS5_PBKDF2::derive_key(size_t key_len, mac->update_be(counter); mac->final(&U[0]); - xor_buf(T, U, T_size); + xor_buf(T, &U[0], T_size); for(size_t j = 1; j != iterations; ++j) { mac->update(U); mac->final(&U[0]); - xor_buf(T, U, T_size); + xor_buf(T, &U[0], T_size); } key_len -= T_size; diff --git a/src/pbkdf/pgps2k/pgp_s2k.cpp b/src/pbkdf/pgps2k/pgp_s2k.cpp index 9cec7304c..6f6de58e2 100644 --- a/src/pbkdf/pgps2k/pgp_s2k.cpp +++ b/src/pbkdf/pgps2k/pgp_s2k.cpp @@ -17,7 +17,7 @@ OctetString OpenPGP_S2K::derive_key(size_t key_len, const byte salt_buf[], size_t salt_size, size_t iterations) const { - SecureVector<byte> key(key_len), hash_buf; + secure_vector<byte> key(key_len), hash_buf; size_t pass = 0, generated = 0, total_size = passphrase.size() + salt_size; @@ -46,7 +46,7 @@ OctetString OpenPGP_S2K::derive_key(size_t key_len, } hash_buf = hash->final(); - key.copy(generated, &hash_buf[0], hash->output_length()); + buffer_insert(key, generated, &hash_buf[0], hash->output_length()); generated += hash->output_length(); ++pass; } diff --git a/src/pk_pad/eme.cpp b/src/pk_pad/eme.cpp index cfdaa240d..f90239d8c 100644 --- a/src/pk_pad/eme.cpp +++ b/src/pk_pad/eme.cpp @@ -12,7 +12,7 @@ namespace Botan { /* * Encode a message */ -SecureVector<byte> EME::encode(const byte msg[], size_t msg_len, +secure_vector<byte> EME::encode(const byte msg[], size_t msg_len, size_t key_bits, RandomNumberGenerator& rng) const { @@ -22,7 +22,7 @@ SecureVector<byte> EME::encode(const byte msg[], size_t msg_len, /* * Encode a message */ -SecureVector<byte> EME::encode(const MemoryRegion<byte>& msg, +secure_vector<byte> EME::encode(const secure_vector<byte>& msg, size_t key_bits, RandomNumberGenerator& rng) const { @@ -32,7 +32,7 @@ SecureVector<byte> EME::encode(const MemoryRegion<byte>& msg, /* * Decode a message */ -SecureVector<byte> EME::decode(const byte msg[], size_t msg_len, +secure_vector<byte> EME::decode(const byte msg[], size_t msg_len, size_t key_bits) const { return unpad(msg, msg_len, key_bits); @@ -41,7 +41,7 @@ SecureVector<byte> EME::decode(const byte msg[], size_t msg_len, /* * Decode a message */ -SecureVector<byte> EME::decode(const MemoryRegion<byte>& msg, +secure_vector<byte> EME::decode(const secure_vector<byte>& msg, size_t key_bits) const { return unpad(&msg[0], msg.size(), key_bits); diff --git a/src/pk_pad/eme.h b/src/pk_pad/eme.h index 4e89ef9d3..6f8acaa23 100644 --- a/src/pk_pad/eme.h +++ b/src/pk_pad/eme.h @@ -34,7 +34,7 @@ class BOTAN_DLL EME * @param rng a random number generator * @return encoded plaintext */ - SecureVector<byte> encode(const byte in[], + secure_vector<byte> encode(const byte in[], size_t in_length, size_t key_length, RandomNumberGenerator& rng) const; @@ -46,7 +46,7 @@ class BOTAN_DLL EME * @param rng a random number generator * @return encoded plaintext */ - SecureVector<byte> encode(const MemoryRegion<byte>& in, + secure_vector<byte> encode(const secure_vector<byte>& in, size_t key_length, RandomNumberGenerator& rng) const; @@ -57,7 +57,7 @@ class BOTAN_DLL EME * @param key_length length of the key in bits * @return plaintext */ - SecureVector<byte> decode(const byte in[], + secure_vector<byte> decode(const byte in[], size_t in_length, size_t key_length) const; @@ -67,7 +67,7 @@ class BOTAN_DLL EME * @param key_length length of the key in bits * @return plaintext */ - SecureVector<byte> decode(const MemoryRegion<byte>& in, + secure_vector<byte> decode(const secure_vector<byte>& in, size_t key_length) const; virtual ~EME() {} @@ -80,7 +80,7 @@ class BOTAN_DLL EME * @param rng a random number generator * @return encoded plaintext */ - virtual SecureVector<byte> pad(const byte in[], + virtual secure_vector<byte> pad(const byte in[], size_t in_length, size_t key_length, RandomNumberGenerator& rng) const = 0; @@ -92,7 +92,7 @@ class BOTAN_DLL EME * @param key_length length of the key in bits * @return plaintext */ - virtual SecureVector<byte> unpad(const byte in[], + virtual secure_vector<byte> unpad(const byte in[], size_t in_length, size_t key_length) const = 0; }; diff --git a/src/pk_pad/eme1/eme1.cpp b/src/pk_pad/eme1/eme1.cpp index 1cc0c332d..57275d4f9 100644 --- a/src/pk_pad/eme1/eme1.cpp +++ b/src/pk_pad/eme1/eme1.cpp @@ -15,7 +15,7 @@ namespace Botan { /* * EME1 Pad Operation */ -SecureVector<byte> EME1::pad(const byte in[], size_t in_length, +secure_vector<byte> EME1::pad(const byte in[], size_t in_length, size_t key_length, RandomNumberGenerator& rng) const { @@ -24,13 +24,13 @@ SecureVector<byte> EME1::pad(const byte in[], size_t in_length, if(in_length > key_length - 2*Phash.size() - 1) throw Invalid_Argument("EME1: Input is too large"); - SecureVector<byte> out(key_length); + secure_vector<byte> out(key_length); rng.randomize(&out[0], Phash.size()); - out.copy(Phash.size(), &Phash[0], Phash.size()); + buffer_insert(out, Phash.size(), &Phash[0], Phash.size()); out[out.size() - in_length - 1] = 0x01; - out.copy(out.size() - in_length, in, in_length); + buffer_insert(out, out.size() - in_length, in, in_length); mgf->mask(&out[0], Phash.size(), &out[Phash.size()], out.size() - Phash.size()); @@ -44,7 +44,7 @@ SecureVector<byte> EME1::pad(const byte in[], size_t in_length, /* * EME1 Unpad Operation */ -SecureVector<byte> EME1::unpad(const byte in[], size_t in_length, +secure_vector<byte> EME1::unpad(const byte in[], size_t in_length, size_t key_length) const { /* @@ -65,8 +65,8 @@ SecureVector<byte> EME1::unpad(const byte in[], size_t in_length, if(in_length > key_length) in_length = 0; - SecureVector<byte> input(key_length); - input.copy(key_length - in_length, in, in_length); + secure_vector<byte> input(key_length); + buffer_insert(input, key_length - in_length, in, in_length); mgf->mask(&input[Phash.size()], input.size() - Phash.size(), &input[0], Phash.size()); @@ -104,8 +104,7 @@ SecureVector<byte> EME1::unpad(const byte in[], size_t in_length, if(bad_input) throw Decoding_Error("Invalid EME1 encoding"); - return SecureVector<byte>(input + delim_idx + 1, - input.size() - delim_idx - 1); + return secure_vector<byte>(&input[delim_idx + 1], &input[input.size()]); } /* diff --git a/src/pk_pad/eme1/eme1.h b/src/pk_pad/eme1/eme1.h index 0d0223de0..eb6fc6bf5 100644 --- a/src/pk_pad/eme1/eme1.h +++ b/src/pk_pad/eme1/eme1.h @@ -30,11 +30,11 @@ class BOTAN_DLL EME1 : public EME ~EME1() { delete mgf; } private: - SecureVector<byte> pad(const byte[], size_t, size_t, + secure_vector<byte> pad(const byte[], size_t, size_t, RandomNumberGenerator&) const; - SecureVector<byte> unpad(const byte[], size_t, size_t) const; + secure_vector<byte> unpad(const byte[], size_t, size_t) const; - SecureVector<byte> Phash; + secure_vector<byte> Phash; MGF* mgf; }; diff --git a/src/pk_pad/eme_pkcs/eme_pkcs.cpp b/src/pk_pad/eme_pkcs/eme_pkcs.cpp index c4d6838b1..0e7d1fc30 100644 --- a/src/pk_pad/eme_pkcs/eme_pkcs.cpp +++ b/src/pk_pad/eme_pkcs/eme_pkcs.cpp @@ -12,7 +12,7 @@ namespace Botan { /* * PKCS1 Pad Operation */ -SecureVector<byte> EME_PKCS1v15::pad(const byte in[], size_t inlen, +secure_vector<byte> EME_PKCS1v15::pad(const byte in[], size_t inlen, size_t olen, RandomNumberGenerator& rng) const { @@ -23,13 +23,13 @@ SecureVector<byte> EME_PKCS1v15::pad(const byte in[], size_t inlen, if(inlen > olen - 10) throw Encoding_Error("PKCS1: Input is too large"); - SecureVector<byte> out(olen); + secure_vector<byte> out(olen); out[0] = 0x02; for(size_t j = 1; j != olen - inlen - 1; ++j) while(out[j] == 0) out[j] = rng.next_byte(); - out.copy(olen - inlen, in, inlen); + buffer_insert(out, olen - inlen, in, inlen); return out; } @@ -37,7 +37,7 @@ SecureVector<byte> EME_PKCS1v15::pad(const byte in[], size_t inlen, /* * PKCS1 Unpad Operation */ -SecureVector<byte> EME_PKCS1v15::unpad(const byte in[], size_t inlen, +secure_vector<byte> EME_PKCS1v15::unpad(const byte in[], size_t inlen, size_t key_len) const { if(inlen != key_len / 8 || inlen < 10 || in[0] != 0x02) @@ -53,7 +53,7 @@ SecureVector<byte> EME_PKCS1v15::unpad(const byte in[], size_t inlen, if(seperator < 9) throw Decoding_Error("PKCS1::unpad"); - return SecureVector<byte>(in + seperator + 1, inlen - seperator - 1); + return secure_vector<byte>(&in[seperator + 1], &in[inlen]); } /* diff --git a/src/pk_pad/eme_pkcs/eme_pkcs.h b/src/pk_pad/eme_pkcs/eme_pkcs.h index 4c4614bda..2808e18d6 100644 --- a/src/pk_pad/eme_pkcs/eme_pkcs.h +++ b/src/pk_pad/eme_pkcs/eme_pkcs.h @@ -20,9 +20,9 @@ class BOTAN_DLL EME_PKCS1v15 : public EME public: size_t maximum_input_size(size_t) const; private: - SecureVector<byte> pad(const byte[], size_t, size_t, + secure_vector<byte> pad(const byte[], size_t, size_t, RandomNumberGenerator&) const; - SecureVector<byte> unpad(const byte[], size_t, size_t) const; + secure_vector<byte> unpad(const byte[], size_t, size_t) const; }; } diff --git a/src/pk_pad/emsa.h b/src/pk_pad/emsa.h index e943fc5eb..821ca782f 100644 --- a/src/pk_pad/emsa.h +++ b/src/pk_pad/emsa.h @@ -29,7 +29,7 @@ class BOTAN_DLL EMSA /** * @return raw hash */ - virtual SecureVector<byte> raw_data() = 0; + virtual secure_vector<byte> raw_data() = 0; /** * Return the encoding of a message @@ -38,7 +38,7 @@ class BOTAN_DLL EMSA * @param rng a random number generator * @return encoded signature */ - virtual SecureVector<byte> encoding_of(const MemoryRegion<byte>& msg, + virtual secure_vector<byte> encoding_of(const secure_vector<byte>& msg, size_t output_bits, RandomNumberGenerator& rng) = 0; @@ -49,8 +49,8 @@ class BOTAN_DLL EMSA * @param key_bits the size of the key in bits * @return true if coded is a valid encoding of raw, otherwise false */ - virtual bool verify(const MemoryRegion<byte>& coded, - const MemoryRegion<byte>& raw, + virtual bool verify(const secure_vector<byte>& coded, + const secure_vector<byte>& raw, size_t key_bits) = 0; virtual ~EMSA() {} }; diff --git a/src/pk_pad/emsa1/emsa1.cpp b/src/pk_pad/emsa1/emsa1.cpp index ba861898a..7f9a1885f 100644 --- a/src/pk_pad/emsa1/emsa1.cpp +++ b/src/pk_pad/emsa1/emsa1.cpp @@ -11,7 +11,7 @@ namespace Botan { namespace { -SecureVector<byte> emsa1_encoding(const MemoryRegion<byte>& msg, +secure_vector<byte> emsa1_encoding(const secure_vector<byte>& msg, size_t output_bits) { if(8*msg.size() <= output_bits) @@ -20,7 +20,7 @@ SecureVector<byte> emsa1_encoding(const MemoryRegion<byte>& msg, size_t shift = 8*msg.size() - output_bits; size_t byte_shift = shift / 8, bit_shift = shift % 8; - SecureVector<byte> digest(msg.size() - byte_shift); + secure_vector<byte> digest(msg.size() - byte_shift); for(size_t j = 0; j != msg.size() - byte_shift; ++j) digest[j] = msg[j]; @@ -51,7 +51,7 @@ void EMSA1::update(const byte input[], size_t length) /* * Return the raw (unencoded) data */ -SecureVector<byte> EMSA1::raw_data() +secure_vector<byte> EMSA1::raw_data() { return hash->final(); } @@ -59,7 +59,7 @@ SecureVector<byte> EMSA1::raw_data() /* * EMSA1 Encode Operation */ -SecureVector<byte> EMSA1::encoding_of(const MemoryRegion<byte>& msg, +secure_vector<byte> EMSA1::encoding_of(const secure_vector<byte>& msg, size_t output_bits, RandomNumberGenerator&) { @@ -71,14 +71,14 @@ SecureVector<byte> EMSA1::encoding_of(const MemoryRegion<byte>& msg, /* * EMSA1 Decode/Verify Operation */ -bool EMSA1::verify(const MemoryRegion<byte>& coded, - const MemoryRegion<byte>& raw, size_t key_bits) +bool EMSA1::verify(const secure_vector<byte>& coded, + const secure_vector<byte>& raw, size_t key_bits) { try { if(raw.size() != hash->output_length()) throw Encoding_Error("EMSA1::encoding_of: Invalid size for input"); - SecureVector<byte> our_coding = emsa1_encoding(raw, key_bits); + secure_vector<byte> our_coding = emsa1_encoding(raw, key_bits); if(our_coding == coded) return true; if(our_coding[0] != 0) return false; diff --git a/src/pk_pad/emsa1/emsa1.h b/src/pk_pad/emsa1/emsa1.h index 120cb0cd3..f84ca5ae7 100644 --- a/src/pk_pad/emsa1/emsa1.h +++ b/src/pk_pad/emsa1/emsa1.h @@ -32,12 +32,12 @@ class BOTAN_DLL EMSA1 : public EMSA const HashFunction* hash_ptr() const { return hash; } private: void update(const byte[], size_t); - SecureVector<byte> raw_data(); + secure_vector<byte> raw_data(); - SecureVector<byte> encoding_of(const MemoryRegion<byte>&, size_t, + secure_vector<byte> encoding_of(const secure_vector<byte>&, size_t, RandomNumberGenerator& rng); - bool verify(const MemoryRegion<byte>&, const MemoryRegion<byte>&, + bool verify(const secure_vector<byte>&, const secure_vector<byte>&, size_t); HashFunction* hash; diff --git a/src/pk_pad/emsa1_bsi/emsa1_bsi.cpp b/src/pk_pad/emsa1_bsi/emsa1_bsi.cpp index bbcc5aae7..9096edfbf 100644 --- a/src/pk_pad/emsa1_bsi/emsa1_bsi.cpp +++ b/src/pk_pad/emsa1_bsi/emsa1_bsi.cpp @@ -13,7 +13,7 @@ namespace Botan { /* * EMSA1 BSI Encode Operation */ -SecureVector<byte> EMSA1_BSI::encoding_of(const MemoryRegion<byte>& msg, +secure_vector<byte> EMSA1_BSI::encoding_of(const secure_vector<byte>& msg, size_t output_bits, RandomNumberGenerator&) { diff --git a/src/pk_pad/emsa1_bsi/emsa1_bsi.h b/src/pk_pad/emsa1_bsi/emsa1_bsi.h index 51ed6bc00..1b90f48df 100644 --- a/src/pk_pad/emsa1_bsi/emsa1_bsi.h +++ b/src/pk_pad/emsa1_bsi/emsa1_bsi.h @@ -26,7 +26,7 @@ class BOTAN_DLL EMSA1_BSI : public EMSA1 */ EMSA1_BSI(HashFunction* hash) : EMSA1(hash) {} private: - SecureVector<byte> encoding_of(const MemoryRegion<byte>&, size_t, + secure_vector<byte> encoding_of(const secure_vector<byte>&, size_t, RandomNumberGenerator& rng); }; diff --git a/src/pk_pad/emsa2/emsa2.cpp b/src/pk_pad/emsa2/emsa2.cpp index 96ac8e908..d299ddacd 100644 --- a/src/pk_pad/emsa2/emsa2.cpp +++ b/src/pk_pad/emsa2/emsa2.cpp @@ -15,9 +15,9 @@ namespace { /* * EMSA2 Encode Operation */ -SecureVector<byte> emsa2_encoding(const MemoryRegion<byte>& msg, +secure_vector<byte> emsa2_encoding(const secure_vector<byte>& msg, size_t output_bits, - const MemoryRegion<byte>& empty_hash, + const secure_vector<byte>& empty_hash, byte hash_id) { const size_t HASH_SIZE = empty_hash.size(); @@ -34,12 +34,12 @@ SecureVector<byte> emsa2_encoding(const MemoryRegion<byte>& msg, if(empty_hash[j] != msg[j]) empty = false; - SecureVector<byte> output(output_length); + secure_vector<byte> output(output_length); output[0] = (empty ? 0x4B : 0x6B); output[output_length - 3 - HASH_SIZE] = 0xBA; set_mem(&output[1], output_length - 4 - HASH_SIZE, 0xBB); - output.copy(output_length - (HASH_SIZE + 2), &msg[0], msg.size()); + buffer_insert(output, output_length - (HASH_SIZE + 2), &msg[0], msg.size()); output[output_length-2] = hash_id; output[output_length-1] = 0xCC; @@ -59,7 +59,7 @@ void EMSA2::update(const byte input[], size_t length) /* * Return the raw (unencoded) data */ -SecureVector<byte> EMSA2::raw_data() +secure_vector<byte> EMSA2::raw_data() { return hash->final(); } @@ -67,7 +67,7 @@ SecureVector<byte> EMSA2::raw_data() /* * EMSA2 Encode Operation */ -SecureVector<byte> EMSA2::encoding_of(const MemoryRegion<byte>& msg, +secure_vector<byte> EMSA2::encoding_of(const secure_vector<byte>& msg, size_t output_bits, RandomNumberGenerator&) { @@ -77,8 +77,8 @@ SecureVector<byte> EMSA2::encoding_of(const MemoryRegion<byte>& msg, /* * EMSA2 Verify Operation */ -bool EMSA2::verify(const MemoryRegion<byte>& coded, - const MemoryRegion<byte>& raw, +bool EMSA2::verify(const secure_vector<byte>& coded, + const secure_vector<byte>& raw, size_t key_bits) { try diff --git a/src/pk_pad/emsa2/emsa2.h b/src/pk_pad/emsa2/emsa2.h index 9e0fa6a95..fb0cecb21 100644 --- a/src/pk_pad/emsa2/emsa2.h +++ b/src/pk_pad/emsa2/emsa2.h @@ -27,15 +27,15 @@ class BOTAN_DLL EMSA2 : public EMSA ~EMSA2() { delete hash; } private: void update(const byte[], size_t); - SecureVector<byte> raw_data(); + secure_vector<byte> raw_data(); - SecureVector<byte> encoding_of(const MemoryRegion<byte>&, size_t, + secure_vector<byte> encoding_of(const secure_vector<byte>&, size_t, RandomNumberGenerator& rng); - bool verify(const MemoryRegion<byte>&, const MemoryRegion<byte>&, + bool verify(const secure_vector<byte>&, const secure_vector<byte>&, size_t); - SecureVector<byte> empty_hash; + secure_vector<byte> empty_hash; HashFunction* hash; byte hash_id; }; diff --git a/src/pk_pad/emsa3/emsa3.cpp b/src/pk_pad/emsa3/emsa3.cpp index a381a82f6..0d603c508 100644 --- a/src/pk_pad/emsa3/emsa3.cpp +++ b/src/pk_pad/emsa3/emsa3.cpp @@ -15,7 +15,7 @@ namespace { /* * EMSA3 Encode Operation */ -SecureVector<byte> emsa3_encoding(const MemoryRegion<byte>& msg, +secure_vector<byte> emsa3_encoding(const secure_vector<byte>& msg, size_t output_bits, const byte hash_id[], size_t hash_id_length) @@ -24,14 +24,14 @@ SecureVector<byte> emsa3_encoding(const MemoryRegion<byte>& msg, if(output_length < hash_id_length + msg.size() + 10) throw Encoding_Error("emsa3_encoding: Output length is too small"); - SecureVector<byte> T(output_length); + secure_vector<byte> T(output_length); const size_t P_LENGTH = output_length - msg.size() - hash_id_length - 2; T[0] = 0x01; set_mem(&T[1], P_LENGTH, 0xFF); T[P_LENGTH+1] = 0x00; - T.copy(P_LENGTH+2, hash_id, hash_id_length); - T.copy(output_length-msg.size(), &msg[0], msg.size()); + buffer_insert(T, P_LENGTH+2, hash_id, hash_id_length); + buffer_insert(T, output_length-msg.size(), &msg[0], msg.size()); return T; } @@ -48,7 +48,7 @@ void EMSA3::update(const byte input[], size_t length) /* * Return the raw (unencoded) data */ -SecureVector<byte> EMSA3::raw_data() +secure_vector<byte> EMSA3::raw_data() { return hash->final(); } @@ -56,7 +56,7 @@ SecureVector<byte> EMSA3::raw_data() /* * EMSA3 Encode Operation */ -SecureVector<byte> EMSA3::encoding_of(const MemoryRegion<byte>& msg, +secure_vector<byte> EMSA3::encoding_of(const secure_vector<byte>& msg, size_t output_bits, RandomNumberGenerator&) { @@ -70,8 +70,8 @@ SecureVector<byte> EMSA3::encoding_of(const MemoryRegion<byte>& msg, /* * Default signature decoding */ -bool EMSA3::verify(const MemoryRegion<byte>& coded, - const MemoryRegion<byte>& raw, +bool EMSA3::verify(const secure_vector<byte>& coded, + const secure_vector<byte>& raw, size_t key_bits) { if(raw.size() != hash->output_length()) @@ -115,9 +115,9 @@ void EMSA3_Raw::update(const byte input[], size_t length) /* * Return the raw (unencoded) data */ -SecureVector<byte> EMSA3_Raw::raw_data() +secure_vector<byte> EMSA3_Raw::raw_data() { - SecureVector<byte> ret; + secure_vector<byte> ret; std::swap(ret, message); return ret; } @@ -125,23 +125,23 @@ SecureVector<byte> EMSA3_Raw::raw_data() /* * EMSA3_Raw Encode Operation */ -SecureVector<byte> EMSA3_Raw::encoding_of(const MemoryRegion<byte>& msg, +secure_vector<byte> EMSA3_Raw::encoding_of(const secure_vector<byte>& msg, size_t output_bits, RandomNumberGenerator&) { - return emsa3_encoding(msg, output_bits, 0, 0); + return emsa3_encoding(msg, output_bits, nullptr, 0); } /* * Default signature decoding */ -bool EMSA3_Raw::verify(const MemoryRegion<byte>& coded, - const MemoryRegion<byte>& raw, +bool EMSA3_Raw::verify(const secure_vector<byte>& coded, + const secure_vector<byte>& raw, size_t key_bits) { try { - return (coded == emsa3_encoding(raw, key_bits, 0, 0)); + return (coded == emsa3_encoding(raw, key_bits, nullptr, 0)); } catch(...) { diff --git a/src/pk_pad/emsa3/emsa3.h b/src/pk_pad/emsa3/emsa3.h index 5faf9d7e5..9fbda67ee 100644 --- a/src/pk_pad/emsa3/emsa3.h +++ b/src/pk_pad/emsa3/emsa3.h @@ -29,16 +29,16 @@ class BOTAN_DLL EMSA3 : public EMSA void update(const byte[], size_t); - SecureVector<byte> raw_data(); + secure_vector<byte> raw_data(); - SecureVector<byte> encoding_of(const MemoryRegion<byte>&, size_t, + secure_vector<byte> encoding_of(const secure_vector<byte>&, size_t, RandomNumberGenerator& rng); - bool verify(const MemoryRegion<byte>&, const MemoryRegion<byte>&, + bool verify(const secure_vector<byte>&, const secure_vector<byte>&, size_t); private: HashFunction* hash; - SecureVector<byte> hash_id; + std::vector<byte> hash_id; }; /** @@ -51,16 +51,16 @@ class BOTAN_DLL EMSA3_Raw : public EMSA public: void update(const byte[], size_t); - SecureVector<byte> raw_data(); + secure_vector<byte> raw_data(); - SecureVector<byte> encoding_of(const MemoryRegion<byte>&, size_t, + secure_vector<byte> encoding_of(const secure_vector<byte>&, size_t, RandomNumberGenerator& rng); - bool verify(const MemoryRegion<byte>&, const MemoryRegion<byte>&, + bool verify(const secure_vector<byte>&, const secure_vector<byte>&, size_t); private: - SecureVector<byte> message; + secure_vector<byte> message; }; } diff --git a/src/pk_pad/emsa4/emsa4.cpp b/src/pk_pad/emsa4/emsa4.cpp index ef88e1953..c8b8cbc6a 100644 --- a/src/pk_pad/emsa4/emsa4.cpp +++ b/src/pk_pad/emsa4/emsa4.cpp @@ -22,7 +22,7 @@ void EMSA4::update(const byte input[], size_t length) /* * Return the raw (unencoded) data */ -SecureVector<byte> EMSA4::raw_data() +secure_vector<byte> EMSA4::raw_data() { return hash->final(); } @@ -30,7 +30,7 @@ SecureVector<byte> EMSA4::raw_data() /* * EMSA4 Encode Operation */ -SecureVector<byte> EMSA4::encoding_of(const MemoryRegion<byte>& msg, +secure_vector<byte> EMSA4::encoding_of(const secure_vector<byte>& msg, size_t output_bits, RandomNumberGenerator& rng) { @@ -43,21 +43,21 @@ SecureVector<byte> EMSA4::encoding_of(const MemoryRegion<byte>& msg, const size_t output_length = (output_bits + 7) / 8; - SecureVector<byte> salt = rng.random_vec(SALT_SIZE); + secure_vector<byte> salt = rng.random_vec(SALT_SIZE); for(size_t j = 0; j != 8; ++j) hash->update(0); hash->update(msg); - hash->update(salt, SALT_SIZE); - SecureVector<byte> H = hash->final(); + hash->update(salt); + secure_vector<byte> H = hash->final(); - SecureVector<byte> EM(output_length); + secure_vector<byte> EM(output_length); EM[output_length - HASH_SIZE - SALT_SIZE - 2] = 0x01; - EM.copy(output_length - 1 - HASH_SIZE - SALT_SIZE, salt, SALT_SIZE); - mgf->mask(H, HASH_SIZE, EM, output_length - HASH_SIZE - 1); + buffer_insert(EM, output_length - 1 - HASH_SIZE - SALT_SIZE, salt); + mgf->mask(&H[0], HASH_SIZE, &EM[0], output_length - HASH_SIZE - 1); EM[0] &= 0xFF >> (8 * ((output_bits + 7) / 8) - output_bits); - EM.copy(output_length - 1 - HASH_SIZE, H, HASH_SIZE); + buffer_insert(EM, output_length - 1 - HASH_SIZE, H); EM[output_length-1] = 0xBC; return EM; @@ -66,26 +66,29 @@ SecureVector<byte> EMSA4::encoding_of(const MemoryRegion<byte>& msg, /* * EMSA4 Decode/Verify Operation */ -bool EMSA4::verify(const MemoryRegion<byte>& const_coded, - const MemoryRegion<byte>& raw, size_t key_bits) +bool EMSA4::verify(const secure_vector<byte>& const_coded, + const secure_vector<byte>& raw, size_t key_bits) { const size_t HASH_SIZE = hash->output_length(); const size_t KEY_BYTES = (key_bits + 7) / 8; if(key_bits < 8*HASH_SIZE + 9) return false; + if(raw.size() != HASH_SIZE) return false; - if(const_coded.size() > KEY_BYTES) + + if(const_coded.size() > KEY_BYTES || const_coded.size() <= 1) return false; + if(const_coded[const_coded.size()-1] != 0xBC) return false; - SecureVector<byte> coded = const_coded; + secure_vector<byte> coded = const_coded; if(coded.size() < KEY_BYTES) { - SecureVector<byte> temp(KEY_BYTES); - temp.copy(KEY_BYTES - coded.size(), coded, coded.size()); + secure_vector<byte> temp(KEY_BYTES); + buffer_insert(temp, KEY_BYTES - coded.size(), coded); coded = temp; } @@ -93,14 +96,17 @@ bool EMSA4::verify(const MemoryRegion<byte>& const_coded, if(TOP_BITS > 8 - high_bit(coded[0])) return false; - SecureVector<byte> DB(&coded[0], coded.size() - HASH_SIZE - 1); - SecureVector<byte> H(&coded[coded.size() - HASH_SIZE - 1], HASH_SIZE); + byte* DB = &coded[0]; + const size_t DB_size = coded.size() - HASH_SIZE - 1; - mgf->mask(H, H.size(), DB, coded.size() - H.size() - 1); + const byte* H = &coded[DB_size]; + const size_t H_size = HASH_SIZE; + + mgf->mask(&H[0], H_size, &DB[0], DB_size); DB[0] &= 0xFF >> TOP_BITS; size_t salt_offset = 0; - for(size_t j = 0; j != DB.size(); ++j) + for(size_t j = 0; j != DB_size; ++j) { if(DB[j] == 0x01) { salt_offset = j + 1; break; } @@ -110,15 +116,13 @@ bool EMSA4::verify(const MemoryRegion<byte>& const_coded, if(salt_offset == 0) return false; - SecureVector<byte> salt(&DB[salt_offset], DB.size() - salt_offset); - for(size_t j = 0; j != 8; ++j) hash->update(0); hash->update(raw); - hash->update(salt); - SecureVector<byte> H2 = hash->final(); + hash->update(&DB[salt_offset], DB_size - salt_offset); + secure_vector<byte> H2 = hash->final(); - return (H == H2); + return same_mem(&H[0], &H2[0], HASH_SIZE); } /* diff --git a/src/pk_pad/emsa4/emsa4.h b/src/pk_pad/emsa4/emsa4.h index bd8b32ca1..44bf5a429 100644 --- a/src/pk_pad/emsa4/emsa4.h +++ b/src/pk_pad/emsa4/emsa4.h @@ -34,11 +34,11 @@ class BOTAN_DLL EMSA4 : public EMSA ~EMSA4() { delete hash; delete mgf; } private: void update(const byte[], size_t); - SecureVector<byte> raw_data(); + secure_vector<byte> raw_data(); - SecureVector<byte> encoding_of(const MemoryRegion<byte>&, size_t, + secure_vector<byte> encoding_of(const secure_vector<byte>&, size_t, RandomNumberGenerator& rng); - bool verify(const MemoryRegion<byte>&, const MemoryRegion<byte>&, + bool verify(const secure_vector<byte>&, const secure_vector<byte>&, size_t); size_t SALT_SIZE; diff --git a/src/pk_pad/emsa_raw/emsa_raw.cpp b/src/pk_pad/emsa_raw/emsa_raw.cpp index d0f3918dd..cb0f99e9c 100644 --- a/src/pk_pad/emsa_raw/emsa_raw.cpp +++ b/src/pk_pad/emsa_raw/emsa_raw.cpp @@ -20,9 +20,9 @@ void EMSA_Raw::update(const byte input[], size_t length) /* * Return the raw (unencoded) data */ -SecureVector<byte> EMSA_Raw::raw_data() +secure_vector<byte> EMSA_Raw::raw_data() { - SecureVector<byte> output; + secure_vector<byte> output; std::swap(message, output); return output; } @@ -30,7 +30,7 @@ SecureVector<byte> EMSA_Raw::raw_data() /* * EMSA-Raw Encode Operation */ -SecureVector<byte> EMSA_Raw::encoding_of(const MemoryRegion<byte>& msg, +secure_vector<byte> EMSA_Raw::encoding_of(const secure_vector<byte>& msg, size_t, RandomNumberGenerator&) { @@ -40,8 +40,8 @@ SecureVector<byte> EMSA_Raw::encoding_of(const MemoryRegion<byte>& msg, /* * EMSA-Raw Verify Operation */ -bool EMSA_Raw::verify(const MemoryRegion<byte>& coded, - const MemoryRegion<byte>& raw, +bool EMSA_Raw::verify(const secure_vector<byte>& coded, + const secure_vector<byte>& raw, size_t) { if(coded.size() == raw.size()) diff --git a/src/pk_pad/emsa_raw/emsa_raw.h b/src/pk_pad/emsa_raw/emsa_raw.h index 2ccd076f2..8ab763575 100644 --- a/src/pk_pad/emsa_raw/emsa_raw.h +++ b/src/pk_pad/emsa_raw/emsa_raw.h @@ -20,14 +20,14 @@ class BOTAN_DLL EMSA_Raw : public EMSA { private: void update(const byte[], size_t); - SecureVector<byte> raw_data(); + secure_vector<byte> raw_data(); - SecureVector<byte> encoding_of(const MemoryRegion<byte>&, size_t, + secure_vector<byte> encoding_of(const secure_vector<byte>&, size_t, RandomNumberGenerator&); - bool verify(const MemoryRegion<byte>&, const MemoryRegion<byte>&, + bool verify(const secure_vector<byte>&, const secure_vector<byte>&, size_t); - SecureVector<byte> message; + secure_vector<byte> message; }; } diff --git a/src/pk_pad/hash_id/hash_id.cpp b/src/pk_pad/hash_id/hash_id.cpp index 74653cb83..a60e53352 100644 --- a/src/pk_pad/hash_id/hash_id.cpp +++ b/src/pk_pad/hash_id/hash_id.cpp @@ -57,32 +57,51 @@ const byte TIGER_PKCS_ID[] = { /* * HashID as specified by PKCS */ -MemoryVector<byte> pkcs_hash_id(const std::string& name) +std::vector<byte> pkcs_hash_id(const std::string& name) { // Special case for SSL/TLS RSA signatures if(name == "Parallel(MD5,SHA-160)") - return MemoryVector<byte>(); + return std::vector<byte>(); if(name == "MD2") - return MemoryVector<byte>(MD2_PKCS_ID, sizeof(MD2_PKCS_ID)); + return std::vector<byte>(MD2_PKCS_ID, + MD2_PKCS_ID + sizeof(MD2_PKCS_ID)); + if(name == "MD5") - return MemoryVector<byte>(MD5_PKCS_ID, sizeof(MD5_PKCS_ID)); + return std::vector<byte>(MD5_PKCS_ID, + MD5_PKCS_ID + sizeof(MD5_PKCS_ID)); + if(name == "RIPEMD-128") - return MemoryVector<byte>(RIPEMD_128_PKCS_ID, sizeof(RIPEMD_128_PKCS_ID)); + return std::vector<byte>(RIPEMD_128_PKCS_ID, + RIPEMD_128_PKCS_ID + sizeof(RIPEMD_128_PKCS_ID)); + if(name == "RIPEMD-160") - return MemoryVector<byte>(RIPEMD_160_PKCS_ID, sizeof(RIPEMD_160_PKCS_ID)); + return std::vector<byte>(RIPEMD_160_PKCS_ID, + RIPEMD_160_PKCS_ID + sizeof(RIPEMD_160_PKCS_ID)); + if(name == "SHA-160") - return MemoryVector<byte>(SHA_160_PKCS_ID, sizeof(SHA_160_PKCS_ID)); + return std::vector<byte>(SHA_160_PKCS_ID, + SHA_160_PKCS_ID + sizeof(SHA_160_PKCS_ID)); + if(name == "SHA-224") - return MemoryVector<byte>(SHA_224_PKCS_ID, sizeof(SHA_224_PKCS_ID)); + return std::vector<byte>(SHA_224_PKCS_ID, + SHA_224_PKCS_ID + sizeof(SHA_224_PKCS_ID)); + if(name == "SHA-256") - return MemoryVector<byte>(SHA_256_PKCS_ID, sizeof(SHA_256_PKCS_ID)); + return std::vector<byte>(SHA_256_PKCS_ID, + SHA_256_PKCS_ID + sizeof(SHA_256_PKCS_ID)); + if(name == "SHA-384") - return MemoryVector<byte>(SHA_384_PKCS_ID, sizeof(SHA_384_PKCS_ID)); + return std::vector<byte>(SHA_384_PKCS_ID, + SHA_384_PKCS_ID + sizeof(SHA_384_PKCS_ID)); + if(name == "SHA-512") - return MemoryVector<byte>(SHA_512_PKCS_ID, sizeof(SHA_512_PKCS_ID)); + return std::vector<byte>(SHA_512_PKCS_ID, + SHA_512_PKCS_ID + sizeof(SHA_512_PKCS_ID)); + if(name == "Tiger(24,3)") - return MemoryVector<byte>(TIGER_PKCS_ID, sizeof(TIGER_PKCS_ID)); + return std::vector<byte>(TIGER_PKCS_ID, + TIGER_PKCS_ID + sizeof(TIGER_PKCS_ID)); throw Invalid_Argument("No PKCS #1 identifier for " + name); } diff --git a/src/pk_pad/hash_id/hash_id.h b/src/pk_pad/hash_id/hash_id.h index 909cc6b19..070e7ddb9 100644 --- a/src/pk_pad/hash_id/hash_id.h +++ b/src/pk_pad/hash_id/hash_id.h @@ -20,7 +20,7 @@ namespace Botan { * @return byte sequence identifying the hash * @throw Invalid_Argument if the hash has no known PKCS #1 hash id */ -BOTAN_DLL MemoryVector<byte> pkcs_hash_id(const std::string& hash_name); +BOTAN_DLL std::vector<byte> pkcs_hash_id(const std::string& hash_name); /** * Return the IEEE 1363 hash identifier diff --git a/src/pubkey/dh/dh.cpp b/src/pubkey/dh/dh.cpp index d58fece12..04941af73 100644 --- a/src/pubkey/dh/dh.cpp +++ b/src/pubkey/dh/dh.cpp @@ -24,9 +24,9 @@ DH_PublicKey::DH_PublicKey(const DL_Group& grp, const BigInt& y1) /* * Return the public value for key agreement */ -MemoryVector<byte> DH_PublicKey::public_value() const +std::vector<byte> DH_PublicKey::public_value() const { - return BigInt::encode_1363(y, group_p().bytes()); + return unlock(BigInt::encode_1363(y, group_p().bytes())); } /* @@ -58,7 +58,7 @@ DH_PrivateKey::DH_PrivateKey(RandomNumberGenerator& rng, * Load a DH private key */ DH_PrivateKey::DH_PrivateKey(const AlgorithmIdentifier& alg_id, - const MemoryRegion<byte>& key_bits, + const secure_vector<byte>& key_bits, RandomNumberGenerator& rng) : DL_Scheme_PrivateKey(alg_id, key_bits, DL_Group::ANSI_X9_42) { @@ -71,7 +71,7 @@ DH_PrivateKey::DH_PrivateKey(const AlgorithmIdentifier& alg_id, /* * Return the public value for key agreement */ -MemoryVector<byte> DH_PrivateKey::public_value() const +std::vector<byte> DH_PrivateKey::public_value() const { return DH_PublicKey::public_value(); } @@ -83,7 +83,7 @@ DH_KA_Operation::DH_KA_Operation(const DH_PrivateKey& dh) : blinder = Blinder(k, powermod_x_p(inverse_mod(k, p)), p); } -SecureVector<byte> DH_KA_Operation::agree(const byte w[], size_t w_len) +secure_vector<byte> DH_KA_Operation::agree(const byte w[], size_t w_len) { BigInt input = BigInt::decode(w, w_len); diff --git a/src/pubkey/dh/dh.h b/src/pubkey/dh/dh.h index 497238417..bf02ffdb9 100644 --- a/src/pubkey/dh/dh.h +++ b/src/pubkey/dh/dh.h @@ -23,13 +23,13 @@ class BOTAN_DLL DH_PublicKey : public virtual DL_Scheme_PublicKey public: std::string algo_name() const { return "DH"; } - MemoryVector<byte> public_value() const; + std::vector<byte> public_value() const; size_t max_input_bits() const { return group_p().bits(); } DL_Group::Format group_format() const { return DL_Group::ANSI_X9_42; } DH_PublicKey(const AlgorithmIdentifier& alg_id, - const MemoryRegion<byte>& key_bits) : + const secure_vector<byte>& key_bits) : DL_Scheme_PublicKey(alg_id, key_bits, DL_Group::ANSI_X9_42) {} /** @@ -50,7 +50,7 @@ class BOTAN_DLL DH_PrivateKey : public DH_PublicKey, public virtual DL_Scheme_PrivateKey { public: - MemoryVector<byte> public_value() const; + std::vector<byte> public_value() const; /** * Load a DH private key @@ -59,7 +59,7 @@ class BOTAN_DLL DH_PrivateKey : public DH_PublicKey, * @param rng a random number generator */ DH_PrivateKey(const AlgorithmIdentifier& alg_id, - const MemoryRegion<byte>& key_bits, + const secure_vector<byte>& key_bits, RandomNumberGenerator& rng); /** @@ -80,7 +80,7 @@ class BOTAN_DLL DH_KA_Operation : public PK_Ops::Key_Agreement public: DH_KA_Operation(const DH_PrivateKey& key); - SecureVector<byte> agree(const byte w[], size_t w_len); + secure_vector<byte> agree(const byte w[], size_t w_len); private: const BigInt& p; diff --git a/src/pubkey/dl_algo/dl_algo.cpp b/src/pubkey/dl_algo/dl_algo.cpp index 8e326ef6a..1034a3252 100644 --- a/src/pubkey/dl_algo/dl_algo.cpp +++ b/src/pubkey/dl_algo/dl_algo.cpp @@ -18,13 +18,13 @@ AlgorithmIdentifier DL_Scheme_PublicKey::algorithm_identifier() const group.DER_encode(group_format())); } -MemoryVector<byte> DL_Scheme_PublicKey::x509_subject_public_key() const +std::vector<byte> DL_Scheme_PublicKey::x509_subject_public_key() const { - return DER_Encoder().encode(y).get_contents(); + return DER_Encoder().encode(y).get_contents_unlocked(); } DL_Scheme_PublicKey::DL_Scheme_PublicKey(const AlgorithmIdentifier& alg_id, - const MemoryRegion<byte>& key_bits, + const secure_vector<byte>& key_bits, DL_Group::Format format) { DataSource_Memory source(alg_id.parameters); @@ -33,13 +33,13 @@ DL_Scheme_PublicKey::DL_Scheme_PublicKey(const AlgorithmIdentifier& alg_id, BER_Decoder(key_bits).decode(y); } -MemoryVector<byte> DL_Scheme_PrivateKey::pkcs8_private_key() const +secure_vector<byte> DL_Scheme_PrivateKey::pkcs8_private_key() const { return DER_Encoder().encode(x).get_contents(); } DL_Scheme_PrivateKey::DL_Scheme_PrivateKey(const AlgorithmIdentifier& alg_id, - const MemoryRegion<byte>& key_bits, + const secure_vector<byte>& key_bits, DL_Group::Format format) { DataSource_Memory source(alg_id.parameters); diff --git a/src/pubkey/dl_algo/dl_algo.h b/src/pubkey/dl_algo/dl_algo.h index 2cc632caa..af2806b02 100644 --- a/src/pubkey/dl_algo/dl_algo.h +++ b/src/pubkey/dl_algo/dl_algo.h @@ -24,7 +24,7 @@ class BOTAN_DLL DL_Scheme_PublicKey : public virtual Public_Key AlgorithmIdentifier algorithm_identifier() const; - MemoryVector<byte> x509_subject_public_key() const; + std::vector<byte> x509_subject_public_key() const; /** * Get the DL domain parameters of this key. @@ -62,7 +62,7 @@ class BOTAN_DLL DL_Scheme_PublicKey : public virtual Public_Key virtual DL_Group::Format group_format() const = 0; DL_Scheme_PublicKey(const AlgorithmIdentifier& alg_id, - const MemoryRegion<byte>& key_bits, + const secure_vector<byte>& key_bits, DL_Group::Format group_format); protected: @@ -94,10 +94,10 @@ class BOTAN_DLL DL_Scheme_PrivateKey : public virtual DL_Scheme_PublicKey, */ const BigInt& get_x() const { return x; } - MemoryVector<byte> pkcs8_private_key() const; + secure_vector<byte> pkcs8_private_key() const; DL_Scheme_PrivateKey(const AlgorithmIdentifier& alg_id, - const MemoryRegion<byte>& key_bits, + const secure_vector<byte>& key_bits, DL_Group::Format group_format); protected: diff --git a/src/pubkey/dl_group/dl_group.cpp b/src/pubkey/dl_group/dl_group.cpp index 7f0160b6b..93bbcbb2d 100644 --- a/src/pubkey/dl_group/dl_group.cpp +++ b/src/pubkey/dl_group/dl_group.cpp @@ -47,7 +47,7 @@ DL_Group::DL_Group(RandomNumberGenerator& rng, PrimeType type, size_t pbits, size_t qbits) { if(pbits < 512) - throw Invalid_Argument("DL_Group: prime size " + to_string(pbits) + + throw Invalid_Argument("DL_Group: prime size " + std::to_string(pbits) + " is too small"); if(type == Strong) @@ -90,7 +90,8 @@ DL_Group::DL_Group(RandomNumberGenerator& rng, * DL_Group Constructor */ DL_Group::DL_Group(RandomNumberGenerator& rng, - const MemoryRegion<byte>& seed, size_t pbits, size_t qbits) + const std::vector<byte>& seed, + size_t pbits, size_t qbits) { if(!generate_dsa_primes(rng, global_state().algorithm_factory(), @@ -202,7 +203,7 @@ const BigInt& DL_Group::get_q() const /* * DER encode the parameters */ -SecureVector<byte> DL_Group::DER_encode(Format format) const +std::vector<byte> DL_Group::DER_encode(Format format) const { init_check(); @@ -217,7 +218,7 @@ SecureVector<byte> DL_Group::DER_encode(Format format) const .encode(q) .encode(g) .end_cons() - .get_contents(); + .get_contents_unlocked(); } else if(format == ANSI_X9_42) { @@ -227,7 +228,7 @@ SecureVector<byte> DL_Group::DER_encode(Format format) const .encode(g) .encode(q) .end_cons() - .get_contents(); + .get_contents_unlocked(); } else if(format == PKCS_3) { @@ -236,10 +237,10 @@ SecureVector<byte> DL_Group::DER_encode(Format format) const .encode(p) .encode(g) .end_cons() - .get_contents(); + .get_contents_unlocked(); } - throw Invalid_Argument("Unknown DL_Group encoding " + to_string(format)); + throw Invalid_Argument("Unknown DL_Group encoding " + std::to_string(format)); } /* @@ -247,7 +248,8 @@ SecureVector<byte> DL_Group::DER_encode(Format format) const */ std::string DL_Group::PEM_encode(Format format) const { - SecureVector<byte> encoding = DER_encode(format); + const std::vector<byte> encoding = DER_encode(format); + if(format == PKCS_3) return PEM_Code::encode(encoding, "DH PARAMETERS"); else if(format == ANSI_X9_57) @@ -255,7 +257,7 @@ std::string DL_Group::PEM_encode(Format format) const else if(format == ANSI_X9_42) return PEM_Code::encode(encoding, "X942 DH PARAMETERS"); else - throw Invalid_Argument("Unknown DL_Group encoding " + to_string(format)); + throw Invalid_Argument("Unknown DL_Group encoding " + std::to_string(format)); } /* @@ -289,7 +291,7 @@ void DL_Group::BER_decode(DataSource& source, Format format) .discard_remaining(); } else - throw Invalid_Argument("Unknown DL_Group encoding " + to_string(format)); + throw Invalid_Argument("Unknown DL_Group encoding " + std::to_string(format)); initialize(new_p, new_q, new_g); } diff --git a/src/pubkey/dl_group/dl_group.h b/src/pubkey/dl_group/dl_group.h index bfc2c04e5..aa90388ae 100644 --- a/src/pubkey/dl_group/dl_group.h +++ b/src/pubkey/dl_group/dl_group.h @@ -77,7 +77,7 @@ class BOTAN_DLL DL_Group * @param format the encoding format * @return string holding the DER encoded group */ - SecureVector<byte> DER_encode(Format format) const; + std::vector<byte> DER_encode(Format format) const; /** * Decode a DER/BER encoded group into this instance. @@ -131,7 +131,8 @@ class BOTAN_DLL DL_Group * @param pbits the desired bit size of the prime p * @param qbits the desired bit size of the prime q. */ - DL_Group(RandomNumberGenerator& rng, const MemoryRegion<byte>& seed, + DL_Group(RandomNumberGenerator& rng, + const std::vector<byte>& seed, size_t pbits = 1024, size_t qbits = 0); /** diff --git a/src/pubkey/dlies/dlies.cpp b/src/pubkey/dlies/dlies.cpp index 2b3f65d06..715b55a36 100644 --- a/src/pubkey/dlies/dlies.cpp +++ b/src/pubkey/dlies/dlies.cpp @@ -34,19 +34,19 @@ DLIES_Encryptor::~DLIES_Encryptor() /* * DLIES Encryption */ -SecureVector<byte> DLIES_Encryptor::enc(const byte in[], size_t length, - RandomNumberGenerator&) const +std::vector<byte> DLIES_Encryptor::enc(const byte in[], size_t length, + RandomNumberGenerator&) const { if(length > maximum_input_size()) throw Invalid_Argument("DLIES: Plaintext too large"); if(other_key.empty()) throw Invalid_State("DLIES: The other key was never set"); - SecureVector<byte> out(my_key.size() + length + mac->output_length()); - out.copy(&my_key[0], my_key.size()); - out.copy(my_key.size(), in, length); + secure_vector<byte> out(my_key.size() + length + mac->output_length()); + buffer_insert(out, 0, my_key); + buffer_insert(out, my_key.size(), in, length); - SecureVector<byte> vz = my_key; + secure_vector<byte> vz(my_key.begin(), my_key.end()); vz += ka.derive_key(0, other_key).bits_of(); const size_t K_LENGTH = length + mac_keylen; @@ -65,13 +65,13 @@ SecureVector<byte> DLIES_Encryptor::enc(const byte in[], size_t length, mac->final(C + length); - return out; + return unlock(out); } /* * Set the other parties public key */ -void DLIES_Encryptor::set_other_key(const MemoryRegion<byte>& ok) +void DLIES_Encryptor::set_other_key(const std::vector<byte>& ok) { other_key = ok; } @@ -108,18 +108,21 @@ DLIES_Decryptor::~DLIES_Decryptor() /* * DLIES Decryption */ -SecureVector<byte> DLIES_Decryptor::dec(const byte msg[], size_t length) const +secure_vector<byte> DLIES_Decryptor::dec(const byte msg[], size_t length) const { if(length < my_key.size() + mac->output_length()) throw Decoding_Error("DLIES decryption: ciphertext is too short"); const size_t CIPHER_LEN = length - my_key.size() - mac->output_length(); - SecureVector<byte> v(msg, my_key.size()); - SecureVector<byte> C(msg + my_key.size(), CIPHER_LEN); - SecureVector<byte> T(msg + my_key.size() + CIPHER_LEN, mac->output_length()); + std::vector<byte> v(msg, msg + my_key.size()); - SecureVector<byte> vz(msg, my_key.size()); + secure_vector<byte> C(msg + my_key.size(), msg + my_key.size() + CIPHER_LEN); + + secure_vector<byte> T(msg + my_key.size() + CIPHER_LEN, + msg + my_key.size() + CIPHER_LEN + mac->output_length()); + + secure_vector<byte> vz(msg, msg + my_key.size()); vz += ka.derive_key(0, v).bits_of(); const size_t K_LENGTH = C.size() + mac_keylen; @@ -131,7 +134,7 @@ SecureVector<byte> DLIES_Decryptor::dec(const byte msg[], size_t length) const mac->update(C); for(size_t j = 0; j != 8; ++j) mac->update(0); - SecureVector<byte> T2 = mac->final(); + secure_vector<byte> T2 = mac->final(); if(T != T2) throw Decoding_Error("DLIES: message authentication failed"); diff --git a/src/pubkey/dlies/dlies.h b/src/pubkey/dlies/dlies.h index 8e5c05852..9739afeb2 100644 --- a/src/pubkey/dlies/dlies.h +++ b/src/pubkey/dlies/dlies.h @@ -27,13 +27,14 @@ class BOTAN_DLL DLIES_Encryptor : public PK_Encryptor ~DLIES_Encryptor(); - void set_other_key(const MemoryRegion<byte>&); + void set_other_key(const std::vector<byte>&); private: - SecureVector<byte> enc(const byte[], size_t, - RandomNumberGenerator&) const; + std::vector<byte> enc(const byte[], size_t, + RandomNumberGenerator&) const; + size_t maximum_input_size() const; - SecureVector<byte> other_key, my_key; + std::vector<byte> other_key, my_key; PK_Key_Agreement ka; KDF* kdf; @@ -55,9 +56,9 @@ class BOTAN_DLL DLIES_Decryptor : public PK_Decryptor ~DLIES_Decryptor(); private: - SecureVector<byte> dec(const byte[], size_t) const; + secure_vector<byte> dec(const byte[], size_t) const; - SecureVector<byte> my_key; + std::vector<byte> my_key; PK_Key_Agreement ka; KDF* kdf; diff --git a/src/pubkey/dsa/dsa.cpp b/src/pubkey/dsa/dsa.cpp index 5e511840f..5d56d6b89 100644 --- a/src/pubkey/dsa/dsa.cpp +++ b/src/pubkey/dsa/dsa.cpp @@ -8,7 +8,7 @@ #include <botan/dsa.h> #include <botan/numthry.h> #include <botan/keypair.h> - +#include <future> namespace Botan { /* @@ -42,7 +42,7 @@ DSA_PrivateKey::DSA_PrivateKey(RandomNumberGenerator& rng, } DSA_PrivateKey::DSA_PrivateKey(const AlgorithmIdentifier& alg_id, - const MemoryRegion<byte>& key_bits, + const secure_vector<byte>& key_bits, RandomNumberGenerator& rng) : DL_Scheme_PrivateKey(alg_id, key_bits, DL_Group::ANSI_X9_57) { @@ -73,7 +73,7 @@ DSA_Signature_Operation::DSA_Signature_Operation(const DSA_PrivateKey& dsa) : { } -SecureVector<byte> +secure_vector<byte> DSA_Signature_Operation::sign(const byte msg[], size_t msg_len, RandomNumberGenerator& rng) { @@ -89,11 +89,15 @@ DSA_Signature_Operation::sign(const byte msg[], size_t msg_len, k.randomize(rng, q.bits()); while(k >= q); - r = mod_q.reduce(powermod_g_p(k)); - s = mod_q.multiply(inverse_mod(k, q), mul_add(x, r, i)); + auto future_r = std::async(std::launch::async, + [&]() { return mod_q.reduce(powermod_g_p(k)); }); + + s = inverse_mod(k, q); + r = future_r.get(); + s = mod_q.multiply(s, mul_add(x, r, i)); } - SecureVector<byte> output(2*q.bytes()); + secure_vector<byte> output(2*q.bytes()); r.binary_encode(&output[output.size() / 2 - r.bytes()]); s.binary_encode(&output[output.size() - s.bytes()]); return output; @@ -124,8 +128,14 @@ bool DSA_Verification_Operation::verify(const byte msg[], size_t msg_len, return false; s = inverse_mod(s, q); - s = mod_p.multiply(powermod_g_p(mod_q.multiply(s, i)), - powermod_y_p(mod_q.multiply(s, r))); + + auto future_s_i = std::async(std::launch::async, + [&]() { return powermod_g_p(mod_q.multiply(s, i)); }); + + BigInt s_r = powermod_y_p(mod_q.multiply(s, r)); + BigInt s_i = future_s_i.get(); + + s = mod_p.multiply(s_i, s_r); return (mod_q.reduce(s) == r); } diff --git a/src/pubkey/dsa/dsa.h b/src/pubkey/dsa/dsa.h index a41a8432c..7d51cfdd0 100644 --- a/src/pubkey/dsa/dsa.h +++ b/src/pubkey/dsa/dsa.h @@ -29,7 +29,7 @@ class BOTAN_DLL DSA_PublicKey : public virtual DL_Scheme_PublicKey size_t max_input_bits() const { return group_q().bits(); } DSA_PublicKey(const AlgorithmIdentifier& alg_id, - const MemoryRegion<byte>& key_bits) : + const secure_vector<byte>& key_bits) : DL_Scheme_PublicKey(alg_id, key_bits, DL_Group::ANSI_X9_57) { } @@ -47,7 +47,7 @@ class BOTAN_DLL DSA_PrivateKey : public DSA_PublicKey, { public: DSA_PrivateKey(const AlgorithmIdentifier& alg_id, - const MemoryRegion<byte>& key_bits, + const secure_vector<byte>& key_bits, RandomNumberGenerator& rng); DSA_PrivateKey(RandomNumberGenerator& rng, @@ -69,7 +69,7 @@ class BOTAN_DLL DSA_Signature_Operation : public PK_Ops::Signature size_t message_part_size() const { return q.bytes(); } size_t max_input_bits() const { return q.bits(); } - SecureVector<byte> sign(const byte msg[], size_t msg_len, + secure_vector<byte> sign(const byte msg[], size_t msg_len, RandomNumberGenerator& rng); private: const BigInt& q; diff --git a/src/pubkey/ec_group/ec_group.cpp b/src/pubkey/ec_group/ec_group.cpp index fe4fae885..88c4616a4 100644 --- a/src/pubkey/ec_group/ec_group.cpp +++ b/src/pubkey/ec_group/ec_group.cpp @@ -37,8 +37,8 @@ EC_Group::EC_Group(const std::string& str) { DataSource_Memory input(str); - SecureVector<byte> ber = - PEM_Code::decode_check_label(input, "EC PARAMETERS"); + std::vector<byte> ber = + unlock(PEM_Code::decode_check_label(input, "EC PARAMETERS")); *this = EC_Group(ber); } @@ -48,7 +48,7 @@ EC_Group::EC_Group(const std::string& str) } } -EC_Group::EC_Group(const MemoryRegion<byte>& ber_data) +EC_Group::EC_Group(const std::vector<byte>& ber_data) { BER_Decoder ber(ber_data); BER_Object obj = ber.get_next_object(); @@ -64,7 +64,7 @@ EC_Group::EC_Group(const MemoryRegion<byte>& ber_data) else if(obj.type_tag == SEQUENCE) { BigInt p, a, b; - SecureVector<byte> sv_base_point; + std::vector<byte> sv_base_point; BER_Decoder(ber_data) .start_cons(SEQUENCE) @@ -91,7 +91,7 @@ EC_Group::EC_Group(const MemoryRegion<byte>& ber_data) throw Decoding_Error("Unexpected tag while decoding ECC domain params"); } -SecureVector<byte> +std::vector<byte> EC_Group::DER_encode(EC_Group_Encoding form) const { if(form == EC_DOMPAR_ENC_EXPLICIT) @@ -118,19 +118,19 @@ EC_Group::DER_encode(EC_Group_Encoding form) const .encode(order) .encode(cofactor) .end_cons() - .get_contents(); + .get_contents_unlocked(); } else if(form == EC_DOMPAR_ENC_OID) - return DER_Encoder().encode(get_oid()).get_contents(); + return DER_Encoder().encode(get_oid()).get_contents_unlocked(); else if(form == EC_DOMPAR_ENC_IMPLICITCA) - return DER_Encoder().encode_null().get_contents(); + return DER_Encoder().encode_null().get_contents_unlocked(); else throw Internal_Error("EC_Group::DER_encode: Unknown encoding"); } std::string EC_Group::PEM_encode() const { - SecureVector<byte> der = DER_encode(EC_DOMPAR_ENC_EXPLICIT); + const std::vector<byte> der = DER_encode(EC_DOMPAR_ENC_EXPLICIT); return PEM_Code::encode(der, "EC PARAMETERS"); } diff --git a/src/pubkey/ec_group/ec_group.h b/src/pubkey/ec_group/ec_group.h index 59a1918c0..756c158dc 100644 --- a/src/pubkey/ec_group/ec_group.h +++ b/src/pubkey/ec_group/ec_group.h @@ -54,7 +54,7 @@ class BOTAN_DLL EC_Group * Decode a BER encoded ECC domain parameter set * @param ber_encoding the bytes of the BER encoding */ - EC_Group(const MemoryRegion<byte>& ber_encoding); + EC_Group(const std::vector<byte>& ber_encoding); /** * Create an EC domain by OID (or throw if unknown) @@ -63,8 +63,8 @@ class BOTAN_DLL EC_Group EC_Group(const OID& oid); /** - * Create an EC domain from PEM encoding (as from PEM_encode), - * or from an OID name (eg "secp160r1", or "1.3.132.0.8") + * Create an EC domain from PEM encoding (as from PEM_encode), or + * from an OID name (eg "secp256r1", or "1.2.840.10045.3.1.7") * @param pem_or_oid PEM-encoded data, or an OID */ EC_Group(const std::string& pem_or_oid = ""); @@ -74,7 +74,7 @@ class BOTAN_DLL EC_Group * @param form of encoding to use * @returns bytes encododed as DER */ - SecureVector<byte> DER_encode(EC_Group_Encoding form) const; + std::vector<byte> DER_encode(EC_Group_Encoding form) const; /** * Return the PEM encoding (always in explicit form) diff --git a/src/pubkey/ecc_key/ecc_key.cpp b/src/pubkey/ecc_key/ecc_key.cpp index 991446f07..ead129ec6 100644 --- a/src/pubkey/ecc_key/ecc_key.cpp +++ b/src/pubkey/ecc_key/ecc_key.cpp @@ -28,7 +28,7 @@ EC_PublicKey::EC_PublicKey(const EC_Group& dom_par, } EC_PublicKey::EC_PublicKey(const AlgorithmIdentifier& alg_id, - const MemoryRegion<byte>& key_bits) + const secure_vector<byte>& key_bits) { domain_params = EC_Group(alg_id.parameters); domain_encoding = EC_DOMPAR_ENC_EXPLICIT; @@ -47,9 +47,9 @@ AlgorithmIdentifier EC_PublicKey::algorithm_identifier() const return AlgorithmIdentifier(get_oid(), DER_domain()); } -MemoryVector<byte> EC_PublicKey::x509_subject_public_key() const +std::vector<byte> EC_PublicKey::x509_subject_public_key() const { - return EC2OSP(public_point(), PointGFp::COMPRESSED); + return unlock(EC2OSP(public_point(), PointGFp::COMPRESSED)); } void EC_PublicKey::set_parameter_encoding(EC_Group_Encoding form) @@ -96,7 +96,7 @@ EC_PrivateKey::EC_PrivateKey(RandomNumberGenerator& rng, "ECC private key was not on the curve"); } -MemoryVector<byte> EC_PrivateKey::pkcs8_private_key() const +secure_vector<byte> EC_PrivateKey::pkcs8_private_key() const { return DER_Encoder() .start_cons(SEQUENCE) @@ -108,7 +108,7 @@ MemoryVector<byte> EC_PrivateKey::pkcs8_private_key() const } EC_PrivateKey::EC_PrivateKey(const AlgorithmIdentifier& alg_id, - const MemoryRegion<byte>& key_bits) + const secure_vector<byte>& key_bits) { domain_params = EC_Group(alg_id.parameters); domain_encoding = EC_DOMPAR_ENC_EXPLICIT; diff --git a/src/pubkey/ecc_key/ecc_key.h b/src/pubkey/ecc_key/ecc_key.h index cccc8d53c..76a63a7e4 100644 --- a/src/pubkey/ecc_key/ecc_key.h +++ b/src/pubkey/ecc_key/ecc_key.h @@ -34,7 +34,7 @@ class BOTAN_DLL EC_PublicKey : public virtual Public_Key const PointGFp& pub_point); EC_PublicKey(const AlgorithmIdentifier& alg_id, - const MemoryRegion<byte>& key_bits); + const secure_vector<byte>& key_bits); /** * Get the public point of this key. @@ -46,7 +46,7 @@ class BOTAN_DLL EC_PublicKey : public virtual Public_Key AlgorithmIdentifier algorithm_identifier() const; - MemoryVector<byte> x509_subject_public_key() const; + std::vector<byte> x509_subject_public_key() const; bool check_key(RandomNumberGenerator& rng, bool strong) const; @@ -69,7 +69,7 @@ class BOTAN_DLL EC_PublicKey : public virtual Public_Key * Return the DER encoding of this keys domain in whatever format * is preset for this particular key */ - MemoryVector<byte> DER_domain() const + std::vector<byte> DER_domain() const { return domain().DER_encode(domain_format()); } /** @@ -98,9 +98,9 @@ class BOTAN_DLL EC_PrivateKey : public virtual EC_PublicKey, const BigInt& private_key); EC_PrivateKey(const AlgorithmIdentifier& alg_id, - const MemoryRegion<byte>& key_bits); + const secure_vector<byte>& key_bits); - MemoryVector<byte> pkcs8_private_key() const; + secure_vector<byte> pkcs8_private_key() const; /** * Get the private key value of this key object. diff --git a/src/pubkey/ecdh/ecdh.cpp b/src/pubkey/ecdh/ecdh.cpp index 656644370..511dd0678 100644 --- a/src/pubkey/ecdh/ecdh.cpp +++ b/src/pubkey/ecdh/ecdh.cpp @@ -20,7 +20,7 @@ ECDH_KA_Operation::ECDH_KA_Operation(const ECDH_PrivateKey& key) : key.private_value(); } -SecureVector<byte> ECDH_KA_Operation::agree(const byte w[], size_t w_len) +secure_vector<byte> ECDH_KA_Operation::agree(const byte w[], size_t w_len) { PointGFp point = OS2ECP(w, w_len, curve); diff --git a/src/pubkey/ecdh/ecdh.h b/src/pubkey/ecdh/ecdh.h index 6fe0697bf..0c5d4e010 100644 --- a/src/pubkey/ecdh/ecdh.h +++ b/src/pubkey/ecdh/ecdh.h @@ -23,7 +23,7 @@ class BOTAN_DLL ECDH_PublicKey : public virtual EC_PublicKey public: ECDH_PublicKey(const AlgorithmIdentifier& alg_id, - const MemoryRegion<byte>& key_bits) : + const secure_vector<byte>& key_bits) : EC_PublicKey(alg_id, key_bits) {} /** @@ -52,8 +52,8 @@ class BOTAN_DLL ECDH_PublicKey : public virtual EC_PublicKey /** * @return public point value */ - MemoryVector<byte> public_value() const - { return EC2OSP(public_point(), PointGFp::UNCOMPRESSED); } + std::vector<byte> public_value() const + { return unlock(EC2OSP(public_point(), PointGFp::UNCOMPRESSED)); } protected: ECDH_PublicKey() {} @@ -69,7 +69,7 @@ class BOTAN_DLL ECDH_PrivateKey : public ECDH_PublicKey, public: ECDH_PrivateKey(const AlgorithmIdentifier& alg_id, - const MemoryRegion<byte>& key_bits) : + const secure_vector<byte>& key_bits) : EC_PrivateKey(alg_id, key_bits) {} /** @@ -83,7 +83,7 @@ class BOTAN_DLL ECDH_PrivateKey : public ECDH_PublicKey, const BigInt& x = 0) : EC_PrivateKey(rng, domain, x) {} - MemoryVector<byte> public_value() const + std::vector<byte> public_value() const { return ECDH_PublicKey::public_value(); } }; @@ -95,7 +95,7 @@ class BOTAN_DLL ECDH_KA_Operation : public PK_Ops::Key_Agreement public: ECDH_KA_Operation(const ECDH_PrivateKey& key); - SecureVector<byte> agree(const byte w[], size_t w_len); + secure_vector<byte> agree(const byte w[], size_t w_len); private: const CurveGFp& curve; const BigInt& cofactor; diff --git a/src/pubkey/ecdsa/ecdsa.cpp b/src/pubkey/ecdsa/ecdsa.cpp index 5c45c5ed3..6ff082649 100644 --- a/src/pubkey/ecdsa/ecdsa.cpp +++ b/src/pubkey/ecdsa/ecdsa.cpp @@ -32,7 +32,7 @@ ECDSA_Signature_Operation::ECDSA_Signature_Operation(const ECDSA_PrivateKey& ecd { } -SecureVector<byte> +secure_vector<byte> ECDSA_Signature_Operation::sign(const byte msg[], size_t msg_len, RandomNumberGenerator& rng) { @@ -56,7 +56,7 @@ ECDSA_Signature_Operation::sign(const byte msg[], size_t msg_len, s = mod_order.multiply(inverse_mod(k, order), mul_add(x, r, m)); } - SecureVector<byte> output(2*order.bytes()); + secure_vector<byte> output(2*order.bytes()); r.binary_encode(&output[output.size() / 2 - r.bytes()]); s.binary_encode(&output[output.size() - s.bytes()]); return output; diff --git a/src/pubkey/ecdsa/ecdsa.h b/src/pubkey/ecdsa/ecdsa.h index f0834abd8..e37fa1562 100644 --- a/src/pubkey/ecdsa/ecdsa.h +++ b/src/pubkey/ecdsa/ecdsa.h @@ -33,7 +33,7 @@ class BOTAN_DLL ECDSA_PublicKey : public virtual EC_PublicKey EC_PublicKey(dom_par, public_point) {} ECDSA_PublicKey(const AlgorithmIdentifier& alg_id, - const MemoryRegion<byte>& key_bits) : + const secure_vector<byte>& key_bits) : EC_PublicKey(alg_id, key_bits) {} /** @@ -72,7 +72,7 @@ class BOTAN_DLL ECDSA_PrivateKey : public ECDSA_PublicKey, * @param key_bits PKCS #8 structure */ ECDSA_PrivateKey(const AlgorithmIdentifier& alg_id, - const MemoryRegion<byte>& key_bits) : + const secure_vector<byte>& key_bits) : EC_PrivateKey(alg_id, key_bits) {} /** @@ -97,7 +97,7 @@ class BOTAN_DLL ECDSA_Signature_Operation : public PK_Ops::Signature public: ECDSA_Signature_Operation(const ECDSA_PrivateKey& ecdsa); - SecureVector<byte> sign(const byte msg[], size_t msg_len, + secure_vector<byte> sign(const byte msg[], size_t msg_len, RandomNumberGenerator& rng); size_t message_parts() const { return 2; } diff --git a/src/pubkey/elgamal/elgamal.cpp b/src/pubkey/elgamal/elgamal.cpp index 6d15aed79..3988f3155 100644 --- a/src/pubkey/elgamal/elgamal.cpp +++ b/src/pubkey/elgamal/elgamal.cpp @@ -44,7 +44,7 @@ ElGamal_PrivateKey::ElGamal_PrivateKey(RandomNumberGenerator& rng, } ElGamal_PrivateKey::ElGamal_PrivateKey(const AlgorithmIdentifier& alg_id, - const MemoryRegion<byte>& key_bits, + const secure_vector<byte>& key_bits, RandomNumberGenerator& rng) : DL_Scheme_PrivateKey(alg_id, key_bits, DL_Group::ANSI_X9_42) { @@ -76,7 +76,7 @@ ElGamal_Encryption_Operation::ElGamal_Encryption_Operation(const ElGamal_PublicK mod_p = Modular_Reducer(p); } -SecureVector<byte> +secure_vector<byte> ElGamal_Encryption_Operation::encrypt(const byte msg[], size_t msg_len, RandomNumberGenerator& rng) { @@ -92,7 +92,7 @@ ElGamal_Encryption_Operation::encrypt(const byte msg[], size_t msg_len, BigInt a = powermod_g_p(k); BigInt b = mod_p.multiply(m, powermod_y_p(k)); - SecureVector<byte> output(2*p.bytes()); + secure_vector<byte> output(2*p.bytes()); a.binary_encode(&output[p.bytes() - a.bytes()]); b.binary_encode(&output[output.size() / 2 + (p.bytes() - b.bytes())]); return output; @@ -109,7 +109,7 @@ ElGamal_Decryption_Operation::ElGamal_Decryption_Operation(const ElGamal_Private blinder = Blinder(k, powermod_x_p(k), p); } -SecureVector<byte> +secure_vector<byte> ElGamal_Decryption_Operation::decrypt(const byte msg[], size_t msg_len) { const BigInt& p = mod_p.get_modulus(); @@ -129,7 +129,7 @@ ElGamal_Decryption_Operation::decrypt(const byte msg[], size_t msg_len) BigInt r = mod_p.multiply(b, inverse_mod(powermod_x_p(a), p)); - return BigInt::encode(blinder.unblind(r)); + return BigInt::encode_locked(blinder.unblind(r)); } } diff --git a/src/pubkey/elgamal/elgamal.h b/src/pubkey/elgamal/elgamal.h index 383a4160b..957aa4656 100644 --- a/src/pubkey/elgamal/elgamal.h +++ b/src/pubkey/elgamal/elgamal.h @@ -28,7 +28,7 @@ class BOTAN_DLL ElGamal_PublicKey : public virtual DL_Scheme_PublicKey size_t max_input_bits() const { return (group_p().bits() - 1); } ElGamal_PublicKey(const AlgorithmIdentifier& alg_id, - const MemoryRegion<byte>& key_bits) : + const secure_vector<byte>& key_bits) : DL_Scheme_PublicKey(alg_id, key_bits, DL_Group::ANSI_X9_42) {} @@ -47,7 +47,7 @@ class BOTAN_DLL ElGamal_PrivateKey : public ElGamal_PublicKey, bool check_key(RandomNumberGenerator& rng, bool) const; ElGamal_PrivateKey(const AlgorithmIdentifier& alg_id, - const MemoryRegion<byte>& key_bits, + const secure_vector<byte>& key_bits, RandomNumberGenerator& rng); ElGamal_PrivateKey(RandomNumberGenerator& rng, @@ -65,7 +65,7 @@ class BOTAN_DLL ElGamal_Encryption_Operation : public PK_Ops::Encryption ElGamal_Encryption_Operation(const ElGamal_PublicKey& key); - SecureVector<byte> encrypt(const byte msg[], size_t msg_len, + secure_vector<byte> encrypt(const byte msg[], size_t msg_len, RandomNumberGenerator& rng); private: @@ -83,7 +83,7 @@ class BOTAN_DLL ElGamal_Decryption_Operation : public PK_Ops::Decryption ElGamal_Decryption_Operation(const ElGamal_PrivateKey& key); - SecureVector<byte> decrypt(const byte msg[], size_t msg_len); + secure_vector<byte> decrypt(const byte msg[], size_t msg_len); private: Fixed_Exponent_Power_Mod powermod_x_p; Modular_Reducer mod_p; diff --git a/src/pubkey/gost_3410/gost_3410.cpp b/src/pubkey/gost_3410/gost_3410.cpp index f97f83aa0..289cdcac4 100644 --- a/src/pubkey/gost_3410/gost_3410.cpp +++ b/src/pubkey/gost_3410/gost_3410.cpp @@ -14,7 +14,7 @@ namespace Botan { -MemoryVector<byte> GOST_3410_PublicKey::x509_subject_public_key() const +std::vector<byte> GOST_3410_PublicKey::x509_subject_public_key() const { // Trust CryptoPro to come up with something obnoxious const BigInt x = public_point().get_affine_x(); @@ -22,7 +22,7 @@ MemoryVector<byte> GOST_3410_PublicKey::x509_subject_public_key() const size_t part_size = std::max(x.bytes(), y.bytes()); - MemoryVector<byte> bits(2*part_size); + std::vector<byte> bits(2*part_size); x.binary_encode(&bits[part_size - x.bytes()]); y.binary_encode(&bits[2*part_size - y.bytes()]); @@ -34,22 +34,22 @@ MemoryVector<byte> GOST_3410_PublicKey::x509_subject_public_key() const std::swap(bits[part_size+i], bits[2*part_size-1-i]); } - return DER_Encoder().encode(bits, OCTET_STRING).get_contents(); + return DER_Encoder().encode(bits, OCTET_STRING).get_contents_unlocked(); } AlgorithmIdentifier GOST_3410_PublicKey::algorithm_identifier() const { - MemoryVector<byte> params = + std::vector<byte> params = DER_Encoder().start_cons(SEQUENCE) .encode(OID(domain().get_oid())) .end_cons() - .get_contents(); + .get_contents_unlocked(); return AlgorithmIdentifier(get_oid(), params); } GOST_3410_PublicKey::GOST_3410_PublicKey(const AlgorithmIdentifier& alg_id, - const MemoryRegion<byte>& key_bits) + const secure_vector<byte>& key_bits) { OID ecc_param_id; @@ -58,7 +58,7 @@ GOST_3410_PublicKey::GOST_3410_PublicKey(const AlgorithmIdentifier& alg_id, domain_params = EC_Group(ecc_param_id); - SecureVector<byte> bits; + secure_vector<byte> bits; BER_Decoder(key_bits).decode(bits, OCTET_STRING); const size_t part_size = bits.size() / 2; @@ -83,7 +83,7 @@ namespace { BigInt decode_le(const byte msg[], size_t msg_len) { - SecureVector<byte> msg_le(msg, msg_len); + secure_vector<byte> msg_le(msg, msg + msg_len); for(size_t i = 0; i != msg_le.size() / 2; ++i) std::swap(msg_le[i], msg_le[msg_le.size()-1-i]); @@ -102,7 +102,7 @@ GOST_3410_Signature_Operation::GOST_3410_Signature_Operation( { } -SecureVector<byte> +secure_vector<byte> GOST_3410_Signature_Operation::sign(const byte msg[], size_t msg_len, RandomNumberGenerator& rng) { @@ -129,7 +129,7 @@ GOST_3410_Signature_Operation::sign(const byte msg[], size_t msg_len, if(r == 0 || s == 0) throw Invalid_State("GOST 34.10: r == 0 || s == 0"); - SecureVector<byte> output(2*order.bytes()); + secure_vector<byte> output(2*order.bytes()); s.binary_encode(&output[output.size() / 2 - s.bytes()]); r.binary_encode(&output[output.size() - r.bytes()]); return output; diff --git a/src/pubkey/gost_3410/gost_3410.h b/src/pubkey/gost_3410/gost_3410.h index 7b638d7b5..6b1506b10 100644 --- a/src/pubkey/gost_3410/gost_3410.h +++ b/src/pubkey/gost_3410/gost_3410.h @@ -35,7 +35,7 @@ class BOTAN_DLL GOST_3410_PublicKey : public virtual EC_PublicKey * Construct from X.509 algorithm id and subject public key bits */ GOST_3410_PublicKey(const AlgorithmIdentifier& alg_id, - const MemoryRegion<byte>& key_bits); + const secure_vector<byte>& key_bits); /** * Get this keys algorithm name. @@ -45,7 +45,7 @@ class BOTAN_DLL GOST_3410_PublicKey : public virtual EC_PublicKey AlgorithmIdentifier algorithm_identifier() const; - MemoryVector<byte> x509_subject_public_key() const; + std::vector<byte> x509_subject_public_key() const; /** * Get the maximum number of bits allowed to be fed to this key. @@ -73,7 +73,7 @@ class BOTAN_DLL GOST_3410_PrivateKey : public GOST_3410_PublicKey, public: GOST_3410_PrivateKey(const AlgorithmIdentifier& alg_id, - const MemoryRegion<byte>& key_bits) : + const secure_vector<byte>& key_bits) : EC_PrivateKey(alg_id, key_bits) {} /** @@ -103,7 +103,7 @@ class BOTAN_DLL GOST_3410_Signature_Operation : public PK_Ops::Signature size_t message_part_size() const { return order.bytes(); } size_t max_input_bits() const { return order.bits(); } - SecureVector<byte> sign(const byte msg[], size_t msg_len, + secure_vector<byte> sign(const byte msg[], size_t msg_len, RandomNumberGenerator& rng); private: diff --git a/src/pubkey/if_algo/if_algo.cpp b/src/pubkey/if_algo/if_algo.cpp index 6e75bc276..f044afd03 100644 --- a/src/pubkey/if_algo/if_algo.cpp +++ b/src/pubkey/if_algo/if_algo.cpp @@ -18,18 +18,18 @@ AlgorithmIdentifier IF_Scheme_PublicKey::algorithm_identifier() const AlgorithmIdentifier::USE_NULL_PARAM); } -MemoryVector<byte> IF_Scheme_PublicKey::x509_subject_public_key() const +std::vector<byte> IF_Scheme_PublicKey::x509_subject_public_key() const { return DER_Encoder() .start_cons(SEQUENCE) .encode(n) .encode(e) .end_cons() - .get_contents(); + .get_contents_unlocked(); } IF_Scheme_PublicKey::IF_Scheme_PublicKey(const AlgorithmIdentifier&, - const MemoryRegion<byte>& key_bits) + const secure_vector<byte>& key_bits) { BER_Decoder(key_bits) .start_cons(SEQUENCE) @@ -49,7 +49,7 @@ bool IF_Scheme_PublicKey::check_key(RandomNumberGenerator&, bool) const return true; } -MemoryVector<byte> IF_Scheme_PrivateKey::pkcs8_private_key() const +secure_vector<byte> IF_Scheme_PrivateKey::pkcs8_private_key() const { return DER_Encoder() .start_cons(SEQUENCE) @@ -68,7 +68,7 @@ MemoryVector<byte> IF_Scheme_PrivateKey::pkcs8_private_key() const IF_Scheme_PrivateKey::IF_Scheme_PrivateKey(RandomNumberGenerator& rng, const AlgorithmIdentifier&, - const MemoryRegion<byte>& key_bits) + const secure_vector<byte>& key_bits) { BER_Decoder(key_bits) .start_cons(SEQUENCE) diff --git a/src/pubkey/if_algo/if_algo.h b/src/pubkey/if_algo/if_algo.h index b6683d30e..5c95aecd1 100644 --- a/src/pubkey/if_algo/if_algo.h +++ b/src/pubkey/if_algo/if_algo.h @@ -22,7 +22,7 @@ class BOTAN_DLL IF_Scheme_PublicKey : public virtual Public_Key { public: IF_Scheme_PublicKey(const AlgorithmIdentifier& alg_id, - const MemoryRegion<byte>& key_bits); + const secure_vector<byte>& key_bits); IF_Scheme_PublicKey(const BigInt& n, const BigInt& e) : n(n), e(e) {} @@ -31,7 +31,7 @@ class BOTAN_DLL IF_Scheme_PublicKey : public virtual Public_Key AlgorithmIdentifier algorithm_identifier() const; - MemoryVector<byte> x509_subject_public_key() const; + std::vector<byte> x509_subject_public_key() const; /** * @return public modulus @@ -67,7 +67,7 @@ class BOTAN_DLL IF_Scheme_PrivateKey : public virtual IF_Scheme_PublicKey, IF_Scheme_PrivateKey(RandomNumberGenerator& rng, const AlgorithmIdentifier& alg_id, - const MemoryRegion<byte>& key_bits); + const secure_vector<byte>& key_bits); bool check_key(RandomNumberGenerator& rng, bool) const; @@ -93,7 +93,7 @@ class BOTAN_DLL IF_Scheme_PrivateKey : public virtual IF_Scheme_PublicKey, const BigInt& get_d1() const { return d1; } const BigInt& get_d2() const { return d2; } - MemoryVector<byte> pkcs8_private_key() const; + secure_vector<byte> pkcs8_private_key() const; protected: IF_Scheme_PrivateKey() {} diff --git a/src/pubkey/keypair/keypair.cpp b/src/pubkey/keypair/keypair.cpp index 857a5328a..a8631062d 100644 --- a/src/pubkey/keypair/keypair.cpp +++ b/src/pubkey/keypair/keypair.cpp @@ -29,14 +29,14 @@ bool encryption_consistency_check(RandomNumberGenerator& rng, if(encryptor.maximum_input_size() == 0) return true; - SecureVector<byte> plaintext = - rng.random_vec(encryptor.maximum_input_size() - 1); + std::vector<byte> plaintext = + unlock(rng.random_vec(encryptor.maximum_input_size() - 1)); - SecureVector<byte> ciphertext = encryptor.encrypt(plaintext, rng); + std::vector<byte> ciphertext = encryptor.encrypt(plaintext, rng); if(ciphertext == plaintext) return false; - SecureVector<byte> decrypted = decryptor.decrypt(ciphertext); + std::vector<byte> decrypted = unlock(decryptor.decrypt(ciphertext)); return (plaintext == decrypted); } @@ -51,9 +51,9 @@ bool signature_consistency_check(RandomNumberGenerator& rng, PK_Signer signer(key, padding); PK_Verifier verifier(key, padding); - SecureVector<byte> message = rng.random_vec(16); + std::vector<byte> message = unlock(rng.random_vec(16)); - SecureVector<byte> signature; + std::vector<byte> signature; try { diff --git a/src/pubkey/nr/nr.cpp b/src/pubkey/nr/nr.cpp index 61cf7eb3f..87cf3d038 100644 --- a/src/pubkey/nr/nr.cpp +++ b/src/pubkey/nr/nr.cpp @@ -8,11 +8,12 @@ #include <botan/nr.h> #include <botan/numthry.h> #include <botan/keypair.h> +#include <future> namespace Botan { NR_PublicKey::NR_PublicKey(const AlgorithmIdentifier& alg_id, - const MemoryRegion<byte>& key_bits) : + const secure_vector<byte>& key_bits) : DL_Scheme_PublicKey(alg_id, key_bits, DL_Group::ANSI_X9_57) { } @@ -48,7 +49,7 @@ NR_PrivateKey::NR_PrivateKey(RandomNumberGenerator& rng, } NR_PrivateKey::NR_PrivateKey(const AlgorithmIdentifier& alg_id, - const MemoryRegion<byte>& key_bits, + const secure_vector<byte>& key_bits, RandomNumberGenerator& rng) : DL_Scheme_PrivateKey(alg_id, key_bits, DL_Group::ANSI_X9_57) { @@ -79,7 +80,7 @@ NR_Signature_Operation::NR_Signature_Operation(const NR_PrivateKey& nr) : { } -SecureVector<byte> +secure_vector<byte> NR_Signature_Operation::sign(const byte msg[], size_t msg_len, RandomNumberGenerator& rng) { @@ -103,7 +104,7 @@ NR_Signature_Operation::sign(const byte msg[], size_t msg_len, d = mod_q.reduce(k - x * c); } - SecureVector<byte> output(2*q.bytes()); + secure_vector<byte> output(2*q.bytes()); c.binary_encode(&output[output.size() / 2 - c.bytes()]); d.binary_encode(&output[output.size() - d.bytes()]); return output; @@ -118,13 +119,13 @@ NR_Verification_Operation::NR_Verification_Operation(const NR_PublicKey& nr) : mod_q = Modular_Reducer(nr.group_q()); } -SecureVector<byte> +secure_vector<byte> NR_Verification_Operation::verify_mr(const byte msg[], size_t msg_len) { const BigInt& q = mod_q.get_modulus(); if(msg_len != 2*q.bytes()) - return false; + throw Invalid_Argument("NR verification: Invalid signature"); BigInt c(msg, q.bytes()); BigInt d(msg + q.bytes(), q.bytes()); @@ -132,8 +133,11 @@ NR_Verification_Operation::verify_mr(const byte msg[], size_t msg_len) if(c.is_zero() || c >= q || d >= q) throw Invalid_Argument("NR verification: Invalid signature"); - BigInt i = mod_p.multiply(powermod_g_p(d), powermod_y_p(c)); - return BigInt::encode(mod_q.reduce(c - i)); + auto future_y_c = std::async(std::launch::async, powermod_y_p, c); + BigInt g_d = powermod_g_p(d); + + BigInt i = mod_p.multiply(g_d, future_y_c.get()); + return BigInt::encode_locked(mod_q.reduce(c - i)); } } diff --git a/src/pubkey/nr/nr.h b/src/pubkey/nr/nr.h index 0d426fb3a..5be336a21 100644 --- a/src/pubkey/nr/nr.h +++ b/src/pubkey/nr/nr.h @@ -30,7 +30,7 @@ class BOTAN_DLL NR_PublicKey : public virtual DL_Scheme_PublicKey size_t max_input_bits() const { return (group_q().bits() - 1); } NR_PublicKey(const AlgorithmIdentifier& alg_id, - const MemoryRegion<byte>& key_bits); + const secure_vector<byte>& key_bits); NR_PublicKey(const DL_Group& group, const BigInt& pub_key); protected: @@ -47,7 +47,7 @@ class BOTAN_DLL NR_PrivateKey : public NR_PublicKey, bool check_key(RandomNumberGenerator& rng, bool strong) const; NR_PrivateKey(const AlgorithmIdentifier& alg_id, - const MemoryRegion<byte>& key_bits, + const secure_vector<byte>& key_bits, RandomNumberGenerator& rng); NR_PrivateKey(RandomNumberGenerator& rng, @@ -67,7 +67,7 @@ class BOTAN_DLL NR_Signature_Operation : public PK_Ops::Signature size_t message_part_size() const { return q.bytes(); } size_t max_input_bits() const { return (q.bits() - 1); } - SecureVector<byte> sign(const byte msg[], size_t msg_len, + secure_vector<byte> sign(const byte msg[], size_t msg_len, RandomNumberGenerator& rng); private: const BigInt& q; @@ -90,7 +90,7 @@ class BOTAN_DLL NR_Verification_Operation : public PK_Ops::Verification bool with_recovery() const { return true; } - SecureVector<byte> verify_mr(const byte msg[], size_t msg_len); + secure_vector<byte> verify_mr(const byte msg[], size_t msg_len); private: const BigInt& q; const BigInt& y; diff --git a/src/pubkey/pk_algs.cpp b/src/pubkey/pk_algs.cpp index 9b3218ac4..9673199e0 100644 --- a/src/pubkey/pk_algs.cpp +++ b/src/pubkey/pk_algs.cpp @@ -47,7 +47,7 @@ namespace Botan { Public_Key* make_public_key(const AlgorithmIdentifier& alg_id, - const MemoryRegion<byte>& key_bits) + const secure_vector<byte>& key_bits) { const std::string alg_name = OIDS::lookup(alg_id.oid); if(alg_name == "") @@ -98,11 +98,11 @@ Public_Key* make_public_key(const AlgorithmIdentifier& alg_id, return new ECDH_PublicKey(alg_id, key_bits); #endif - return 0; + return nullptr; } Private_Key* make_private_key(const AlgorithmIdentifier& alg_id, - const MemoryRegion<byte>& key_bits, + const secure_vector<byte>& key_bits, RandomNumberGenerator& rng) { const std::string alg_name = OIDS::lookup(alg_id.oid); @@ -154,7 +154,7 @@ Private_Key* make_private_key(const AlgorithmIdentifier& alg_id, return new ECDH_PrivateKey(alg_id, key_bits); #endif - return 0; + return nullptr; } } diff --git a/src/pubkey/pk_algs.h b/src/pubkey/pk_algs.h index a1e65cb3d..d8f24a1b8 100644 --- a/src/pubkey/pk_algs.h +++ b/src/pubkey/pk_algs.h @@ -13,10 +13,10 @@ namespace Botan { Public_Key* make_public_key(const AlgorithmIdentifier& alg_id, - const MemoryRegion<byte>& key_bits); + const secure_vector<byte>& key_bits); Private_Key* make_private_key(const AlgorithmIdentifier& alg_id, - const MemoryRegion<byte>& key_bits, + const secure_vector<byte>& key_bits, RandomNumberGenerator& rng); } diff --git a/src/pubkey/pk_keys.h b/src/pubkey/pk_keys.h index 770949b59..a3b693956 100644 --- a/src/pubkey/pk_keys.h +++ b/src/pubkey/pk_keys.h @@ -69,7 +69,7 @@ class BOTAN_DLL Public_Key /** * @return X.509 subject key encoding for this key object */ - virtual MemoryVector<byte> x509_subject_public_key() const = 0; + virtual std::vector<byte> x509_subject_public_key() const = 0; virtual ~Public_Key() {} protected: @@ -89,7 +89,7 @@ class BOTAN_DLL Private_Key : public virtual Public_Key /** * @return PKCS #8 private key encoding for this key object */ - virtual MemoryVector<byte> pkcs8_private_key() const = 0; + virtual secure_vector<byte> pkcs8_private_key() const = 0; /** * @return PKCS #8 AlgorithmIdentifier for this key @@ -121,7 +121,7 @@ class BOTAN_DLL PK_Key_Agreement_Key : public virtual Private_Key /* * @return public component of this key */ - virtual MemoryVector<byte> public_value() const = 0; + virtual std::vector<byte> public_value() const = 0; virtual ~PK_Key_Agreement_Key() {} }; diff --git a/src/pubkey/pk_ops.h b/src/pubkey/pk_ops.h index 51543cd33..8a08ef430 100644 --- a/src/pubkey/pk_ops.h +++ b/src/pubkey/pk_ops.h @@ -23,7 +23,7 @@ class BOTAN_DLL Encryption public: virtual size_t max_input_bits() const = 0; - virtual SecureVector<byte> encrypt(const byte msg[], size_t msg_len, + virtual secure_vector<byte> encrypt(const byte msg[], size_t msg_len, RandomNumberGenerator& rng) = 0; virtual ~Encryption() {} @@ -37,7 +37,7 @@ class BOTAN_DLL Decryption public: virtual size_t max_input_bits() const = 0; - virtual SecureVector<byte> decrypt(const byte msg[], + virtual secure_vector<byte> decrypt(const byte msg[], size_t msg_len) = 0; virtual ~Decryption() {} @@ -73,7 +73,7 @@ class BOTAN_DLL Signature * @param msg_len the length of msg in bytes * @param rng a random number generator */ - virtual SecureVector<byte> sign(const byte msg[], size_t msg_len, + virtual secure_vector<byte> sign(const byte msg[], size_t msg_len, RandomNumberGenerator& rng) = 0; virtual ~Signature() {} @@ -130,7 +130,7 @@ class BOTAN_DLL Verification * @param msg_len the length of msg in bytes * @returns recovered message */ - virtual SecureVector<byte> verify_mr(const byte[], + virtual secure_vector<byte> verify_mr(const byte[], size_t) { throw Invalid_State("Message recovery not supported"); @@ -151,7 +151,7 @@ class BOTAN_DLL Key_Agreement * @param w_len the length of w in bytes * @returns the agreed key */ - virtual SecureVector<byte> agree(const byte w[], size_t w_len) = 0; + virtual secure_vector<byte> agree(const byte w[], size_t w_len) = 0; virtual ~Key_Agreement() {} }; diff --git a/src/pubkey/pkcs8.cpp b/src/pubkey/pkcs8.cpp index 16440b648..baf6d1250 100644 --- a/src/pubkey/pkcs8.cpp +++ b/src/pubkey/pkcs8.cpp @@ -24,10 +24,10 @@ namespace { /* * Get info from an EncryptedPrivateKeyInfo */ -SecureVector<byte> PKCS8_extract(DataSource& source, +secure_vector<byte> PKCS8_extract(DataSource& source, AlgorithmIdentifier& pbe_alg_id) { - SecureVector<byte> key_data; + secure_vector<byte> key_data; BER_Decoder(source) .start_cons(SEQUENCE) @@ -41,11 +41,13 @@ SecureVector<byte> PKCS8_extract(DataSource& source, /* * PEM decode and/or decrypt a private key */ -SecureVector<byte> PKCS8_decode(DataSource& source, const User_Interface& ui, - AlgorithmIdentifier& pk_alg_id) +secure_vector<byte> PKCS8_decode( + DataSource& source, + std::function<std::pair<bool,std::string> ()> get_passphrase, + AlgorithmIdentifier& pk_alg_id) { AlgorithmIdentifier pbe_alg_id; - SecureVector<byte> key_data, key; + secure_vector<byte> key_data, key; bool is_encrypted = true; try { @@ -69,9 +71,9 @@ SecureVector<byte> PKCS8_decode(DataSource& source, const User_Interface& ui, if(key_data.empty()) throw PKCS8_Exception("No key data found"); } - catch(Decoding_Error) + catch(Decoding_Error& e) { - throw Decoding_Error("PKCS #8 private key decoding failed"); + throw Decoding_Error("PKCS #8 private key decoding failed: " + std::string(e.what())); } if(!is_encrypted) @@ -89,16 +91,14 @@ SecureVector<byte> PKCS8_decode(DataSource& source, const User_Interface& ui, if(is_encrypted) { DataSource_Memory params(pbe_alg_id.parameters); - std::auto_ptr<PBE> pbe(get_pbe(pbe_alg_id.oid, params)); + std::unique_ptr<PBE> pbe(get_pbe(pbe_alg_id.oid, params)); - User_Interface::UI_Result result = User_Interface::OK; - const std::string passphrase = - ui.get_passphrase("PKCS #8 private key", source.id(), result); + std::pair<bool, std::string> pass = get_passphrase(); - if(result == User_Interface::CANCEL_ACTION) + if(pass.first == false) break; - pbe->set_key(passphrase); + pbe->set_key(pass.second); Pipe decryptor(pbe.release()); decryptor.process_msg(key_data); @@ -131,7 +131,7 @@ SecureVector<byte> PKCS8_decode(DataSource& source, const User_Interface& ui, /* * BER encode a PKCS #8 private key, unencrypted */ -SecureVector<byte> BER_encode(const Private_Key& key) +secure_vector<byte> BER_encode(const Private_Key& key) { const size_t PKCS8_VERSION = 0; @@ -155,14 +155,14 @@ std::string PEM_encode(const Private_Key& key) /* * BER encode a PKCS #8 private key, encrypted */ -SecureVector<byte> BER_encode(const Private_Key& key, +secure_vector<byte> BER_encode(const Private_Key& key, RandomNumberGenerator& rng, const std::string& pass, const std::string& pbe_algo) { const std::string DEFAULT_PBE = "PBE-PKCS5v20(SHA-1,AES-256/CBC)"; - std::auto_ptr<PBE> pbe(get_pbe(((pbe_algo != "") ? pbe_algo : DEFAULT_PBE))); + std::unique_ptr<PBE> pbe(get_pbe(((pbe_algo != "") ? pbe_algo : DEFAULT_PBE))); pbe->new_params(rng); pbe->set_key(pass); @@ -200,10 +200,10 @@ std::string PEM_encode(const Private_Key& key, */ Private_Key* load_key(DataSource& source, RandomNumberGenerator& rng, - const User_Interface& ui) + std::function<std::pair<bool, std::string> ()> get_pass) { AlgorithmIdentifier alg_id; - SecureVector<byte> pkcs8_key = PKCS8_decode(source, ui, alg_id); + secure_vector<byte> pkcs8_key = PKCS8_decode(source, get_pass, alg_id); const std::string alg_name = OIDS::lookup(alg_id.oid); if(alg_name == "" || alg_name == alg_id.oid.as_string()) @@ -218,12 +218,38 @@ Private_Key* load_key(DataSource& source, */ Private_Key* load_key(const std::string& fsname, RandomNumberGenerator& rng, - const User_Interface& ui) + std::function<std::pair<bool, std::string> ()> get_pass) { DataSource_Stream source(fsname, true); - return PKCS8::load_key(source, rng, ui); + return PKCS8::load_key(source, rng, get_pass); } +namespace { + +class Single_Shot_Passphrase + { + public: + Single_Shot_Passphrase(const std::string& pass) : + passphrase(pass), first(true) {} + + std::pair<bool, std::string> operator()() + { + if(first) + { + first = false; + return std::make_pair(true, passphrase); + } + else + return std::make_pair(false, ""); + } + + private: + std::string passphrase; + bool first; + }; + +} + /* * Extract a private key and return it */ @@ -231,7 +257,7 @@ Private_Key* load_key(DataSource& source, RandomNumberGenerator& rng, const std::string& pass) { - return PKCS8::load_key(source, rng, User_Interface(pass)); + return PKCS8::load_key(source, rng, Single_Shot_Passphrase(pass)); } /* @@ -241,7 +267,7 @@ Private_Key* load_key(const std::string& fsname, RandomNumberGenerator& rng, const std::string& pass) { - return PKCS8::load_key(fsname, rng, User_Interface(pass)); + return PKCS8::load_key(fsname, rng, Single_Shot_Passphrase(pass)); } /* diff --git a/src/pubkey/pkcs8.h b/src/pubkey/pkcs8.h index 00607b329..fae1633a8 100644 --- a/src/pubkey/pkcs8.h +++ b/src/pubkey/pkcs8.h @@ -9,7 +9,7 @@ #define BOTAN_PKCS8_H__ #include <botan/x509_key.h> -#include <botan/ui.h> +#include <functional> namespace Botan { @@ -32,7 +32,7 @@ namespace PKCS8 { * @param key the private key to encode * @return BER encoded key */ -BOTAN_DLL SecureVector<byte> BER_encode(const Private_Key& key); +BOTAN_DLL secure_vector<byte> BER_encode(const Private_Key& key); /** * Get a string containing a PEM encoded private key. @@ -51,7 +51,7 @@ BOTAN_DLL std::string PEM_encode(const Private_Key& key); default will be chosen. * @return encrypted key in binary BER form */ -BOTAN_DLL SecureVector<byte> BER_encode(const Private_Key& key, +BOTAN_DLL secure_vector<byte> BER_encode(const Private_Key& key, RandomNumberGenerator& rng, const std::string& pass, const std::string& pbe_algo = ""); @@ -123,18 +123,19 @@ inline void encrypt_key(const Private_Key& key, * Load a key from a data source. * @param source the data source providing the encoded key * @param rng the rng to use -* @param ui the user interface to be used for passphrase dialog +* @param get_passphrase a function that returns passphrases * @return loaded private key object */ -BOTAN_DLL Private_Key* load_key(DataSource& source, - RandomNumberGenerator& rng, - const User_Interface& ui); +BOTAN_DLL Private_Key* load_key( + DataSource& source, + RandomNumberGenerator& rng, + std::function<std::pair<bool, std::string> ()> get_passphrase); /** Load a key from a data source. * @param source the data source providing the encoded key * @param rng the rng to use * @param pass the passphrase to decrypt the key. Provide an empty -* string if the key is not encoded. +* string if the key is not encrypted * @return loaded private key object */ BOTAN_DLL Private_Key* load_key(DataSource& source, @@ -145,18 +146,19 @@ BOTAN_DLL Private_Key* load_key(DataSource& source, * Load a key from a file. * @param filename the path to the file containing the encoded key * @param rng the rng to use -* @param ui the user interface to be used for passphrase dialog +* @param get_passphrase a function that returns passphrases * @return loaded private key object */ -BOTAN_DLL Private_Key* load_key(const std::string& filename, - RandomNumberGenerator& rng, - const User_Interface& ui); +BOTAN_DLL Private_Key* load_key( + const std::string& filename, + RandomNumberGenerator& rng, + std::function<std::pair<bool, std::string> ()> get_passphrase); /** Load a key from a file. * @param filename the path to the file containing the encoded key * @param rng the rng to use * @param pass the passphrase to decrypt the key. Provide an empty -* string if the key is not encoded. +* string if the key is not encrypted * @return loaded private key object */ BOTAN_DLL Private_Key* load_key(const std::string& filename, diff --git a/src/pubkey/pubkey.cpp b/src/pubkey/pubkey.cpp index 6e63f9fc9..c27cf4a05 100644 --- a/src/pubkey/pubkey.cpp +++ b/src/pubkey/pubkey.cpp @@ -38,33 +38,33 @@ PK_Encryptor_EME::PK_Encryptor_EME(const Public_Key& key, throw Lookup_Error("PK_Encryptor_EME: No working engine for " + key.algo_name()); - eme = (eme_name == "Raw") ? 0 : get_eme(eme_name); + eme = (eme_name == "Raw") ? nullptr : get_eme(eme_name); } /* * Encrypt a message */ -SecureVector<byte> +std::vector<byte> PK_Encryptor_EME::enc(const byte in[], size_t length, RandomNumberGenerator& rng) const { if(eme) { - SecureVector<byte> encoded = + secure_vector<byte> encoded = eme->encode(in, length, op->max_input_bits(), rng); if(8*(encoded.size() - 1) + high_bit(encoded[0]) > op->max_input_bits()) throw Invalid_Argument("PK_Encryptor_EME: Input is too large"); - return op->encrypt(&encoded[0], encoded.size(), rng); + return unlock(op->encrypt(&encoded[0], encoded.size(), rng)); } else { if(8*(length - 1) + high_bit(in[0]) > op->max_input_bits()) throw Invalid_Argument("PK_Encryptor_EME: Input is too large"); - return op->encrypt(&in[0], length, rng); + return unlock(op->encrypt(&in[0], length, rng)); } } @@ -98,17 +98,17 @@ PK_Decryptor_EME::PK_Decryptor_EME(const Private_Key& key, throw Lookup_Error("PK_Decryptor_EME: No working engine for " + key.algo_name()); - eme = (eme_name == "Raw") ? 0 : get_eme(eme_name); + eme = (eme_name == "Raw") ? nullptr : get_eme(eme_name); } /* * Decrypt a message */ -SecureVector<byte> PK_Decryptor_EME::dec(const byte msg[], - size_t length) const +secure_vector<byte> PK_Decryptor_EME::dec(const byte msg[], + size_t length) const { try { - SecureVector<byte> decrypted = op->decrypt(msg, length); + secure_vector<byte> decrypted = op->decrypt(msg, length); if(eme) return eme->decode(decrypted, op->max_input_bits()); else @@ -130,8 +130,8 @@ PK_Signer::PK_Signer(const Private_Key& key, { Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory()); - op = 0; - verify_op = 0; + op = nullptr; + verify_op = nullptr; while(const Engine* engine = i.next()) { @@ -156,7 +156,7 @@ PK_Signer::PK_Signer(const Private_Key& key, /* * Sign a message */ -SecureVector<byte> PK_Signer::sign_message(const byte msg[], size_t length, +std::vector<byte> PK_Signer::sign_message(const byte msg[], size_t length, RandomNumberGenerator& rng) { update(msg, length); @@ -174,16 +174,16 @@ void PK_Signer::update(const byte in[], size_t length) /* * Check the signature we just created, to help prevent fault attacks */ -bool PK_Signer::self_test_signature(const MemoryRegion<byte>& msg, - const MemoryRegion<byte>& sig) const +bool PK_Signer::self_test_signature(const std::vector<byte>& msg, + const std::vector<byte>& sig) const { if(!verify_op) return true; // checking disabled, assume ok if(verify_op->with_recovery()) { - SecureVector<byte> recovered = - verify_op->verify_mr(&sig[0], sig.size()); + std::vector<byte> recovered = + unlock(verify_op->verify_mr(&sig[0], sig.size())); if(msg.size() > recovered.size()) { @@ -206,13 +206,13 @@ bool PK_Signer::self_test_signature(const MemoryRegion<byte>& msg, /* * Create a signature */ -SecureVector<byte> PK_Signer::signature(RandomNumberGenerator& rng) +std::vector<byte> PK_Signer::signature(RandomNumberGenerator& rng) { - SecureVector<byte> encoded = emsa->encoding_of(emsa->raw_data(), - op->max_input_bits(), - rng); + std::vector<byte> encoded = unlock(emsa->encoding_of(emsa->raw_data(), + op->max_input_bits(), + rng)); - SecureVector<byte> plain_sig = op->sign(&encoded[0], encoded.size(), rng); + std::vector<byte> plain_sig = unlock(op->sign(&encoded[0], encoded.size(), rng)); BOTAN_ASSERT(self_test_signature(encoded, plain_sig), "PK_Signer consistency check failed"); @@ -234,11 +234,11 @@ SecureVector<byte> PK_Signer::signature(RandomNumberGenerator& rng) .start_cons(SEQUENCE) .encode_list(sig_parts) .end_cons() - .get_contents(); + .get_contents_unlocked(); } else throw Encoding_Error("PK_Signer: Unknown signature format " + - to_string(sig_format)); + std::to_string(sig_format)); } /* @@ -307,7 +307,7 @@ bool PK_Verifier::check_signature(const byte sig[], size_t length) BER_Decoder ber_sig = decoder.start_cons(SEQUENCE); size_t count = 0; - SecureVector<byte> real_sig; + std::vector<byte> real_sig; while(ber_sig.more_items()) { BigInt sig_part; @@ -324,7 +324,7 @@ bool PK_Verifier::check_signature(const byte sig[], size_t length) } else throw Decoding_Error("PK_Verifier: Unknown signature format " + - to_string(sig_format)); + std::to_string(sig_format)); } catch(Invalid_Argument) { return false; } } @@ -332,19 +332,19 @@ bool PK_Verifier::check_signature(const byte sig[], size_t length) /* * Verify a signature */ -bool PK_Verifier::validate_signature(const MemoryRegion<byte>& msg, +bool PK_Verifier::validate_signature(const secure_vector<byte>& msg, const byte sig[], size_t sig_len) { if(op->with_recovery()) { - SecureVector<byte> output_of_key = op->verify_mr(sig, sig_len); + secure_vector<byte> output_of_key = op->verify_mr(sig, sig_len); return emsa->verify(output_of_key, msg, op->max_input_bits()); } else { Null_RNG rng; - SecureVector<byte> encoded = + secure_vector<byte> encoded = emsa->encoding_of(msg, op->max_input_bits(), rng); return op->verify(&encoded[0], encoded.size(), sig, sig_len); @@ -370,14 +370,14 @@ PK_Key_Agreement::PK_Key_Agreement(const PK_Key_Agreement_Key& key, throw Lookup_Error("PK_Key_Agreement: No working engine for " + key.algo_name()); - kdf = (kdf_name == "Raw") ? 0 : get_kdf(kdf_name); + kdf = (kdf_name == "Raw") ? nullptr : get_kdf(kdf_name); } SymmetricKey PK_Key_Agreement::derive_key(size_t key_len, const byte in[], size_t in_len, const byte params[], size_t params_len) const { - SecureVector<byte> z = op->agree(in, in_len); + secure_vector<byte> z = op->agree(in, in_len); if(!kdf) return z; diff --git a/src/pubkey/pubkey.h b/src/pubkey/pubkey.h index cd813dc65..5013a1ed1 100644 --- a/src/pubkey/pubkey.h +++ b/src/pubkey/pubkey.h @@ -45,7 +45,7 @@ class BOTAN_DLL PK_Encryptor * @param rng the random number source to use * @return encrypted message */ - SecureVector<byte> encrypt(const byte in[], size_t length, + std::vector<byte> encrypt(const byte in[], size_t length, RandomNumberGenerator& rng) const { return enc(in, length, rng); @@ -57,8 +57,9 @@ class BOTAN_DLL PK_Encryptor * @param rng the random number source to use * @return encrypted message */ - SecureVector<byte> encrypt(const MemoryRegion<byte>& in, - RandomNumberGenerator& rng) const + template<typename Alloc> + std::vector<byte> encrypt(const std::vector<byte, Alloc>& in, + RandomNumberGenerator& rng) const { return enc(&in[0], in.size(), rng); } @@ -75,7 +76,7 @@ class BOTAN_DLL PK_Encryptor PK_Encryptor(const PK_Encryptor&) {} PK_Encryptor& operator=(const PK_Encryptor&) { return *this; } - virtual SecureVector<byte> enc(const byte[], size_t, + virtual std::vector<byte> enc(const byte[], size_t, RandomNumberGenerator&) const = 0; }; @@ -91,7 +92,7 @@ class BOTAN_DLL PK_Decryptor * @param length the length of the above byte array * @return decrypted message */ - SecureVector<byte> decrypt(const byte in[], size_t length) const + secure_vector<byte> decrypt(const byte in[], size_t length) const { return dec(in, length); } @@ -101,7 +102,8 @@ class BOTAN_DLL PK_Decryptor * @param in the ciphertext * @return decrypted message */ - SecureVector<byte> decrypt(const MemoryRegion<byte>& in) const + template<typename Alloc> + secure_vector<byte> decrypt(const std::vector<byte, Alloc>& in) const { return dec(&in[0], in.size()); } @@ -112,7 +114,7 @@ class BOTAN_DLL PK_Decryptor PK_Decryptor(const PK_Decryptor&) {} PK_Decryptor& operator=(const PK_Decryptor&) { return *this; } - virtual SecureVector<byte> dec(const byte[], size_t) const = 0; + virtual secure_vector<byte> dec(const byte[], size_t) const = 0; }; /** @@ -130,7 +132,7 @@ class BOTAN_DLL PK_Signer * @param rng the rng to use * @return signature */ - SecureVector<byte> sign_message(const byte in[], size_t length, + std::vector<byte> sign_message(const byte in[], size_t length, RandomNumberGenerator& rng); /** @@ -139,8 +141,12 @@ class BOTAN_DLL PK_Signer * @param rng the rng to use * @return signature */ - SecureVector<byte> sign_message(const MemoryRegion<byte>& in, - RandomNumberGenerator& rng) + std::vector<byte> sign_message(const std::vector<byte>& in, + RandomNumberGenerator& rng) + { return sign_message(&in[0], in.size(), rng); } + + std::vector<byte> sign_message(const secure_vector<byte>& in, + RandomNumberGenerator& rng) { return sign_message(&in[0], in.size(), rng); } /** @@ -160,7 +166,7 @@ class BOTAN_DLL PK_Signer * Add a message part. * @param in the message part to add */ - void update(const MemoryRegion<byte>& in) { update(&in[0], in.size()); } + void update(const std::vector<byte>& in) { update(&in[0], in.size()); } /** * Get the signature of the so far processed message (provided by the @@ -168,7 +174,7 @@ class BOTAN_DLL PK_Signer * @param rng the rng to use * @return signature of the total message */ - SecureVector<byte> signature(RandomNumberGenerator& rng); + std::vector<byte> signature(RandomNumberGenerator& rng); /** * Set the output format of the signature. @@ -191,8 +197,8 @@ class BOTAN_DLL PK_Signer ~PK_Signer() { delete op; delete verify_op; delete emsa; } private: - bool self_test_signature(const MemoryRegion<byte>& msg, - const MemoryRegion<byte>& sig) const; + bool self_test_signature(const std::vector<byte>& msg, + const std::vector<byte>& sig) const; PK_Signer(const PK_Signer&) {} PK_Signer& operator=(const PK_Signer&) { return *this; } @@ -227,8 +233,9 @@ class BOTAN_DLL PK_Verifier * @param sig the signature * @return true if the signature is valid */ - bool verify_message(const MemoryRegion<byte>& msg, - const MemoryRegion<byte>& sig) + template<typename Alloc, typename Alloc2> + bool verify_message(const std::vector<byte, Alloc>& msg, + const std::vector<byte, Alloc2>& sig) { return verify_message(&msg[0], msg.size(), &sig[0], sig.size()); @@ -254,7 +261,7 @@ class BOTAN_DLL PK_Verifier * signature to be verified. * @param in the new message part */ - void update(const MemoryRegion<byte>& in) + void update(const std::vector<byte>& in) { update(&in[0], in.size()); } /** @@ -272,7 +279,8 @@ class BOTAN_DLL PK_Verifier * @param sig the signature to be verified * @return true if the signature is valid, false otherwise */ - bool check_signature(const MemoryRegion<byte>& sig) + template<typename Alloc> + bool check_signature(const std::vector<byte, Alloc>& sig) { return check_signature(&sig[0], sig.size()); } @@ -298,7 +306,7 @@ class BOTAN_DLL PK_Verifier PK_Verifier(const PK_Verifier&) {} PK_Verifier& operator=(const PK_Verifier&) { return *this; } - bool validate_signature(const MemoryRegion<byte>& msg, + bool validate_signature(const secure_vector<byte>& msg, const byte sig[], size_t sig_len); PK_Ops::Verification* op; @@ -336,7 +344,7 @@ class BOTAN_DLL PK_Key_Agreement * @param params_len the length of params in bytes */ SymmetricKey derive_key(size_t key_len, - const MemoryRegion<byte>& in, + const std::vector<byte>& in, const byte params[], size_t params_len) const { @@ -367,7 +375,7 @@ class BOTAN_DLL PK_Key_Agreement * @param params extra derivation params */ SymmetricKey derive_key(size_t key_len, - const MemoryRegion<byte>& in, + const std::vector<byte>& in, const std::string& params = "") const { return derive_key(key_len, &in[0], in.size(), @@ -410,7 +418,7 @@ class BOTAN_DLL PK_Encryptor_EME : public PK_Encryptor ~PK_Encryptor_EME() { delete op; delete eme; } private: - SecureVector<byte> enc(const byte[], size_t, + std::vector<byte> enc(const byte[], size_t, RandomNumberGenerator& rng) const; PK_Ops::Encryption* op; @@ -433,7 +441,7 @@ class BOTAN_DLL PK_Decryptor_EME : public PK_Decryptor ~PK_Decryptor_EME() { delete op; delete eme; } private: - SecureVector<byte> dec(const byte[], size_t) const; + secure_vector<byte> dec(const byte[], size_t) const; PK_Ops::Decryption* op; const EME* eme; diff --git a/src/pubkey/rsa/rsa.cpp b/src/pubkey/rsa/rsa.cpp index 40c3968af..22474d7d5 100644 --- a/src/pubkey/rsa/rsa.cpp +++ b/src/pubkey/rsa/rsa.cpp @@ -11,6 +11,7 @@ #include <botan/numthry.h> #include <botan/keypair.h> #include <botan/internal/assert.h> +#include <future> namespace Botan { @@ -22,7 +23,7 @@ RSA_PrivateKey::RSA_PrivateKey(RandomNumberGenerator& rng, { if(bits < 512) throw Invalid_Argument(algo_name() + ": Can't make a key that is only " + - to_string(bits) + " bits long"); + std::to_string(bits) + " bits long"); if(exp < 3 || exp % 2 == 0) throw Invalid_Argument(algo_name() + ": Invalid encryption exponent"); @@ -78,15 +79,16 @@ BigInt RSA_Private_Operation::private_op(const BigInt& m) const if(m >= n) throw Invalid_Argument("RSA private op - input is too large"); - BigInt j1 = powermod_d1_p(m); + auto future_j1 = std::async(std::launch::async, powermod_d1_p, m); BigInt j2 = powermod_d2_q(m); + BigInt j1 = future_j1.get(); j1 = mod_p.reduce(sub_mul(j1, j2, c)); return mul_add(j1, q, j2); } -SecureVector<byte> +secure_vector<byte> RSA_Private_Operation::sign(const byte msg[], size_t msg_len, RandomNumberGenerator&) { @@ -103,7 +105,7 @@ RSA_Private_Operation::sign(const byte msg[], size_t msg_len, /* * RSA Decryption Operation */ -SecureVector<byte> +secure_vector<byte> RSA_Private_Operation::decrypt(const byte msg[], size_t msg_len) { BigInt m(msg, msg_len); @@ -112,7 +114,7 @@ RSA_Private_Operation::decrypt(const byte msg[], size_t msg_len) BOTAN_ASSERT(m == powermod_e_n(x), "RSA private op failed consistency check"); - return BigInt::encode(x); + return BigInt::encode_locked(x); } } diff --git a/src/pubkey/rsa/rsa.h b/src/pubkey/rsa/rsa.h index dddecdbed..0942d92ad 100644 --- a/src/pubkey/rsa/rsa.h +++ b/src/pubkey/rsa/rsa.h @@ -24,7 +24,7 @@ class BOTAN_DLL RSA_PublicKey : public virtual IF_Scheme_PublicKey std::string algo_name() const { return "RSA"; } RSA_PublicKey(const AlgorithmIdentifier& alg_id, - const MemoryRegion<byte>& key_bits) : + const secure_vector<byte>& key_bits) : IF_Scheme_PublicKey(alg_id, key_bits) {} @@ -51,7 +51,7 @@ class BOTAN_DLL RSA_PrivateKey : public RSA_PublicKey, bool check_key(RandomNumberGenerator& rng, bool) const; RSA_PrivateKey(const AlgorithmIdentifier& alg_id, - const MemoryRegion<byte>& key_bits, + const secure_vector<byte>& key_bits, RandomNumberGenerator& rng) : IF_Scheme_PrivateKey(rng, alg_id, key_bits) {} @@ -94,10 +94,10 @@ class BOTAN_DLL RSA_Private_Operation : public PK_Ops::Signature, size_t max_input_bits() const { return (n.bits() - 1); } - SecureVector<byte> sign(const byte msg[], size_t msg_len, + secure_vector<byte> sign(const byte msg[], size_t msg_len, RandomNumberGenerator& rng); - SecureVector<byte> decrypt(const byte msg[], size_t msg_len); + secure_vector<byte> decrypt(const byte msg[], size_t msg_len); private: BigInt private_op(const BigInt& m) const; @@ -124,17 +124,17 @@ class BOTAN_DLL RSA_Public_Operation : public PK_Ops::Verification, size_t max_input_bits() const { return (n.bits() - 1); } bool with_recovery() const { return true; } - SecureVector<byte> encrypt(const byte msg[], size_t msg_len, + secure_vector<byte> encrypt(const byte msg[], size_t msg_len, RandomNumberGenerator&) { BigInt m(msg, msg_len); return BigInt::encode_1363(public_op(m), n.bytes()); } - SecureVector<byte> verify_mr(const byte msg[], size_t msg_len) + secure_vector<byte> verify_mr(const byte msg[], size_t msg_len) { BigInt m(msg, msg_len); - return BigInt::encode(public_op(m)); + return BigInt::encode_locked(public_op(m)); } private: diff --git a/src/pubkey/rw/rw.cpp b/src/pubkey/rw/rw.cpp index 5f58d8e88..d57b967e9 100644 --- a/src/pubkey/rw/rw.cpp +++ b/src/pubkey/rw/rw.cpp @@ -10,6 +10,7 @@ #include <botan/keypair.h> #include <botan/parsing.h> #include <algorithm> +#include <future> namespace Botan { @@ -21,7 +22,7 @@ RW_PrivateKey::RW_PrivateKey(RandomNumberGenerator& rng, { if(bits < 512) throw Invalid_Argument(algo_name() + ": Can't make a key that is only " + - to_string(bits) + " bits long"); + std::to_string(bits) + " bits long"); if(exp < 2 || exp % 2 == 1) throw Invalid_Argument(algo_name() + ": Invalid encryption exponent"); @@ -70,7 +71,7 @@ RW_Signature_Operation::RW_Signature_Operation(const RW_PrivateKey& rw) : { } -SecureVector<byte> +secure_vector<byte> RW_Signature_Operation::sign(const byte msg[], size_t msg_len, RandomNumberGenerator& rng) { @@ -90,18 +91,18 @@ RW_Signature_Operation::sign(const byte msg[], size_t msg_len, i = blinder.blind(i); - BigInt j1 = powermod_d1_p(i); - BigInt j2 = powermod_d2_q(i); - j1 = mod_p.reduce(sub_mul(j1, j2, c)); + auto future_j1 = std::async(std::launch::async, powermod_d1_p, i); + const BigInt j2 = powermod_d2_q(i); + BigInt j1 = future_j1.get(); - BigInt r = blinder.unblind(mul_add(j1, q, j2)); + j1 = mod_p.reduce(sub_mul(j1, j2, c)); - r = std::min(r, n - r); + const BigInt r = blinder.unblind(mul_add(j1, q, j2)); - return BigInt::encode_1363(r, n.bytes()); + return BigInt::encode_1363(std::min(r, n - r), n.bytes()); } -SecureVector<byte> +secure_vector<byte> RW_Verification_Operation::verify_mr(const byte msg[], size_t msg_len) { BigInt m(msg, msg_len); @@ -111,15 +112,15 @@ RW_Verification_Operation::verify_mr(const byte msg[], size_t msg_len) BigInt r = powermod_e_n(m); if(r % 16 == 12) - return BigInt::encode(r); + return BigInt::encode_locked(r); if(r % 8 == 6) - return BigInt::encode(2*r); + return BigInt::encode_locked(2*r); r = n - r; if(r % 16 == 12) - return BigInt::encode(r); + return BigInt::encode_locked(r); if(r % 8 == 6) - return BigInt::encode(2*r); + return BigInt::encode_locked(2*r); throw Invalid_Argument("RW signature verification: Invalid signature"); } diff --git a/src/pubkey/rw/rw.h b/src/pubkey/rw/rw.h index b8d92eb3a..1e918e70c 100644 --- a/src/pubkey/rw/rw.h +++ b/src/pubkey/rw/rw.h @@ -24,7 +24,7 @@ class BOTAN_DLL RW_PublicKey : public virtual IF_Scheme_PublicKey std::string algo_name() const { return "RW"; } RW_PublicKey(const AlgorithmIdentifier& alg_id, - const MemoryRegion<byte>& key_bits) : + const secure_vector<byte>& key_bits) : IF_Scheme_PublicKey(alg_id, key_bits) {} @@ -44,7 +44,7 @@ class BOTAN_DLL RW_PrivateKey : public RW_PublicKey, { public: RW_PrivateKey(const AlgorithmIdentifier& alg_id, - const MemoryRegion<byte>& key_bits, + const secure_vector<byte>& key_bits, RandomNumberGenerator& rng) : IF_Scheme_PrivateKey(rng, alg_id, key_bits) {} @@ -69,7 +69,7 @@ class BOTAN_DLL RW_Signature_Operation : public PK_Ops::Signature size_t max_input_bits() const { return (n.bits() - 1); } - SecureVector<byte> sign(const byte msg[], size_t msg_len, + secure_vector<byte> sign(const byte msg[], size_t msg_len, RandomNumberGenerator& rng); private: const BigInt& n; @@ -95,7 +95,7 @@ class BOTAN_DLL RW_Verification_Operation : public PK_Ops::Verification size_t max_input_bits() const { return (n.bits() - 1); } bool with_recovery() const { return true; } - SecureVector<byte> verify_mr(const byte msg[], size_t msg_len); + secure_vector<byte> verify_mr(const byte msg[], size_t msg_len); private: const BigInt& n; diff --git a/src/pubkey/workfactor.cpp b/src/pubkey/workfactor.cpp index f3d5d164a..72ba75cf9 100644 --- a/src/pubkey/workfactor.cpp +++ b/src/pubkey/workfactor.cpp @@ -1,6 +1,6 @@ /* * Public Key Work Factor Functions -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2007,2012 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -11,39 +11,40 @@ namespace Botan { -/* -* Choose the exponent size for a DL group -*/ size_t dl_work_factor(size_t bits) { -#if 0 /* - These values were taken from RFC 3526 + Based on GNFS work factors. Constant is 1.43 times the asymptotic + value; I'm not sure but I believe that came from a paper on 'real + world' runtimes, but I don't remember where now. + + Sample return values: + |512| -> 64 + |1024| -> 86 + |1536| -> 102 + |2048| -> 116 + |3072| -> 138 + |4096| -> 155 + |8192| -> 206 + + For DL algos, we use an exponent of twice the size of the result; + the assumption is that an arbitrary discrete log on a group of size + bits would take about 2^n effort, and thus using an exponent of + size 2^(2*n) implies that all available attacks are about as easy + (as e.g Pollard's kangaroo algorithm can compute the DL in sqrt(x) + operations) while minimizing the exponent size for performance + reasons. */ - if(bits <= 1536) - return 90; - else if(bits <= 2048) - return 110; - else if(bits <= 3072) - return 130; - else if(bits <= 4096) - return 150; - else if(bits <= 6144) - return 170; - else if(bits <= 8192) - return 190; - return 256; -#else - const double MIN_ESTIMATE = 64; - - const double log_x = bits / 1.44; + + const size_t MIN_WORKFACTOR = 64; + + // approximates natural logarithm of p + const double log_p = bits / 1.4426; const double strength = - 2.76 * std::pow(log_x, 1.0/3.0) * std::pow(std::log(log_x), 2.0/3.0); + 2.76 * std::pow(log_p, 1.0/3.0) * std::pow(std::log(log_p), 2.0/3.0); - return static_cast<size_t>(std::max(strength, MIN_ESTIMATE)); -#endif + return std::max(static_cast<size_t>(strength), MIN_WORKFACTOR); } - } diff --git a/src/pubkey/workfactor.h b/src/pubkey/workfactor.h index bd1a43298..179b580e7 100644 --- a/src/pubkey/workfactor.h +++ b/src/pubkey/workfactor.h @@ -13,7 +13,7 @@ namespace Botan { /** -* Estimate work factor +* Estimate work factor for discrete logarithm * @param prime_group_size size of the group in bits * @return estimated security level for this group */ diff --git a/src/pubkey/x509_key.cpp b/src/pubkey/x509_key.cpp index c55f37d94..797ec273c 100644 --- a/src/pubkey/x509_key.cpp +++ b/src/pubkey/x509_key.cpp @@ -18,14 +18,14 @@ namespace Botan { namespace X509 { -MemoryVector<byte> BER_encode(const Public_Key& key) +std::vector<byte> BER_encode(const Public_Key& key) { return DER_Encoder() .start_cons(SEQUENCE) .encode(key.algorithm_identifier()) .encode(key.x509_subject_public_key(), BIT_STRING) .end_cons() - .get_contents(); + .get_contents_unlocked(); } /* @@ -44,7 +44,7 @@ Public_Key* load_key(DataSource& source) { try { AlgorithmIdentifier alg_id; - MemoryVector<byte> key_bits; + secure_vector<byte> key_bits; if(ASN1::maybe_BER(source) && !PEM_Code::matches(source)) { @@ -92,7 +92,7 @@ Public_Key* load_key(const std::string& fsname) /* * Extract a public key and return it */ -Public_Key* load_key(const MemoryRegion<byte>& mem) +Public_Key* load_key(const secure_vector<byte>& mem) { DataSource_Memory source(mem); return X509::load_key(source); diff --git a/src/pubkey/x509_key.h b/src/pubkey/x509_key.h index 13ad7e635..fde765715 100644 --- a/src/pubkey/x509_key.h +++ b/src/pubkey/x509_key.h @@ -30,7 +30,7 @@ namespace X509 { * @param key the public key to encode * @return BER encoding of this key */ -BOTAN_DLL MemoryVector<byte> BER_encode(const Public_Key& key); +BOTAN_DLL std::vector<byte> BER_encode(const Public_Key& key); /** * PEM encode a public key into a string. @@ -58,7 +58,7 @@ BOTAN_DLL Public_Key* load_key(const std::string& filename); * @param enc the memory region containing the DER or PEM encoded key * @return new public key object */ -BOTAN_DLL Public_Key* load_key(const MemoryRegion<byte>& enc); +BOTAN_DLL Public_Key* load_key(const secure_vector<byte>& enc); /** * Copy a key. diff --git a/src/rng/hmac_rng/hmac_rng.cpp b/src/rng/hmac_rng/hmac_rng.cpp index 74ba522a4..da7535b18 100644 --- a/src/rng/hmac_rng/hmac_rng.cpp +++ b/src/rng/hmac_rng/hmac_rng.cpp @@ -8,7 +8,6 @@ #include <botan/hmac_rng.h> #include <botan/get_byte.h> #include <botan/internal/xor_buf.h> -#include <botan/internal/stl_util.h> #include <algorithm> namespace Botan { @@ -16,7 +15,7 @@ namespace Botan { namespace { void hmac_prf(MessageAuthenticationCode* prf, - MemoryRegion<byte>& K, + secure_vector<byte>& K, u32bit& counter, const std::string& label) { @@ -124,7 +123,7 @@ void HMAC_RNG::reseed(size_t poll_bits) */ void HMAC_RNG::add_entropy(const byte input[], size_t length) { - const size_t USER_ENTROPY_WATERSHED = 20; + const size_t USER_ENTROPY_WATERSHED = 64; extractor->update(input, length); user_input_len += length; @@ -136,7 +135,7 @@ void HMAC_RNG::add_entropy(const byte input[], size_t length) * the extractor input. */ if(user_input_len >= USER_ENTROPY_WATERSHED) - reseed(128); + reseed(0); } /* @@ -201,7 +200,7 @@ HMAC_RNG::HMAC_RNG(MessageAuthenticationCode* extractor_mac, the estimated entropy counter is high enough. That variable is only set when a reseeding is performed. */ - MemoryVector<byte> prf_key(extractor->output_length()); + secure_vector<byte> prf_key(extractor->output_length()); prf->set_key(prf_key); /* @@ -224,8 +223,8 @@ HMAC_RNG::~HMAC_RNG() delete extractor; delete prf; - std::for_each(entropy_sources.begin(), entropy_sources.end(), - del_fun<EntropySource>()); + for(auto src : entropy_sources) + delete src; counter = 0; } diff --git a/src/rng/hmac_rng/hmac_rng.h b/src/rng/hmac_rng/hmac_rng.h index fc6a14f3a..1e70c00a7 100644 --- a/src/rng/hmac_rng/hmac_rng.h +++ b/src/rng/hmac_rng/hmac_rng.h @@ -51,7 +51,7 @@ class BOTAN_DLL HMAC_RNG : public RandomNumberGenerator std::vector<EntropySource*> entropy_sources; bool seeded; - SecureVector<byte> K, io_buffer; + secure_vector<byte> K, io_buffer; size_t user_input_len; u32bit counter; }; diff --git a/src/rng/randpool/randpool.cpp b/src/rng/randpool/randpool.cpp index 92f225a9c..ef55f3975 100644 --- a/src/rng/randpool/randpool.cpp +++ b/src/rng/randpool/randpool.cpp @@ -8,8 +8,8 @@ #include <botan/randpool.h> #include <botan/get_byte.h> #include <botan/internal/xor_buf.h> -#include <botan/internal/stl_util.h> #include <algorithm> +#include <chrono> namespace Botan { @@ -56,7 +56,7 @@ void Randpool::update_buffer() mac->update(static_cast<byte>(GEN_OUTPUT)); mac->update(counter); - SecureVector<byte> mac_val = mac->final(); + secure_vector<byte> mac_val = mac->final(); for(size_t i = 0; i != mac_val.size(); ++i) buffer[i % buffer.size()] ^= mac_val[i]; @@ -112,7 +112,7 @@ void Randpool::reseed(size_t poll_bits) } } - SecureVector<byte> mac_val = mac->final(); + secure_vector<byte> mac_val = mac->final(); xor_buf(pool, mac_val, mac_val.size()); mix_pool(); @@ -126,7 +126,7 @@ void Randpool::reseed(size_t poll_bits) */ void Randpool::add_entropy(const byte input[], size_t length) { - SecureVector<byte> mac_val = mac->process(input, length); + secure_vector<byte> mac_val = mac->process(input, length); xor_buf(pool, mac_val, mac_val.size()); mix_pool(); @@ -202,8 +202,8 @@ Randpool::~Randpool() delete cipher; delete mac; - std::for_each(entropy_sources.begin(), entropy_sources.end(), - del_fun<EntropySource>()); + for(auto i = entropy_sources.begin(); i != entropy_sources.end(); ++i) + delete *i; } } diff --git a/src/rng/randpool/randpool.h b/src/rng/randpool/randpool.h index ed224221c..64572bcfb 100644 --- a/src/rng/randpool/randpool.h +++ b/src/rng/randpool/randpool.h @@ -52,7 +52,7 @@ class BOTAN_DLL Randpool : public RandomNumberGenerator MessageAuthenticationCode* mac; std::vector<EntropySource*> entropy_sources; - SecureVector<byte> pool, buffer, counter; + secure_vector<byte> pool, buffer, counter; bool seeded; }; diff --git a/src/rng/rng.h b/src/rng/rng.h index c078ef08f..12b423e7c 100644 --- a/src/rng/rng.h +++ b/src/rng/rng.h @@ -37,9 +37,9 @@ class BOTAN_DLL RandomNumberGenerator * @param bytes number of bytes in the result * @return randomized vector of length bytes */ - SecureVector<byte> random_vec(size_t bytes) + secure_vector<byte> random_vec(size_t bytes) { - SecureVector<byte> output(bytes); + secure_vector<byte> output(bytes); randomize(&output[0], output.size()); return output; } diff --git a/src/rng/x931_rng/x931_rng.cpp b/src/rng/x931_rng/x931_rng.cpp index ac77b4344..7562c7ad5 100644 --- a/src/rng/x931_rng/x931_rng.cpp +++ b/src/rng/x931_rng/x931_rng.cpp @@ -40,7 +40,7 @@ void ANSI_X931_RNG::update_buffer() { const size_t BLOCK_SIZE = cipher->block_size(); - SecureVector<byte> DT = prng->random_vec(BLOCK_SIZE); + secure_vector<byte> DT = prng->random_vec(BLOCK_SIZE); cipher->encrypt(DT); xor_buf(&R[0], &V[0], &DT[0], BLOCK_SIZE); diff --git a/src/rng/x931_rng/x931_rng.h b/src/rng/x931_rng/x931_rng.h index 41fa9328b..c8a1b8707 100644 --- a/src/rng/x931_rng/x931_rng.h +++ b/src/rng/x931_rng/x931_rng.h @@ -42,7 +42,7 @@ class BOTAN_DLL ANSI_X931_RNG : public RandomNumberGenerator BlockCipher* cipher; RandomNumberGenerator* prng; - SecureVector<byte> V, R; + secure_vector<byte> V, R; size_t position; }; diff --git a/src/selftest/selftest.cpp b/src/selftest/selftest.cpp index 0dac31cef..8f4dc70d8 100644 --- a/src/selftest/selftest.cpp +++ b/src/selftest/selftest.cpp @@ -125,8 +125,7 @@ namespace { void verify_results(const std::string& algo, const std::map<std::string, bool>& results) { - for(std::map<std::string, bool>::const_iterator i = results.begin(); - i != results.end(); ++i) + for(auto i = results.begin(); i != results.end(); ++i) { if(!i->second) throw Self_Test_Failure(algo + " self-test failed, provider "+ diff --git a/src/ssl/c_kex.cpp b/src/ssl/c_kex.cpp deleted file mode 100644 index 0f20b819c..000000000 --- a/src/ssl/c_kex.cpp +++ /dev/null @@ -1,165 +0,0 @@ -/* -* Client Key Exchange Message -* (C) 2004-2010 Jack Lloyd -* -* Released under the terms of the Botan license -*/ - -#include <botan/internal/tls_messages.h> -#include <botan/internal/tls_reader.h> -#include <botan/pubkey.h> -#include <botan/dh.h> -#include <botan/rsa.h> -#include <botan/rng.h> -#include <botan/loadstor.h> -#include <memory> - -namespace Botan { - -/** -* Create a new Client Key Exchange message -*/ -Client_Key_Exchange::Client_Key_Exchange(RandomNumberGenerator& rng, - Record_Writer& writer, - HandshakeHash& hash, - const Public_Key* pub_key, - Version_Code using_version, - Version_Code pref_version) - { - include_length = true; - - if(const DH_PublicKey* dh_pub = dynamic_cast<const DH_PublicKey*>(pub_key)) - { - DH_PrivateKey priv_key(rng, dh_pub->get_domain()); - - PK_Key_Agreement ka(priv_key, "Raw"); - - pre_master = ka.derive_key(0, dh_pub->public_value()).bits_of(); - - key_material = priv_key.public_value(); - } - else if(const RSA_PublicKey* rsa_pub = dynamic_cast<const RSA_PublicKey*>(pub_key)) - { - pre_master = rng.random_vec(48); - pre_master[0] = (pref_version >> 8) & 0xFF; - pre_master[1] = (pref_version ) & 0xFF; - - PK_Encryptor_EME encryptor(*rsa_pub, "PKCS1v15"); - - key_material = encryptor.encrypt(pre_master, rng); - - if(using_version == SSL_V3) - include_length = false; - } - else - throw Invalid_Argument("Client_Key_Exchange: Key not RSA or DH"); - - send(writer, hash); - } - -/** -* Read a Client Key Exchange message -*/ -Client_Key_Exchange::Client_Key_Exchange(const MemoryRegion<byte>& contents, - const CipherSuite& suite, - Version_Code using_version) - { - include_length = true; - - if(using_version == SSL_V3 && (suite.kex_type() == TLS_ALGO_KEYEXCH_RSA)) - include_length = false; - - deserialize(contents); - } - -/** -* Serialize a Client Key Exchange message -*/ -SecureVector<byte> Client_Key_Exchange::serialize() const - { - if(include_length) - { - SecureVector<byte> buf; - append_tls_length_value(buf, key_material, 2); - return buf; - } - else - return key_material; - } - -/** -* Deserialize a Client Key Exchange message -*/ -void Client_Key_Exchange::deserialize(const MemoryRegion<byte>& buf) - { - if(include_length) - { - TLS_Data_Reader reader(buf); - key_material = reader.get_range<byte>(2, 0, 65535); - } - else - key_material = buf; - } - -/** -* Return the pre_master_secret -*/ -SecureVector<byte> -Client_Key_Exchange::pre_master_secret(RandomNumberGenerator& rng, - const Private_Key* priv_key, - Version_Code version) - { - - if(const DH_PrivateKey* dh_priv = dynamic_cast<const DH_PrivateKey*>(priv_key)) - { - try { - PK_Key_Agreement ka(*dh_priv, "Raw"); - - pre_master = ka.derive_key(0, key_material).bits_of(); - } - catch(...) - { - /* - * Something failed in the DH computation. To avoid possible - * timing attacks, randomize the pre-master output and carry - * on, allowing the protocol to fail later in the finished - * checks. - */ - pre_master = rng.random_vec(dh_priv->public_value().size()); - } - - return pre_master; - } - else if(const RSA_PrivateKey* rsa_priv = dynamic_cast<const RSA_PrivateKey*>(priv_key)) - { - PK_Decryptor_EME decryptor(*rsa_priv, "PKCS1v15"); - - try { - pre_master = decryptor.decrypt(key_material); - - if(pre_master.size() != 48 || - make_u16bit(pre_master[0], pre_master[1]) != version) - throw Decoding_Error("Client_Key_Exchange: Secret corrupted"); - } - catch(...) - { - pre_master = rng.random_vec(48); - pre_master[0] = (version >> 8) & 0xFF; - pre_master[1] = (version ) & 0xFF; - } - - return pre_master; - } - else - throw Invalid_Argument("Client_Key_Exchange: Bad key for decrypt"); - } - -/** -* Return the pre_master_secret -*/ -SecureVector<byte> Client_Key_Exchange::pre_master_secret() const - { - return pre_master; - } - -} diff --git a/src/ssl/cert_req.cpp b/src/ssl/cert_req.cpp deleted file mode 100644 index b8b2624bf..000000000 --- a/src/ssl/cert_req.cpp +++ /dev/null @@ -1,151 +0,0 @@ -/* -* Certificate Request Message -* (C) 2004-2006 Jack Lloyd -* -* Released under the terms of the Botan license -*/ - -#include <botan/internal/tls_messages.h> -#include <botan/internal/tls_reader.h> -#include <botan/der_enc.h> -#include <botan/ber_dec.h> -#include <botan/loadstor.h> -#include <botan/secqueue.h> - -namespace Botan { - -/** -* Create a new Certificate Request message -*/ -Certificate_Req::Certificate_Req(Record_Writer& writer, - HandshakeHash& hash, - const std::vector<X509_Certificate>& certs) - { - for(size_t i = 0; i != certs.size(); ++i) - names.push_back(certs[i].subject_dn()); - - // FIXME: should be able to choose what to ask for - types.push_back(RSA_CERT); - types.push_back(DSS_CERT); - - send(writer, hash); - } - -/** -* Serialize a Certificate Request message -*/ -SecureVector<byte> Certificate_Req::serialize() const - { - SecureVector<byte> buf; - - append_tls_length_value(buf, types, 1); - - DER_Encoder encoder; - for(size_t i = 0; i != names.size(); ++i) - encoder.encode(names[i]); - - append_tls_length_value(buf, encoder.get_contents(), 2); - - return buf; - } - -/** -* Deserialize a Certificate Request message -*/ -void Certificate_Req::deserialize(const MemoryRegion<byte>& buf) - { - if(buf.size() < 4) - throw Decoding_Error("Certificate_Req: Bad certificate request"); - - size_t types_size = buf[0]; - - if(buf.size() < types_size + 3) - throw Decoding_Error("Certificate_Req: Bad certificate request"); - - for(size_t i = 0; i != types_size; ++i) - types.push_back(static_cast<Certificate_Type>(buf[i+1])); - - size_t names_size = make_u16bit(buf[types_size+2], buf[types_size+3]); - - if(buf.size() != names_size + types_size + 3) - throw Decoding_Error("Certificate_Req: Bad certificate request"); - - BER_Decoder decoder(&buf[types_size + 3], names_size); - - while(decoder.more_items()) - { - X509_DN name; - decoder.decode(name); - names.push_back(name); - } - } - -/** -* Create a new Certificate message -*/ -Certificate::Certificate(Record_Writer& writer, - const std::vector<X509_Certificate>& cert_list, - HandshakeHash& hash) - { - certs = cert_list; - send(writer, hash); - } - -/** -* Serialize a Certificate message -*/ -SecureVector<byte> Certificate::serialize() const - { - SecureVector<byte> buf(3); - - for(size_t i = 0; i != certs.size(); ++i) - { - SecureVector<byte> raw_cert = certs[i].BER_encode(); - const size_t cert_size = raw_cert.size(); - for(size_t i = 0; i != 3; ++i) - buf.push_back(get_byte<u32bit>(i+1, cert_size)); - buf += raw_cert; - } - - const size_t buf_size = buf.size() - 3; - for(size_t i = 0; i != 3; ++i) - buf[i] = get_byte<u32bit>(i+1, buf_size); - - return buf; - } - -/** -* Deserialize a Certificate message -*/ -void Certificate::deserialize(const MemoryRegion<byte>& buf) - { - if(buf.size() < 3) - throw Decoding_Error("Certificate: Message malformed"); - - const size_t total_size = make_u32bit(0, buf[0], buf[1], buf[2]); - - SecureQueue queue; - queue.write(&buf[3], buf.size() - 3); - - if(queue.size() != total_size) - throw Decoding_Error("Certificate: Message malformed"); - - while(queue.size()) - { - if(queue.size() < 3) - throw Decoding_Error("Certificate: Message malformed"); - - byte len[3]; - queue.read(len, 3); - - const size_t cert_size = make_u32bit(0, len[0], len[1], len[2]); - const size_t original_size = queue.size(); - - X509_Certificate cert(queue); - if(queue.size() + cert_size != original_size) - throw Decoding_Error("Certificate: Message malformed"); - certs.push_back(cert); - } - } - -} diff --git a/src/ssl/cert_ver.cpp b/src/ssl/cert_ver.cpp deleted file mode 100644 index 3220a8c9e..000000000 --- a/src/ssl/cert_ver.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* -* Certificate Verify Message -* (C) 2004-2010 Jack Lloyd -* -* Released under the terms of the Botan license -*/ - -#include <botan/internal/tls_messages.h> -#include <botan/internal/tls_reader.h> -#include <botan/pubkey.h> -#include <botan/rsa.h> -#include <botan/dsa.h> -#include <botan/loadstor.h> -#include <memory> - -namespace Botan { - -/** -* Create a new Certificate Verify message -*/ -Certificate_Verify::Certificate_Verify(RandomNumberGenerator& rng, - Record_Writer& writer, - HandshakeHash& hash, - const Private_Key* priv_key) - { - std::string padding = ""; - Signature_Format format = IEEE_1363; - - if(priv_key->algo_name() == "RSA") - padding = "EMSA3(TLS.Digest.0)"; - else if(priv_key->algo_name() == "DSA") - { - padding == "EMSA1(SHA-1)"; - format = DER_SEQUENCE; - } - else - throw Invalid_Argument(priv_key->algo_name() + - " is invalid/unknown for TLS signatures"); - - PK_Signer signer(*priv_key, padding, format); - - signature = signer.sign_message(hash.final(), rng); - send(writer, hash); - } - -/** -* Serialize a Certificate Verify message -*/ -SecureVector<byte> Certificate_Verify::serialize() const - { - SecureVector<byte> buf; - - const u16bit sig_len = signature.size(); - buf.push_back(get_byte(0, sig_len)); - buf.push_back(get_byte(1, sig_len)); - buf += signature; - - return buf; - } - -/** -* Deserialize a Certificate Verify message -*/ -void Certificate_Verify::deserialize(const MemoryRegion<byte>& buf) - { - TLS_Data_Reader reader(buf); - signature = reader.get_range<byte>(2, 0, 65535); - } - -/** -* Verify a Certificate Verify message -*/ -bool Certificate_Verify::verify(const X509_Certificate& cert, - HandshakeHash& hash) - { - // FIXME: duplicate of Server_Key_Exchange::verify - - std::auto_ptr<Public_Key> key(cert.subject_public_key()); - - std::string padding = ""; - Signature_Format format = IEEE_1363; - - if(key->algo_name() == "RSA") - padding = "EMSA3(TLS.Digest.0)"; - else if(key->algo_name() == "DSA") - { - padding == "EMSA1(SHA-1)"; - format = DER_SEQUENCE; - } - else - throw Invalid_Argument(key->algo_name() + - " is invalid/unknown for TLS signatures"); - - PK_Verifier verifier(*key, padding, format); - return verifier.verify_message(hash.final(), signature); - } - -} diff --git a/src/ssl/finished.cpp b/src/ssl/finished.cpp deleted file mode 100644 index d76fbd884..000000000 --- a/src/ssl/finished.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/* -* Finished Message -* (C) 2004-2006 Jack Lloyd -* -* Released under the terms of the Botan license -*/ - -#include <botan/internal/tls_messages.h> -#include <botan/prf_tls.h> - -namespace Botan { - -/** -* Create a new Finished message -*/ -Finished::Finished(Record_Writer& writer, - Version_Code version, Connection_Side side, - const MemoryRegion<byte>& master_secret, - HandshakeHash& hash) - { - verification_data = compute_verify(master_secret, hash, side, version); - send(writer, hash); - } - -/** -* Serialize a Finished message -*/ -SecureVector<byte> Finished::serialize() const - { - return verification_data; - } - -/** -* Deserialize a Finished message -*/ -void Finished::deserialize(const MemoryRegion<byte>& buf) - { - verification_data = buf; - } - -/** -* Verify a Finished message -*/ -bool Finished::verify(const MemoryRegion<byte>& secret, Version_Code version, - const HandshakeHash& hash, Connection_Side side) - { - SecureVector<byte> computed = compute_verify(secret, hash, side, version); - if(computed == verification_data) - return true; - return false; - } - -/** -* Compute the verify_data -*/ -SecureVector<byte> Finished::compute_verify(const MemoryRegion<byte>& secret, - HandshakeHash hash, - Connection_Side side, - Version_Code version) - { - if(version == SSL_V3) - { - const byte SSL_CLIENT_LABEL[] = { 0x43, 0x4C, 0x4E, 0x54 }; - const byte SSL_SERVER_LABEL[] = { 0x53, 0x52, 0x56, 0x52 }; - - SecureVector<byte> ssl3_finished; - - if(side == CLIENT) - hash.update(SSL_CLIENT_LABEL, sizeof(SSL_CLIENT_LABEL)); - else - hash.update(SSL_SERVER_LABEL, sizeof(SSL_SERVER_LABEL)); - - return hash.final_ssl3(secret); - } - else if(version == TLS_V10 || version == TLS_V11) - { - const byte TLS_CLIENT_LABEL[] = { - 0x63, 0x6C, 0x69, 0x65, 0x6E, 0x74, 0x20, 0x66, 0x69, 0x6E, 0x69, - 0x73, 0x68, 0x65, 0x64 }; - - const byte TLS_SERVER_LABEL[] = { - 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x66, 0x69, 0x6E, 0x69, - 0x73, 0x68, 0x65, 0x64 }; - - TLS_PRF prf; - - SecureVector<byte> input; - if(side == CLIENT) - input += std::make_pair(TLS_CLIENT_LABEL, sizeof(TLS_CLIENT_LABEL)); - else - input += std::make_pair(TLS_SERVER_LABEL, sizeof(TLS_SERVER_LABEL)); - input += hash.final(); - - return prf.derive_key(12, secret, input); - } - else - throw Invalid_Argument("Finished message: Unknown protocol version"); - } - -} diff --git a/src/ssl/hello.cpp b/src/ssl/hello.cpp deleted file mode 100644 index ae0d9607b..000000000 --- a/src/ssl/hello.cpp +++ /dev/null @@ -1,331 +0,0 @@ -/* -* TLS Hello Messages -* (C) 2004-2010 Jack Lloyd -* -* Released under the terms of the Botan license -*/ - -#include <botan/internal/tls_messages.h> -#include <botan/internal/tls_reader.h> - -namespace Botan { - -/* -* Encode and send a Handshake message -*/ -void HandshakeMessage::send(Record_Writer& writer, HandshakeHash& hash) const - { - SecureVector<byte> buf = serialize(); - SecureVector<byte> send_buf(4); - - const size_t buf_size = buf.size(); - - send_buf[0] = type(); - - for(size_t i = 1; i != 4; ++i) - send_buf[i] = get_byte<u32bit>(i, buf_size); - - send_buf += buf; - - hash.update(send_buf); - - writer.send(HANDSHAKE, &send_buf[0], send_buf.size()); - writer.flush(); - } - -/* -* Create a new Hello Request message -*/ -Hello_Request::Hello_Request(Record_Writer& writer) - { - HandshakeHash dummy; // FIXME: *UGLY* - send(writer, dummy); - } - -/* -* Serialize a Hello Request message -*/ -SecureVector<byte> Hello_Request::serialize() const - { - return SecureVector<byte>(); - } - -/* -* Deserialize a Hello Request message -*/ -void Hello_Request::deserialize(const MemoryRegion<byte>& buf) - { - if(buf.size()) - throw Decoding_Error("Hello_Request: Must be empty, and is not"); - } - -/* -* Create a new Client Hello message -*/ -Client_Hello::Client_Hello(RandomNumberGenerator& rng, - Record_Writer& writer, - const TLS_Policy& policy, - HandshakeHash& hash) - { - c_random = rng.random_vec(32); - - suites = policy.ciphersuites(); - comp_algos = policy.compression(); - c_version = policy.pref_version(); - - send(writer, hash); - } - -/* -* Serialize a Client Hello message -*/ -SecureVector<byte> Client_Hello::serialize() const - { - SecureVector<byte> buf; - - buf.push_back(static_cast<byte>(c_version >> 8)); - buf.push_back(static_cast<byte>(c_version )); - buf += c_random; - - append_tls_length_value(buf, sess_id, 1); - append_tls_length_value(buf, suites, 2); - append_tls_length_value(buf, comp_algos, 1); - - return buf; - } - -void Client_Hello::deserialize_sslv2(const MemoryRegion<byte>& buf) - { - if(buf.size() < 12 || buf[0] != 1) - throw Decoding_Error("Client_Hello: SSLv2 hello corrupted"); - - const size_t cipher_spec_len = make_u16bit(buf[3], buf[4]); - const size_t sess_id_len = make_u16bit(buf[5], buf[6]); - const size_t challenge_len = make_u16bit(buf[7], buf[8]); - - const size_t expected_size = - (9 + sess_id_len + cipher_spec_len + challenge_len); - - if(buf.size() != expected_size) - throw Decoding_Error("Client_Hello: SSLv2 hello corrupted"); - - if(sess_id_len != 0 || cipher_spec_len % 3 != 0 || - (challenge_len < 16 || challenge_len > 32)) - { - throw Decoding_Error("Client_Hello: SSLv2 hello corrupted"); - } - - for(size_t i = 9; i != 9 + cipher_spec_len; i += 3) - { - if(buf[i] != 0) // a SSLv2 cipherspec; ignore it - continue; - - suites.push_back(make_u16bit(buf[i+1], buf[i+2])); - } - - c_version = static_cast<Version_Code>(make_u16bit(buf[1], buf[2])); - - c_random.resize(challenge_len); - copy_mem(&c_random[0], &buf[9+cipher_spec_len+sess_id_len], challenge_len); - } - -/* -* Deserialize a Client Hello message -*/ -void Client_Hello::deserialize(const MemoryRegion<byte>& buf) - { - if(buf.size() == 0) - throw Decoding_Error("Client_Hello: Packet corrupted"); - - if(buf.size() < 41) - throw Decoding_Error("Client_Hello: Packet corrupted"); - - TLS_Data_Reader reader(buf); - - c_version = static_cast<Version_Code>(reader.get_u16bit()); - c_random = reader.get_fixed<byte>(32); - - sess_id = reader.get_range<byte>(1, 0, 32); - - suites = reader.get_range_vector<u16bit>(2, 1, 32767); - - comp_algos = reader.get_range_vector<byte>(1, 1, 255); - - if(reader.has_remaining()) - { - const u16bit all_extn_size = reader.get_u16bit(); - - if(reader.remaining_bytes() != all_extn_size) - throw Decoding_Error("Client_Hello: Bad extension size"); - - while(reader.has_remaining()) - { - const u16bit extension_code = reader.get_u16bit(); - const u16bit extension_size = reader.get_u16bit(); - - if(extension_code == TLSEXT_SERVER_NAME_INDICATION) - { - u16bit name_bytes = reader.get_u16bit(); - - while(name_bytes) - { - byte name_type = reader.get_byte(); - name_bytes--; - - if(name_type == 0) // DNS - { - std::vector<byte> name = - reader.get_range_vector<byte>(2, 1, 65535); - - requested_hostname.assign( - reinterpret_cast<const char*>(&name[0]), - name.size()); - - name_bytes -= (2 + name.size()); - } - else - { - reader.discard_next(name_bytes); - name_bytes = 0; - } - } - } - else if(extension_code == TLSEXT_SRP_IDENTIFIER) - { - std::vector<byte> name = reader.get_range_vector<byte>(1, 1, 255); - - requested_srp_id.assign( - reinterpret_cast<char*>(&name[0]), - name.size()); - } - else - { - reader.discard_next(extension_size); - } - } - } - } - -/* -* Check if we offered this ciphersuite -*/ -bool Client_Hello::offered_suite(u16bit ciphersuite) const - { - for(size_t i = 0; i != suites.size(); ++i) - if(suites[i] == ciphersuite) - return true; - return false; - } - -/* -* Create a new Server Hello message -*/ -Server_Hello::Server_Hello(RandomNumberGenerator& rng, - Record_Writer& writer, - const TLS_Policy& policy, - const std::vector<X509_Certificate>& certs, - const Client_Hello& c_hello, - Version_Code ver, - HandshakeHash& hash) - { - bool have_rsa = false, have_dsa = false; - - for(size_t i = 0; i != certs.size(); ++i) - { - Public_Key* key = certs[i].subject_public_key(); - if(key->algo_name() == "RSA") - have_rsa = true; - - if(key->algo_name() == "DSA") - have_dsa = true; - } - - suite = policy.choose_suite(c_hello.ciphersuites(), have_rsa, have_dsa); - - if(suite == 0) - throw TLS_Exception(PROTOCOL_VERSION, - "Can't agree on a ciphersuite with client"); - - comp_algo = policy.choose_compression(c_hello.compression_algos()); - - s_version = ver; - s_random = rng.random_vec(32); - - send(writer, hash); - } - -/* -* Serialize a Server Hello message -*/ -SecureVector<byte> Server_Hello::serialize() const - { - SecureVector<byte> buf; - - buf.push_back(static_cast<byte>(s_version >> 8)); - buf.push_back(static_cast<byte>(s_version )); - buf += s_random; - - append_tls_length_value(buf, sess_id, 1); - - buf.push_back(get_byte(0, suite)); - buf.push_back(get_byte(1, suite)); - - buf.push_back(comp_algo); - - return buf; - } - -/* -* Deserialize a Server Hello message -*/ -void Server_Hello::deserialize(const MemoryRegion<byte>& buf) - { - if(buf.size() < 38) - throw Decoding_Error("Server_Hello: Packet corrupted"); - - TLS_Data_Reader reader(buf); - - s_version = static_cast<Version_Code>(reader.get_u16bit()); - - if(s_version != SSL_V3 && s_version != TLS_V10 && s_version != TLS_V11) - { - throw TLS_Exception(PROTOCOL_VERSION, - "Server_Hello: Unsupported server version"); - } - - s_random = reader.get_fixed<byte>(32); - - sess_id = reader.get_range<byte>(1, 0, 32); - - suite = reader.get_u16bit(); - - comp_algo = reader.get_byte(); - } - -/* -* Create a new Server Hello Done message -*/ -Server_Hello_Done::Server_Hello_Done(Record_Writer& writer, - HandshakeHash& hash) - { - send(writer, hash); - } - -/* -* Serialize a Server Hello Done message -*/ -SecureVector<byte> Server_Hello_Done::serialize() const - { - return SecureVector<byte>(); - } - -/* -* Deserialize a Server Hello Done message -*/ -void Server_Hello_Done::deserialize(const MemoryRegion<byte>& buf) - { - if(buf.size()) - throw Decoding_Error("Server_Hello_Done: Must be empty, and is not"); - } - -} diff --git a/src/ssl/info.txt b/src/ssl/info.txt deleted file mode 100644 index fd2c255fc..000000000 --- a/src/ssl/info.txt +++ /dev/null @@ -1,71 +0,0 @@ -define SSL_TLS - -load_on request - -<comment> -A new TLS API is being developed. This version has numerous -performance and usability issues and will not be supported in the -future. Only use it if you need it for compatability with code written -against previous versions. -</comment> - -uses_tr1 yes - -<header:public> -tls_client.h -tls_connection.h -tls_exceptn.h -tls_magic.h -tls_policy.h -tls_record.h -tls_server.h -tls_session_key.h -tls_suites.h -</header:public> - -<header:internal> -tls_alerts.h -tls_handshake_hash.h -tls_messages.h -tls_reader.h -tls_state.h -</header:internal> - -<source> -c_kex.cpp -cert_req.cpp -cert_ver.cpp -finished.cpp -tls_handshake_hash.cpp -hello.cpp -rec_read.cpp -rec_wri.cpp -s_kex.cpp -tls_client.cpp -tls_policy.cpp -tls_server.cpp -tls_session_key.cpp -tls_state.cpp -tls_suites.cpp -</source> - -<requires> -aes -arc4 -asn1 -des -dh -dsa -eme_pkcs -emsa3 -filters -hmac -md5 -prf_ssl3 -prf_tls -rng -rsa -sha1 -ssl3mac -x509 -</requires> diff --git a/src/ssl/rec_read.cpp b/src/ssl/rec_read.cpp deleted file mode 100644 index 7e295f8a4..000000000 --- a/src/ssl/rec_read.cpp +++ /dev/null @@ -1,260 +0,0 @@ -/* -* TLS Record Reading -* (C) 2004-2010 Jack Lloyd -* -* Released under the terms of the Botan license -*/ - -#include <botan/tls_record.h> -#include <botan/lookup.h> -#include <botan/loadstor.h> - -namespace Botan { - -/* -* Reset the state -*/ -void Record_Reader::reset() - { - cipher.reset(); - - delete mac; - mac = 0; - - mac_size = 0; - block_size = 0; - iv_size = 0; - major = minor = 0; - seq_no = 0; - } - -/* -* Set the version to use -*/ -void Record_Reader::set_version(Version_Code version) - { - if(version != SSL_V3 && version != TLS_V10 && version != TLS_V11) - throw Invalid_Argument("Record_Reader: Invalid protocol version"); - - major = (version >> 8) & 0xFF; - minor = (version & 0xFF); - } - -/* -* Set the keys for reading -*/ -void Record_Reader::set_keys(const CipherSuite& suite, const SessionKeys& keys, - Connection_Side side) - { - cipher.reset(); - delete mac; - mac = 0; - - SymmetricKey mac_key, cipher_key; - InitializationVector iv; - - if(side == CLIENT) - { - cipher_key = keys.server_cipher_key(); - iv = keys.server_iv(); - mac_key = keys.server_mac_key(); - } - else - { - cipher_key = keys.client_cipher_key(); - iv = keys.client_iv(); - mac_key = keys.client_mac_key(); - } - - const std::string cipher_algo = suite.cipher_algo(); - const std::string mac_algo = suite.mac_algo(); - - if(have_block_cipher(cipher_algo)) - { - cipher.append(get_cipher( - cipher_algo + "/CBC/NoPadding", - cipher_key, iv, DECRYPTION) - ); - block_size = block_size_of(cipher_algo); - - if(major > 3 || (major == 3 && minor >= 2)) - iv_size = block_size; - else - iv_size = 0; - } - else if(have_stream_cipher(cipher_algo)) - { - cipher.append(get_cipher(cipher_algo, cipher_key, DECRYPTION)); - block_size = 0; - iv_size = 0; - } - else - throw Invalid_Argument("Record_Reader: Unknown cipher " + cipher_algo); - - if(have_hash(mac_algo)) - { - Algorithm_Factory& af = global_state().algorithm_factory(); - - if(major == 3 && minor == 0) - mac = af.make_mac("SSL3-MAC(" + mac_algo + ")"); - else - mac = af.make_mac("HMAC(" + mac_algo + ")"); - - mac->set_key(mac_key); - mac_size = mac->output_length(); - } - else - throw Invalid_Argument("Record_Reader: Unknown hash " + mac_algo); - } - -void Record_Reader::add_input(const byte input[], size_t input_size) - { - input_queue.write(input, input_size); - } - -/* -* Retrieve the next record -*/ -size_t Record_Reader::get_record(byte& msg_type, - MemoryRegion<byte>& output) - { - byte header[5] = { 0 }; - - const size_t have_in_queue = input_queue.size(); - - if(have_in_queue < sizeof(header)) - return (sizeof(header) - have_in_queue); - - /* - * We peek first to make sure we have the full record - */ - input_queue.peek(header, sizeof(header)); - - // SSLv2-format client hello? - if(header[0] & 0x80 && header[2] == 1 && header[3] == 3) - { - size_t record_len = make_u16bit(header[0], header[1]) & 0x7FFF; - - if(have_in_queue < record_len + 2) - return (record_len + 2 - have_in_queue); - - msg_type = HANDSHAKE; - output.resize(record_len + 4); - - input_queue.read(&output[2], record_len + 2); - output[0] = CLIENT_HELLO_SSLV2; - output[1] = 0; - output[2] = header[0] & 0x7F; - output[3] = header[1]; - - return 0; - } - - if(header[0] != CHANGE_CIPHER_SPEC && - header[0] != ALERT && - header[0] != HANDSHAKE && - header[0] != APPLICATION_DATA) - { - throw TLS_Exception(UNEXPECTED_MESSAGE, - "Record_Reader: Unknown record type"); - } - - const u16bit version = make_u16bit(header[1], header[2]); - const u16bit record_len = make_u16bit(header[3], header[4]); - - if(major && (header[1] != major || header[2] != minor)) - throw TLS_Exception(PROTOCOL_VERSION, - "Record_Reader: Got unexpected version"); - - // If insufficient data, return without doing anything - if(have_in_queue < (sizeof(header) + record_len)) - return (sizeof(header) + record_len - have_in_queue); - - SecureVector<byte> buffer(record_len); - - input_queue.read(header, sizeof(header)); // pull off the header - input_queue.read(&buffer[0], buffer.size()); - - /* - * We are handshaking, no crypto to do so return as-is - * TODO: Check msg_type to confirm a handshake? - */ - if(mac_size == 0) - { - msg_type = header[0]; - output = buffer; - return 0; // got a full record - } - - // Otherwise, decrypt, check MAC, return plaintext - - cipher.process_msg(buffer); - SecureVector<byte> plaintext = cipher.read_all(Pipe::LAST_MESSAGE); - - size_t pad_size = 0; - - if(block_size) - { - byte pad_value = plaintext[plaintext.size()-1]; - pad_size = pad_value + 1; - - /* - * Check the padding; if it is wrong, then say we have 0 bytes of - * padding, which should ensure that the MAC check below does not - * suceed. This hides a timing channel. - * - * This particular countermeasure is recommended in the TLS 1.2 - * spec (RFC 5246) in section 6.2.3.2 - */ - if(version == SSL_V3) - { - if(pad_value > block_size) - pad_size = 0; - } - else - { - bool padding_good = true; - - for(size_t i = 0; i != pad_size; ++i) - if(plaintext[plaintext.size()-i-1] != pad_value) - padding_good = false; - - if(!padding_good) - pad_size = 0; - } - } - - if(plaintext.size() < mac_size + pad_size + iv_size) - throw Decoding_Error("Record_Reader: Record truncated"); - - const size_t mac_offset = plaintext.size() - (mac_size + pad_size); - SecureVector<byte> received_mac(&plaintext[mac_offset], - mac_size); - - const u16bit plain_length = plaintext.size() - (mac_size + pad_size + iv_size); - - mac->update_be(seq_no); - mac->update(header[0]); // msg_type - - if(version != SSL_V3) - for(size_t i = 0; i != 2; ++i) - mac->update(get_byte(i, version)); - - mac->update_be(plain_length); - mac->update(&plaintext[iv_size], plain_length); - - ++seq_no; - - SecureVector<byte> computed_mac = mac->final(); - - if(received_mac != computed_mac) - throw TLS_Exception(BAD_RECORD_MAC, "Record_Reader: MAC failure"); - - msg_type = header[0]; - - output.resize(plain_length); - copy_mem(&output[0], &plaintext[iv_size], plain_length); - return 0; - } - -} diff --git a/src/ssl/rec_wri.cpp b/src/ssl/rec_wri.cpp deleted file mode 100644 index 59dead3cd..000000000 --- a/src/ssl/rec_wri.cpp +++ /dev/null @@ -1,270 +0,0 @@ -/* -* TLS Record Writing -* (C) 2004-2010 Jack Lloyd -* -* Released under the terms of the Botan license -*/ - -#include <botan/tls_record.h> -#include <botan/internal/tls_handshake_hash.h> -#include <botan/lookup.h> -#include <botan/loadstor.h> -#include <botan/libstate.h> - -namespace Botan { - -/** -* Record_Writer Constructor -*/ -Record_Writer::Record_Writer(std::tr1::function<void (const byte[], size_t)> out) : - output_fn(out), - buffer(DEFAULT_BUFFERSIZE) - { - mac = 0; - reset(); - } - -/** -* Reset the state -*/ -void Record_Writer::reset() - { - cipher.reset(); - - delete mac; - mac = 0; - - zeroise(buffer); - buf_pos = 0; - - major = minor = buf_type = 0; - block_size = 0; - mac_size = 0; - iv_size = 0; - - seq_no = 0; - } - -/** -* Set the version to use -*/ -void Record_Writer::set_version(Version_Code version) - { - if(version != SSL_V3 && version != TLS_V10 && version != TLS_V11) - throw Invalid_Argument("Record_Writer: Invalid protocol version"); - - major = (version >> 8) & 0xFF; - minor = (version & 0xFF); - } - -/** -* Set the keys for writing -*/ -void Record_Writer::set_keys(const CipherSuite& suite, const SessionKeys& keys, - Connection_Side side) - { - cipher.reset(); - delete mac; - mac = 0; - - SymmetricKey mac_key, cipher_key; - InitializationVector iv; - - if(side == CLIENT) - { - cipher_key = keys.client_cipher_key(); - iv = keys.client_iv(); - mac_key = keys.client_mac_key(); - } - else - { - cipher_key = keys.server_cipher_key(); - iv = keys.server_iv(); - mac_key = keys.server_mac_key(); - } - - const std::string cipher_algo = suite.cipher_algo(); - const std::string mac_algo = suite.mac_algo(); - - if(have_block_cipher(cipher_algo)) - { - cipher.append(get_cipher( - cipher_algo + "/CBC/NoPadding", - cipher_key, iv, ENCRYPTION) - ); - block_size = block_size_of(cipher_algo); - - if(major > 3 || (major == 3 && minor >= 2)) - iv_size = block_size; - else - iv_size = 0; - } - else if(have_stream_cipher(cipher_algo)) - { - cipher.append(get_cipher(cipher_algo, cipher_key, ENCRYPTION)); - block_size = 0; - iv_size = 0; - } - else - throw Invalid_Argument("Record_Writer: Unknown cipher " + cipher_algo); - - if(have_hash(mac_algo)) - { - Algorithm_Factory& af = global_state().algorithm_factory(); - - if(major == 3 && minor == 0) - mac = af.make_mac("SSL3-MAC(" + mac_algo + ")"); - else - mac = af.make_mac("HMAC(" + mac_algo + ")"); - - mac->set_key(mac_key); - mac_size = mac->output_length(); - } - else - throw Invalid_Argument("Record_Writer: Unknown hash " + mac_algo); - } - -/** -* Send one or more records to the other side -*/ -void Record_Writer::send(byte type, const byte input[], size_t length) - { - if(type != buf_type) - flush(); - - const size_t BUFFER_SIZE = buffer.size(); - buf_type = type; - - // FIXME: compression right here - - buffer.copy(buf_pos, input, length); - if(buf_pos + length >= BUFFER_SIZE) - { - send_record(buf_type, &buffer[0], length); - input += (BUFFER_SIZE - buf_pos); - length -= (BUFFER_SIZE - buf_pos); - while(length >= BUFFER_SIZE) - { - send_record(buf_type, input, BUFFER_SIZE); - input += BUFFER_SIZE; - length -= BUFFER_SIZE; - } - buffer.copy(input, length); - buf_pos = 0; - } - buf_pos += length; - } - -/** -* Split buffer into records, and send them all -*/ -void Record_Writer::flush() - { - const byte* buf_ptr = &buffer[0]; - size_t offset = 0; - - while(offset != buf_pos) - { - size_t record_size = buf_pos - offset; - if(record_size > MAX_PLAINTEXT_SIZE) - record_size = MAX_PLAINTEXT_SIZE; - - send_record(buf_type, buf_ptr + offset, record_size); - offset += record_size; - } - buf_type = 0; - buf_pos = 0; - } - -/** -* Encrypt and send the record -*/ -void Record_Writer::send_record(byte type, const byte buf[], size_t length) - { - if(length >= MAX_COMPRESSED_SIZE) - throw TLS_Exception(INTERNAL_ERROR, - "Record_Writer: Compressed packet is too big"); - - if(mac_size == 0) - send_record(type, major, minor, buf, length); - else - { - mac->update_be(seq_no); - mac->update(type); - - if(major > 3 || (major == 3 && minor != 0)) - { - mac->update(major); - mac->update(minor); - } - - mac->update(get_byte<u16bit>(0, length)); - mac->update(get_byte<u16bit>(1, length)); - mac->update(buf, length); - - SecureVector<byte> buf_mac = mac->final(); - - // TODO: This could all use a single buffer - cipher.start_msg(); - - if(iv_size) - { - RandomNumberGenerator& rng = global_state().global_rng(); - - SecureVector<byte> random_iv(iv_size); - - rng.randomize(&random_iv[0], random_iv.size()); - - cipher.write(random_iv); - } - - cipher.write(buf, length); - cipher.write(buf_mac); - - if(block_size) - { - size_t pad_val = - (block_size - (1 + length + buf_mac.size())) % block_size; - - for(size_t i = 0; i != pad_val + 1; ++i) - cipher.write(pad_val); - } - cipher.end_msg(); - - SecureVector<byte> output = cipher.read_all(Pipe::LAST_MESSAGE); - - send_record(type, major, minor, &output[0], output.size()); - - seq_no++; - } - } - -/** -* Send a final record packet -*/ -void Record_Writer::send_record(byte type, byte major, byte minor, - const byte out[], size_t length) - { - if(length >= MAX_CIPHERTEXT_SIZE) - throw TLS_Exception(INTERNAL_ERROR, - "Record_Writer: Record is too big"); - - byte header[5] = { type, major, minor, 0 }; - for(size_t i = 0; i != 2; ++i) - header[i+3] = get_byte<u16bit>(i, length); - - output_fn(header, 5); - output_fn(out, length); - } - -/** -* Send an alert -*/ -void Record_Writer::alert(Alert_Level level, Alert_Type type) - { - byte alert[2] = { level, type }; - send(ALERT, alert, sizeof(alert)); - flush(); - } - -} diff --git a/src/ssl/s_kex.cpp b/src/ssl/s_kex.cpp deleted file mode 100644 index 1e7de31d0..000000000 --- a/src/ssl/s_kex.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/* -* Server Key Exchange Message -* (C) 2004-2010 Jack Lloyd -* -* Released under the terms of the Botan license -*/ - -#include <botan/internal/tls_messages.h> -#include <botan/internal/tls_reader.h> -#include <botan/pubkey.h> -#include <botan/dh.h> -#include <botan/rsa.h> -#include <botan/dsa.h> -#include <botan/loadstor.h> -#include <memory> - -namespace Botan { - -/** -* Create a new Server Key Exchange message -*/ -Server_Key_Exchange::Server_Key_Exchange(RandomNumberGenerator& rng, - Record_Writer& writer, - const Public_Key* kex_key, - const Private_Key* priv_key, - const MemoryRegion<byte>& c_random, - const MemoryRegion<byte>& s_random, - HandshakeHash& hash) - { - const DH_PublicKey* dh_pub = dynamic_cast<const DH_PublicKey*>(kex_key); - const RSA_PublicKey* rsa_pub = dynamic_cast<const RSA_PublicKey*>(kex_key); - - if(dh_pub) - { - params.push_back(dh_pub->get_domain().get_p()); - params.push_back(dh_pub->get_domain().get_g()); - params.push_back(BigInt::decode(dh_pub->public_value())); - } - else if(rsa_pub) - { - params.push_back(rsa_pub->get_n()); - params.push_back(rsa_pub->get_e()); - } - else - throw Invalid_Argument("Bad key for TLS key exchange: not DH or RSA"); - - - std::string padding = ""; - Signature_Format format = IEEE_1363; - - if(priv_key->algo_name() == "RSA") - padding = "EMSA3(TLS.Digest.0)"; - else if(priv_key->algo_name() == "DSA") - { - padding = "EMSA1(SHA-1)"; - format = DER_SEQUENCE; - } - else - throw Invalid_Argument(priv_key->algo_name() + - " is invalid/unknown for TLS signatures"); - - PK_Signer signer(*priv_key, padding, format); - - signer.update(c_random); - signer.update(s_random); - signer.update(serialize_params()); - signature = signer.signature(rng); - - send(writer, hash); - } - -/** -* Serialize a Server Key Exchange message -*/ -SecureVector<byte> Server_Key_Exchange::serialize() const - { - SecureVector<byte> buf = serialize_params(); - append_tls_length_value(buf, signature, 2); - return buf; - } - -/** -* Serialize the ServerParams structure -*/ -SecureVector<byte> Server_Key_Exchange::serialize_params() const - { - SecureVector<byte> buf; - - for(size_t i = 0; i != params.size(); ++i) - append_tls_length_value(buf, BigInt::encode(params[i]), 2); - - return buf; - } - -/** -* Deserialize a Server Key Exchange message -*/ -void Server_Key_Exchange::deserialize(const MemoryRegion<byte>& buf) - { - if(buf.size() < 6) - throw Decoding_Error("Server_Key_Exchange: Packet corrupted"); - - SecureVector<byte> values[4]; - size_t so_far = 0; - - for(size_t i = 0; i != 4; ++i) - { - const u16bit len = make_u16bit(buf[so_far], buf[so_far+1]); - so_far += 2; - - if(len + so_far > buf.size()) - throw Decoding_Error("Server_Key_Exchange: Packet corrupted"); - - values[i].resize(len); - copy_mem(&values[i][0], &buf[so_far], len); - so_far += len; - - if(i == 2 && so_far == buf.size()) - break; - } - - params.push_back(BigInt::decode(values[0])); - params.push_back(BigInt::decode(values[1])); - if(values[3].size()) - { - params.push_back(BigInt::decode(values[2])); - signature = values[3]; - } - else - signature = values[2]; - } - -/** -* Return the public key -*/ -Public_Key* Server_Key_Exchange::key() const - { - if(params.size() == 2) - return new RSA_PublicKey(params[0], params[1]); - else if(params.size() == 3) - return new DH_PublicKey(DL_Group(params[0], params[1]), params[2]); - else - throw Internal_Error("Server_Key_Exchange::key: No key set"); - } - -/** -* Verify a Server Key Exchange message -*/ -bool Server_Key_Exchange::verify(const X509_Certificate& cert, - const MemoryRegion<byte>& c_random, - const MemoryRegion<byte>& s_random) const - { - - std::auto_ptr<Public_Key> key(cert.subject_public_key()); - - std::string padding = ""; - Signature_Format format = IEEE_1363; - - if(key->algo_name() == "RSA") - padding = "EMSA3(TLS.Digest.0)"; - else if(key->algo_name() == "DSA") - { - padding == "EMSA1(SHA-1)"; - format = DER_SEQUENCE; - } - else - throw Invalid_Argument(key->algo_name() + - " is invalid/unknown for TLS signatures"); - - PK_Verifier verifier(*key, padding, format); - - SecureVector<byte> params_got = serialize_params(); - verifier.update(c_random); - verifier.update(s_random); - verifier.update(params_got); - - return verifier.check_signature(signature); - } - -} diff --git a/src/ssl/tls_alerts.h b/src/ssl/tls_alerts.h deleted file mode 100644 index 241599aa8..000000000 --- a/src/ssl/tls_alerts.h +++ /dev/null @@ -1,54 +0,0 @@ -/* -* Alert Message -* (C) 2004-2006 Jack Lloyd -* -* Released under the terms of the Botan license -*/ - -#ifndef BOTAN_TLS_ALERT_H__ -#define BOTAN_TLS_ALERT_H__ - -#include <botan/tls_exceptn.h> - -namespace Botan { - -/** -* SSL/TLS Alert Message -*/ -class Alert - { - public: - /** - * @return if this alert is a fatal one or not - */ - bool is_fatal() const { return fatal; } - - /** - * @return type of alert - */ - Alert_Type type() const { return type_code; } - - /** - * Deserialize an Alert message - * @param buf the serialized alert - */ - Alert(const MemoryRegion<byte>& buf) - { - if(buf.size() != 2) - throw Decoding_Error("Alert: Bad size for alert message"); - - if(buf[0] == 1) fatal = false; - else if(buf[0] == 2) fatal = true; - else - throw Decoding_Error("Alert: Bad type code for alert level"); - - type_code = static_cast<Alert_Type>(buf[1]); - } - private: - bool fatal; - Alert_Type type_code; - }; - -} - -#endif diff --git a/src/ssl/tls_client.cpp b/src/ssl/tls_client.cpp deleted file mode 100644 index a136752fd..000000000 --- a/src/ssl/tls_client.cpp +++ /dev/null @@ -1,586 +0,0 @@ -/* -* TLS Client -* (C) 2004-2010 Jack Lloyd -* -* Released under the terms of the Botan license -*/ - -#include <botan/tls_client.h> -#include <botan/internal/tls_alerts.h> -#include <botan/internal/tls_state.h> -#include <botan/loadstor.h> -#include <botan/rsa.h> -#include <botan/dsa.h> -#include <botan/dh.h> - -namespace Botan { - -namespace { - -/** -* Verify the state transition is allowed -* FIXME: checks are wrong for session reuse (add a flag for that) -*/ -void client_check_state(Handshake_Type new_msg, Handshake_State* state) - { - class State_Transition_Error : public Unexpected_Message - { - public: - State_Transition_Error(const std::string& err) : - Unexpected_Message("State transition error from " + err) {} - }; - - if(new_msg == HELLO_REQUEST) - { - if(state->client_hello) - throw State_Transition_Error("HelloRequest"); - } - else if(new_msg == SERVER_HELLO) - { - if(!state->client_hello || state->server_hello) - throw State_Transition_Error("ServerHello"); - } - else if(new_msg == CERTIFICATE) - { - if(!state->server_hello || state->server_kex || - state->cert_req || state->server_hello_done) - throw State_Transition_Error("ServerCertificate"); - } - else if(new_msg == SERVER_KEX) - { - if(!state->server_hello || state->server_kex || - state->cert_req || state->server_hello_done) - throw State_Transition_Error("ServerKeyExchange"); - } - else if(new_msg == CERTIFICATE_REQUEST) - { - if(!state->server_certs || state->cert_req || state->server_hello_done) - throw State_Transition_Error("CertificateRequest"); - } - else if(new_msg == SERVER_HELLO_DONE) - { - if(!state->server_hello || state->server_hello_done) - throw State_Transition_Error("ServerHelloDone"); - } - else if(new_msg == HANDSHAKE_CCS) - { - if(!state->client_finished || state->server_finished) - throw State_Transition_Error("ServerChangeCipherSpec"); - } - else if(new_msg == FINISHED) - { - if(!state->got_server_ccs) - throw State_Transition_Error("ServerFinished"); - } - else - throw Unexpected_Message("Unexpected message in handshake"); - } - -} - -/** -* TLS Client Constructor -*/ -TLS_Client::TLS_Client(std::tr1::function<size_t (byte[], size_t)> input_fn, - std::tr1::function<void (const byte[], size_t)> output_fn, - const TLS_Policy& policy, - RandomNumberGenerator& rng) : - input_fn(input_fn), - policy(policy), - rng(rng), - writer(output_fn) - { - initialize(); - } - -void TLS_Client::add_client_cert(const X509_Certificate& cert, - Private_Key* cert_key) - { - certs.push_back(std::make_pair(cert, cert_key)); - } - -/** -* TLS Client Destructor -*/ -TLS_Client::~TLS_Client() - { - close(); - for(size_t i = 0; i != certs.size(); i++) - delete certs[i].second; - delete state; - } - -/** -* Initialize a TLS client connection -*/ -void TLS_Client::initialize() - { - std::string error_str; - Alert_Type error_type = NO_ALERT_TYPE; - - try { - state = 0; - active = false; - writer.set_version(policy.pref_version()); - do_handshake(); - } - catch(TLS_Exception& e) - { - error_str = e.what(); - error_type = e.type(); - } - catch(std::exception& e) - { - error_str = e.what(); - error_type = HANDSHAKE_FAILURE; - } - - if(error_type != NO_ALERT_TYPE) - { - if(active) - { - active = false; - reader.reset(); - - writer.alert(FATAL, error_type); - writer.reset(); - } - - if(state) - { - delete state; - state = 0; - } - - throw Stream_IO_Error("TLS_Client: Handshake failed: " + error_str); - } - } - -/** -* Return the peer's certificate chain -*/ -std::vector<X509_Certificate> TLS_Client::peer_cert_chain() const - { - return peer_certs; - } - -/** -* Write to a TLS connection -*/ -void TLS_Client::write(const byte buf[], size_t length) - { - if(!active) - throw TLS_Exception(INTERNAL_ERROR, - "TLS_Client::write called while closed"); - - writer.send(APPLICATION_DATA, buf, length); - } - -/** -* Read from a TLS connection -*/ -size_t TLS_Client::read(byte out[], size_t length) - { - if(!active) - return 0; - - writer.flush(); - - while(read_buf.size() == 0) - { - state_machine(); - if(active == false) - break; - } - - size_t got = std::min<size_t>(read_buf.size(), length); - read_buf.read(out, got); - return got; - } - -/** -* Close a TLS connection -*/ -void TLS_Client::close() - { - close(WARNING, CLOSE_NOTIFY); - } - -/** -* Check connection status -*/ -bool TLS_Client::is_closed() const - { - if(!active) - return true; - return false; - } - -/** -* Close a TLS connection -*/ -void TLS_Client::close(Alert_Level level, Alert_Type alert_code) - { - if(active) - { - try { - writer.alert(level, alert_code); - writer.flush(); - } - catch(...) {} - - active = false; - } - } - -/** -* Iterate the TLS state machine -*/ -void TLS_Client::state_machine() - { - byte rec_type = CONNECTION_CLOSED; - SecureVector<byte> record(1024); - - size_t bytes_needed = reader.get_record(rec_type, record); - - while(bytes_needed) - { - size_t to_get = std::min<size_t>(record.size(), bytes_needed); - size_t got = input_fn(&record[0], to_get); - - if(got == 0) - { - rec_type = CONNECTION_CLOSED; - break; - } - - reader.add_input(&record[0], got); - - bytes_needed = reader.get_record(rec_type, record); - } - - if(rec_type == CONNECTION_CLOSED) - { - active = false; - reader.reset(); - writer.reset(); - } - else if(rec_type == APPLICATION_DATA) - { - if(active) - read_buf.write(&record[0], record.size()); - else - throw Unexpected_Message("Application data before handshake done"); - } - else if(rec_type == HANDSHAKE || rec_type == CHANGE_CIPHER_SPEC) - read_handshake(rec_type, record); - else if(rec_type == ALERT) - { - Alert alert(record); - - if(alert.is_fatal() || alert.type() == CLOSE_NOTIFY) - { - if(alert.type() == CLOSE_NOTIFY) - writer.alert(WARNING, CLOSE_NOTIFY); - - reader.reset(); - writer.reset(); - active = false; - if(state) - { - delete state; - state = 0; - } - } - } - else - throw Unexpected_Message("Unknown message type received"); - } - -/** -* Split up and process handshake messages -*/ -void TLS_Client::read_handshake(byte rec_type, - const MemoryRegion<byte>& rec_buf) - { - if(rec_type == HANDSHAKE) - state->queue.write(&rec_buf[0], rec_buf.size()); - - while(true) - { - Handshake_Type type = HANDSHAKE_NONE; - SecureVector<byte> contents; - - if(rec_type == HANDSHAKE) - { - if(state->queue.size() >= 4) - { - byte head[4] = { 0 }; - state->queue.peek(head, 4); - - const size_t length = make_u32bit(0, head[1], head[2], head[3]); - - if(state->queue.size() >= length + 4) - { - type = static_cast<Handshake_Type>(head[0]); - contents.resize(length); - state->queue.read(head, 4); - state->queue.read(&contents[0], contents.size()); - } - } - } - else if(rec_type == CHANGE_CIPHER_SPEC) - { - if(state->queue.size() == 0 && rec_buf.size() == 1 && rec_buf[0] == 1) - type = HANDSHAKE_CCS; - else - throw Decoding_Error("Malformed ChangeCipherSpec message"); - } - else - throw Decoding_Error("Unknown message type in handshake processing"); - - if(type == HANDSHAKE_NONE) - break; - - process_handshake_msg(type, contents); - - if(type == HANDSHAKE_CCS || !state) - break; - } - } - -/** -* Process a handshake message -*/ -void TLS_Client::process_handshake_msg(Handshake_Type type, - const MemoryRegion<byte>& contents) - { - rng.add_entropy(&contents[0], contents.size()); - - if(type == HELLO_REQUEST) - { - if(state == 0) - state = new Handshake_State(); - else - return; - } - - if(state == 0) - throw Unexpected_Message("Unexpected handshake message"); - - if(type != HANDSHAKE_CCS && type != HELLO_REQUEST && type != FINISHED) - { - state->hash.update(static_cast<byte>(type)); - const size_t record_length = contents.size(); - for(size_t i = 0; i != 3; i++) - state->hash.update(get_byte<u32bit>(i+1, record_length)); - state->hash.update(contents); - } - - if(type == HELLO_REQUEST) - { - client_check_state(type, state); - - Hello_Request hello_request(contents); - state->client_hello = new Client_Hello(rng, writer, policy, state->hash); - } - else if(type == SERVER_HELLO) - { - client_check_state(type, state); - - state->server_hello = new Server_Hello(contents); - - if(!state->client_hello->offered_suite( - state->server_hello->ciphersuite() - ) - ) - throw TLS_Exception(HANDSHAKE_FAILURE, - "TLS_Client: Server replied with bad ciphersuite"); - - state->version = state->server_hello->version(); - - if(state->version > state->client_hello->version()) - throw TLS_Exception(HANDSHAKE_FAILURE, - "TLS_Client: Server replied with bad version"); - - if(state->version < policy.min_version()) - throw TLS_Exception(PROTOCOL_VERSION, - "TLS_Client: Server is too old for specified policy"); - - writer.set_version(state->version); - reader.set_version(state->version); - - state->suite = CipherSuite(state->server_hello->ciphersuite()); - } - else if(type == CERTIFICATE) - { - client_check_state(type, state); - - if(state->suite.sig_type() == TLS_ALGO_SIGNER_ANON) - throw Unexpected_Message("Recived certificate from anonymous server"); - - state->server_certs = new Certificate(contents); - - peer_certs = state->server_certs->cert_chain(); - if(peer_certs.size() == 0) - throw TLS_Exception(HANDSHAKE_FAILURE, - "TLS_Client: No certificates sent by server"); - - if(!policy.check_cert(peer_certs)) - throw TLS_Exception(BAD_CERTIFICATE, - "TLS_Client: Server certificate is not valid"); - - state->kex_pub = peer_certs[0].subject_public_key(); - - bool is_dsa = false, is_rsa = false; - - if(dynamic_cast<DSA_PublicKey*>(state->kex_pub)) - is_dsa = true; - else if(dynamic_cast<RSA_PublicKey*>(state->kex_pub)) - is_rsa = true; - else - throw TLS_Exception(UNSUPPORTED_CERTIFICATE, - "Unknown key type received in server kex"); - - if((is_dsa && state->suite.sig_type() != TLS_ALGO_SIGNER_DSA) || - (is_rsa && state->suite.sig_type() != TLS_ALGO_SIGNER_RSA)) - throw TLS_Exception(ILLEGAL_PARAMETER, - "Certificate key type did not match ciphersuite"); - } - else if(type == SERVER_KEX) - { - client_check_state(type, state); - - if(state->suite.kex_type() == TLS_ALGO_KEYEXCH_NOKEX) - throw Unexpected_Message("Unexpected key exchange from server"); - - state->server_kex = new Server_Key_Exchange(contents); - - if(state->kex_pub) - delete state->kex_pub; - - state->kex_pub = state->server_kex->key(); - - bool is_dh = false, is_rsa = false; - - if(dynamic_cast<DH_PublicKey*>(state->kex_pub)) - is_dh = true; - else if(dynamic_cast<RSA_PublicKey*>(state->kex_pub)) - is_rsa = true; - else - throw TLS_Exception(HANDSHAKE_FAILURE, - "Unknown key type received in server kex"); - - if((is_dh && state->suite.kex_type() != TLS_ALGO_KEYEXCH_DH) || - (is_rsa && state->suite.kex_type() != TLS_ALGO_KEYEXCH_RSA)) - throw TLS_Exception(ILLEGAL_PARAMETER, - "Certificate key type did not match ciphersuite"); - - if(state->suite.sig_type() != TLS_ALGO_SIGNER_ANON) - { - if(!state->server_kex->verify(peer_certs[0], - state->client_hello->random(), - state->server_hello->random())) - throw TLS_Exception(DECRYPT_ERROR, - "Bad signature on server key exchange"); - } - } - else if(type == CERTIFICATE_REQUEST) - { - client_check_state(type, state); - - state->cert_req = new Certificate_Req(contents); - state->do_client_auth = true; - } - else if(type == SERVER_HELLO_DONE) - { - client_check_state(type, state); - - state->server_hello_done = new Server_Hello_Done(contents); - - if(state->do_client_auth) - { - std::vector<X509_Certificate> send_certs; - - std::vector<Certificate_Type> types = - state->cert_req->acceptable_types(); - - // FIXME: Fill in useful certs here, if any - state->client_certs = new Certificate(writer, send_certs, - state->hash); - } - - state->client_kex = - new Client_Key_Exchange(rng, writer, state->hash, - state->kex_pub, state->version, - state->client_hello->version()); - - if(state->do_client_auth) - { - Private_Key* key_matching_cert = 0; // FIXME - state->client_verify = new Certificate_Verify(rng, - writer, state->hash, - key_matching_cert); - } - - state->keys = SessionKeys(state->suite, state->version, - state->client_kex->pre_master_secret(), - state->client_hello->random(), - state->server_hello->random()); - - writer.send(CHANGE_CIPHER_SPEC, 1); - writer.flush(); - - writer.set_keys(state->suite, state->keys, CLIENT); - - state->client_finished = new Finished(writer, state->version, CLIENT, - state->keys.master_secret(), - state->hash); - } - else if(type == HANDSHAKE_CCS) - { - client_check_state(type, state); - - reader.set_keys(state->suite, state->keys, CLIENT); - state->got_server_ccs = true; - } - else if(type == FINISHED) - { - client_check_state(type, state); - - state->server_finished = new Finished(contents); - - if(!state->server_finished->verify(state->keys.master_secret(), - state->version, state->hash, SERVER)) - throw TLS_Exception(DECRYPT_ERROR, - "Finished message didn't verify"); - - delete state; - state = 0; - active = true; - } - else - throw Unexpected_Message("Unknown handshake message received"); - } - -/** -* Perform a client-side TLS handshake -*/ -void TLS_Client::do_handshake() - { - state = new Handshake_State; - - state->client_hello = new Client_Hello(rng, writer, policy, state->hash); - - while(true) - { - if(active && !state) - break; - if(!active && !state) - throw TLS_Exception(HANDSHAKE_FAILURE, "TLS_Client: Handshake failed (do_handshake)"); - - state_machine(); - } - } - -} diff --git a/src/ssl/tls_client.h b/src/ssl/tls_client.h deleted file mode 100644 index 7d2ce9cda..000000000 --- a/src/ssl/tls_client.h +++ /dev/null @@ -1,73 +0,0 @@ -/* -* TLS Client -* (C) 2004-2010 Jack Lloyd -* -* Released under the terms of the Botan license -*/ - -#ifndef BOTAN_TLS_CLIENT_H__ -#define BOTAN_TLS_CLIENT_H__ - -#include <botan/tls_connection.h> -#include <botan/tls_policy.h> -#include <botan/tls_record.h> -#include <vector> -#include <string> - -namespace Botan { - -/** -* SSL/TLS Client -*/ -class BOTAN_DLL TLS_Client : public TLS_Connection - { - public: - size_t read(byte buf[], size_t buf_len); - void write(const byte buf[], size_t buf_len); - - void close(); - bool is_closed() const; - - std::vector<X509_Certificate> peer_cert_chain() const; - - void add_client_cert(const X509_Certificate& cert, - Private_Key* cert_key); - - TLS_Client(std::tr1::function<size_t (byte[], size_t)> input_fn, - std::tr1::function<void (const byte[], size_t)> output_fn, - const TLS_Policy& policy, - RandomNumberGenerator& rng); - - ~TLS_Client(); - private: - void close(Alert_Level, Alert_Type); - - size_t get_pending_socket_input(byte output[], size_t length); - - void initialize(); - void do_handshake(); - - void state_machine(); - void read_handshake(byte, const MemoryRegion<byte>&); - void process_handshake_msg(Handshake_Type, const MemoryRegion<byte>&); - - std::tr1::function<size_t (byte[], size_t)> input_fn; - - const TLS_Policy& policy; - RandomNumberGenerator& rng; - - Record_Writer writer; - Record_Reader reader; - - std::vector<X509_Certificate> peer_certs; - std::vector<std::pair<X509_Certificate, Private_Key*> > certs; - - class Handshake_State* state; - SecureVector<byte> session_id; - SecureQueue read_buf; - bool active; - }; - -} - -#endif diff --git a/src/ssl/tls_connection.h b/src/ssl/tls_connection.h deleted file mode 100644 index bbefa2114..000000000 --- a/src/ssl/tls_connection.h +++ /dev/null @@ -1,36 +0,0 @@ -/* -* TLS Connection -* (C) 2004-2006 Jack Lloyd -* -* Released under the terms of the Botan license -*/ - -#ifndef BOTAN_TLS_CONNECTION_H__ -#define BOTAN_TLS_CONNECTION_H__ - -#include <botan/x509cert.h> -#include <vector> - -namespace Botan { - -/** -* TLS Connection -*/ -class BOTAN_DLL TLS_Connection - { - public: - virtual size_t read(byte[], size_t) = 0; - virtual void write(const byte[], size_t) = 0; - size_t read(byte& in) { return read(&in, 1); } - void write(byte out) { write(&out, 1); } - - virtual std::vector<X509_Certificate> peer_cert_chain() const = 0; - - virtual void close() = 0; - - virtual ~TLS_Connection() {} - }; - -} - -#endif diff --git a/src/ssl/tls_handshake_hash.cpp b/src/ssl/tls_handshake_hash.cpp deleted file mode 100644 index 7c1e2e385..000000000 --- a/src/ssl/tls_handshake_hash.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/* -* TLS Handshake Hash -* (C) 2004-2006 Jack Lloyd -* -* Released under the terms of the Botan license -*/ - -#include <botan/internal/tls_handshake_hash.h> -#include <botan/md5.h> -#include <botan/sha160.h> -#include <memory> - -namespace Botan { - -/** -* Return a TLS Handshake Hash -*/ -SecureVector<byte> HandshakeHash::final() - { - MD5 md5; - SHA_160 sha1; - - md5.update(data); - sha1.update(data); - - SecureVector<byte> output; - output += md5.final(); - output += sha1.final(); - return output; - } - -/** -* Return a SSLv3 Handshake Hash -*/ -SecureVector<byte> HandshakeHash::final_ssl3(const MemoryRegion<byte>& secret) - { - const byte PAD_INNER = 0x36, PAD_OUTER = 0x5C; - - MD5 md5; - SHA_160 sha1; - - md5.update(data); - sha1.update(data); - - md5.update(secret); - sha1.update(secret); - - for(size_t i = 0; i != 48; ++i) - md5.update(PAD_INNER); - for(size_t i = 0; i != 40; ++i) - sha1.update(PAD_INNER); - - SecureVector<byte> inner_md5 = md5.final(), inner_sha1 = sha1.final(); - - md5.update(secret); - sha1.update(secret); - for(size_t i = 0; i != 48; ++i) - md5.update(PAD_OUTER); - for(size_t i = 0; i != 40; ++i) - sha1.update(PAD_OUTER); - md5.update(inner_md5); - sha1.update(inner_sha1); - - SecureVector<byte> output; - output += md5.final(); - output += sha1.final(); - return output; - } - -} diff --git a/src/ssl/tls_handshake_hash.h b/src/ssl/tls_handshake_hash.h deleted file mode 100644 index cea612a71..000000000 --- a/src/ssl/tls_handshake_hash.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -* TLS Handshake Hash -* (C) 2004-2006 Jack Lloyd -* -* Released under the terms of the Botan license -*/ - -#ifndef BOTAN_TLS_HANDSHAKE_HASH_H__ -#define BOTAN_TLS_HANDSHAKE_HASH_H__ - -#include <botan/secmem.h> - -namespace Botan { - -using namespace Botan; - -/** -* TLS Handshake Hash -*/ -class HandshakeHash - { - public: - void update(const byte in[], size_t length) - { data += std::make_pair(in, length); } - - void update(const MemoryRegion<byte>& in) - { data += in; } - - void update(byte in) - { data.push_back(in); } - - SecureVector<byte> final(); - SecureVector<byte> final_ssl3(const MemoryRegion<byte>&); - private: - SecureVector<byte> data; - }; - -} - -#endif diff --git a/src/ssl/tls_magic.h b/src/ssl/tls_magic.h deleted file mode 100644 index 00898738e..000000000 --- a/src/ssl/tls_magic.h +++ /dev/null @@ -1,192 +0,0 @@ -/* -* SSL/TLS Protocol Constants -* (C) 2004-2010 Jack Lloyd -* -* Released under the terms of the Botan license -*/ - -#ifndef BOTAN_TLS_PROTOCOL_MAGIC_H__ -#define BOTAN_TLS_PROTOCOL_MAGIC_H__ - -namespace Botan { - -/** -* Protocol Constants for SSL/TLS -*/ -enum Size_Limits { - MAX_PLAINTEXT_SIZE = 16*1024, - MAX_COMPRESSED_SIZE = MAX_PLAINTEXT_SIZE + 1024, - MAX_CIPHERTEXT_SIZE = MAX_COMPRESSED_SIZE + 1024 -}; - -enum Version_Code { - NO_VERSION_SET = 0x0000, - SSL_V3 = 0x0300, - TLS_V10 = 0x0301, - TLS_V11 = 0x0302 -}; - -enum Connection_Side { CLIENT, SERVER }; - -enum Record_Type { - CONNECTION_CLOSED = 0, - - CHANGE_CIPHER_SPEC = 20, - ALERT = 21, - HANDSHAKE = 22, - APPLICATION_DATA = 23 -}; - -enum Handshake_Type { - HELLO_REQUEST = 0, - CLIENT_HELLO = 1, - CLIENT_HELLO_SSLV2 = 255, // not a wire value - SERVER_HELLO = 2, - CERTIFICATE = 11, - SERVER_KEX = 12, - CERTIFICATE_REQUEST = 13, - SERVER_HELLO_DONE = 14, - CERTIFICATE_VERIFY = 15, - CLIENT_KEX = 16, - FINISHED = 20, - - HANDSHAKE_CCS = 100, - HANDSHAKE_NONE = 101 -}; - -enum Alert_Level { - WARNING = 1, - FATAL = 2 -}; - -enum Alert_Type { - CLOSE_NOTIFY = 0, - UNEXPECTED_MESSAGE = 10, - BAD_RECORD_MAC = 20, - DECRYPTION_FAILED = 21, - RECORD_OVERFLOW = 22, - DECOMPRESSION_FAILURE = 30, - HANDSHAKE_FAILURE = 40, - BAD_CERTIFICATE = 42, - UNSUPPORTED_CERTIFICATE = 43, - CERTIFICATE_REVOKED = 44, - CERTIFICATE_EXPIRED = 45, - CERTIFICATE_UNKNOWN = 46, - ILLEGAL_PARAMETER = 47, - UNKNOWN_CA = 48, - ACCESS_DENIED = 49, - DECODE_ERROR = 50, - DECRYPT_ERROR = 51, - EXPORT_RESTRICTION = 60, - PROTOCOL_VERSION = 70, - INSUFFICIENT_SECURITY = 71, - INTERNAL_ERROR = 80, - USER_CANCELED = 90, - NO_RENEGOTIATION = 100, - - UNKNOWN_PSK_IDENTITY = 115, - - NO_ALERT_TYPE = 0xFFFF -}; - -enum Certificate_Type { - RSA_CERT = 1, - DSS_CERT = 2, - DH_RSA_CERT = 3, - DH_DSS_CERT = 4 -}; - -enum Ciphersuite_Code { - TLS_RSA_WITH_RC4_128_MD5 = 0x0004, - TLS_RSA_WITH_RC4_128_SHA = 0x0005, - - TLS_RSA_WITH_3DES_EDE_CBC_SHA = 0x000A, - TLS_RSA_WITH_AES_128_CBC_SHA = 0x002F, - TLS_RSA_WITH_AES_256_CBC_SHA = 0x0035, - TLS_RSA_WITH_AES_128_CBC_SHA256 = 0x003C, - TLS_RSA_WITH_AES_256_CBC_SHA256 = 0x003D, - TLS_RSA_WITH_SEED_CBC_SHA = 0x0096, - - TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA = 0x0013, - TLS_DHE_DSS_WITH_AES_128_CBC_SHA = 0x0032, - TLS_DHE_DSS_WITH_AES_256_CBC_SHA = 0x0038, - TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 = 0x0040, - TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 = 0x006A, - TLS_DHE_DSS_WITH_SEED_CBC_SHA = 0x0099, - - TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0x0016, - TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 0x0033, - TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0x0039, - TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0x0067, - TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x006B, - TLS_DHE_RSA_WITH_SEED_CBC_SHA = 0x009A, - - TLS_ECDHE_ECDSA_WITH_RC4_128_SHA = 0xC007, - TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA = 0xC008, - TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA = 0xC009, - TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA = 0xC00A, - TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC023, - TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 = 0xC024, - - TLS_ECDHE_RSA_WITH_RC4_128_SHA = 0xC011, - TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA = 0xC012, - TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 0xC013, - TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xC014, - TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 = 0xC027, - TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 = 0xC028 -}; - -/* -* Form of the ciphersuites broken down by field instead of -* being randomly assigned codepoints. -*/ -enum TLS_Ciphersuite_Algos { - TLS_ALGO_SIGNER_MASK = 0xFF000000, - TLS_ALGO_SIGNER_ANON = 0x01000000, - TLS_ALGO_SIGNER_RSA = 0x02000000, - TLS_ALGO_SIGNER_DSA = 0x03000000, - TLS_ALGO_SIGNER_ECDSA = 0x04000000, - - TLS_ALGO_KEYEXCH_MASK = 0x00FF0000, - TLS_ALGO_KEYEXCH_NOKEX = 0x00010000, - TLS_ALGO_KEYEXCH_RSA = 0x00020000, - TLS_ALGO_KEYEXCH_DH = 0x00030000, - TLS_ALGO_KEYEXCH_ECDH = 0x00040000, - - TLS_ALGO_MAC_MASK = 0x0000FF00, - TLS_ALGO_MAC_MD5 = 0x00000100, - TLS_ALGO_MAC_SHA1 = 0x00000200, - TLS_ALGO_MAC_SHA256 = 0x00000300, - TLS_ALGO_MAC_SHA384 = 0x00000400, - - TLS_ALGO_CIPHER_MASK = 0x000000FF, - TLS_ALGO_CIPHER_RC4_128 = 0x00000001, - TLS_ALGO_CIPHER_3DES_CBC = 0x00000002, - TLS_ALGO_CIPHER_AES128_CBC = 0x00000003, - TLS_ALGO_CIPHER_AES256_CBC = 0x00000004, - TLS_ALGO_CIPHER_SEED_CBC = 0x00000005 -}; - -enum Compression_Algo { - NO_COMPRESSION = 0x00 -}; - -enum TLS_Handshake_Extension_Type { - TLSEXT_SERVER_NAME_INDICATION = 0, - TLSEXT_MAX_FRAGMENT_LENGTH = 1, - TLSEXT_CLIENT_CERT_URL = 2, - TLSEXT_TRUSTED_CA_KEYS = 3, - TLSEXT_TRUNCATED_HMAC = 4, - - TLSEXT_USABLE_ELLIPTIC_CURVES = 10, - TLSEXT_EC_POINT_FORMATS = 11, - - TLSEXT_SRP_IDENTIFIER = 12, - - TLSEXT_CERTIFICATE_TYPES = 9, - TLSEXT_SESSION_TICKET = 35 -}; - -} - -#endif diff --git a/src/ssl/tls_messages.h b/src/ssl/tls_messages.h deleted file mode 100644 index e7eaa56e1..000000000 --- a/src/ssl/tls_messages.h +++ /dev/null @@ -1,297 +0,0 @@ -/* -* TLS Messages -* (C) 2004-2010 Jack Lloyd -* -* Released under the terms of the Botan license -*/ - -#ifndef BOTAN_TLS_MESSAGES_H__ -#define BOTAN_TLS_MESSAGES_H__ - -#include <botan/tls_record.h> -#include <botan/internal/tls_handshake_hash.h> -#include <botan/tls_policy.h> -#include <botan/bigint.h> -#include <botan/pkcs8.h> -#include <botan/x509cert.h> -#include <vector> - -namespace Botan { - -/** -* TLS Handshake Message Base Class -*/ -class HandshakeMessage - { - public: - void send(Record_Writer&, HandshakeHash&) const; - - virtual Handshake_Type type() const = 0; - - virtual ~HandshakeMessage() {} - private: - HandshakeMessage& operator=(const HandshakeMessage&) { return (*this); } - virtual SecureVector<byte> serialize() const = 0; - virtual void deserialize(const MemoryRegion<byte>&) = 0; - }; - -/** -* Client Hello Message -*/ -class Client_Hello : public HandshakeMessage - { - public: - Handshake_Type type() const { return CLIENT_HELLO; } - Version_Code version() const { return c_version; } - const SecureVector<byte>& session_id() const { return sess_id; } - std::vector<u16bit> ciphersuites() const { return suites; } - std::vector<byte> compression_algos() const { return comp_algos; } - - const SecureVector<byte>& random() const { return c_random; } - - std::string hostname() const { return requested_hostname; } - - std::string srp_identifier() const { return requested_srp_id; } - - bool offered_suite(u16bit) const; - - Client_Hello(RandomNumberGenerator& rng, - Record_Writer&, const TLS_Policy&, HandshakeHash&); - - Client_Hello(const MemoryRegion<byte>& buf, - Handshake_Type type) - { - if(type == CLIENT_HELLO) - deserialize(buf); - else - deserialize_sslv2(buf); - } - - private: - SecureVector<byte> serialize() const; - void deserialize(const MemoryRegion<byte>&); - void deserialize_sslv2(const MemoryRegion<byte>&); - - Version_Code c_version; - SecureVector<byte> sess_id, c_random; - std::vector<u16bit> suites; - std::vector<byte> comp_algos; - std::string requested_hostname; - std::string requested_srp_id; - }; - -/** -* Client Key Exchange Message -*/ -class Client_Key_Exchange : public HandshakeMessage - { - public: - Handshake_Type type() const { return CLIENT_KEX; } - - SecureVector<byte> pre_master_secret() const; - - SecureVector<byte> pre_master_secret(RandomNumberGenerator& rng, - const Private_Key* key, - Version_Code version); - - Client_Key_Exchange(RandomNumberGenerator& rng, - Record_Writer& output, - HandshakeHash& hash, - const Public_Key* my_key, - Version_Code using_version, - Version_Code pref_version); - - Client_Key_Exchange(const MemoryRegion<byte>& buf, - const CipherSuite& suite, - Version_Code using_version); - private: - SecureVector<byte> serialize() const; - void deserialize(const MemoryRegion<byte>&); - - SecureVector<byte> key_material, pre_master; - bool include_length; - }; - -/** -* Certificate Message -*/ -class Certificate : public HandshakeMessage - { - public: - Handshake_Type type() const { return CERTIFICATE; } - std::vector<X509_Certificate> cert_chain() const { return certs; } - - Certificate(Record_Writer&, const std::vector<X509_Certificate>&, - HandshakeHash&); - Certificate(const MemoryRegion<byte>& buf) { deserialize(buf); } - private: - SecureVector<byte> serialize() const; - void deserialize(const MemoryRegion<byte>&); - std::vector<X509_Certificate> certs; - }; - -/** -* Certificate Request Message -*/ -class Certificate_Req : public HandshakeMessage - { - public: - Handshake_Type type() const { return CERTIFICATE_REQUEST; } - - std::vector<Certificate_Type> acceptable_types() const { return types; } - std::vector<X509_DN> acceptable_CAs() const { return names; } - - /* TODO - Certificate_Req(Record_Writer&, HandshakeHash&, - const X509_Certificate&); - */ - Certificate_Req(Record_Writer&, HandshakeHash&, - const std::vector<X509_Certificate>&); - - Certificate_Req(const MemoryRegion<byte>& buf) { deserialize(buf); } - private: - SecureVector<byte> serialize() const; - void deserialize(const MemoryRegion<byte>&); - - std::vector<X509_DN> names; - std::vector<Certificate_Type> types; - }; - -/** -* Certificate Verify Message -*/ -class Certificate_Verify : public HandshakeMessage - { - public: - Handshake_Type type() const { return CERTIFICATE_VERIFY; } - - bool verify(const X509_Certificate&, HandshakeHash&); - - Certificate_Verify(RandomNumberGenerator& rng, - Record_Writer&, HandshakeHash&, - const Private_Key*); - - Certificate_Verify(const MemoryRegion<byte>& buf) { deserialize(buf); } - private: - SecureVector<byte> serialize() const; - void deserialize(const MemoryRegion<byte>&); - - SecureVector<byte> signature; - }; - -/** -* Finished Message -*/ -class Finished : public HandshakeMessage - { - public: - Handshake_Type type() const { return FINISHED; } - - bool verify(const MemoryRegion<byte>&, Version_Code, - const HandshakeHash&, Connection_Side); - - Finished(Record_Writer&, Version_Code, Connection_Side, - const MemoryRegion<byte>&, HandshakeHash&); - Finished(const MemoryRegion<byte>& buf) { deserialize(buf); } - private: - SecureVector<byte> serialize() const; - void deserialize(const MemoryRegion<byte>&); - - SecureVector<byte> compute_verify(const MemoryRegion<byte>&, - HandshakeHash, Connection_Side, - Version_Code); - - Connection_Side side; - SecureVector<byte> verification_data; - }; - -/** -* Hello Request Message -*/ -class Hello_Request : public HandshakeMessage - { - public: - Handshake_Type type() const { return HELLO_REQUEST; } - - Hello_Request(Record_Writer&); - Hello_Request(const MemoryRegion<byte>& buf) { deserialize(buf); } - private: - SecureVector<byte> serialize() const; - void deserialize(const MemoryRegion<byte>&); - }; - -/** -* Server Hello Message -*/ -class Server_Hello : public HandshakeMessage - { - public: - Handshake_Type type() const { return SERVER_HELLO; } - Version_Code version() { return s_version; } - const SecureVector<byte>& session_id() const { return sess_id; } - u16bit ciphersuite() const { return suite; } - byte compression_algo() const { return comp_algo; } - - const SecureVector<byte>& random() const { return s_random; } - - Server_Hello(RandomNumberGenerator& rng, - Record_Writer&, const TLS_Policy&, - const std::vector<X509_Certificate>&, - const Client_Hello&, Version_Code, HandshakeHash&); - - Server_Hello(const MemoryRegion<byte>& buf) { deserialize(buf); } - private: - SecureVector<byte> serialize() const; - void deserialize(const MemoryRegion<byte>&); - - Version_Code s_version; - SecureVector<byte> sess_id, s_random; - u16bit suite; - byte comp_algo; - }; - -/** -* Server Key Exchange Message -*/ -class Server_Key_Exchange : public HandshakeMessage - { - public: - Handshake_Type type() const { return SERVER_KEX; } - Public_Key* key() const; - - bool verify(const X509_Certificate&, const MemoryRegion<byte>&, - const MemoryRegion<byte>&) const; - - Server_Key_Exchange(RandomNumberGenerator& rng, - Record_Writer&, const Public_Key*, - const Private_Key*, const MemoryRegion<byte>&, - const MemoryRegion<byte>&, HandshakeHash&); - - Server_Key_Exchange(const MemoryRegion<byte>& buf) { deserialize(buf); } - private: - SecureVector<byte> serialize() const; - SecureVector<byte> serialize_params() const; - void deserialize(const MemoryRegion<byte>&); - - std::vector<BigInt> params; - SecureVector<byte> signature; - }; - -/** -* Server Hello Done Message -*/ -class Server_Hello_Done : public HandshakeMessage - { - public: - Handshake_Type type() const { return SERVER_HELLO_DONE; } - - Server_Hello_Done(Record_Writer&, HandshakeHash&); - Server_Hello_Done(const MemoryRegion<byte>& buf) { deserialize(buf); } - private: - SecureVector<byte> serialize() const; - void deserialize(const MemoryRegion<byte>&); - }; - -} - -#endif diff --git a/src/ssl/tls_policy.cpp b/src/ssl/tls_policy.cpp deleted file mode 100644 index b73ff7850..000000000 --- a/src/ssl/tls_policy.cpp +++ /dev/null @@ -1,118 +0,0 @@ -/* -* Policies for TLS -* (C) 2004-2010 Jack Lloyd -* -* Released under the terms of the Botan license -*/ - -#include <botan/tls_policy.h> -#include <botan/tls_exceptn.h> - -namespace Botan { - -/* -* Return allowed ciphersuites -*/ -std::vector<u16bit> TLS_Policy::ciphersuites() const - { - return suite_list(allow_static_rsa(), allow_edh_rsa(), allow_edh_dsa()); - } - -/* -* Return allowed ciphersuites -*/ -std::vector<u16bit> TLS_Policy::suite_list(bool use_rsa, - bool use_edh_rsa, - bool use_edh_dsa) const - { - std::vector<u16bit> suites; - - if(use_edh_dsa) - { - suites.push_back(TLS_DHE_DSS_WITH_AES_256_CBC_SHA); - suites.push_back(TLS_DHE_DSS_WITH_AES_128_CBC_SHA); - suites.push_back(TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA); - suites.push_back(TLS_DHE_DSS_WITH_SEED_CBC_SHA); - } - - if(use_edh_rsa) - { - suites.push_back(TLS_DHE_RSA_WITH_AES_256_CBC_SHA); - suites.push_back(TLS_DHE_RSA_WITH_AES_128_CBC_SHA); - suites.push_back(TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA); - suites.push_back(TLS_DHE_RSA_WITH_SEED_CBC_SHA); - } - - if(use_rsa) - { - suites.push_back(TLS_RSA_WITH_AES_256_CBC_SHA); - suites.push_back(TLS_RSA_WITH_AES_128_CBC_SHA); - suites.push_back(TLS_RSA_WITH_3DES_EDE_CBC_SHA); - suites.push_back(TLS_RSA_WITH_SEED_CBC_SHA); - suites.push_back(TLS_RSA_WITH_RC4_128_SHA); - suites.push_back(TLS_RSA_WITH_RC4_128_MD5); - } - - if(suites.size() == 0) - throw TLS_Exception(INTERNAL_ERROR, - "TLS_Policy error: All ciphersuites disabled"); - - return suites; - } - -/* -* Return allowed compression algorithms -*/ -std::vector<byte> TLS_Policy::compression() const - { - std::vector<byte> algs; - algs.push_back(NO_COMPRESSION); - return algs; - } - -/* -* Choose which ciphersuite to use -*/ -u16bit TLS_Policy::choose_suite(const std::vector<u16bit>& c_suites, - bool have_rsa, - bool have_dsa) const - { - bool use_static_rsa = allow_static_rsa() && have_rsa; - bool use_edh_rsa = allow_edh_rsa() && have_rsa; - bool use_edh_dsa = allow_edh_dsa() && have_dsa; - - std::vector<u16bit> s_suites = suite_list(use_static_rsa, use_edh_rsa, - use_edh_dsa); - - for(size_t i = 0; i != s_suites.size(); ++i) - for(size_t j = 0; j != c_suites.size(); ++j) - if(s_suites[i] == c_suites[j]) - return s_suites[i]; - - return 0; - } - -/* -* Choose which compression algorithm to use -*/ -byte TLS_Policy::choose_compression(const std::vector<byte>& c_comp) const - { - std::vector<byte> s_comp = compression(); - - for(size_t i = 0; i != s_comp.size(); ++i) - for(size_t j = 0; j != c_comp.size(); ++j) - if(s_comp[i] == c_comp[j]) - return s_comp[i]; - - return NO_COMPRESSION; - } - -/* -* Return the group to use for empheral DH -*/ -DL_Group TLS_Policy::dh_group() const - { - return DL_Group("modp/ietf/1024"); - } - -} diff --git a/src/ssl/tls_policy.h b/src/ssl/tls_policy.h deleted file mode 100644 index 461164d2f..000000000 --- a/src/ssl/tls_policy.h +++ /dev/null @@ -1,63 +0,0 @@ -/* -* Policies -* (C) 2004-2006 Jack Lloyd -* -* Released under the terms of the Botan license -*/ - -#ifndef BOTAN_TLS_POLICY_H__ -#define BOTAN_TLS_POLICY_H__ - -#include <botan/tls_magic.h> -#include <botan/x509cert.h> -#include <botan/dl_group.h> -#include <vector> - -namespace Botan { - -/** -* TLS Policy Base Class -* Inherit and overload as desired to suite local policy concerns -*/ -class BOTAN_DLL TLS_Policy - { - public: - std::vector<u16bit> ciphersuites() const; - virtual std::vector<byte> compression() const; - - virtual u16bit choose_suite(const std::vector<u16bit>& client_suites, - bool rsa_ok, - bool dsa_ok) const; - - virtual byte choose_compression(const std::vector<byte>& client) const; - - virtual bool allow_static_rsa() const { return true; } - virtual bool allow_edh_rsa() const { return true; } - virtual bool allow_edh_dsa() const { return true; } - virtual bool require_client_auth() const { return false; } - - virtual DL_Group dh_group() const; - virtual size_t rsa_export_keysize() const { return 512; } - - /* - * @return the minimum version that we will negotiate - */ - virtual Version_Code min_version() const { return SSL_V3; } - - /* - * @return the version we would prefer to negotiate - */ - virtual Version_Code pref_version() const { return TLS_V11; } - - virtual bool check_cert(const std::vector<X509_Certificate>& cert_chain) const = 0; - - virtual ~TLS_Policy() {} - private: - virtual std::vector<u16bit> suite_list(bool use_rsa, - bool use_edh_rsa, - bool use_edh_dsa) const; - }; - -} - -#endif diff --git a/src/ssl/tls_record.h b/src/ssl/tls_record.h deleted file mode 100644 index 09fd921c6..000000000 --- a/src/ssl/tls_record.h +++ /dev/null @@ -1,117 +0,0 @@ -/* -* TLS Record Handling -* (C) 2004-2010 Jack Lloyd -* -* Released under the terms of the Botan license -*/ - -#ifndef BOTAN_TLS_RECORDS_H__ -#define BOTAN_TLS_RECORDS_H__ - -#include <botan/tls_session_key.h> -#include <botan/tls_suites.h> -#include <botan/pipe.h> -#include <botan/mac.h> -#include <botan/secqueue.h> -#include <vector> - -#if defined(BOTAN_USE_STD_TR1) - -#if defined(BOTAN_BUILD_COMPILER_IS_MSVC) - #include <functional> -#else - #include <tr1/functional> -#endif - -#elif defined(BOTAN_USE_BOOST_TR1) - #include <boost/tr1/functional.hpp> -#else - #error "No TR1 library defined for use" -#endif - -namespace Botan { - -using namespace std::tr1::placeholders; - -/** -* TLS Record Writer -*/ -class BOTAN_DLL Record_Writer - { - public: - void send(byte type, const byte input[], size_t length); - void send(byte type, byte val) { send(type, &val, 1); } - - void flush(); - - void alert(Alert_Level, Alert_Type); - - void set_keys(const CipherSuite&, const SessionKeys&, Connection_Side); - - void set_version(Version_Code); - - void reset(); - - Record_Writer(std::tr1::function<void (const byte[], size_t)> output_fn); - - ~Record_Writer() { delete mac; } - private: - void send_record(byte type, const byte input[], size_t length); - void send_record(byte type, byte major, byte minor, - const byte input[], size_t length); - - std::tr1::function<void (const byte[], size_t)> output_fn; - Pipe cipher; - MessageAuthenticationCode* mac; - - SecureVector<byte> buffer; - size_t buf_pos; - - size_t block_size, mac_size, iv_size; - - u64bit seq_no; - byte major, minor, buf_type; - }; - -/** -* TLS Record Reader -*/ -class BOTAN_DLL Record_Reader - { - public: - void add_input(const byte input[], size_t input_size); - - /** - * @param msg_type (output variable) - * @param buffer (output variable) - * @return Number of bytes still needed (minimum), or 0 if success - */ - size_t get_record(byte& msg_type, - MemoryRegion<byte>& buffer); - - SecureVector<byte> get_record(byte& msg_type); - - void set_keys(const CipherSuite& suite, - const SessionKeys& keys, - Connection_Side side); - - void set_version(Version_Code version); - - void reset(); - - Record_Reader() { mac = 0; reset(); } - - ~Record_Reader() { delete mac; } - private: - SecureQueue input_queue; - - Pipe cipher; - MessageAuthenticationCode* mac; - size_t block_size, mac_size, iv_size; - u64bit seq_no; - byte major, minor; - }; - -} - -#endif diff --git a/src/ssl/tls_server.cpp b/src/ssl/tls_server.cpp deleted file mode 100644 index 8964be3d7..000000000 --- a/src/ssl/tls_server.cpp +++ /dev/null @@ -1,494 +0,0 @@ -/* -* TLS Server -* (C) 2004-2010 Jack Lloyd -* -* Released under the terms of the Botan license -*/ - -#include <botan/tls_server.h> -#include <botan/internal/tls_alerts.h> -#include <botan/internal/tls_state.h> -#include <botan/loadstor.h> -#include <botan/rsa.h> -#include <botan/dh.h> - -namespace Botan { - -namespace { - -/* -* Choose what version to respond with -*/ -Version_Code choose_version(Version_Code client, Version_Code minimum) - { - if(client < minimum) - throw TLS_Exception(PROTOCOL_VERSION, - "Client version is unacceptable by policy"); - - if(client == SSL_V3 || client == TLS_V10 || client == TLS_V11) - return client; - return TLS_V11; - } - -// FIXME: checks are wrong for session reuse (add a flag for that) -/* -* Verify the state transition is allowed -*/ -void server_check_state(Handshake_Type new_msg, Handshake_State* state) - { - class State_Transition_Error : public Unexpected_Message - { - public: - State_Transition_Error(const std::string& err) : - Unexpected_Message("State transition error from " + err) {} - }; - - if(new_msg == CLIENT_HELLO || new_msg == CLIENT_HELLO_SSLV2) - { - if(state->server_hello) - throw State_Transition_Error("ClientHello"); - } - else if(new_msg == CERTIFICATE) - { - if(!state->do_client_auth || !state->cert_req || - !state->server_hello_done || state->client_kex) - throw State_Transition_Error("ClientCertificate"); - } - else if(new_msg == CLIENT_KEX) - { - if(!state->server_hello_done || state->client_verify || - state->got_client_ccs) - throw State_Transition_Error("ClientKeyExchange"); - } - else if(new_msg == CERTIFICATE_VERIFY) - { - if(!state->cert_req || !state->client_certs || !state->client_kex || - state->got_client_ccs) - throw State_Transition_Error("CertificateVerify"); - } - else if(new_msg == HANDSHAKE_CCS) - { - if(!state->client_kex || state->client_finished) - throw State_Transition_Error("ClientChangeCipherSpec"); - } - else if(new_msg == FINISHED) - { - if(!state->got_client_ccs) - throw State_Transition_Error("ClientFinished"); - } - else - throw Unexpected_Message("Unexpected message in handshake"); - } - -} - -/* -* TLS Server Constructor -*/ -TLS_Server::TLS_Server(std::tr1::function<size_t (byte[], size_t)> input_fn, - std::tr1::function<void (const byte[], size_t)> output_fn, - const TLS_Policy& policy, - RandomNumberGenerator& rng, - const X509_Certificate& cert, - const Private_Key& cert_key) : - input_fn(input_fn), - policy(policy), - rng(rng), - writer(output_fn) - { - state = 0; - - cert_chain.push_back(cert); - private_key = PKCS8::copy_key(cert_key, rng); - - try { - active = false; - writer.set_version(TLS_V10); - do_handshake(); - active = true; - } - catch(std::exception& e) - { - if(state) - { - delete state; - state = 0; - } - - writer.alert(FATAL, HANDSHAKE_FAILURE); - throw Stream_IO_Error(std::string("TLS_Server: Handshake failed: ") + - e.what()); - } - } - -/* -* TLS Server Destructor -*/ -TLS_Server::~TLS_Server() - { - close(); - delete private_key; - delete state; - } - -/* -* Return the peer's certificate chain -*/ -std::vector<X509_Certificate> TLS_Server::peer_cert_chain() const - { - return peer_certs; - } - -/* -* Write to a TLS connection -*/ -void TLS_Server::write(const byte buf[], size_t length) - { - if(!active) - throw Internal_Error("TLS_Server::write called while closed"); - - writer.send(APPLICATION_DATA, buf, length); - } - -/* -* Read from a TLS connection -*/ -size_t TLS_Server::read(byte out[], size_t length) - { - if(!active) - throw Internal_Error("TLS_Server::read called while closed"); - - writer.flush(); - - while(read_buf.size() == 0) - { - state_machine(); - if(active == false) - break; - } - - size_t got = std::min<size_t>(read_buf.size(), length); - read_buf.read(out, got); - return got; - } - -/* -* Check connection status -*/ -bool TLS_Server::is_closed() const - { - if(!active) - return true; - return false; - } - -/* -* Close a TLS connection -*/ -void TLS_Server::close() - { - close(WARNING, CLOSE_NOTIFY); - } - -/* -* Close a TLS connection -*/ -void TLS_Server::close(Alert_Level level, Alert_Type alert_code) - { - if(active) - { - try { - active = false; - writer.alert(level, alert_code); - writer.flush(); - } - catch(...) {} - } - } - -/* -* Iterate the TLS state machine -*/ -void TLS_Server::state_machine() - { - byte rec_type = CONNECTION_CLOSED; - SecureVector<byte> record(1024); - - size_t bytes_needed = reader.get_record(rec_type, record); - - while(bytes_needed) - { - size_t to_get = std::min<size_t>(record.size(), bytes_needed); - size_t got = input_fn(&record[0], to_get); - - if(got == 0) - { - rec_type = CONNECTION_CLOSED; - break; - } - - reader.add_input(&record[0], got); - - bytes_needed = reader.get_record(rec_type, record); - } - - if(rec_type == CONNECTION_CLOSED) - { - active = false; - reader.reset(); - writer.reset(); - } - else if(rec_type == APPLICATION_DATA) - { - if(active) - read_buf.write(&record[0], record.size()); - else - throw Unexpected_Message("Application data before handshake done"); - } - else if(rec_type == HANDSHAKE || rec_type == CHANGE_CIPHER_SPEC) - read_handshake(rec_type, record); - else if(rec_type == ALERT) - { - Alert alert(record); - - if(alert.is_fatal() || alert.type() == CLOSE_NOTIFY) - { - if(alert.type() == CLOSE_NOTIFY) - writer.alert(WARNING, CLOSE_NOTIFY); - - reader.reset(); - writer.reset(); - active = false; - } - } - else - throw Unexpected_Message("Unknown message type received"); - } - -/* -* Split up and process handshake messages -*/ -void TLS_Server::read_handshake(byte rec_type, - const MemoryRegion<byte>& rec_buf) - { - if(rec_type == HANDSHAKE) - { - if(!state) - state = new Handshake_State; - state->queue.write(&rec_buf[0], rec_buf.size()); - } - - while(true) - { - Handshake_Type type = HANDSHAKE_NONE; - SecureVector<byte> contents; - - if(rec_type == HANDSHAKE) - { - if(state->queue.size() >= 4) - { - byte head[4] = { 0 }; - state->queue.peek(head, 4); - - const size_t length = make_u32bit(0, head[1], head[2], head[3]); - - if(state->queue.size() >= length + 4) - { - type = static_cast<Handshake_Type>(head[0]); - contents.resize(length); - state->queue.read(head, 4); - state->queue.read(&contents[0], contents.size()); - } - } - } - else if(rec_type == CHANGE_CIPHER_SPEC) - { - if(state->queue.size() == 0 && rec_buf.size() == 1 && rec_buf[0] == 1) - type = HANDSHAKE_CCS; - else - throw Decoding_Error("Malformed ChangeCipherSpec message"); - } - else - throw Decoding_Error("Unknown message type in handshake processing"); - - if(type == HANDSHAKE_NONE) - break; - - process_handshake_msg(type, contents); - - if(type == HANDSHAKE_CCS || !state) - break; - } - } - -/* -* Process a handshake message -*/ -void TLS_Server::process_handshake_msg(Handshake_Type type, - const MemoryRegion<byte>& contents) - { - rng.add_entropy(&contents[0], contents.size()); - - if(state == 0) - throw Unexpected_Message("Unexpected handshake message"); - - if(type != HANDSHAKE_CCS && type != FINISHED) - { - if(type != CLIENT_HELLO_SSLV2) - { - state->hash.update(static_cast<byte>(type)); - - const size_t record_length = contents.size(); - for(size_t i = 0; i != 3; i++) - state->hash.update(get_byte<u32bit>(i+1, record_length)); - } - - state->hash.update(contents); - } - - if(type == CLIENT_HELLO || type == CLIENT_HELLO_SSLV2) - { - server_check_state(type, state); - - state->client_hello = new Client_Hello(contents, type); - - client_requested_hostname = state->client_hello->hostname(); - - state->version = choose_version(state->client_hello->version(), - policy.min_version()); - - writer.set_version(state->version); - reader.set_version(state->version); - - state->server_hello = new Server_Hello(rng, writer, - policy, cert_chain, - *(state->client_hello), - state->version, state->hash); - - state->suite = CipherSuite(state->server_hello->ciphersuite()); - - if(state->suite.sig_type() != TLS_ALGO_SIGNER_ANON) - { - // FIXME: should choose certs based on sig type - state->server_certs = new Certificate(writer, cert_chain, - state->hash); - } - - state->kex_priv = PKCS8::copy_key(*private_key, rng); - if(state->suite.kex_type() != TLS_ALGO_KEYEXCH_NOKEX) - { - if(state->suite.kex_type() == TLS_ALGO_KEYEXCH_RSA) - { - state->kex_priv = new RSA_PrivateKey(rng, - policy.rsa_export_keysize()); - } - else if(state->suite.kex_type() == TLS_ALGO_KEYEXCH_DH) - { - state->kex_priv = new DH_PrivateKey(rng, policy.dh_group()); - } - else - throw Internal_Error("TLS_Server: Unknown ciphersuite kex type"); - - state->server_kex = - new Server_Key_Exchange(rng, writer, - state->kex_priv, private_key, - state->client_hello->random(), - state->server_hello->random(), - state->hash); - } - - if(policy.require_client_auth()) - { - state->do_client_auth = true; - throw Internal_Error("Client auth not implemented"); - // FIXME: send client auth request here - } - - state->server_hello_done = new Server_Hello_Done(writer, state->hash); - } - else if(type == CERTIFICATE) - { - server_check_state(type, state); - // FIXME: process this - } - else if(type == CLIENT_KEX) - { - server_check_state(type, state); - - state->client_kex = new Client_Key_Exchange(contents, state->suite, - state->version); - - SecureVector<byte> pre_master = - state->client_kex->pre_master_secret(rng, state->kex_priv, - state->server_hello->version()); - - state->keys = SessionKeys(state->suite, state->version, pre_master, - state->client_hello->random(), - state->server_hello->random()); - } - else if(type == CERTIFICATE_VERIFY) - { - server_check_state(type, state); - // FIXME: process this - } - else if(type == HANDSHAKE_CCS) - { - server_check_state(type, state); - - reader.set_keys(state->suite, state->keys, SERVER); - state->got_client_ccs = true; - } - else if(type == FINISHED) - { - server_check_state(type, state); - - state->client_finished = new Finished(contents); - - if(!state->client_finished->verify(state->keys.master_secret(), - state->version, state->hash, CLIENT)) - throw TLS_Exception(DECRYPT_ERROR, - "Finished message didn't verify"); - - state->hash.update(static_cast<byte>(type)); - - const size_t record_length = contents.size(); - for(size_t i = 0; i != 3; i++) - state->hash.update(get_byte<u32bit>(i+1, record_length)); - - state->hash.update(contents); - - writer.send(CHANGE_CIPHER_SPEC, 1); - writer.flush(); - - writer.set_keys(state->suite, state->keys, SERVER); - - state->server_finished = new Finished(writer, state->version, SERVER, - state->keys.master_secret(), - state->hash); - - delete state; - state = 0; - active = true; - } - else - throw Unexpected_Message("Unknown handshake message received"); - } - -/* -* Perform a server-side TLS handshake -*/ -void TLS_Server::do_handshake() - { - while(true) - { - if(active && !state) - break; - - state_machine(); - - if(!active && !state) - throw TLS_Exception(HANDSHAKE_FAILURE, "TLS_Server: Handshake failed"); - } - } - -} diff --git a/src/ssl/tls_server.h b/src/ssl/tls_server.h deleted file mode 100644 index a6b0f9cb4..000000000 --- a/src/ssl/tls_server.h +++ /dev/null @@ -1,77 +0,0 @@ -/* -* TLS Server -* (C) 2004-2010 Jack Lloyd -* -* Released under the terms of the Botan license -*/ - -#ifndef BOTAN_TLS_SERVER_H__ -#define BOTAN_TLS_SERVER_H__ - -#include <botan/tls_connection.h> -#include <botan/tls_record.h> -#include <botan/tls_policy.h> -#include <vector> - -namespace Botan { - -/** -* TLS Server -*/ -class BOTAN_DLL TLS_Server : public TLS_Connection - { - public: - size_t read(byte buf[], size_t buf_len); - void write(const byte buf[], size_t buf_len); - - std::vector<X509_Certificate> peer_cert_chain() const; - - std::string requested_hostname() const - { return client_requested_hostname; } - - void close(); - bool is_closed() const; - - /* - * FIXME: support cert chains (!) - * FIXME: support anonymous servers - */ - TLS_Server(std::tr1::function<size_t (byte[], size_t)> input_fn, - std::tr1::function<void (const byte[], size_t)> output_fn, - const TLS_Policy& policy, - RandomNumberGenerator& rng, - const X509_Certificate& cert, - const Private_Key& cert_key); - - ~TLS_Server(); - private: - void close(Alert_Level, Alert_Type); - - void do_handshake(); - void state_machine(); - void read_handshake(byte, const MemoryRegion<byte>&); - - void process_handshake_msg(Handshake_Type, const MemoryRegion<byte>&); - - std::tr1::function<size_t (byte[], size_t)> input_fn; - - const TLS_Policy& policy; - RandomNumberGenerator& rng; - - Record_Writer writer; - Record_Reader reader; - - // FIXME: rename to match TLS_Client - std::vector<X509_Certificate> cert_chain, peer_certs; - Private_Key* private_key; - - class Handshake_State* state; - SecureVector<byte> session_id; - SecureQueue read_buf; - std::string client_requested_hostname; - bool active; - }; - -} - -#endif diff --git a/src/ssl/tls_session_key.cpp b/src/ssl/tls_session_key.cpp deleted file mode 100644 index 7c75d1758..000000000 --- a/src/ssl/tls_session_key.cpp +++ /dev/null @@ -1,170 +0,0 @@ -/* -* TLS Session Key -* (C) 2004-2006 Jack Lloyd -* -* Released under the terms of the Botan license -*/ - -#include <botan/tls_session_key.h> -#include <botan/prf_ssl3.h> -#include <botan/prf_tls.h> -#include <botan/lookup.h> - -namespace Botan { - -/** -* Return the client cipher key -*/ -SymmetricKey SessionKeys::client_cipher_key() const - { - return c_cipher; - } - -/** -* Return the server cipher key -*/ -SymmetricKey SessionKeys::server_cipher_key() const - { - return s_cipher; - } - -/** -* Return the client MAC key -*/ -SymmetricKey SessionKeys::client_mac_key() const - { - return c_mac; - } - -/** -* Return the server MAC key -*/ -SymmetricKey SessionKeys::server_mac_key() const - { - return s_mac; - } - -/** -* Return the client cipher IV -*/ -InitializationVector SessionKeys::client_iv() const - { - return c_iv; - } - -/** -* Return the server cipher IV -*/ -InitializationVector SessionKeys::server_iv() const - { - return s_iv; - } - -/** -* Return the TLS master secret -*/ -SecureVector<byte> SessionKeys::master_secret() const - { - return master_sec; - } - -/** -* Generate SSLv3 session keys -*/ -SymmetricKey SessionKeys::ssl3_keygen(size_t prf_gen, - const MemoryRegion<byte>& pre_master, - const MemoryRegion<byte>& client_random, - const MemoryRegion<byte>& server_random) - { - SSL3_PRF prf; - - SecureVector<byte> salt; - salt += client_random; - salt += server_random; - - master_sec = prf.derive_key(48, pre_master, salt); - - salt.clear(); - salt += server_random; - salt += client_random; - - return prf.derive_key(prf_gen, master_sec, salt); - } - -/** -* Generate TLS 1.0 session keys -*/ -SymmetricKey SessionKeys::tls1_keygen(size_t prf_gen, - const MemoryRegion<byte>& pre_master, - const MemoryRegion<byte>& client_random, - const MemoryRegion<byte>& server_random) - { - const byte MASTER_SECRET_MAGIC[] = { - 0x6D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x73, 0x65, 0x63, 0x72, 0x65, - 0x74 }; - const byte KEY_GEN_MAGIC[] = { - 0x6B, 0x65, 0x79, 0x20, 0x65, 0x78, 0x70, 0x61, 0x6E, 0x73, 0x69, 0x6F, - 0x6E }; - - TLS_PRF prf; - - SecureVector<byte> salt; - salt += std::make_pair(MASTER_SECRET_MAGIC, sizeof(MASTER_SECRET_MAGIC)); - salt += client_random; - salt += server_random; - - master_sec = prf.derive_key(48, pre_master, salt); - - salt.clear(); - salt += std::make_pair(KEY_GEN_MAGIC, sizeof(KEY_GEN_MAGIC)); - salt += server_random; - salt += client_random; - - return prf.derive_key(prf_gen, master_sec, salt); - } - -/** -* SessionKeys Constructor -*/ -SessionKeys::SessionKeys(const CipherSuite& suite, Version_Code version, - const MemoryRegion<byte>& pre_master_secret, - const MemoryRegion<byte>& c_random, - const MemoryRegion<byte>& s_random) - { - if(version != SSL_V3 && version != TLS_V10 && version != TLS_V11) - throw Invalid_Argument("SessionKeys: Unknown version code"); - - const size_t mac_keylen = output_length_of(suite.mac_algo()); - const size_t cipher_keylen = suite.cipher_keylen(); - - size_t cipher_ivlen = 0; - if(have_block_cipher(suite.cipher_algo())) - cipher_ivlen = block_size_of(suite.cipher_algo()); - - const size_t prf_gen = 2 * (mac_keylen + cipher_keylen + cipher_ivlen); - - SymmetricKey keyblock = (version == SSL_V3) ? - ssl3_keygen(prf_gen, pre_master_secret, c_random, s_random) : - tls1_keygen(prf_gen, pre_master_secret, c_random, s_random); - - const byte* key_data = keyblock.begin(); - - c_mac = SymmetricKey(key_data, mac_keylen); - key_data += mac_keylen; - - s_mac = SymmetricKey(key_data, mac_keylen); - key_data += mac_keylen; - - c_cipher = SymmetricKey(key_data, cipher_keylen); - key_data += cipher_keylen; - - s_cipher = SymmetricKey(key_data, cipher_keylen); - key_data += cipher_keylen; - - c_iv = InitializationVector(key_data, cipher_ivlen); - key_data += cipher_ivlen; - - s_iv = InitializationVector(key_data, cipher_ivlen); - } - -} diff --git a/src/ssl/tls_session_key.h b/src/ssl/tls_session_key.h deleted file mode 100644 index 51397984b..000000000 --- a/src/ssl/tls_session_key.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -* TLS Session Key -* (C) 2004-2006 Jack Lloyd -* -* Released under the terms of the Botan license -*/ - -#ifndef BOTAN_TLS_SESSION_KEYS_H__ -#define BOTAN_TLS_SESSION_KEYS_H__ - -#include <botan/tls_suites.h> -#include <botan/tls_exceptn.h> -#include <botan/symkey.h> - -namespace Botan { - -/** -* TLS Session Keys -*/ -class BOTAN_DLL SessionKeys - { - public: - SymmetricKey client_cipher_key() const; - SymmetricKey server_cipher_key() const; - - SymmetricKey client_mac_key() const; - SymmetricKey server_mac_key() const; - - InitializationVector client_iv() const; - InitializationVector server_iv() const; - - SecureVector<byte> master_secret() const; - - SessionKeys() {} - SessionKeys(const CipherSuite&, Version_Code, const MemoryRegion<byte>&, - const MemoryRegion<byte>&, const MemoryRegion<byte>&); - private: - SymmetricKey ssl3_keygen(size_t, const MemoryRegion<byte>&, - const MemoryRegion<byte>&, - const MemoryRegion<byte>&); - SymmetricKey tls1_keygen(size_t, const MemoryRegion<byte>&, - const MemoryRegion<byte>&, - const MemoryRegion<byte>&); - - SecureVector<byte> master_sec; - SymmetricKey c_cipher, s_cipher, c_mac, s_mac; - InitializationVector c_iv, s_iv; - }; - -} - -#endif diff --git a/src/ssl/tls_state.cpp b/src/ssl/tls_state.cpp deleted file mode 100644 index 6aaf5e201..000000000 --- a/src/ssl/tls_state.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/* -* TLS Handshaking -* (C) 2004-2006 Jack Lloyd -* -* Released under the terms of the Botan license -*/ - -#include <botan/internal/tls_state.h> - -namespace Botan { - -/** -* Initialize the SSL/TLS Handshake State -*/ -Handshake_State::Handshake_State() - { - client_hello = 0; - server_hello = 0; - server_certs = 0; - server_kex = 0; - cert_req = 0; - server_hello_done = 0; - - client_certs = 0; - client_kex = 0; - client_verify = 0; - client_finished = 0; - server_finished = 0; - - kex_pub = 0; - kex_priv = 0; - - do_client_auth = got_client_ccs = got_server_ccs = false; - version = SSL_V3; - } - -/** -* Destroy the SSL/TLS Handshake State -*/ -Handshake_State::~Handshake_State() - { - delete client_hello; - delete server_hello; - delete server_certs; - delete server_kex; - delete cert_req; - delete server_hello_done; - - delete client_certs; - delete client_kex; - delete client_verify; - delete client_finished; - delete server_finished; - - delete kex_pub; - delete kex_priv; - } - -} diff --git a/src/ssl/tls_state.h b/src/ssl/tls_state.h deleted file mode 100644 index e2728198f..000000000 --- a/src/ssl/tls_state.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -* TLS Handshake State -* (C) 2004-2006 Jack Lloyd -* -* Released under the terms of the Botan license -*/ - -#ifndef BOTAN_TLS_HANDSHAKE_H__ -#define BOTAN_TLS_HANDSHAKE_H__ - -#include <botan/internal/tls_messages.h> -#include <botan/secqueue.h> - -namespace Botan { - -/** -* SSL/TLS Handshake State -*/ -class Handshake_State - { - public: - Client_Hello* client_hello; - Server_Hello* server_hello; - Certificate* server_certs; - Server_Key_Exchange* server_kex; - Certificate_Req* cert_req; - Server_Hello_Done* server_hello_done; - - Certificate* client_certs; - Client_Key_Exchange* client_kex; - Certificate_Verify* client_verify; - Finished* client_finished; - Finished* server_finished; - - Public_Key* kex_pub; - Private_Key* kex_priv; - - CipherSuite suite; - SessionKeys keys; - HandshakeHash hash; - - SecureQueue queue; - - Version_Code version; - bool got_client_ccs, got_server_ccs, do_client_auth; - - Handshake_State(); - ~Handshake_State(); - }; - -} - -#endif diff --git a/src/ssl/tls_suites.cpp b/src/ssl/tls_suites.cpp deleted file mode 100644 index 07cbec608..000000000 --- a/src/ssl/tls_suites.cpp +++ /dev/null @@ -1,281 +0,0 @@ -/* -* TLS Cipher Suites -* (C) 2004-2010 Jack Lloyd -* -* Released under the terms of the Botan license -*/ - -#include <botan/tls_suites.h> -#include <botan/tls_exceptn.h> - -namespace Botan { - -/** -* Convert an SSL/TLS ciphersuite to algorithm fields -*/ -TLS_Ciphersuite_Algos CipherSuite::lookup_ciphersuite(u16bit suite) - { - if(suite == TLS_RSA_WITH_RC4_128_MD5) - return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_RSA | - TLS_ALGO_KEYEXCH_NOKEX | - TLS_ALGO_MAC_MD5 | - TLS_ALGO_CIPHER_RC4_128); - - if(suite == TLS_RSA_WITH_RC4_128_SHA) - return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_RSA | - TLS_ALGO_KEYEXCH_NOKEX | - TLS_ALGO_MAC_SHA1 | - TLS_ALGO_CIPHER_RC4_128); - - if(suite == TLS_RSA_WITH_3DES_EDE_CBC_SHA) - return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_RSA | - TLS_ALGO_KEYEXCH_NOKEX | - TLS_ALGO_MAC_SHA1 | - TLS_ALGO_CIPHER_3DES_CBC); - - if(suite == TLS_RSA_WITH_AES_128_CBC_SHA) - return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_RSA | - TLS_ALGO_KEYEXCH_NOKEX | - TLS_ALGO_MAC_SHA1 | - TLS_ALGO_CIPHER_AES128_CBC); - - if(suite == TLS_RSA_WITH_AES_256_CBC_SHA) - return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_RSA | - TLS_ALGO_KEYEXCH_NOKEX | - TLS_ALGO_MAC_SHA1 | - TLS_ALGO_CIPHER_AES256_CBC); - - if(suite == TLS_RSA_WITH_SEED_CBC_SHA) - return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_RSA | - TLS_ALGO_KEYEXCH_NOKEX | - TLS_ALGO_MAC_SHA1 | - TLS_ALGO_CIPHER_SEED_CBC); - - if(suite == TLS_RSA_WITH_AES_128_CBC_SHA256) - return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_RSA | - TLS_ALGO_KEYEXCH_NOKEX | - TLS_ALGO_MAC_SHA256 | - TLS_ALGO_CIPHER_AES128_CBC); - - if(suite == TLS_RSA_WITH_AES_256_CBC_SHA256) - return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_RSA | - TLS_ALGO_KEYEXCH_NOKEX | - TLS_ALGO_MAC_SHA256 | - TLS_ALGO_CIPHER_AES256_CBC); - - if(suite == TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA) - return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_DSA | - TLS_ALGO_KEYEXCH_DH | - TLS_ALGO_MAC_SHA1 | - TLS_ALGO_CIPHER_3DES_CBC); - - if(suite == TLS_DHE_DSS_WITH_AES_128_CBC_SHA) - return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_DSA | - TLS_ALGO_KEYEXCH_DH | - TLS_ALGO_MAC_SHA1 | - TLS_ALGO_CIPHER_AES128_CBC); - - if(suite == TLS_DHE_DSS_WITH_SEED_CBC_SHA) - return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_DSA | - TLS_ALGO_KEYEXCH_DH | - TLS_ALGO_MAC_SHA1 | - TLS_ALGO_CIPHER_SEED_CBC); - - if(suite == TLS_DHE_DSS_WITH_AES_256_CBC_SHA) - return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_DSA | - TLS_ALGO_KEYEXCH_DH | - TLS_ALGO_MAC_SHA1 | - TLS_ALGO_CIPHER_AES256_CBC); - - if(suite == TLS_DHE_DSS_WITH_AES_128_CBC_SHA256) - return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_DSA | - TLS_ALGO_KEYEXCH_DH | - TLS_ALGO_MAC_SHA256 | - TLS_ALGO_CIPHER_AES128_CBC); - - if(suite == TLS_DHE_DSS_WITH_AES_256_CBC_SHA256) - return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_DSA | - TLS_ALGO_KEYEXCH_DH | - TLS_ALGO_MAC_SHA256 | - TLS_ALGO_CIPHER_AES256_CBC); - - if(suite == TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA) - return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_RSA | - TLS_ALGO_KEYEXCH_DH | - TLS_ALGO_MAC_SHA1 | - TLS_ALGO_CIPHER_3DES_CBC); - - if(suite == TLS_DHE_RSA_WITH_AES_128_CBC_SHA) - return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_RSA | - TLS_ALGO_KEYEXCH_DH | - TLS_ALGO_MAC_SHA1 | - TLS_ALGO_CIPHER_AES128_CBC); - - if(suite == TLS_DHE_DSS_WITH_SEED_CBC_SHA) - return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_RSA | - TLS_ALGO_KEYEXCH_DH | - TLS_ALGO_MAC_SHA1 | - TLS_ALGO_CIPHER_SEED_CBC); - - if(suite == TLS_DHE_RSA_WITH_AES_256_CBC_SHA) - return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_RSA | - TLS_ALGO_KEYEXCH_DH | - TLS_ALGO_MAC_SHA1 | - TLS_ALGO_CIPHER_AES256_CBC); - - if(suite == TLS_DHE_RSA_WITH_AES_128_CBC_SHA256) - return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_RSA | - TLS_ALGO_KEYEXCH_DH | - TLS_ALGO_MAC_SHA256 | - TLS_ALGO_CIPHER_AES128_CBC); - - if(suite == TLS_DHE_RSA_WITH_AES_256_CBC_SHA256) - return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_RSA | - TLS_ALGO_KEYEXCH_DH | - TLS_ALGO_MAC_SHA256 | - TLS_ALGO_CIPHER_AES256_CBC); - - if(suite == TLS_ECDHE_ECDSA_WITH_RC4_128_SHA) - return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_ECDSA | - TLS_ALGO_KEYEXCH_ECDH | - TLS_ALGO_MAC_SHA1 | - TLS_ALGO_CIPHER_RC4_128); - - if(suite == TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA) - return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_ECDSA | - TLS_ALGO_KEYEXCH_ECDH | - TLS_ALGO_MAC_SHA1 | - TLS_ALGO_CIPHER_3DES_CBC); - - if(suite == TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA) - return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_ECDSA | - TLS_ALGO_KEYEXCH_ECDH | - TLS_ALGO_MAC_SHA1 | - TLS_ALGO_CIPHER_AES128_CBC); - - if(suite == TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA) - return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_ECDSA | - TLS_ALGO_KEYEXCH_ECDH | - TLS_ALGO_MAC_SHA1 | - TLS_ALGO_CIPHER_AES256_CBC); - - if(suite == TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256) - return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_ECDSA | - TLS_ALGO_KEYEXCH_ECDH | - TLS_ALGO_MAC_SHA256 | - TLS_ALGO_CIPHER_AES128_CBC); - - if(suite == TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384) - return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_ECDSA | - TLS_ALGO_KEYEXCH_ECDH | - TLS_ALGO_MAC_SHA384 | - TLS_ALGO_CIPHER_AES256_CBC); - - if(suite == TLS_ECDHE_RSA_WITH_RC4_128_SHA) - return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_RSA | - TLS_ALGO_KEYEXCH_ECDH | - TLS_ALGO_MAC_SHA1 | - TLS_ALGO_CIPHER_RC4_128); - - if(suite == TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA) - return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_RSA | - TLS_ALGO_KEYEXCH_ECDH | - TLS_ALGO_MAC_SHA1 | - TLS_ALGO_CIPHER_3DES_CBC); - - if(suite == TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) - return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_RSA | - TLS_ALGO_KEYEXCH_ECDH | - TLS_ALGO_MAC_SHA1 | - TLS_ALGO_CIPHER_AES128_CBC); - - if(suite == TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) - return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_RSA | - TLS_ALGO_KEYEXCH_ECDH | - TLS_ALGO_MAC_SHA1 | - TLS_ALGO_CIPHER_AES256_CBC); - - if(suite == TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) - return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_ECDSA | - TLS_ALGO_KEYEXCH_ECDH | - TLS_ALGO_MAC_SHA256 | - TLS_ALGO_CIPHER_AES128_CBC); - - if(suite == TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) - return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_ECDSA | - TLS_ALGO_KEYEXCH_ECDH | - TLS_ALGO_MAC_SHA384 | - TLS_ALGO_CIPHER_AES256_CBC); - - return TLS_Ciphersuite_Algos(0); - } - -namespace { - -std::pair<std::string, size_t> cipher_code_to_name(TLS_Ciphersuite_Algos algo) - { - if((algo & TLS_ALGO_CIPHER_MASK) == TLS_ALGO_CIPHER_RC4_128) - return std::make_pair("ARC4", 16); - - if((algo & TLS_ALGO_CIPHER_MASK) == TLS_ALGO_CIPHER_3DES_CBC) - return std::make_pair("3DES", 24); - - if((algo & TLS_ALGO_CIPHER_MASK) == TLS_ALGO_CIPHER_AES128_CBC) - return std::make_pair("AES-128", 16); - - if((algo & TLS_ALGO_CIPHER_MASK) == TLS_ALGO_CIPHER_AES256_CBC) - return std::make_pair("AES-256", 32); - - if((algo & TLS_ALGO_CIPHER_MASK) == TLS_ALGO_CIPHER_SEED_CBC) - return std::make_pair("SEED", 16); - - throw TLS_Exception(INTERNAL_ERROR, - "CipherSuite: Unknown cipher type " + to_string(algo)); - } - -std::string mac_code_to_name(TLS_Ciphersuite_Algos algo) - { - if((algo & TLS_ALGO_MAC_MASK) == TLS_ALGO_MAC_MD5) - return "MD5"; - - if((algo & TLS_ALGO_MAC_MASK) == TLS_ALGO_MAC_SHA1) - return "SHA-1"; - - if((algo & TLS_ALGO_MAC_MASK) == TLS_ALGO_MAC_SHA256) - return "SHA-256"; - - if((algo & TLS_ALGO_MAC_MASK) == TLS_ALGO_MAC_SHA384) - return "SHA-384"; - - throw TLS_Exception(INTERNAL_ERROR, - "CipherSuite: Unknown MAC type " + to_string(algo)); - } - -} - -/** -* CipherSuite Constructor -*/ -CipherSuite::CipherSuite(u16bit suite_code) - { - if(suite_code == 0) - return; - - TLS_Ciphersuite_Algos algos = lookup_ciphersuite(suite_code); - - if(algos == 0) - throw Invalid_Argument("Unknown ciphersuite: " + to_string(suite_code)); - - sig_algo = TLS_Ciphersuite_Algos(algos & TLS_ALGO_SIGNER_MASK); - - kex_algo = TLS_Ciphersuite_Algos(algos & TLS_ALGO_KEYEXCH_MASK); - - std::pair<std::string, size_t> cipher_info = cipher_code_to_name(algos); - - cipher = cipher_info.first; - cipher_key_length = cipher_info.second; - - mac = mac_code_to_name(algos); - } - -} diff --git a/src/ssl/tls_suites.h b/src/ssl/tls_suites.h deleted file mode 100644 index 8d6db0e8b..000000000 --- a/src/ssl/tls_suites.h +++ /dev/null @@ -1,42 +0,0 @@ -/* -* Cipher Suites -* (C) 2004-2010 Jack Lloyd -* -* Released under the terms of the Botan license -*/ - -#ifndef BOTAN_TLS_CIPHERSUITES_H__ -#define BOTAN_TLS_CIPHERSUITES_H__ - -#include <botan/types.h> -#include <botan/tls_magic.h> -#include <string> - -namespace Botan { - -/** -* Ciphersuite Information -*/ -class BOTAN_DLL CipherSuite - { - public: - static TLS_Ciphersuite_Algos lookup_ciphersuite(u16bit suite); - - std::string cipher_algo() const { return cipher; } - std::string mac_algo() const { return mac; } - - size_t cipher_keylen() const { return cipher_key_length; } - - TLS_Ciphersuite_Algos kex_type() const { return kex_algo; } - TLS_Ciphersuite_Algos sig_type() const { return sig_algo; } - - CipherSuite(u16bit = 0); - private: - TLS_Ciphersuite_Algos kex_algo, sig_algo; - std::string cipher, mac; - size_t cipher_key_length; - }; - -} - -#endif diff --git a/src/stream/arc4/arc4.cpp b/src/stream/arc4/arc4.cpp index 6eea7bb45..13eb6ff9e 100644 --- a/src/stream/arc4/arc4.cpp +++ b/src/stream/arc4/arc4.cpp @@ -61,7 +61,10 @@ void ARC4::generate() */ void ARC4::key_schedule(const byte key[], size_t length) { - clear(); + state.resize(256); + buffer.resize(DEFAULT_BUFFERSIZE); + + position = X = Y = 0; for(size_t i = 0; i != 256; ++i) state[i] = static_cast<byte>(i); @@ -85,7 +88,7 @@ std::string ARC4::name() const { if(SKIP == 0) return "ARC4"; if(SKIP == 256) return "MARK-4"; - else return "RC4_skip(" + to_string(SKIP) + ")"; + else return "RC4_skip(" + std::to_string(SKIP) + ")"; } /* @@ -93,19 +96,14 @@ std::string ARC4::name() const */ void ARC4::clear() { - zeroise(state); - zeroise(buffer); + state.clear(); + buffer.clear(); position = X = Y = 0; } /* * ARC4 Constructor */ -ARC4::ARC4(size_t s) : SKIP(s), - state(256), - buffer(DEFAULT_BUFFERSIZE) - { - clear(); - } +ARC4::ARC4(size_t s) : SKIP(s) {} } diff --git a/src/stream/arc4/arc4.h b/src/stream/arc4/arc4.h index e3df97f83..8f8de87b6 100644 --- a/src/stream/arc4/arc4.h +++ b/src/stream/arc4/arc4.h @@ -44,9 +44,9 @@ class BOTAN_DLL ARC4 : public StreamCipher const size_t SKIP; byte X, Y; - SecureVector<byte> state; + secure_vector<byte> state; - SecureVector<byte> buffer; + secure_vector<byte> buffer; size_t position; }; diff --git a/src/stream/ctr/ctr.cpp b/src/stream/ctr/ctr.cpp index 3a370eca3..87ec86c65 100644 --- a/src/stream/ctr/ctr.cpp +++ b/src/stream/ctr/ctr.cpp @@ -49,7 +49,7 @@ void CTR_BE::key_schedule(const byte key[], size_t key_len) permutation->set_key(key, key_len); // Set a default all-zeros IV - set_iv(0, 0); + set_iv(nullptr, 0); } /* @@ -89,14 +89,14 @@ void CTR_BE::set_iv(const byte iv[], size_t iv_len) zeroise(counter); - counter.copy(0, iv, iv_len); + buffer_insert(counter, 0, iv, iv_len); /* * Set counter blocks to IV, IV + 1, ... IV + 255 */ for(size_t i = 1; i != 256; ++i) { - counter.copy(i*bs, &counter[(i-1)*bs], bs); + buffer_insert(counter, i*bs, &counter[(i-1)*bs], bs); for(size_t j = 0; j != bs; ++j) if(++counter[i*bs + (bs - 1 - j)]) diff --git a/src/stream/ctr/ctr.h b/src/stream/ctr/ctr.h index 64b43b0f5..9f391da7e 100644 --- a/src/stream/ctr/ctr.h +++ b/src/stream/ctr/ctr.h @@ -48,7 +48,7 @@ class BOTAN_DLL CTR_BE : public StreamCipher void increment_counter(); BlockCipher* permutation; - SecureVector<byte> counter, buffer; + secure_vector<byte> counter, buffer; size_t position; }; diff --git a/src/stream/ofb/ofb.cpp b/src/stream/ofb/ofb.cpp index 382a2b4dd..1137a58af 100644 --- a/src/stream/ofb/ofb.cpp +++ b/src/stream/ofb/ofb.cpp @@ -46,7 +46,7 @@ void OFB::key_schedule(const byte key[], size_t key_len) permutation->set_key(key, key_len); // Set a default all-zeros IV - set_iv(0, 0); + set_iv(nullptr, 0); } /* @@ -84,7 +84,7 @@ void OFB::set_iv(const byte iv[], size_t iv_len) throw Invalid_IV_Length(name(), iv_len); zeroise(buffer); - buffer.copy(0, iv, iv_len); + buffer_insert(buffer, 0, iv, iv_len); permutation->encrypt(buffer); position = 0; diff --git a/src/stream/ofb/ofb.h b/src/stream/ofb/ofb.h index c4d8b2601..9d4fd882f 100644 --- a/src/stream/ofb/ofb.h +++ b/src/stream/ofb/ofb.h @@ -47,7 +47,7 @@ class BOTAN_DLL OFB : public StreamCipher void key_schedule(const byte key[], size_t key_len); BlockCipher* permutation; - SecureVector<byte> buffer; + secure_vector<byte> buffer; size_t position; }; diff --git a/src/stream/salsa20/salsa20.cpp b/src/stream/salsa20/salsa20.cpp index 7d062befe..a7d1b2622 100644 --- a/src/stream/salsa20/salsa20.cpp +++ b/src/stream/salsa20/salsa20.cpp @@ -134,7 +134,8 @@ void Salsa20::key_schedule(const byte key[], size_t length) static const u32bit SIGMA[] = { 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574 }; - clear(); + state.resize(16); + buffer.resize(64); if(length == 16) { @@ -167,6 +168,8 @@ void Salsa20::key_schedule(const byte key[], size_t length) state[15] = SIGMA[3]; } + position = 0; + const byte ZERO[8] = { 0 }; set_iv(ZERO, sizeof(ZERO)); } @@ -193,7 +196,7 @@ void Salsa20::set_iv(const byte iv[], size_t length) state[8] = load_le<u32bit>(iv, 2); state[9] = load_le<u32bit>(iv, 3); - SecureVector<u32bit> hsalsa(8); + secure_vector<u32bit> hsalsa(8); hsalsa20(&hsalsa[0], &state[0]); state[ 1] = hsalsa[0]; @@ -232,8 +235,8 @@ std::string Salsa20::name() const */ void Salsa20::clear() { - zeroise(state); - zeroise(buffer); + state.clear(); + buffer.clear(); position = 0; } diff --git a/src/stream/salsa20/salsa20.h b/src/stream/salsa20/salsa20.h index d9645015f..b68bb979e 100644 --- a/src/stream/salsa20/salsa20.h +++ b/src/stream/salsa20/salsa20.h @@ -33,13 +33,11 @@ class BOTAN_DLL Salsa20 : public StreamCipher void clear(); std::string name() const; StreamCipher* clone() const { return new Salsa20; } - - Salsa20() : state(16), buffer(64), position(0) {} private: void key_schedule(const byte key[], size_t key_len); - SecureVector<u32bit> state; - SecureVector<byte> buffer; + secure_vector<u32bit> state; + secure_vector<byte> buffer; size_t position; }; diff --git a/src/stream/turing/turing.cpp b/src/stream/turing/turing.cpp index 697c660ed..bdc53cff1 100644 --- a/src/stream/turing/turing.cpp +++ b/src/stream/turing/turing.cpp @@ -17,7 +17,7 @@ namespace { /* * Perform an N-way PHT */ -inline void PHT(MemoryRegion<u32bit>& B) +inline void PHT(secure_vector<u32bit>& B) { u32bit sum = 0; for(size_t i = 0; i < B.size() - 1; ++i) @@ -247,6 +247,13 @@ void Turing::key_schedule(const byte key[], size_t length) PHT(K); + R.resize(17); + S0.resize(256); + S1.resize(256); + S2.resize(256); + S3.resize(256); + buffer.resize(17*20); + for(u32bit i = 0; i != 256; ++i) { u32bit W0 = 0, C0 = i; @@ -273,7 +280,7 @@ void Turing::key_schedule(const byte key[], size_t length) S3[i] = (W3 & 0xFFFFFF00) | C3; } - set_iv(0, 0); + set_iv(nullptr, 0); } /* @@ -284,7 +291,7 @@ void Turing::set_iv(const byte iv[], size_t length) if(!valid_iv_length(length)) throw Invalid_IV_Length(name(), length); - SecureVector<u32bit> IV(length / 4); + secure_vector<u32bit> IV(length / 4); for(size_t i = 0; i != length; ++i) IV[i/4] = (IV[i/4] << 8) + iv[i]; @@ -313,12 +320,13 @@ void Turing::set_iv(const byte iv[], size_t length) */ void Turing::clear() { - zeroise(S0); - zeroise(S1); - zeroise(S2); - zeroise(S3); - - zeroise(buffer); + S0.clear(); + S1.clear(); + S2.clear(); + S3.clear(); + R.clear(); + K.clear(); + buffer.clear(); position = 0; } diff --git a/src/stream/turing/turing.h b/src/stream/turing/turing.h index aff314080..f2453127a 100644 --- a/src/stream/turing/turing.h +++ b/src/stream/turing/turing.h @@ -33,9 +33,6 @@ class BOTAN_DLL Turing : public StreamCipher std::string name() const { return "Turing"; } StreamCipher* clone() const { return new Turing; } - Turing() : S0(256), S1(256), S2(256), S3(256), - R(17), buffer(340), position(0) {} - private: void key_schedule(const byte[], size_t); void generate(); @@ -45,10 +42,9 @@ class BOTAN_DLL Turing : public StreamCipher static const u32bit Q_BOX[256]; static const byte SBOX[256]; - SecureVector<u32bit> S0, S1, S2, S3; - SecureVector<u32bit> R; - SecureVector<u32bit> K; - SecureVector<byte> buffer; + secure_vector<u32bit> S0, S1, S2, S3; + secure_vector<u32bit> R, K; + secure_vector<byte> buffer; size_t position; }; diff --git a/src/stream/wid_wake/wid_wake.cpp b/src/stream/wid_wake/wid_wake.cpp index 51159064d..e4ab6477f 100644 --- a/src/stream/wid_wake/wid_wake.cpp +++ b/src/stream/wid_wake/wid_wake.cpp @@ -74,6 +74,10 @@ void WiderWake_41_BE::generate(size_t length) */ void WiderWake_41_BE::key_schedule(const byte key[], size_t) { + t_key.resize(4); + state.resize(5); + buffer.resize(DEFAULT_BUFFERSIZE); + for(size_t i = 0; i != 4; ++i) t_key[i] = load_be<u32bit>(key, i); @@ -81,6 +85,7 @@ void WiderWake_41_BE::key_schedule(const byte key[], size_t) 0x726A8F3B, 0xE69A3B5C, 0xD3C71FE5, 0xAB3C73D2, 0x4D3A8EB3, 0x0396D6E8, 0x3D4C2F7A, 0x9EE27CF3 }; + T.resize(256); for(size_t i = 0; i != 4; ++i) T[i] = t_key[i]; @@ -143,10 +148,10 @@ void WiderWake_41_BE::set_iv(const byte iv[], size_t length) void WiderWake_41_BE::clear() { position = 0; - zeroise(t_key); - zeroise(state); - zeroise(T); - zeroise(buffer); + t_key.clear(); + state.clear(); + T.clear(); + buffer.clear(); } } diff --git a/src/stream/wid_wake/wid_wake.h b/src/stream/wid_wake/wid_wake.h index 05842a574..501345011 100644 --- a/src/stream/wid_wake/wid_wake.h +++ b/src/stream/wid_wake/wid_wake.h @@ -36,19 +36,15 @@ class BOTAN_DLL WiderWake_41_BE : public StreamCipher std::string name() const { return "WiderWake4+1-BE"; } StreamCipher* clone() const { return new WiderWake_41_BE; } - WiderWake_41_BE() : T(256), state(5), t_key(4), - buffer(DEFAULT_BUFFERSIZE), position(0) - {} - private: void key_schedule(const byte[], size_t); void generate(size_t); - SecureVector<u32bit> T; - SecureVector<u32bit> state; - SecureVector<u32bit> t_key; - SecureVector<byte> buffer; + secure_vector<u32bit> T; + secure_vector<u32bit> state; + secure_vector<u32bit> t_key; + secure_vector<byte> buffer; size_t position; }; diff --git a/src/tls/c_hello.cpp b/src/tls/c_hello.cpp new file mode 100644 index 000000000..e63dc91ba --- /dev/null +++ b/src/tls/c_hello.cpp @@ -0,0 +1,394 @@ +/* +* TLS Hello Request and Client Hello Messages +* (C) 2004-2011 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#include <botan/internal/tls_messages.h> +#include <botan/internal/tls_reader.h> +#include <botan/internal/tls_session_key.h> +#include <botan/internal/tls_extensions.h> +#include <botan/tls_record.h> +#include <botan/internal/stl_util.h> +#include <chrono> + +namespace Botan { + +namespace TLS { + +enum { + TLS_EMPTY_RENEGOTIATION_INFO_SCSV = 0x00FF +}; + +std::vector<byte> make_hello_random(RandomNumberGenerator& rng) + { + std::vector<byte> buf(32); + + const u32bit time32 = static_cast<u32bit>( + std::chrono::system_clock::to_time_t(std::chrono::system_clock::now())); + + store_be(time32, &buf[0]); + rng.randomize(&buf[4], buf.size() - 4); + return buf; + } + +/* +* Create a new Hello Request message +*/ +Hello_Request::Hello_Request(Record_Writer& writer) + { + writer.send(*this); + } + +/* +* Deserialize a Hello Request message +*/ +Hello_Request::Hello_Request(const std::vector<byte>& buf) + { + if(buf.size()) + throw Decoding_Error("Bad Hello_Request, has non-zero size"); + } + +/* +* Serialize a Hello Request message +*/ +std::vector<byte> Hello_Request::serialize() const + { + return std::vector<byte>(); + } + +/* +* Create a new Client Hello message +*/ +Client_Hello::Client_Hello(Record_Writer& writer, + Handshake_Hash& hash, + const Policy& policy, + RandomNumberGenerator& rng, + const std::vector<byte>& reneg_info, + bool next_protocol, + const std::string& hostname, + const std::string& srp_identifier) : + m_version(policy.pref_version()), + m_random(make_hello_random(rng)), + m_suites(ciphersuite_list(policy, (srp_identifier != ""))), + m_comp_methods(policy.compression()), + m_hostname(hostname), + m_srp_identifier(srp_identifier), + m_next_protocol(next_protocol), + m_fragment_size(0), + m_secure_renegotiation(true), + m_renegotiation_info(reneg_info), + m_supported_curves(policy.allowed_ecc_curves()), + m_supports_session_ticket(true), + m_supports_heartbeats(true), + m_peer_can_send_heartbeats(true) + { + std::vector<std::string> hashes = policy.allowed_hashes(); + std::vector<std::string> sigs = policy.allowed_signature_methods(); + + for(size_t i = 0; i != hashes.size(); ++i) + for(size_t j = 0; j != sigs.size(); ++j) + m_supported_algos.push_back(std::make_pair(hashes[i], sigs[j])); + + hash.update(writer.send(*this)); + } + +/* +* Create a new Client Hello message (session resumption case) +*/ +Client_Hello::Client_Hello(Record_Writer& writer, + Handshake_Hash& hash, + const Policy& policy, + RandomNumberGenerator& rng, + const std::vector<byte>& reneg_info, + const Session& session, + bool next_protocol) : + m_version(session.version()), + m_session_id(session.session_id()), + m_random(make_hello_random(rng)), + m_suites(ciphersuite_list(policy, (session.srp_identifier() != ""))), + m_comp_methods(policy.compression()), + m_hostname(session.sni_hostname()), + m_srp_identifier(session.srp_identifier()), + m_next_protocol(next_protocol), + m_fragment_size(session.fragment_size()), + m_secure_renegotiation(session.secure_renegotiation()), + m_renegotiation_info(reneg_info), + m_supported_curves(policy.allowed_ecc_curves()), + m_supports_session_ticket(true), + m_session_ticket(session.session_ticket()), + m_supports_heartbeats(true), + m_peer_can_send_heartbeats(true) + { + if(!value_exists(m_suites, session.ciphersuite_code())) + m_suites.push_back(session.ciphersuite_code()); + + if(!value_exists(m_comp_methods, session.compression_method())) + m_comp_methods.push_back(session.compression_method()); + + std::vector<std::string> hashes = policy.allowed_hashes(); + std::vector<std::string> sigs = policy.allowed_signature_methods(); + + for(size_t i = 0; i != hashes.size(); ++i) + for(size_t j = 0; j != sigs.size(); ++j) + m_supported_algos.push_back(std::make_pair(hashes[i], sigs[j])); + + hash.update(writer.send(*this)); + } + +/* +* Read a counterparty client hello +*/ +Client_Hello::Client_Hello(const std::vector<byte>& buf, Handshake_Type type) + { + m_next_protocol = false; + m_secure_renegotiation = false; + m_supports_session_ticket = false; + m_supports_heartbeats = false; + m_peer_can_send_heartbeats = false; + m_fragment_size = 0; + + if(type == CLIENT_HELLO) + deserialize(buf); + else + deserialize_sslv2(buf); + } + +/* +* Serialize a Client Hello message +*/ +std::vector<byte> Client_Hello::serialize() const + { + std::vector<byte> buf; + + buf.push_back(m_version.major_version()); + buf.push_back(m_version.minor_version()); + buf += m_random; + + append_tls_length_value(buf, m_session_id, 1); + append_tls_length_value(buf, m_suites, 2); + append_tls_length_value(buf, m_comp_methods, 1); + + /* + * May not want to send extensions at all in some cases. + * If so, should include SCSV value (if reneg info is empty, if + * not we are renegotiating with a modern server and should only + * send that extension. + */ + + Extensions extensions; + + if(m_secure_renegotiation) + extensions.add(new Renegotation_Extension(m_renegotiation_info)); + + extensions.add(new Session_Ticket(m_session_ticket)); + + extensions.add(new Server_Name_Indicator(m_hostname)); + extensions.add(new SRP_Identifier(m_srp_identifier)); + + extensions.add(new Supported_Elliptic_Curves(m_supported_curves)); + + if(m_version >= Protocol_Version::TLS_V12) + extensions.add(new Signature_Algorithms(m_supported_algos)); + + extensions.add(new Heartbeat_Support_Indicator(true)); + + if(m_renegotiation_info.empty() && m_next_protocol) + extensions.add(new Next_Protocol_Notification()); + + buf += extensions.serialize(); + + return buf; + } + +void Client_Hello::deserialize_sslv2(const std::vector<byte>& buf) + { + if(buf.size() < 12 || buf[0] != 1) + throw Decoding_Error("Client_Hello: SSLv2 hello corrupted"); + + const size_t cipher_spec_len = make_u16bit(buf[3], buf[4]); + const size_t m_session_id_len = make_u16bit(buf[5], buf[6]); + const size_t challenge_len = make_u16bit(buf[7], buf[8]); + + const size_t expected_size = + (9 + m_session_id_len + cipher_spec_len + challenge_len); + + if(buf.size() != expected_size) + throw Decoding_Error("Client_Hello: SSLv2 hello corrupted"); + + if(m_session_id_len != 0 || cipher_spec_len % 3 != 0 || + (challenge_len < 16 || challenge_len > 32)) + { + throw Decoding_Error("Client_Hello: SSLv2 hello corrupted"); + } + + for(size_t i = 9; i != 9 + cipher_spec_len; i += 3) + { + if(buf[i] != 0) // a SSLv2 cipherspec; ignore it + continue; + + m_suites.push_back(make_u16bit(buf[i+1], buf[i+2])); + } + + m_version = Protocol_Version(buf[1], buf[2]); + + m_random.resize(challenge_len); + copy_mem(&m_random[0], &buf[9+cipher_spec_len+m_session_id_len], challenge_len); + + m_secure_renegotiation = + value_exists(m_suites, static_cast<u16bit>(TLS_EMPTY_RENEGOTIATION_INFO_SCSV)); + } + +/* +* Deserialize a Client Hello message +*/ +void Client_Hello::deserialize(const std::vector<byte>& buf) + { + if(buf.size() == 0) + throw Decoding_Error("Client_Hello: Packet corrupted"); + + if(buf.size() < 41) + throw Decoding_Error("Client_Hello: Packet corrupted"); + + TLS_Data_Reader reader(buf); + + const byte major_version = reader.get_byte(); + const byte minor_version = reader.get_byte(); + + m_version = Protocol_Version(major_version, minor_version); + + m_random = reader.get_fixed<byte>(32); + + m_session_id = reader.get_range<byte>(1, 0, 32); + + m_suites = reader.get_range_vector<u16bit>(2, 1, 32767); + + m_comp_methods = reader.get_range_vector<byte>(1, 1, 255); + + Extensions extensions(reader); + + if(Server_Name_Indicator* sni = extensions.get<Server_Name_Indicator>()) + { + m_hostname = sni->host_name(); + } + + if(SRP_Identifier* srp = extensions.get<SRP_Identifier>()) + { + m_srp_identifier = srp->identifier(); + } + + if(Next_Protocol_Notification* npn = extensions.get<Next_Protocol_Notification>()) + { + if(!npn->protocols().empty()) + throw Decoding_Error("Client sent non-empty NPN extension"); + + m_next_protocol = true; + } + + if(Maximum_Fragment_Length* frag = extensions.get<Maximum_Fragment_Length>()) + { + m_fragment_size = frag->fragment_size(); + } + + if(Renegotation_Extension* reneg = extensions.get<Renegotation_Extension>()) + { + // checked by Client / Server as they know the handshake state + m_secure_renegotiation = true; + m_renegotiation_info = reneg->renegotiation_info(); + } + + if(Supported_Elliptic_Curves* ecc = extensions.get<Supported_Elliptic_Curves>()) + m_supported_curves = ecc->curves(); + + if(Signature_Algorithms* sigs = extensions.get<Signature_Algorithms>()) + { + m_supported_algos = sigs->supported_signature_algorthms(); + } + else + { + if(m_version >= Protocol_Version::TLS_V12) + { + /* + The rule for when a TLS 1.2 client not sending the extension + is strange; in theory, the server is supposed to act as if + the client had sent only SHA-1 using whatever signature + algorithm we end up negotiating. Right here, we don't know + what we'll end up negotiating (depends on policy), but we do + know that we'll only negotiate something the client sent, so + we can safely say it supports everything here and know that + we'll filter it out later. + */ + m_supported_algos.push_back(std::make_pair("SHA-1", "RSA")); + m_supported_algos.push_back(std::make_pair("SHA-1", "DSA")); + m_supported_algos.push_back(std::make_pair("SHA-1", "ECDSA")); + } + else + { + // For versions before TLS 1.2, insert fake values for the old defaults + + m_supported_algos.push_back(std::make_pair("TLS.Digest.0", "RSA")); + m_supported_algos.push_back(std::make_pair("SHA-1", "DSA")); + m_supported_algos.push_back(std::make_pair("SHA-1", "ECDSA")); + } + } + + if(Maximum_Fragment_Length* frag = extensions.get<Maximum_Fragment_Length>()) + { + m_fragment_size = frag->fragment_size(); + } + + if(Session_Ticket* ticket = extensions.get<Session_Ticket>()) + { + m_supports_session_ticket = true; + m_session_ticket = ticket->contents(); + } + + if(Heartbeat_Support_Indicator* hb = extensions.get<Heartbeat_Support_Indicator>()) + { + m_supports_heartbeats = true; + m_peer_can_send_heartbeats = hb->peer_allowed_to_send(); + } + + if(Renegotation_Extension* reneg = extensions.get<Renegotation_Extension>()) + { + // checked by TLS_Client / TLS_Server as they know the handshake state + m_secure_renegotiation = true; + m_renegotiation_info = reneg->renegotiation_info(); + } + + if(value_exists(m_suites, static_cast<u16bit>(TLS_EMPTY_RENEGOTIATION_INFO_SCSV))) + { + /* + * Clients are allowed to send both the extension and the SCSV + * though it is not recommended. If it did, require that the + * extension value be empty. + */ + if(m_secure_renegotiation) + { + if(!m_renegotiation_info.empty()) + { + throw TLS_Exception(Alert::HANDSHAKE_FAILURE, + "Client send SCSV and non-empty extension"); + } + } + + m_secure_renegotiation = true; + m_renegotiation_info.clear(); + } + } + +/* +* Check if we offered this ciphersuite +*/ +bool Client_Hello::offered_suite(u16bit ciphersuite) const + { + for(size_t i = 0; i != m_suites.size(); ++i) + if(m_suites[i] == ciphersuite) + return true; + return false; + } + +} + +} diff --git a/src/tls/c_kex.cpp b/src/tls/c_kex.cpp new file mode 100644 index 000000000..5ff9ec1ce --- /dev/null +++ b/src/tls/c_kex.cpp @@ -0,0 +1,393 @@ +/* +* Client Key Exchange Message +* (C) 2004-2010 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#include <botan/internal/tls_messages.h> +#include <botan/internal/tls_reader.h> +#include <botan/internal/tls_extensions.h> +#include <botan/tls_record.h> +#include <botan/internal/assert.h> +#include <botan/credentials_manager.h> +#include <botan/pubkey.h> +#include <botan/dh.h> +#include <botan/ecdh.h> +#include <botan/rsa.h> +#include <botan/srp6.h> +#include <botan/rng.h> +#include <botan/loadstor.h> +#include <memory> + +namespace Botan { + +namespace TLS { + +namespace { + +secure_vector<byte> strip_leading_zeros(const secure_vector<byte>& input) + { + size_t leading_zeros = 0; + + for(size_t i = 0; i != input.size(); ++i) + { + if(input[i] != 0) + break; + ++leading_zeros; + } + + secure_vector<byte> output(&input[leading_zeros], + &input[input.size()-1]); + return output; + } + +} + +/* +* Create a new Client Key Exchange message +*/ +Client_Key_Exchange::Client_Key_Exchange(Record_Writer& writer, + Handshake_State* state, + Credentials_Manager& creds, + const std::vector<X509_Certificate>& peer_certs, + const std::string& hostname, + RandomNumberGenerator& rng) + { + const std::string kex_algo = state->suite.kex_algo(); + + if(kex_algo == "PSK") + { + std::string identity_hint = ""; + + if(state->server_kex) + { + TLS_Data_Reader reader(state->server_kex->params()); + identity_hint = reader.get_string(2, 0, 65535); + } + + const std::string hostname = state->client_hello->sni_hostname(); + + const std::string psk_identity = creds.psk_identity("tls-client", + hostname, + identity_hint); + + append_tls_length_value(key_material, psk_identity, 2); + + SymmetricKey psk = creds.psk("tls-client", hostname, psk_identity); + + std::vector<byte> zeros(psk.length()); + + append_tls_length_value(pre_master, zeros, 2); + append_tls_length_value(pre_master, psk.bits_of(), 2); + } + else if(state->server_kex) + { + TLS_Data_Reader reader(state->server_kex->params()); + + SymmetricKey psk; + + if(kex_algo == "DHE_PSK" || kex_algo == "ECDHE_PSK") + { + std::string identity_hint = reader.get_string(2, 0, 65535); + + const std::string hostname = state->client_hello->sni_hostname(); + + const std::string psk_identity = creds.psk_identity("tls-client", + hostname, + identity_hint); + + append_tls_length_value(key_material, psk_identity, 2); + + psk = creds.psk("tls-client", hostname, psk_identity); + } + + if(kex_algo == "DH" || kex_algo == "DHE_PSK") + { + BigInt p = BigInt::decode(reader.get_range<byte>(2, 1, 65535)); + BigInt g = BigInt::decode(reader.get_range<byte>(2, 1, 65535)); + BigInt Y = BigInt::decode(reader.get_range<byte>(2, 1, 65535)); + + if(reader.remaining_bytes()) + throw Decoding_Error("Bad params size for DH key exchange"); + + DL_Group group(p, g); + + if(!group.verify_group(rng, true)) + throw Internal_Error("DH group failed validation, possible attack"); + + DH_PublicKey counterparty_key(group, Y); + + // FIXME Check that public key is residue? + + DH_PrivateKey priv_key(rng, group); + + PK_Key_Agreement ka(priv_key, "Raw"); + + secure_vector<byte> dh_secret = strip_leading_zeros( + ka.derive_key(0, counterparty_key.public_value()).bits_of()); + + if(kex_algo == "DH") + pre_master = dh_secret; + else + { + append_tls_length_value(pre_master, dh_secret, 2); + append_tls_length_value(pre_master, psk.bits_of(), 2); + } + + append_tls_length_value(key_material, priv_key.public_value(), 2); + } + else if(kex_algo == "ECDH" || kex_algo == "ECDHE_PSK") + { + const byte curve_type = reader.get_byte(); + + if(curve_type != 3) + throw Decoding_Error("Server sent non-named ECC curve"); + + const u16bit curve_id = reader.get_u16bit(); + + const std::string name = Supported_Elliptic_Curves::curve_id_to_name(curve_id); + + if(name == "") + throw Decoding_Error("Server sent unknown named curve " + std::to_string(curve_id)); + + EC_Group group(name); + + std::vector<byte> ecdh_key = reader.get_range<byte>(1, 1, 255); + + ECDH_PublicKey counterparty_key(group, OS2ECP(ecdh_key, group.get_curve())); + + ECDH_PrivateKey priv_key(rng, group); + + PK_Key_Agreement ka(priv_key, "Raw"); + + secure_vector<byte> ecdh_secret = ka.derive_key(0, counterparty_key.public_value()).bits_of(); + + if(kex_algo == "ECDH") + pre_master = ecdh_secret; + else + { + append_tls_length_value(pre_master, ecdh_secret, 2); + append_tls_length_value(pre_master, psk.bits_of(), 2); + } + + append_tls_length_value(key_material, priv_key.public_value(), 1); + } + else if(kex_algo == "SRP_SHA") + { + const BigInt N = BigInt::decode(reader.get_range<byte>(2, 1, 65535)); + const BigInt g = BigInt::decode(reader.get_range<byte>(2, 1, 65535)); + std::vector<byte> salt = reader.get_range<byte>(1, 1, 255); + const BigInt B = BigInt::decode(reader.get_range<byte>(2, 1, 65535)); + + const std::string srp_group = srp6_group_identifier(N, g); + + const std::string srp_identifier = + creds.srp_identifier("tls-client", hostname); + + const std::string srp_password = + creds.srp_password("tls-client", hostname, srp_identifier); + + std::pair<BigInt, SymmetricKey> srp_vals = + srp6_client_agree(srp_identifier, + srp_password, + srp_group, + "SHA-1", + salt, + B, + rng); + + append_tls_length_value(key_material, BigInt::encode(srp_vals.first), 2); + pre_master = srp_vals.second.bits_of(); + } + else + { + throw Internal_Error("Client_Key_Exchange: Unknown kex " + + kex_algo); + } + } + else + { + // No server key exchange msg better mean RSA kex + RSA key in cert + + if(kex_algo != "RSA") + throw Unexpected_Message("No server kex but negotiated kex " + kex_algo); + + if(peer_certs.empty()) + throw Internal_Error("No certificate and no server key exchange"); + + std::unique_ptr<Public_Key> pub_key(peer_certs[0].subject_public_key()); + + if(const RSA_PublicKey* rsa_pub = dynamic_cast<const RSA_PublicKey*>(pub_key.get())) + { + const Protocol_Version pref_version = state->client_hello->version(); + + pre_master = rng.random_vec(48); + pre_master[0] = pref_version.major_version(); + pre_master[1] = pref_version.minor_version(); + + PK_Encryptor_EME encryptor(*rsa_pub, "PKCS1v15"); + + std::vector<byte> encrypted_key = encryptor.encrypt(pre_master, rng); + + if(state->version() == Protocol_Version::SSL_V3) + key_material = encrypted_key; // no length field + else + append_tls_length_value(key_material, encrypted_key, 2); + } + else + throw TLS_Exception(Alert::HANDSHAKE_FAILURE, + "Expected a RSA key in server cert but got " + + pub_key->algo_name()); + } + + state->hash.update(writer.send(*this)); + } + +/* +* Read a Client Key Exchange message +*/ +Client_Key_Exchange::Client_Key_Exchange(const std::vector<byte>& contents, + const Handshake_State* state, + Credentials_Manager& creds, + const Policy& policy, + RandomNumberGenerator& rng) + { + const std::string kex_algo = state->suite.kex_algo(); + + if(kex_algo == "RSA") + { + BOTAN_ASSERT(state->server_certs && !state->server_certs->cert_chain().empty(), + "No server certificate to use for RSA"); + + const Private_Key* private_key = state->server_rsa_kex_key; + + if(!private_key) + throw Internal_Error("Expected RSA kex but no server kex key set"); + + if(!dynamic_cast<const RSA_PrivateKey*>(private_key)) + throw Internal_Error("Expected RSA key but got " + private_key->algo_name()); + + PK_Decryptor_EME decryptor(*private_key, "PKCS1v15"); + + Protocol_Version client_version = state->client_hello->version(); + + try + { + if(state->version() == Protocol_Version::SSL_V3) + { + pre_master = decryptor.decrypt(contents); + } + else + { + TLS_Data_Reader reader(contents); + pre_master = decryptor.decrypt(reader.get_range<byte>(2, 0, 65535)); + } + + if(pre_master.size() != 48 || + client_version.major_version() != pre_master[0] || + client_version.minor_version() != pre_master[1]) + { + throw Decoding_Error("Client_Key_Exchange: Secret corrupted"); + } + } + catch(...) + { + // Randomize the hide timing channel + pre_master = rng.random_vec(48); + pre_master[0] = client_version.major_version(); + pre_master[1] = client_version.minor_version(); + } + } + else + { + TLS_Data_Reader reader(contents); + + SymmetricKey psk; + + if(kex_algo == "PSK" || kex_algo == "DHE_PSK" || kex_algo == "ECDHE_PSK") + { + const std::string psk_identity = reader.get_string(2, 0, 65535); + + psk = creds.psk("tls-server", + state->client_hello->sni_hostname(), + psk_identity); + + if(psk.length() == 0) + { + if(policy.hide_unknown_users()) + psk = SymmetricKey(rng, 16); + else + throw TLS_Exception(Alert::UNKNOWN_PSK_IDENTITY, + "No PSK for identifier " + psk_identity); + } + + } + + if(kex_algo == "PSK") + { + std::vector<byte> zeros(psk.length()); + append_tls_length_value(pre_master, zeros, 2); + append_tls_length_value(pre_master, psk.bits_of(), 2); + } + else if(kex_algo == "SRP_SHA") + { + SRP6_Server_Session& srp = state->server_kex->server_srp_params(); + + pre_master = srp.step2(BigInt::decode(reader.get_range<byte>(2, 0, 65535))).bits_of(); + } + else if(kex_algo == "DH" || kex_algo == "DHE_PSK" || + kex_algo == "ECDH" || kex_algo == "ECDHE_PSK") + { + const Private_Key& private_key = state->server_kex->server_kex_key(); + + const PK_Key_Agreement_Key* ka_key = + dynamic_cast<const PK_Key_Agreement_Key*>(&private_key); + + if(!ka_key) + throw Internal_Error("Expected key agreement key type but got " + + private_key.algo_name()); + + try + { + PK_Key_Agreement ka(*ka_key, "Raw"); + + std::vector<byte> client_pubkey; + + if(ka_key->algo_name() == "DH") + client_pubkey = reader.get_range<byte>(2, 0, 65535); + else + client_pubkey = reader.get_range<byte>(1, 0, 255); + + secure_vector<byte> shared_secret = ka.derive_key(0, client_pubkey).bits_of(); + + if(ka_key->algo_name() == "DH") + shared_secret = strip_leading_zeros(shared_secret); + + if(kex_algo == "DHE_PSK" || kex_algo == "ECDHE_PSK") + { + append_tls_length_value(pre_master, shared_secret, 2); + append_tls_length_value(pre_master, psk.bits_of(), 2); + } + else + pre_master = shared_secret; + } + catch(std::exception &e) + { + /* + * Something failed in the DH computation. To avoid possible + * timing attacks, randomize the pre-master output and carry + * on, allowing the protocol to fail later in the finished + * checks. + */ + pre_master = rng.random_vec(ka_key->public_value().size()); + } + } + else + throw Internal_Error("Client_Key_Exchange: Unknown kex type " + kex_algo); + } + } + +} + +} diff --git a/src/tls/cert_req.cpp b/src/tls/cert_req.cpp new file mode 100644 index 000000000..6ec5339bb --- /dev/null +++ b/src/tls/cert_req.cpp @@ -0,0 +1,241 @@ +/* +* Certificate Request Message +* (C) 2004-2006,2012 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#include <botan/internal/tls_messages.h> +#include <botan/internal/tls_reader.h> +#include <botan/internal/tls_extensions.h> +#include <botan/tls_record.h> +#include <botan/der_enc.h> +#include <botan/ber_dec.h> +#include <botan/loadstor.h> + +namespace Botan { + +namespace TLS { + +namespace { + +std::string cert_type_code_to_name(byte code) + { + switch(code) + { + case 1: + return "RSA"; + case 2: + return "DSA"; + case 64: + return "ECDSA"; + default: + return ""; // DH or something else + } + } + +byte cert_type_name_to_code(const std::string& name) + { + if(name == "RSA") + return 1; + if(name == "DSA") + return 2; + if(name == "ECDSA") + return 64; + + throw Invalid_Argument("Unknown cert type " + name); + } + +} + +/** +* Create a new Certificate Request message +*/ +Certificate_Req::Certificate_Req(Record_Writer& writer, + Handshake_Hash& hash, + const Policy& policy, + const std::vector<X509_Certificate>& ca_certs, + Protocol_Version version) + { + for(size_t i = 0; i != ca_certs.size(); ++i) + names.push_back(ca_certs[i].subject_dn()); + + cert_key_types.push_back("RSA"); + cert_key_types.push_back("DSA"); + cert_key_types.push_back("ECDSA"); + + if(version >= Protocol_Version::TLS_V12) + { + std::vector<std::string> hashes = policy.allowed_hashes(); + std::vector<std::string> sigs = policy.allowed_signature_methods(); + + for(size_t i = 0; i != hashes.size(); ++i) + for(size_t j = 0; j != sigs.size(); ++j) + m_supported_algos.push_back(std::make_pair(hashes[i], sigs[j])); + } + + hash.update(writer.send(*this)); + } + +/** +* Deserialize a Certificate Request message +*/ +Certificate_Req::Certificate_Req(const std::vector<byte>& buf, + Protocol_Version version) + { + if(buf.size() < 4) + throw Decoding_Error("Certificate_Req: Bad certificate request"); + + TLS_Data_Reader reader(buf); + + std::vector<byte> cert_type_codes = reader.get_range_vector<byte>(1, 1, 255); + + for(size_t i = 0; i != cert_type_codes.size(); ++i) + { + const std::string cert_type_name = cert_type_code_to_name(cert_type_codes[i]); + + if(cert_type_name == "") // something we don't know + continue; + + cert_key_types.push_back(cert_type_name); + } + + if(version >= Protocol_Version::TLS_V12) + { + std::vector<byte> sig_hash_algs = reader.get_range_vector<byte>(2, 2, 65534); + + if(sig_hash_algs.size() % 2 != 0) + throw Decoding_Error("Bad length for signature IDs in certificate request"); + + for(size_t i = 0; i != sig_hash_algs.size(); i += 2) + { + std::string hash = Signature_Algorithms::hash_algo_name(sig_hash_algs[i]); + std::string sig = Signature_Algorithms::sig_algo_name(sig_hash_algs[i+1]); + m_supported_algos.push_back(std::make_pair(hash, sig)); + } + } + else + { + // The hardcoded settings from previous protocol versions + m_supported_algos.push_back(std::make_pair("TLS.Digest.0", "RSA")); + m_supported_algos.push_back(std::make_pair("SHA-1", "DSA")); + m_supported_algos.push_back(std::make_pair("SHA-1", "ECDSA")); + } + + const u16bit purported_size = reader.get_u16bit(); + + if(reader.remaining_bytes() != purported_size) + throw Decoding_Error("Inconsistent length in certificate request"); + + while(reader.has_remaining()) + { + std::vector<byte> name_bits = reader.get_range_vector<byte>(2, 0, 65535); + + BER_Decoder decoder(&name_bits[0], name_bits.size()); + X509_DN name; + decoder.decode(name); + names.push_back(name); + } + } + +/** +* Serialize a Certificate Request message +*/ +std::vector<byte> Certificate_Req::serialize() const + { + std::vector<byte> buf; + + std::vector<byte> cert_types; + + for(size_t i = 0; i != cert_key_types.size(); ++i) + cert_types.push_back(cert_type_name_to_code(cert_key_types[i])); + + append_tls_length_value(buf, cert_types, 1); + + if(!m_supported_algos.empty()) + buf += Signature_Algorithms(m_supported_algos).serialize(); + + std::vector<byte> encoded_names; + + for(size_t i = 0; i != names.size(); ++i) + { + DER_Encoder encoder; + encoder.encode(names[i]); + + append_tls_length_value(encoded_names, encoder.get_contents(), 2); + } + + append_tls_length_value(buf, encoded_names, 2); + + return buf; + } + +/** +* Create a new Certificate message +*/ +Certificate::Certificate(Record_Writer& writer, + Handshake_Hash& hash, + const std::vector<X509_Certificate>& cert_list) : + m_certs(cert_list) + { + hash.update(writer.send(*this)); + } + +/** +* Deserialize a Certificate message +*/ +Certificate::Certificate(const std::vector<byte>& buf) + { + if(buf.size() < 3) + throw Decoding_Error("Certificate: Message malformed"); + + const size_t total_size = make_u32bit(0, buf[0], buf[1], buf[2]); + + if(total_size != buf.size() - 3) + throw Decoding_Error("Certificate: Message malformed"); + + const byte* certs = &buf[3]; + + while(size_t remaining_bytes = &buf[buf.size()] - certs) + { + if(remaining_bytes < 3) + throw Decoding_Error("Certificate: Message malformed"); + + const size_t cert_size = make_u32bit(0, certs[0], certs[1], certs[2]); + + if(remaining_bytes < (3 + cert_size)) + throw Decoding_Error("Certificate: Message malformed"); + + DataSource_Memory cert_buf(&certs[3], cert_size); + m_certs.push_back(X509_Certificate(cert_buf)); + + certs += cert_size + 3; + } + } + +/** +* Serialize a Certificate message +*/ +std::vector<byte> Certificate::serialize() const + { + std::vector<byte> buf(3); + + for(size_t i = 0; i != m_certs.size(); ++i) + { + std::vector<byte> raw_cert = m_certs[i].BER_encode(); + const size_t cert_size = raw_cert.size(); + for(size_t i = 0; i != 3; ++i) + buf.push_back(get_byte<u32bit>(i+1, cert_size)); + buf += raw_cert; + } + + const size_t buf_size = buf.size() - 3; + for(size_t i = 0; i != 3; ++i) + buf[i] = get_byte<u32bit>(i+1, buf_size); + + return buf; + } + +} + +} diff --git a/src/tls/cert_ver.cpp b/src/tls/cert_ver.cpp new file mode 100644 index 000000000..e6d90b060 --- /dev/null +++ b/src/tls/cert_ver.cpp @@ -0,0 +1,117 @@ +/* +* Certificate Verify Message +* (C) 2004,2006,2011,2012 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#include <botan/internal/tls_messages.h> +#include <botan/internal/tls_reader.h> +#include <botan/internal/tls_extensions.h> +#include <botan/tls_record.h> +#include <botan/internal/assert.h> +#include <memory> + +namespace Botan { + +namespace TLS { + +/* +* Create a new Certificate Verify message +*/ +Certificate_Verify::Certificate_Verify(Record_Writer& writer, + Handshake_State* state, + RandomNumberGenerator& rng, + const Private_Key* priv_key) + { + BOTAN_ASSERT_NONNULL(priv_key); + + std::pair<std::string, Signature_Format> format = + state->choose_sig_format(priv_key, hash_algo, sig_algo, true); + + PK_Signer signer(*priv_key, format.first, format.second); + + if(state->version() == Protocol_Version::SSL_V3) + { + secure_vector<byte> md5_sha = state->hash.final_ssl3( + state->keys.master_secret()); + + if(priv_key->algo_name() == "DSA") + signature = signer.sign_message(&md5_sha[16], md5_sha.size()-16, rng); + else + signature = signer.sign_message(md5_sha, rng); + } + else + { + signature = signer.sign_message(state->hash.get_contents(), rng); + } + + state->hash.update(writer.send(*this)); + } + +/* +* Deserialize a Certificate Verify message +*/ +Certificate_Verify::Certificate_Verify(const std::vector<byte>& buf, + Protocol_Version version) + { + TLS_Data_Reader reader(buf); + + if(version >= Protocol_Version::TLS_V12) + { + hash_algo = Signature_Algorithms::hash_algo_name(reader.get_byte()); + sig_algo = Signature_Algorithms::sig_algo_name(reader.get_byte()); + } + + signature = reader.get_range<byte>(2, 0, 65535); + } + +/* +* Serialize a Certificate Verify message +*/ +std::vector<byte> Certificate_Verify::serialize() const + { + std::vector<byte> buf; + + if(hash_algo != "" && sig_algo != "") + { + buf.push_back(Signature_Algorithms::hash_algo_code(hash_algo)); + buf.push_back(Signature_Algorithms::sig_algo_code(sig_algo)); + } + + const u16bit sig_len = signature.size(); + buf.push_back(get_byte(0, sig_len)); + buf.push_back(get_byte(1, sig_len)); + buf += signature; + + return buf; + } + +/* +* Verify a Certificate Verify message +*/ +bool Certificate_Verify::verify(const X509_Certificate& cert, + Handshake_State* state) + { + std::unique_ptr<Public_Key> key(cert.subject_public_key()); + + std::pair<std::string, Signature_Format> format = + state->understand_sig_format(key.get(), hash_algo, sig_algo, true); + + PK_Verifier verifier(*key, format.first, format.second); + + if(state->version() == Protocol_Version::SSL_V3) + { + secure_vector<byte> md5_sha = state->hash.final_ssl3( + state->keys.master_secret()); + + return verifier.verify_message(&md5_sha[16], md5_sha.size()-16, + &signature[0], signature.size()); + } + + return verifier.verify_message(state->hash.get_contents(), signature); + } + +} + +} diff --git a/src/tls/finished.cpp b/src/tls/finished.cpp new file mode 100644 index 000000000..c8ae4a343 --- /dev/null +++ b/src/tls/finished.cpp @@ -0,0 +1,104 @@ +/* +* Finished Message +* (C) 2004-2006,2012 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#include <botan/internal/tls_messages.h> +#include <botan/tls_record.h> +#include <memory> + +namespace Botan { + +namespace TLS { + +namespace { + +/* +* Compute the verify_data +*/ +std::vector<byte> finished_compute_verify(Handshake_State* state, + Connection_Side side) + { + if(state->version() == Protocol_Version::SSL_V3) + { + const byte SSL_CLIENT_LABEL[] = { 0x43, 0x4C, 0x4E, 0x54 }; + const byte SSL_SERVER_LABEL[] = { 0x53, 0x52, 0x56, 0x52 }; + + Handshake_Hash hash = state->hash; // don't modify state + + std::vector<byte> ssl3_finished; + + if(side == CLIENT) + hash.update(SSL_CLIENT_LABEL, sizeof(SSL_CLIENT_LABEL)); + else + hash.update(SSL_SERVER_LABEL, sizeof(SSL_SERVER_LABEL)); + + return unlock(hash.final_ssl3(state->keys.master_secret())); + } + else + { + const byte TLS_CLIENT_LABEL[] = { + 0x63, 0x6C, 0x69, 0x65, 0x6E, 0x74, 0x20, 0x66, 0x69, 0x6E, 0x69, + 0x73, 0x68, 0x65, 0x64 }; + + const byte TLS_SERVER_LABEL[] = { + 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x66, 0x69, 0x6E, 0x69, + 0x73, 0x68, 0x65, 0x64 }; + + std::unique_ptr<KDF> prf(state->protocol_specific_prf()); + + std::vector<byte> input; + if(side == CLIENT) + input += std::make_pair(TLS_CLIENT_LABEL, sizeof(TLS_CLIENT_LABEL)); + else + input += std::make_pair(TLS_SERVER_LABEL, sizeof(TLS_SERVER_LABEL)); + + input += state->hash.final(state->version(), state->suite.mac_algo()); + + return unlock(prf->derive_key(12, state->keys.master_secret(), input)); + } + } + +} + +/* +* Create a new Finished message +*/ +Finished::Finished(Record_Writer& writer, + Handshake_State* state, + Connection_Side side) + { + verification_data = finished_compute_verify(state, side); + state->hash.update(writer.send(*this)); + } + +/* +* Serialize a Finished message +*/ +std::vector<byte> Finished::serialize() const + { + return verification_data; + } + +/* +* Deserialize a Finished message +*/ +Finished::Finished(const std::vector<byte>& buf) + { + verification_data = buf; + } + +/* +* Verify a Finished message +*/ +bool Finished::verify(Handshake_State* state, + Connection_Side side) + { + return (verification_data == finished_compute_verify(state, side)); + } + +} + +} diff --git a/src/tls/hello_verify.cpp b/src/tls/hello_verify.cpp new file mode 100644 index 000000000..c77076e4c --- /dev/null +++ b/src/tls/hello_verify.cpp @@ -0,0 +1,61 @@ +/* +* DTLS Hello Verify Request +* (C) 2012 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#include <botan/internal/tls_messages.h> +#include <botan/lookup.h> +#include <memory> + +namespace Botan { + +namespace TLS { + +Hello_Verify_Request::Hello_Verify_Request(const std::vector<byte>& buf) + { + if(buf.size() < 3) + throw Decoding_Error("Hello verify request too small"); + + if(buf[0] != 254 || (buf[1] != 255 && buf[1] != 253)) + throw Decoding_Error("Unknown version from server in hello verify request"); + + m_cookie.resize(buf.size() - 2); + copy_mem(&m_cookie[0], &buf[2], buf.size() - 2); + } + +Hello_Verify_Request::Hello_Verify_Request(const std::vector<byte>& client_hello_bits, + const std::string& client_identity, + const SymmetricKey& secret_key) + { + std::unique_ptr<MessageAuthenticationCode> hmac(get_mac("HMAC(SHA-256)")); + hmac->set_key(secret_key); + + hmac->update_be(client_hello_bits.size()); + hmac->update(client_hello_bits); + hmac->update_be(client_identity.size()); + hmac->update(client_identity); + + m_cookie = unlock(hmac->final()); + } + +std::vector<byte> Hello_Verify_Request::serialize() const + { + /* DTLS 1.2 server implementations SHOULD use DTLS version 1.0 + regardless of the version of TLS that is expected to be + negotiated (RFC 6347, section 4.2.1) + */ + + Protocol_Version format_version(Protocol_Version::TLS_V11); + + std::vector<byte> bits; + bits.push_back(format_version.major_version()); + bits.push_back(format_version.minor_version()); + bits += m_cookie; + return bits; + } + +} + +} diff --git a/src/tls/info.txt b/src/tls/info.txt new file mode 100644 index 000000000..9c0051abd --- /dev/null +++ b/src/tls/info.txt @@ -0,0 +1,95 @@ +define TLS + +load_on auto + +<comment> +The TLS code is complex, new, and not yet reviewed, there may be +serious bugs or security issues. +</comment> + +<header:public> +tls_alert.h +tls_channel.h +tls_ciphersuite.h +tls_client.h +tls_exceptn.h +tls_magic.h +tls_policy.h +tls_record.h +tls_server.h +tls_session.h +tls_session_manager.h +tls_version.h +</header:public> + +<header:internal> +tls_extensions.h +tls_handshake_hash.h +tls_handshake_reader.h +tls_handshake_state.h +tls_heartbeats.h +tls_messages.h +tls_reader.h +tls_session_key.h +</header:internal> + +<source> +c_hello.cpp +c_kex.cpp +cert_req.cpp +cert_ver.cpp +finished.cpp +hello_verify.cpp +next_protocol.cpp +rec_read.cpp +rec_wri.cpp +s_hello.cpp +s_kex.cpp +session_ticket.cpp +tls_alert.cpp +tls_channel.cpp +tls_ciphersuite.cpp +tls_client.cpp +tls_extensions.cpp +tls_handshake_hash.cpp +tls_handshake_reader.cpp +tls_handshake_state.cpp +tls_heartbeats.cpp +tls_policy.cpp +tls_server.cpp +tls_session.cpp +tls_session_key.cpp +tls_session_manager.cpp +tls_suite_info.cpp +tls_version.cpp +</source> + +<requires> +aes +arc4 +asn1 +camellia +cbc +credentials +des +dh +dsa +ecdh +ecdsa +eme_pkcs +emsa3 +filters +hmac +kdf2 +md5 +prf_ssl3 +prf_tls +rng +rsa +seed +srp6 +sha1 +sha2_32 +ssl3mac +x509 +</requires> diff --git a/src/tls/next_protocol.cpp b/src/tls/next_protocol.cpp new file mode 100644 index 000000000..adf9acbe9 --- /dev/null +++ b/src/tls/next_protocol.cpp @@ -0,0 +1,55 @@ +/* +* Next Protocol Negotation +* (C) 2012 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#include <botan/internal/tls_messages.h> +#include <botan/internal/tls_extensions.h> +#include <botan/internal/tls_reader.h> +#include <botan/tls_record.h> + +namespace Botan { + +namespace TLS { + +Next_Protocol::Next_Protocol(Record_Writer& writer, + Handshake_Hash& hash, + const std::string& protocol) : + m_protocol(protocol) + { + hash.update(writer.send(*this)); + } + +Next_Protocol::Next_Protocol(const std::vector<byte>& buf) + { + TLS_Data_Reader reader(buf); + + m_protocol = reader.get_string(1, 0, 255); + + reader.get_range_vector<byte>(1, 0, 255); // padding, ignored + } + +std::vector<byte> Next_Protocol::serialize() const + { + std::vector<byte> buf; + + append_tls_length_value(buf, + reinterpret_cast<const byte*>(m_protocol.data()), + m_protocol.size(), + 1); + + const byte padding_len = 32 - ((m_protocol.size() + 2) % 32); + + buf.push_back(padding_len); + + for(size_t i = 0; i != padding_len; ++i) + buf.push_back(0); + + return buf; + } + +} + +} diff --git a/src/tls/rec_read.cpp b/src/tls/rec_read.cpp new file mode 100644 index 000000000..fd57496c8 --- /dev/null +++ b/src/tls/rec_read.cpp @@ -0,0 +1,353 @@ +/* +* TLS Record Reading +* (C) 2004-2012 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#include <botan/tls_record.h> +#include <botan/lookup.h> +#include <botan/loadstor.h> +#include <botan/internal/tls_session_key.h> +#include <botan/internal/rounding.h> +#include <botan/internal/assert.h> + +namespace Botan { + +namespace TLS { + +Record_Reader::Record_Reader() : + m_readbuf(TLS_HEADER_SIZE + MAX_CIPHERTEXT_SIZE), + m_mac(nullptr) + { + reset(); + set_maximum_fragment_size(0); + } + +/* +* Reset the state +*/ +void Record_Reader::reset() + { + m_macbuf.clear(); + + zeroise(m_readbuf); + m_readbuf_pos = 0; + + m_cipher.reset(); + + delete m_mac; + m_mac = nullptr; + + m_block_size = 0; + m_iv_size = 0; + m_version = Protocol_Version(); + m_seq_no = 0; + set_maximum_fragment_size(0); + } + +void Record_Reader::set_maximum_fragment_size(size_t max_fragment) + { + if(max_fragment == 0) + m_max_fragment = MAX_PLAINTEXT_SIZE; + else + m_max_fragment = clamp(max_fragment, 128, MAX_PLAINTEXT_SIZE); + } + +/* +* Set the version to use +*/ +void Record_Reader::set_version(Protocol_Version version) + { + m_version = version; + } + +/* +* Set the keys for reading +*/ +void Record_Reader::activate(Connection_Side side, + const Ciphersuite& suite, + const Session_Keys& keys, + byte compression_method) + { + m_cipher.reset(); + delete m_mac; + m_mac = nullptr; + m_seq_no = 0; + + if(compression_method != NO_COMPRESSION) + throw Internal_Error("Negotiated unknown compression algorithm"); + + SymmetricKey mac_key, cipher_key; + InitializationVector iv; + + if(side == CLIENT) + { + cipher_key = keys.server_cipher_key(); + iv = keys.server_iv(); + mac_key = keys.server_mac_key(); + } + else + { + cipher_key = keys.client_cipher_key(); + iv = keys.client_iv(); + mac_key = keys.client_mac_key(); + } + + const std::string cipher_algo = suite.cipher_algo(); + const std::string mac_algo = suite.mac_algo(); + + if(have_block_cipher(cipher_algo)) + { + m_cipher.append(get_cipher( + cipher_algo + "/CBC/NoPadding", + cipher_key, iv, DECRYPTION) + ); + m_block_size = block_size_of(cipher_algo); + + if(m_version >= Protocol_Version::TLS_V11) + m_iv_size = m_block_size; + else + m_iv_size = 0; + } + else if(have_stream_cipher(cipher_algo)) + { + m_cipher.append(get_cipher(cipher_algo, cipher_key, DECRYPTION)); + m_block_size = 0; + m_iv_size = 0; + } + else + throw Invalid_Argument("Record_Reader: Unknown cipher " + cipher_algo); + + if(have_hash(mac_algo)) + { + Algorithm_Factory& af = global_state().algorithm_factory(); + + if(m_version == Protocol_Version::SSL_V3) + m_mac = af.make_mac("SSL3-MAC(" + mac_algo + ")"); + else + m_mac = af.make_mac("HMAC(" + mac_algo + ")"); + + m_mac->set_key(mac_key); + m_macbuf.resize(m_mac->output_length()); + } + else + throw Invalid_Argument("Record_Reader: Unknown hash " + mac_algo); + } + +size_t Record_Reader::fill_buffer_to(const byte*& input, + size_t& input_size, + size_t& input_consumed, + size_t desired) + { + if(desired <= m_readbuf_pos) + return 0; // already have it + + const size_t space_available = (m_readbuf.size() - m_readbuf_pos); + const size_t taken = std::min(input_size, desired - m_readbuf_pos); + + if(taken > space_available) + throw TLS_Exception(Alert::RECORD_OVERFLOW, + "Record is larger than allowed maximum size"); + + copy_mem(&m_readbuf[m_readbuf_pos], input, taken); + m_readbuf_pos += taken; + input_consumed += taken; + input_size -= taken; + input += taken; + + return (desired - m_readbuf_pos); // how many bytes do we still need? + } + +/* +* Retrieve the next record +*/ +size_t Record_Reader::add_input(const byte input_array[], size_t input_sz, + size_t& consumed, + byte& msg_type, + std::vector<byte>& msg) + { + const byte* input = &input_array[0]; + + consumed = 0; + + if(m_readbuf_pos < TLS_HEADER_SIZE) // header incomplete? + { + if(size_t needed = fill_buffer_to(input, input_sz, consumed, TLS_HEADER_SIZE)) + return needed; + + BOTAN_ASSERT_EQUAL(m_readbuf_pos, TLS_HEADER_SIZE, + "Have an entire header"); + } + + // Possible SSLv2 format client hello + if((!m_mac) && (m_readbuf[0] & 0x80) && (m_readbuf[2] == 1)) + { + if(m_readbuf[3] == 0 && m_readbuf[4] == 2) + throw TLS_Exception(Alert::PROTOCOL_VERSION, + "Client claims to only support SSLv2, rejecting"); + + if(m_readbuf[3] >= 3) // SSLv2 mapped TLS hello, then? + { + size_t record_len = make_u16bit(m_readbuf[0], m_readbuf[1]) & 0x7FFF; + + if(size_t needed = fill_buffer_to(input, input_sz, consumed, record_len + 2)) + return needed; + + BOTAN_ASSERT_EQUAL(m_readbuf_pos, (record_len + 2), + "Have the entire SSLv2 hello"); + + msg_type = HANDSHAKE; + + msg.resize(record_len + 4); + + // Fake v3-style handshake message wrapper + msg[0] = CLIENT_HELLO_SSLV2; + msg[1] = 0; + msg[2] = m_readbuf[0] & 0x7F; + msg[3] = m_readbuf[1]; + + copy_mem(&msg[4], &m_readbuf[2], m_readbuf_pos - 2); + m_readbuf_pos = 0; + return 0; + } + } + + if(m_readbuf[0] != CHANGE_CIPHER_SPEC && + m_readbuf[0] != ALERT && + m_readbuf[0] != HANDSHAKE && + m_readbuf[0] != APPLICATION_DATA && + m_readbuf[0] != HEARTBEAT) + { + throw Unexpected_Message( + "Unknown record type " + std::to_string(m_readbuf[0]) + + " from counterparty"); + } + + const size_t record_len = make_u16bit(m_readbuf[3], m_readbuf[4]); + + if(m_version.major_version()) + { + if(m_readbuf[1] != m_version.major_version() || + m_readbuf[2] != m_version.minor_version()) + { + throw TLS_Exception(Alert::PROTOCOL_VERSION, + "Got unexpected version from counterparty"); + } + } + + if(record_len > MAX_CIPHERTEXT_SIZE) + throw TLS_Exception(Alert::RECORD_OVERFLOW, + "Got message that exceeds maximum size"); + + if(size_t needed = fill_buffer_to(input, input_sz, consumed, + TLS_HEADER_SIZE + record_len)) + return needed; + + BOTAN_ASSERT_EQUAL(static_cast<size_t>(TLS_HEADER_SIZE) + record_len, + m_readbuf_pos, + "Have the full record"); + + // Null mac means no encryption either, only valid during handshake + if(!m_mac) + { + if(m_readbuf[0] != CHANGE_CIPHER_SPEC && + m_readbuf[0] != ALERT && + m_readbuf[0] != HANDSHAKE) + { + throw Decoding_Error("Invalid msg type received during handshake"); + } + + msg_type = m_readbuf[0]; + msg.resize(record_len); + copy_mem(&msg[0], &m_readbuf[TLS_HEADER_SIZE], record_len); + + m_readbuf_pos = 0; + return 0; // got a full record + } + + // Otherwise, decrypt, check MAC, return plaintext + + // FIXME: avoid memory allocation by processing in place + m_cipher.process_msg(&m_readbuf[TLS_HEADER_SIZE], record_len); + size_t got_back = m_cipher.read(&m_readbuf[TLS_HEADER_SIZE], record_len, Pipe::LAST_MESSAGE); + BOTAN_ASSERT_EQUAL(got_back, record_len, "Cipher encrypted full amount"); + + BOTAN_ASSERT_EQUAL(m_cipher.remaining(Pipe::LAST_MESSAGE), 0, + "Cipher had no remaining inputs"); + + size_t pad_size = 0; + + if(m_block_size) + { + byte pad_value = m_readbuf[TLS_HEADER_SIZE + (record_len-1)]; + pad_size = pad_value + 1; + + /* + * Check the padding; if it is wrong, then say we have 0 bytes of + * padding, which should ensure that the MAC check below does not + * succeed. This hides a timing channel. + * + * This particular countermeasure is recommended in the TLS 1.2 + * spec (RFC 5246) in section 6.2.3.2 + */ + if(m_version == Protocol_Version::SSL_V3) + { + if(pad_value > m_block_size) + pad_size = 0; + } + else + { + bool padding_good = true; + + for(size_t i = 0; i != pad_size; ++i) + if(m_readbuf[TLS_HEADER_SIZE + (record_len-i-1)] != pad_value) + padding_good = false; + + if(!padding_good) + pad_size = 0; + } + } + + const size_t mac_pad_iv_size = m_macbuf.size() + pad_size + m_iv_size; + + if(record_len < mac_pad_iv_size) + throw Decoding_Error("Record sent with invalid length"); + + const u16bit plain_length = record_len - mac_pad_iv_size; + + if(plain_length > m_max_fragment) + throw TLS_Exception(Alert::RECORD_OVERFLOW, "Plaintext record is too large"); + + m_mac->update_be(m_seq_no); + m_mac->update(m_readbuf[0]); // msg_type + + if(m_version != Protocol_Version::SSL_V3) + { + m_mac->update(m_version.major_version()); + m_mac->update(m_version.minor_version()); + } + + m_mac->update_be(plain_length); + m_mac->update(&m_readbuf[TLS_HEADER_SIZE + m_iv_size], plain_length); + + ++m_seq_no; + + m_mac->final(&m_macbuf[0]); + + const size_t mac_offset = record_len - (m_macbuf.size() + pad_size); + + if(!same_mem(&m_readbuf[TLS_HEADER_SIZE + mac_offset], &m_macbuf[0], m_macbuf.size())) + throw TLS_Exception(Alert::BAD_RECORD_MAC, "Message authentication failure"); + + msg_type = m_readbuf[0]; + + msg.resize(plain_length); + copy_mem(&msg[0], &m_readbuf[TLS_HEADER_SIZE + m_iv_size], plain_length); + m_readbuf_pos = 0; + return 0; + } + +} + +} diff --git a/src/tls/rec_wri.cpp b/src/tls/rec_wri.cpp new file mode 100644 index 000000000..d18ab6594 --- /dev/null +++ b/src/tls/rec_wri.cpp @@ -0,0 +1,317 @@ +/* +* TLS Record Writing +* (C) 2004-2012 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#include <botan/tls_record.h> +#include <botan/internal/tls_messages.h> +#include <botan/internal/tls_session_key.h> +#include <botan/internal/tls_handshake_hash.h> +#include <botan/lookup.h> +#include <botan/internal/rounding.h> +#include <botan/internal/assert.h> +#include <botan/loadstor.h> +#include <botan/libstate.h> + +namespace Botan { + +namespace TLS { + +/* +* Record_Writer Constructor +*/ +Record_Writer::Record_Writer(std::function<void (const byte[], size_t)> out) : + m_output_fn(out), + m_writebuf(TLS_HEADER_SIZE + MAX_CIPHERTEXT_SIZE), + m_mac(nullptr) + { + reset(); + set_maximum_fragment_size(0); + } + +void Record_Writer::set_maximum_fragment_size(size_t max_fragment) + { + if(max_fragment == 0) + m_max_fragment = MAX_PLAINTEXT_SIZE; + else + m_max_fragment = clamp(max_fragment, 128, MAX_PLAINTEXT_SIZE); + } + +/* +* Reset the state +*/ +void Record_Writer::reset() + { + set_maximum_fragment_size(0); + m_cipher.reset(); + + delete m_mac; + m_mac = nullptr; + + m_version = Protocol_Version(); + m_block_size = 0; + m_mac_size = 0; + m_iv_size = 0; + + m_seq_no = 0; + } + +/* +* Set the version to use +*/ +void Record_Writer::set_version(Protocol_Version version) + { + m_version = version; + } + +/* +* Set the keys for writing +*/ +void Record_Writer::activate(Connection_Side side, + const Ciphersuite& suite, + const Session_Keys& keys, + byte compression_method) + { + m_cipher.reset(); + delete m_mac; + m_mac = nullptr; + + if(compression_method != NO_COMPRESSION) + throw Internal_Error("Negotiated unknown compression algorithm"); + + /* + RFC 4346: + A sequence number is incremented after each record: specifically, + the first record transmitted under a particular connection state + MUST use sequence number 0 + */ + m_seq_no = 0; + + SymmetricKey mac_key, cipher_key; + InitializationVector iv; + + if(side == CLIENT) + { + cipher_key = keys.client_cipher_key(); + iv = keys.client_iv(); + mac_key = keys.client_mac_key(); + } + else + { + cipher_key = keys.server_cipher_key(); + iv = keys.server_iv(); + mac_key = keys.server_mac_key(); + } + + const std::string cipher_algo = suite.cipher_algo(); + const std::string mac_algo = suite.mac_algo(); + + if(have_block_cipher(cipher_algo)) + { + m_cipher.append(get_cipher( + cipher_algo + "/CBC/NoPadding", + cipher_key, iv, ENCRYPTION) + ); + m_block_size = block_size_of(cipher_algo); + + if(m_version >= Protocol_Version::TLS_V11) + m_iv_size = m_block_size; + else + m_iv_size = 0; + } + else if(have_stream_cipher(cipher_algo)) + { + m_cipher.append(get_cipher(cipher_algo, cipher_key, ENCRYPTION)); + m_block_size = 0; + m_iv_size = 0; + } + else + throw Invalid_Argument("Record_Writer: Unknown cipher " + cipher_algo); + + if(have_hash(mac_algo)) + { + Algorithm_Factory& af = global_state().algorithm_factory(); + + if(m_version == Protocol_Version::SSL_V3) + m_mac = af.make_mac("SSL3-MAC(" + mac_algo + ")"); + else + m_mac = af.make_mac("HMAC(" + mac_algo + ")"); + + m_mac->set_key(mac_key); + m_mac_size = m_mac->output_length(); + } + else + throw Invalid_Argument("Record_Writer: Unknown hash " + mac_algo); + } + +std::vector<byte> Record_Writer::send(Handshake_Message& msg) + { + const std::vector<byte> buf = msg.serialize(); + std::vector<byte> send_buf(4); + + const size_t buf_size = buf.size(); + + send_buf[0] = msg.type(); + + for(size_t i = 1; i != 4; ++i) + send_buf[i] = get_byte<u32bit>(i, buf_size); + + send_buf += buf; + + send(HANDSHAKE, &send_buf[0], send_buf.size()); + + return send_buf; + } + +/* +* Send one or more records to the other side +*/ +void Record_Writer::send(byte type, const byte input[], size_t length) + { + if(length == 0) + return; + + /* + * If using CBC mode in SSLv3/TLS v1.0, send a single byte of + * plaintext to randomize the (implicit) IV of the following main + * block. If using a stream cipher, or TLS v1.1, this isn't + * necessary. + * + * An empty record also works but apparently some implementations do + * not like this (https://bugzilla.mozilla.org/show_bug.cgi?id=665814) + * + * See http://www.openssl.org/~bodo/tls-cbc.txt for background. + */ + if((type == APPLICATION) && (m_block_size > 0) && (m_iv_size == 0)) + { + send_record(type, &input[0], 1); + input += 1; + length -= 1; + } + + while(length) + { + const size_t sending = std::min(length, m_max_fragment); + send_record(type, &input[0], sending); + + input += sending; + length -= sending; + } + } + +/* +* Encrypt and send the record +*/ +void Record_Writer::send_record(byte type, const byte input[], size_t length) + { + if(length >= MAX_PLAINTEXT_SIZE) + throw Internal_Error("Record_Writer: Compressed packet is too big"); + + if(m_mac_size == 0) // initial unencrypted handshake records + { + m_writebuf[0] = type; + m_writebuf[1] = m_version.major_version(); + m_writebuf[2] = m_version.minor_version(); + m_writebuf[3] = get_byte<u16bit>(0, length); + m_writebuf[4] = get_byte<u16bit>(1, length); + + copy_mem(&m_writebuf[TLS_HEADER_SIZE], input, length); + + m_output_fn(&m_writebuf[0], TLS_HEADER_SIZE + length); + return; + } + + m_mac->update_be(m_seq_no); + m_mac->update(type); + + if(m_version != Protocol_Version::SSL_V3) + { + m_mac->update(m_version.major_version()); + m_mac->update(m_version.minor_version()); + } + + m_mac->update(get_byte<u16bit>(0, length)); + m_mac->update(get_byte<u16bit>(1, length)); + m_mac->update(input, length); + + const size_t buf_size = round_up(m_iv_size + length + + m_mac->output_length() + + (m_block_size ? 1 : 0), + m_block_size); + + if(buf_size >= MAX_CIPHERTEXT_SIZE) + throw Internal_Error("Record_Writer: Record is too big"); + + BOTAN_ASSERT(m_writebuf.size() >= TLS_HEADER_SIZE + MAX_CIPHERTEXT_SIZE, + "Write buffer is big enough"); + + // TLS record header + m_writebuf[0] = type; + m_writebuf[1] = m_version.major_version(); + m_writebuf[2] = m_version.minor_version(); + m_writebuf[3] = get_byte<u16bit>(0, buf_size); + m_writebuf[4] = get_byte<u16bit>(1, buf_size); + + byte* buf_write_ptr = &m_writebuf[TLS_HEADER_SIZE]; + + if(m_iv_size) + { + RandomNumberGenerator& rng = global_state().global_rng(); + rng.randomize(buf_write_ptr, m_iv_size); + buf_write_ptr += m_iv_size; + } + + copy_mem(buf_write_ptr, input, length); + buf_write_ptr += length; + + m_mac->final(buf_write_ptr); + buf_write_ptr += m_mac->output_length(); + + if(m_block_size) + { + const size_t pad_val = + buf_size - (m_iv_size + length + m_mac->output_length() + 1); + + for(size_t i = 0; i != pad_val + 1; ++i) + { + *buf_write_ptr = pad_val; + buf_write_ptr += 1; + } + } + + // FIXME: this could be done in-place without copying + m_cipher.process_msg(&m_writebuf[TLS_HEADER_SIZE], buf_size); + + const size_t ctext_size = m_cipher.remaining(Pipe::LAST_MESSAGE); + + BOTAN_ASSERT_EQUAL(ctext_size, buf_size, "Cipher encrypted full amount"); + + if(ctext_size > MAX_CIPHERTEXT_SIZE) + throw Internal_Error("Produced ciphertext larger than protocol allows"); + + m_cipher.read(&m_writebuf[TLS_HEADER_SIZE], ctext_size, Pipe::LAST_MESSAGE); + + BOTAN_ASSERT_EQUAL(m_cipher.remaining(Pipe::LAST_MESSAGE), 0, + "No data remains in pipe"); + + m_output_fn(&m_writebuf[0], TLS_HEADER_SIZE + buf_size); + + m_seq_no++; + } + +/* +* Send an alert +*/ +void Record_Writer::send_alert(const Alert& alert) + { + const byte alert_bits[2] = { static_cast<byte>(alert.is_fatal() ? 2 : 1), + static_cast<byte>(alert.type()) }; + + send(ALERT, alert_bits, sizeof(alert_bits)); + } + +} + +} diff --git a/src/tls/s_hello.cpp b/src/tls/s_hello.cpp new file mode 100644 index 000000000..d4cc4a1ab --- /dev/null +++ b/src/tls/s_hello.cpp @@ -0,0 +1,186 @@ +;/* +* TLS Server Hello and Server Hello Done +* (C) 2004-2011 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#include <botan/internal/tls_messages.h> +#include <botan/internal/tls_reader.h> +#include <botan/internal/tls_session_key.h> +#include <botan/internal/tls_extensions.h> +#include <botan/tls_record.h> +#include <botan/internal/stl_util.h> + +namespace Botan { + +namespace TLS { + +/* +* Create a new Server Hello message +*/ +Server_Hello::Server_Hello(Record_Writer& writer, + Handshake_Hash& hash, + const std::vector<byte>& session_id, + Protocol_Version ver, + u16bit ciphersuite, + byte compression, + size_t max_fragment_size, + bool client_has_secure_renegotiation, + const std::vector<byte>& reneg_info, + bool offer_session_ticket, + bool client_has_npn, + const std::vector<std::string>& next_protocols, + bool client_has_heartbeat, + RandomNumberGenerator& rng) : + m_version(ver), + m_session_id(session_id), + m_random(make_hello_random(rng)), + m_ciphersuite(ciphersuite), + m_comp_method(compression), + m_fragment_size(max_fragment_size), + m_secure_renegotiation(client_has_secure_renegotiation), + m_renegotiation_info(reneg_info), + m_next_protocol(client_has_npn), + m_next_protocols(next_protocols), + m_supports_session_ticket(offer_session_ticket), + m_supports_heartbeats(client_has_heartbeat), + m_peer_can_send_heartbeats(true) + { + hash.update(writer.send(*this)); + } + +/* +* Deserialize a Server Hello message +*/ +Server_Hello::Server_Hello(const std::vector<byte>& buf) + { + m_secure_renegotiation = false; + m_supports_session_ticket = false; + m_next_protocol = false; + + if(buf.size() < 38) + throw Decoding_Error("Server_Hello: Packet corrupted"); + + TLS_Data_Reader reader(buf); + + const byte major_version = reader.get_byte(); + const byte minor_version = reader.get_byte(); + + m_version = Protocol_Version(major_version, minor_version); + + if(m_version != Protocol_Version::SSL_V3 && + m_version != Protocol_Version::TLS_V10 && + m_version != Protocol_Version::TLS_V11 && + m_version != Protocol_Version::TLS_V12) + { + throw TLS_Exception(Alert::PROTOCOL_VERSION, + "Server_Hello: Unsupported server version"); + } + + m_random = reader.get_fixed<byte>(32); + + m_session_id = reader.get_range<byte>(1, 0, 32); + + m_ciphersuite = reader.get_u16bit(); + + m_comp_method = reader.get_byte(); + + Extensions extensions(reader); + + if(Renegotation_Extension* reneg = extensions.get<Renegotation_Extension>()) + { + // checked by Client / Server as they know the handshake state + m_secure_renegotiation = true; + m_renegotiation_info = reneg->renegotiation_info(); + } + + if(Next_Protocol_Notification* npn = extensions.get<Next_Protocol_Notification>()) + { + m_next_protocols = npn->protocols(); + m_next_protocol = true; + } + + if(Session_Ticket* ticket = extensions.get<Session_Ticket>()) + { + if(!ticket->contents().empty()) + throw Decoding_Error("TLS server sent non-empty session ticket extension"); + m_supports_session_ticket = true; + } + + if(Heartbeat_Support_Indicator* hb = extensions.get<Heartbeat_Support_Indicator>()) + { + m_supports_heartbeats = true; + m_peer_can_send_heartbeats = hb->peer_allowed_to_send(); + } + } + +/* +* Serialize a Server Hello message +*/ +std::vector<byte> Server_Hello::serialize() const + { + std::vector<byte> buf; + + buf.push_back(m_version.major_version()); + buf.push_back(m_version.minor_version()); + buf += m_random; + + append_tls_length_value(buf, m_session_id, 1); + + buf.push_back(get_byte(0, m_ciphersuite)); + buf.push_back(get_byte(1, m_ciphersuite)); + + buf.push_back(m_comp_method); + + Extensions extensions; + + if(m_supports_heartbeats) + extensions.add(new Heartbeat_Support_Indicator(m_peer_can_send_heartbeats)); + + if(m_secure_renegotiation) + extensions.add(new Renegotation_Extension(m_renegotiation_info)); + + if(m_fragment_size != 0) + extensions.add(new Maximum_Fragment_Length(m_fragment_size)); + + if(m_next_protocol) + extensions.add(new Next_Protocol_Notification(m_next_protocols)); + + if(m_supports_session_ticket) + extensions.add(new Session_Ticket()); + + buf += extensions.serialize(); + + return buf; + } + +/* +* Create a new Server Hello Done message +*/ +Server_Hello_Done::Server_Hello_Done(Record_Writer& writer, + Handshake_Hash& hash) + { + hash.update(writer.send(*this)); + } + +/* +* Deserialize a Server Hello Done message +*/ +Server_Hello_Done::Server_Hello_Done(const std::vector<byte>& buf) + { + if(buf.size()) + throw Decoding_Error("Server_Hello_Done: Must be empty, and is not"); + } + +/* +* Serialize a Server Hello Done message +*/ +std::vector<byte> Server_Hello_Done::serialize() const + { + return std::vector<byte>(); + } + +} + +} diff --git a/src/tls/s_kex.cpp b/src/tls/s_kex.cpp new file mode 100644 index 000000000..48901d311 --- /dev/null +++ b/src/tls/s_kex.cpp @@ -0,0 +1,292 @@ +/* +* Server Key Exchange Message +* (C) 2004-2010,2012 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#include <botan/internal/tls_messages.h> +#include <botan/internal/tls_reader.h> +#include <botan/internal/tls_extensions.h> +#include <botan/tls_record.h> +#include <botan/internal/assert.h> +#include <botan/credentials_manager.h> +#include <botan/loadstor.h> +#include <botan/pubkey.h> +#include <botan/dh.h> +#include <botan/ecdh.h> +#include <botan/rsa.h> +#include <botan/srp6.h> +#include <botan/oids.h> +#include <memory> + +namespace Botan { + +namespace TLS { + +/** +* Create a new Server Key Exchange message +*/ +Server_Key_Exchange::Server_Key_Exchange(Record_Writer& writer, + Handshake_State* state, + const Policy& policy, + Credentials_Manager& creds, + RandomNumberGenerator& rng, + const Private_Key* signing_key) : + m_kex_key(nullptr), m_srp_params(nullptr) + { + const std::string hostname = state->client_hello->sni_hostname(); + const std::string kex_algo = state->suite.kex_algo(); + + if(kex_algo == "PSK" || kex_algo == "DHE_PSK" || kex_algo == "ECDHE_PSK") + { + std::string identity_hint = + creds.psk_identity_hint("tls-server", hostname); + + append_tls_length_value(m_params, identity_hint, 2); + } + + if(kex_algo == "DH" || kex_algo == "DHE_PSK") + { + std::unique_ptr<DH_PrivateKey> dh(new DH_PrivateKey(rng, policy.dh_group())); + + append_tls_length_value(m_params, BigInt::encode(dh->get_domain().get_p()), 2); + append_tls_length_value(m_params, BigInt::encode(dh->get_domain().get_g()), 2); + append_tls_length_value(m_params, dh->public_value(), 2); + m_kex_key = dh.release(); + } + else if(kex_algo == "ECDH" || kex_algo == "ECDHE_PSK") + { + const std::vector<std::string>& curves = + state->client_hello->supported_ecc_curves(); + + if(curves.empty()) + throw Internal_Error("Client sent no ECC extension but we negotiated ECDH"); + + const std::string curve_name = policy.choose_curve(curves); + + if(curve_name == "") + throw TLS_Exception(Alert::HANDSHAKE_FAILURE, + "Could not agree on an ECC curve with the client"); + + EC_Group ec_group(curve_name); + + std::unique_ptr<ECDH_PrivateKey> ecdh(new ECDH_PrivateKey(rng, ec_group)); + + const std::string ecdh_domain_oid = ecdh->domain().get_oid(); + const std::string domain = OIDS::lookup(OID(ecdh_domain_oid)); + + if(domain == "") + throw Internal_Error("Could not find name of ECDH domain " + ecdh_domain_oid); + + const u16bit named_curve_id = Supported_Elliptic_Curves::name_to_curve_id(domain); + + m_params.push_back(3); // named curve + m_params.push_back(get_byte(0, named_curve_id)); + m_params.push_back(get_byte(1, named_curve_id)); + + append_tls_length_value(m_params, ecdh->public_value(), 1); + + m_kex_key = ecdh.release(); + } + else if(kex_algo == "SRP_SHA") + { + const std::string srp_identifier = state->client_hello->srp_identifier(); + + std::string group_id; + BigInt v; + std::vector<byte> salt; + + const bool found = creds.srp_verifier("tls-server", hostname, + srp_identifier, + group_id, v, salt, + policy.hide_unknown_users()); + + if(!found) + throw TLS_Exception(Alert::UNKNOWN_PSK_IDENTITY, + "Unknown SRP user " + srp_identifier); + + m_srp_params = new SRP6_Server_Session; + + BigInt B = m_srp_params->step1(v, group_id, + "SHA-1", rng); + + DL_Group group(group_id); + + append_tls_length_value(m_params, BigInt::encode(group.get_p()), 2); + append_tls_length_value(m_params, BigInt::encode(group.get_g()), 2); + append_tls_length_value(m_params, salt, 1); + append_tls_length_value(m_params, BigInt::encode(B), 2); + } + else if(kex_algo != "PSK") + throw Internal_Error("Server_Key_Exchange: Unknown kex type " + kex_algo); + + if(state->suite.sig_algo() != "") + { + BOTAN_ASSERT(signing_key, "No signing key set"); + + std::pair<std::string, Signature_Format> format = + state->choose_sig_format(signing_key, m_hash_algo, m_sig_algo, false); + + PK_Signer signer(*signing_key, format.first, format.second); + + signer.update(state->client_hello->random()); + signer.update(state->server_hello->random()); + signer.update(params()); + m_signature = signer.signature(rng); + } + + state->hash.update(writer.send(*this)); + } + +/** +* Deserialize a Server Key Exchange message +*/ +Server_Key_Exchange::Server_Key_Exchange(const std::vector<byte>& buf, + const std::string& kex_algo, + const std::string& sig_algo, + Protocol_Version version) : + m_kex_key(nullptr), m_srp_params(nullptr) + { + if(buf.size() < 6) + throw Decoding_Error("Server_Key_Exchange: Packet corrupted"); + + TLS_Data_Reader reader(buf); + + /* + * We really are just serializing things back to what they were + * before, but unfortunately to know where the signature is we need + * to be able to parse the whole thing anyway. + */ + + if(kex_algo == "PSK" || kex_algo == "DHE_PSK" || kex_algo == "ECDHE_PSK") + { + const std::string identity_hint = reader.get_string(2, 0, 65535); + append_tls_length_value(m_params, identity_hint, 2); + } + + if(kex_algo == "DH" || kex_algo == "DHE_PSK") + { + // 3 bigints, DH p, g, Y + + for(size_t i = 0; i != 3; ++i) + { + BigInt v = BigInt::decode(reader.get_range<byte>(2, 1, 65535)); + append_tls_length_value(m_params, BigInt::encode(v), 2); + } + } + else if(kex_algo == "ECDH" || kex_algo == "ECDHE_PSK") + { + const byte curve_type = reader.get_byte(); + + if(curve_type != 3) + throw Decoding_Error("Server_Key_Exchange: Server sent non-named ECC curve"); + + const u16bit curve_id = reader.get_u16bit(); + + const std::string name = Supported_Elliptic_Curves::curve_id_to_name(curve_id); + + std::vector<byte> ecdh_key = reader.get_range<byte>(1, 1, 255); + + if(name == "") + throw Decoding_Error("Server_Key_Exchange: Server sent unknown named curve " + + std::to_string(curve_id)); + + m_params.push_back(curve_type); + m_params.push_back(get_byte(0, curve_id)); + m_params.push_back(get_byte(1, curve_id)); + append_tls_length_value(m_params, ecdh_key, 1); + } + else if(kex_algo == "SRP_SHA") + { + // 2 bigints (N,g) then salt, then server B + + const BigInt N = BigInt::decode(reader.get_range<byte>(2, 1, 65535)); + const BigInt g = BigInt::decode(reader.get_range<byte>(2, 1, 65535)); + std::vector<byte> salt = reader.get_range<byte>(1, 1, 255); + const BigInt B = BigInt::decode(reader.get_range<byte>(2, 1, 65535)); + + append_tls_length_value(m_params, BigInt::encode(N), 2); + append_tls_length_value(m_params, BigInt::encode(g), 2); + append_tls_length_value(m_params, salt, 1); + append_tls_length_value(m_params, BigInt::encode(B), 2); + } + else if(kex_algo != "PSK") + throw Decoding_Error("Server_Key_Exchange: Unsupported kex type " + kex_algo); + + if(sig_algo != "") + { + if(version >= Protocol_Version::TLS_V12) + { + m_hash_algo = Signature_Algorithms::hash_algo_name(reader.get_byte()); + m_sig_algo = Signature_Algorithms::sig_algo_name(reader.get_byte()); + } + + m_signature = reader.get_range<byte>(2, 0, 65535); + } + } + +Server_Key_Exchange::~Server_Key_Exchange() + { + delete m_kex_key; + delete m_srp_params; + } + + +/** +* Serialize a Server Key Exchange message +*/ +std::vector<byte> Server_Key_Exchange::serialize() const + { + std::vector<byte> buf = params(); + + if(m_signature.size()) + { + // This should be an explicit version check + if(m_hash_algo != "" && m_sig_algo != "") + { + buf.push_back(Signature_Algorithms::hash_algo_code(m_hash_algo)); + buf.push_back(Signature_Algorithms::sig_algo_code(m_sig_algo)); + } + + append_tls_length_value(buf, m_signature, 2); + } + + return buf; + } + +/** +* Verify a Server Key Exchange message +*/ +bool Server_Key_Exchange::verify(const X509_Certificate& cert, + Handshake_State* state) const + { + std::unique_ptr<Public_Key> key(cert.subject_public_key()); + + std::pair<std::string, Signature_Format> format = + state->understand_sig_format(key.get(), m_hash_algo, m_sig_algo, false); + + PK_Verifier verifier(*key, format.first, format.second); + + verifier.update(state->client_hello->random()); + verifier.update(state->server_hello->random()); + verifier.update(params()); + + return verifier.check_signature(m_signature); + } + +const Private_Key& Server_Key_Exchange::server_kex_key() const + { + BOTAN_ASSERT(m_kex_key, "Key is non-NULL"); + return *m_kex_key; + } + +// Only valid for SRP negotiation +SRP6_Server_Session& Server_Key_Exchange::server_srp_params() + { + BOTAN_ASSERT(m_srp_params, "SRP params are non-NULL"); + return *m_srp_params; + } +} + +} diff --git a/src/tls/session_ticket.cpp b/src/tls/session_ticket.cpp new file mode 100644 index 000000000..8cee2a454 --- /dev/null +++ b/src/tls/session_ticket.cpp @@ -0,0 +1,57 @@ +/* +* Session Tickets +* (C) 2012 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#include <botan/internal/tls_messages.h> +#include <botan/internal/tls_extensions.h> +#include <botan/internal/tls_reader.h> +#include <botan/tls_record.h> +#include <botan/loadstor.h> + +namespace Botan { + +namespace TLS { + +New_Session_Ticket::New_Session_Ticket(Record_Writer& writer, + Handshake_Hash& hash, + const std::vector<byte>& ticket, + u32bit lifetime) : + m_ticket_lifetime_hint(lifetime), + m_ticket(ticket) + { + hash.update(writer.send(*this)); + } + +New_Session_Ticket::New_Session_Ticket(Record_Writer& writer, + Handshake_Hash& hash) : + m_ticket_lifetime_hint(0) + { + hash.update(writer.send(*this)); + } + +New_Session_Ticket::New_Session_Ticket(const std::vector<byte>& buf) : + m_ticket_lifetime_hint(0) + { + if(buf.size() < 6) + throw Decoding_Error("Session ticket message too short to be valid"); + + TLS_Data_Reader reader(buf); + + m_ticket_lifetime_hint = reader.get_u32bit(); + m_ticket = reader.get_range<byte>(2, 0, 65535); + } + +std::vector<byte> New_Session_Ticket::serialize() const + { + std::vector<byte> buf(4); + store_be(m_ticket_lifetime_hint, &buf[0]); + append_tls_length_value(buf, m_ticket, 2); + return buf; + } + +} + +} diff --git a/src/tls/sessions_sqlite/info.txt b/src/tls/sessions_sqlite/info.txt new file mode 100644 index 000000000..c5fc35952 --- /dev/null +++ b/src/tls/sessions_sqlite/info.txt @@ -0,0 +1,11 @@ +define TLS_SQLITE_SESSION_MANAGER + +load_on request + +<libs> +all -> sqlite3 +</libs> + +<requires> +pbkdf2 +</requires> diff --git a/src/tls/sessions_sqlite/tls_sqlite_sess_mgr.cpp b/src/tls/sessions_sqlite/tls_sqlite_sess_mgr.cpp new file mode 100644 index 000000000..b6aaa3498 --- /dev/null +++ b/src/tls/sessions_sqlite/tls_sqlite_sess_mgr.cpp @@ -0,0 +1,350 @@ +/* +* SQLite TLS Session Manager +* (C) 2012 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#include <botan/tls_sqlite_sess_mgr.h> +#include <botan/internal/assert.h> +#include <botan/lookup.h> +#include <botan/hex.h> +#include <botan/loadstor.h> +#include <memory> +#include <chrono> + +#include <sqlite3.h> + +namespace Botan { + +namespace TLS { + +namespace { + +class sqlite3_statement + { + public: + sqlite3_statement(sqlite3* db, const std::string& base_sql) + { + int rc = sqlite3_prepare_v2(db, base_sql.c_str(), -1, &m_stmt, 0); + + if(rc != SQLITE_OK) + throw std::runtime_error("sqlite3_prepare failed " + base_sql + + ", code " + std::to_string(rc)); + } + + void bind(int column, const std::string& val) + { + int rc = sqlite3_bind_text(m_stmt, column, val.c_str(), -1, SQLITE_TRANSIENT); + if(rc != SQLITE_OK) + throw std::runtime_error("sqlite3_bind_text failed, code " + std::to_string(rc)); + } + + void bind(int column, int val) + { + int rc = sqlite3_bind_int(m_stmt, column, val); + if(rc != SQLITE_OK) + throw std::runtime_error("sqlite3_bind_int failed, code " + std::to_string(rc)); + } + + void bind(int column, std::chrono::system_clock::time_point time) + { + const int timeval = std::chrono::duration_cast<std::chrono::seconds>(time.time_since_epoch()).count(); + bind(column, timeval); + } + + void bind(int column, const std::vector<byte>& val) + { + int rc = sqlite3_bind_blob(m_stmt, column, &val[0], val.size(), SQLITE_TRANSIENT); + if(rc != SQLITE_OK) + throw std::runtime_error("sqlite3_bind_text failed, code " + std::to_string(rc)); + } + + std::pair<const byte*, size_t> get_blob(int column) + { + BOTAN_ASSERT(sqlite3_column_type(m_stmt, 0) == SQLITE_BLOB, + "Return value is a blob"); + + const void* session_blob = sqlite3_column_blob(m_stmt, column); + const int session_blob_size = sqlite3_column_bytes(m_stmt, column); + + BOTAN_ASSERT(session_blob_size >= 0, "Blob size is non-negative"); + + return std::make_pair(static_cast<const byte*>(session_blob), + static_cast<size_t>(session_blob_size)); + } + + size_t get_size_t(int column) + { + BOTAN_ASSERT(sqlite3_column_type(m_stmt, column) == SQLITE_INTEGER, + "Return count is an integer"); + + const int sessions_int = sqlite3_column_int(m_stmt, column); + + BOTAN_ASSERT(sessions_int >= 0, "Expected size_t is non-negative"); + + return static_cast<size_t>(sessions_int); + } + + void spin() + { + while(sqlite3_step(m_stmt) == SQLITE_ROW) + {} + } + + int step() + { + return sqlite3_step(m_stmt); + } + + sqlite3_stmt* stmt() { return m_stmt; } + + ~sqlite3_statement() { sqlite3_finalize(m_stmt); } + private: + sqlite3_stmt* m_stmt; + }; + +size_t row_count(sqlite3* db, const std::string& table_name) + { + sqlite3_statement stmt(db, "select count(*) from " + table_name); + + if(stmt.step() == SQLITE_ROW) + return stmt.get_size_t(0); + else + throw std::runtime_error("Querying size of table " + table_name + " failed"); + } + +void create_table(sqlite3* db, const char* table_schema) + { + char* errmsg = 0; + int rc = sqlite3_exec(db, table_schema, 0, 0, &errmsg); + + if(rc != SQLITE_OK) + { + const std::string err_msg = errmsg; + sqlite3_free(errmsg); + sqlite3_close(db); + throw std::runtime_error("sqlite3_exec for table failed - " + err_msg); + } + } + + +SymmetricKey derive_key(const std::string& passphrase, + const byte salt[], + size_t salt_len, + size_t iterations, + size_t& check_val) + { + std::unique_ptr<PBKDF> pbkdf(get_pbkdf("PBKDF2(SHA-512)")); + + std::vector<byte> x = pbkdf->derive_key(32 + 3, + passphrase, + salt, salt_len, + iterations).bits_of(); + + check_val = make_u32bit(0, x[0], x[1], x[2]); + return SymmetricKey(&x[3], x.size() - 3); + } + +} + +Session_Manager_SQLite::Session_Manager_SQLite(const std::string& passphrase, + RandomNumberGenerator& rng, + const std::string& db_filename, + size_t max_sessions, + std::chrono::seconds session_lifetime) : + m_rng(rng), + m_max_sessions(max_sessions), + m_session_lifetime(session_lifetime) + { + int rc = sqlite3_open(db_filename.c_str(), &m_db); + + if(rc) + { + const std::string err_msg = sqlite3_errmsg(m_db); + sqlite3_close(m_db); + throw std::runtime_error("sqlite3_open failed - " + err_msg); + } + + create_table(m_db, + "create table if not exists tls_sessions " + "(" + "session_id TEXT PRIMARY KEY, " + "session_start INTEGER, " + "hostname TEXT, " + "hostport INTEGER, " + "session BLOB" + ")"); + + create_table(m_db, + "create table if not exists tls_sessions_metadata " + "(" + "passphrase_salt BLOB, " + "passphrase_iterations INTEGER, " + "passphrase_check INTEGER " + ")"); + + const size_t salts = row_count(m_db, "tls_sessions_metadata"); + + if(salts == 1) + { + // existing db + sqlite3_statement stmt(m_db, "select * from tls_sessions_metadata"); + + int rc = stmt.step(); + if(rc == SQLITE_ROW) + { + std::pair<const byte*, size_t> salt = stmt.get_blob(0); + const size_t iterations = stmt.get_size_t(1); + const size_t check_val_db = stmt.get_size_t(2); + + size_t check_val_created; + m_session_key = derive_key(passphrase, + salt.first, + salt.second, + iterations, + check_val_created); + + if(check_val_created != check_val_db) + throw std::runtime_error("Session database password not valid"); + } + } + else + { + // maybe just zap the salts + sessions tables in this case? + if(salts != 0) + throw std::runtime_error("Seemingly corrupted database, multiple salts found"); + + // new database case + + std::vector<byte> salt = rng.random_vec(16); + const size_t iterations = 64 * 1024; + size_t check_val = 0; + + m_session_key = derive_key(passphrase, &salt[0], salt.size(), + iterations, check_val); + + sqlite3_statement stmt(m_db, "insert into tls_sessions_metadata" + " values(?1, ?2, ?3)"); + + stmt.bind(1, salt); + stmt.bind(2, iterations); + stmt.bind(3, check_val); + + stmt.spin(); + } + } + +Session_Manager_SQLite::~Session_Manager_SQLite() + { + sqlite3_close(m_db); + } + +bool Session_Manager_SQLite::load_from_session_id(const std::vector<byte>& session_id, + Session& session) + { + sqlite3_statement stmt(m_db, "select session from tls_sessions where session_id = ?1"); + + stmt.bind(1, hex_encode(session_id)); + + int rc = stmt.step(); + + while(rc == SQLITE_ROW) + { + std::pair<const byte*, size_t> blob = stmt.get_blob(0); + + try + { + session = Session::decrypt(blob.first, blob.second, m_session_key); + return true; + } + catch(...) + { + } + + rc = stmt.step(); + } + + return false; + } + +bool Session_Manager_SQLite::load_from_host_info(const std::string& hostname, + u16bit port, + Session& session) + { + sqlite3_statement stmt(m_db, "select session from tls_sessions" + " where hostname = ?1 and hostport = ?2" + " order by session_start desc"); + + stmt.bind(1, hostname); + stmt.bind(2, port); + + int rc = stmt.step(); + + while(rc == SQLITE_ROW) + { + std::pair<const byte*, size_t> blob = stmt.get_blob(0); + + try + { + session = Session::decrypt(blob.first, blob.second, m_session_key); + return true; + } + catch(...) + { + } + + rc = stmt.step(); + } + + return false; + } + +void Session_Manager_SQLite::remove_entry(const std::vector<byte>& session_id) + { + sqlite3_statement stmt(m_db, "delete from tls_sessions where session_id = ?1"); + + stmt.bind(1, hex_encode(session_id)); + + stmt.spin(); + } + +void Session_Manager_SQLite::save(const Session& session) + { + sqlite3_statement stmt(m_db, "insert or replace into tls_sessions" + " values(?1, ?2, ?3, ?4, ?5)"); + + stmt.bind(1, hex_encode(session.session_id())); + stmt.bind(2, session.start_time()); + stmt.bind(3, session.sni_hostname()); + stmt.bind(4, 0); + stmt.bind(5, session.encrypt(m_session_key, m_rng)); + + stmt.spin(); + + prune_session_cache(); + } + +void Session_Manager_SQLite::prune_session_cache() + { + sqlite3_statement remove_expired(m_db, "delete from tls_sessions where session_start <= ?1"); + + remove_expired.bind(1, std::chrono::system_clock::now() - m_session_lifetime); + + remove_expired.spin(); + + const size_t sessions = row_count(m_db, "tls_sessions"); + + if(sessions > m_max_sessions) + { + sqlite3_statement remove_some(m_db, "delete from tls_sessions where session_id in " + "(select session_id from tls_sessions limit ?1)"); + + remove_some.bind(1, sessions - m_max_sessions); + remove_some.spin(); + } + } + +} + +} diff --git a/src/tls/sessions_sqlite/tls_sqlite_sess_mgr.h b/src/tls/sessions_sqlite/tls_sqlite_sess_mgr.h new file mode 100644 index 000000000..923915496 --- /dev/null +++ b/src/tls/sessions_sqlite/tls_sqlite_sess_mgr.h @@ -0,0 +1,71 @@ +/* +* SQLite TLS Session Manager +* (C) 2012 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#ifndef BOTAN_TLS_SQLITE_SESSION_MANAGER_H__ +#define BOTAN_TLS_SQLITE_SESSION_MANAGER_H__ + +#include <botan/tls_session_manager.h> +#include <botan/rng.h> + +class sqlite3; + +namespace Botan { + +namespace TLS { + +/** +*/ +class BOTAN_DLL Session_Manager_SQLite : public Session_Manager + { + public: + /** + * @param passphrase used to encrypt the session data + * @param db_filename filename of the SQLite database file. + The table names tls_sessions and tls_sessions_metadata + will be used + * @param max_sessions a hint on the maximum number of sessions + * to keep in memory at any one time. (If zero, don't cap) + * @param session_lifetime sessions are expired after this many + * seconds have elapsed from initial handshake. + */ + Session_Manager_SQLite(const std::string& passphrase, + RandomNumberGenerator& rng, + const std::string& db_filename, + size_t max_sessions = 1000, + std::chrono::seconds session_lifetime = std::chrono::seconds(7200)); + + ~Session_Manager_SQLite(); + + bool load_from_session_id(const std::vector<byte>& session_id, + Session& session); + + bool load_from_host_info(const std::string& hostname, u16bit port, + Session& session); + + void remove_entry(const std::vector<byte>& session_id); + + void save(const Session& session_data); + + std::chrono::seconds session_lifetime() const { return m_session_lifetime; } + private: + Session_Manager_SQLite(const Session_Manager_SQLite&); + Session_Manager_SQLite& operator=(const Session_Manager_SQLite&); + + void prune_session_cache(); + + SymmetricKey m_session_key; + RandomNumberGenerator& m_rng; + size_t m_max_sessions; + std::chrono::seconds m_session_lifetime; + class sqlite3* m_db; + }; + +} + +} + +#endif diff --git a/src/tls/tls_alert.cpp b/src/tls/tls_alert.cpp new file mode 100644 index 000000000..5bc2e7484 --- /dev/null +++ b/src/tls/tls_alert.cpp @@ -0,0 +1,122 @@ +/* +* Alert Message +* (C) 2004-2006,2011 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#include <botan/tls_alert.h> +#include <botan/exceptn.h> + +namespace Botan { + +namespace TLS { + +Alert::Alert(const std::vector<byte>& buf) + { + if(buf.size() != 2) + throw Decoding_Error("Alert: Bad size " + std::to_string(buf.size()) + + " for alert message"); + + if(buf[0] == 1) fatal = false; + else if(buf[0] == 2) fatal = true; + else + throw Decoding_Error("Alert: Bad code for alert level"); + + const byte dc = buf[1]; + + /* + * This is allowed by the specification but is not allocated and we're + * using it internally as a special 'no alert' type. + */ + if(dc == 255) + throw Internal_Error("Alert: description code 255, rejecting"); + + type_code = static_cast<Type>(dc); + } + +std::string Alert::type_string() const + { + switch(type()) + { + case CLOSE_NOTIFY: + return "close_notify"; + case UNEXPECTED_MESSAGE: + return "unexpected_message"; + case BAD_RECORD_MAC: + return "bad_record_mac"; + case DECRYPTION_FAILED: + return "decryption_failed"; + case RECORD_OVERFLOW: + return "record_overflow"; + case DECOMPRESSION_FAILURE: + return "decompression_failure"; + case HANDSHAKE_FAILURE: + return "handshake_failure"; + case NO_CERTIFICATE: + return "no_certificate"; + case BAD_CERTIFICATE: + return "bad_certificate"; + case UNSUPPORTED_CERTIFICATE: + return "unsupported_certificate"; + case CERTIFICATE_REVOKED: + return "certificate_revoked"; + case CERTIFICATE_EXPIRED: + return "certificate_expired"; + case CERTIFICATE_UNKNOWN: + return "certificate_unknown"; + case ILLEGAL_PARAMETER: + return "illegal_parameter"; + case UNKNOWN_CA: + return "unknown_ca"; + case ACCESS_DENIED: + return "access_denied"; + case DECODE_ERROR: + return "decode_error"; + case DECRYPT_ERROR: + return "decrypt_error"; + case EXPORT_RESTRICTION: + return "export_restriction"; + case PROTOCOL_VERSION: + return "protocol_version"; + case INSUFFICIENT_SECURITY: + return "insufficient_security"; + case INTERNAL_ERROR: + return "internal_error"; + case USER_CANCELED: + return "user_canceled"; + case NO_RENEGOTIATION: + return "no_renegotiation"; + + case UNSUPPORTED_EXTENSION: + return "unsupported_extension"; + case CERTIFICATE_UNOBTAINABLE: + return "certificate_unobtainable"; + case UNRECOGNIZED_NAME: + return "unrecognized_name"; + case BAD_CERTIFICATE_STATUS_RESPONSE: + return "bad_certificate_status_response"; + case BAD_CERTIFICATE_HASH_VALUE: + return "bad_certificate_hash_value"; + case UNKNOWN_PSK_IDENTITY: + return "unknown_psk_identity"; + + case NULL_ALERT: + return "none"; + + case HEARTBEAT_PAYLOAD: + return "heartbeat_payload"; + } + + /* + * This is effectively the default case for the switch above, but we + * leave it out so that when an alert type is added to the enum the + * compiler can warn us that it is not included in the switch + * statement. + */ + return "unrecognized_alert_" + std::to_string(type()); + } + +} + +} diff --git a/src/tls/tls_alert.h b/src/tls/tls_alert.h new file mode 100644 index 000000000..b3001f259 --- /dev/null +++ b/src/tls/tls_alert.h @@ -0,0 +1,100 @@ +/* +* Alert Message +* (C) 2004-2006,2011 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#ifndef BOTAN_TLS_ALERT_H__ +#define BOTAN_TLS_ALERT_H__ + +#include <botan/secmem.h> +#include <string> + +namespace Botan { + +namespace TLS { + +/** +* SSL/TLS Alert Message +*/ +class BOTAN_DLL Alert + { + public: + enum Type { + CLOSE_NOTIFY = 0, + UNEXPECTED_MESSAGE = 10, + BAD_RECORD_MAC = 20, + DECRYPTION_FAILED = 21, + RECORD_OVERFLOW = 22, + DECOMPRESSION_FAILURE = 30, + HANDSHAKE_FAILURE = 40, + NO_CERTIFICATE = 41, // SSLv3 only + BAD_CERTIFICATE = 42, + UNSUPPORTED_CERTIFICATE = 43, + CERTIFICATE_REVOKED = 44, + CERTIFICATE_EXPIRED = 45, + CERTIFICATE_UNKNOWN = 46, + ILLEGAL_PARAMETER = 47, + UNKNOWN_CA = 48, + ACCESS_DENIED = 49, + DECODE_ERROR = 50, + DECRYPT_ERROR = 51, + EXPORT_RESTRICTION = 60, + PROTOCOL_VERSION = 70, + INSUFFICIENT_SECURITY = 71, + INTERNAL_ERROR = 80, + USER_CANCELED = 90, + NO_RENEGOTIATION = 100, + UNSUPPORTED_EXTENSION = 110, + CERTIFICATE_UNOBTAINABLE = 111, + UNRECOGNIZED_NAME = 112, + BAD_CERTIFICATE_STATUS_RESPONSE = 113, + BAD_CERTIFICATE_HASH_VALUE = 114, + UNKNOWN_PSK_IDENTITY = 115, + + NULL_ALERT = 255, + + HEARTBEAT_PAYLOAD = 256 + }; + + /** + * @return true iff this alert is non-empty + */ + bool is_valid() const { return (type_code != NULL_ALERT); } + + /** + * @return if this alert is a fatal one or not + */ + bool is_fatal() const { return fatal; } + + /** + * @return type of alert + */ + Type type() const { return type_code; } + + /** + * @return type of alert + */ + std::string type_string() const; + + /** + * Deserialize an Alert message + * @param buf the serialized alert + */ + Alert(const std::vector<byte>& buf); + + Alert(Type alert_type, bool is_fatal = false) : + fatal(is_fatal), type_code(alert_type) {} + + Alert() : fatal(false), type_code(NULL_ALERT) {} + private: + bool fatal; + Type type_code; + }; + +} + +} + +#endif diff --git a/src/tls/tls_channel.cpp b/src/tls/tls_channel.cpp new file mode 100644 index 000000000..dadf26e90 --- /dev/null +++ b/src/tls/tls_channel.cpp @@ -0,0 +1,326 @@ +/* +* TLS Channels +* (C) 2011-2012 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#include <botan/tls_channel.h> +#include <botan/internal/tls_handshake_state.h> +#include <botan/internal/tls_messages.h> +#include <botan/internal/tls_heartbeats.h> +#include <botan/internal/assert.h> +#include <botan/loadstor.h> + +namespace Botan { + +namespace TLS { + +Channel::Channel(std::function<void (const byte[], size_t)> socket_output_fn, + std::function<void (const byte[], size_t, Alert)> proc_fn, + std::function<bool (const Session&)> handshake_complete) : + proc_fn(proc_fn), + handshake_fn(handshake_complete), + writer(socket_output_fn), + state(nullptr), + handshake_completed(false), + connection_closed(false), + m_peer_supports_heartbeats(false), + m_heartbeat_sending_allowed(false) + { + } + +Channel::~Channel() + { + delete state; + state = nullptr; + } + +size_t Channel::received_data(const byte buf[], size_t buf_size) + { + try + { + while(buf_size) + { + byte rec_type = CONNECTION_CLOSED; + std::vector<byte> record; + size_t consumed = 0; + + const size_t needed = reader.add_input(buf, buf_size, + consumed, + rec_type, record); + + buf += consumed; + buf_size -= consumed; + + BOTAN_ASSERT(buf_size == 0 || needed == 0, + "Got a full record or consumed all input"); + + if(buf_size == 0 && needed != 0) + return needed; // need more data to complete record + + if(rec_type == HANDSHAKE || rec_type == CHANGE_CIPHER_SPEC) + { + read_handshake(rec_type, record); + } + else if(rec_type == HEARTBEAT && m_peer_supports_heartbeats) + { + Heartbeat_Message heartbeat(record); + + const std::vector<byte>& payload = heartbeat.payload(); + + if(heartbeat.is_request() && !state) + { + Heartbeat_Message response(Heartbeat_Message::RESPONSE, + &payload[0], payload.size()); + + writer.send(HEARTBEAT, response.contents()); + } + else + { + // pass up to the application + proc_fn(&payload[0], payload.size(), Alert(Alert::HEARTBEAT_PAYLOAD)); + } + } + else if(rec_type == APPLICATION_DATA) + { + if(handshake_completed) + { + /* + * OpenSSL among others sends empty records in versions + * before TLS v1.1 in order to randomize the IV of the + * following record. Avoid spurious callbacks. + */ + if(record.size() > 0) + proc_fn(&record[0], record.size(), Alert()); + } + else + { + throw Unexpected_Message("Application data before handshake done"); + } + } + else if(rec_type == ALERT) + { + Alert alert_msg(record); + + alert_notify(alert_msg); + + proc_fn(nullptr, 0, alert_msg); + + if(alert_msg.type() == Alert::CLOSE_NOTIFY) + { + if(connection_closed) + reader.reset(); + else + send_alert(Alert(Alert::CLOSE_NOTIFY)); // reply in kind + } + else if(alert_msg.is_fatal()) + { + // delete state immediately + connection_closed = true; + + delete state; + state = nullptr; + + writer.reset(); + reader.reset(); + } + } + else + throw Unexpected_Message("Unknown TLS message type " + + std::to_string(rec_type) + " received"); + } + + return 0; // on a record boundary + } + catch(TLS_Exception& e) + { + send_alert(Alert(e.type(), true)); + throw; + } + catch(Decoding_Error& e) + { + send_alert(Alert(Alert::DECODE_ERROR, true)); + throw; + } + catch(Internal_Error& e) + { + send_alert(Alert(Alert::INTERNAL_ERROR, true)); + throw; + } + catch(std::exception& e) + { + send_alert(Alert(Alert::INTERNAL_ERROR, true)); + throw; + } + } + +/* +* Split up and process handshake messages +*/ +void Channel::read_handshake(byte rec_type, + const std::vector<byte>& rec_buf) + { + if(rec_type == HANDSHAKE) + { + if(!state) + state = new Handshake_State(new Stream_Handshake_Reader); + state->handshake_reader()->add_input(&rec_buf[0], rec_buf.size()); + } + + BOTAN_ASSERT(state, "Handshake message recieved without state in place"); + + while(true) + { + Handshake_Type type = HANDSHAKE_NONE; + + if(rec_type == HANDSHAKE) + { + if(state->handshake_reader()->have_full_record()) + { + std::pair<Handshake_Type, std::vector<byte> > msg = + state->handshake_reader()->get_next_record(); + process_handshake_msg(msg.first, msg.second); + } + else + break; + } + else if(rec_type == CHANGE_CIPHER_SPEC) + { + if(state->handshake_reader()->empty() && rec_buf.size() == 1 && rec_buf[0] == 1) + process_handshake_msg(HANDSHAKE_CCS, std::vector<byte>()); + else + throw Decoding_Error("Malformed ChangeCipherSpec message"); + } + else + throw Decoding_Error("Unknown message type in handshake processing"); + + if(type == HANDSHAKE_CCS || !state || !state->handshake_reader()->have_full_record()) + break; + } + } + +void Channel::heartbeat(const byte payload[], size_t payload_size) + { + if(!is_active()) + throw std::runtime_error("Heartbeat cannot be sent on inactive TLS connection"); + + if(m_heartbeat_sending_allowed) + { + Heartbeat_Message heartbeat(Heartbeat_Message::REQUEST, + payload, payload_size); + + writer.send(HEARTBEAT, heartbeat.contents()); + } + } + +void Channel::send(const byte buf[], size_t buf_size) + { + if(!is_active()) + throw std::runtime_error("Data cannot be sent on inactive TLS connection"); + + writer.send(APPLICATION_DATA, buf, buf_size); + } + +void Channel::send_alert(const Alert& alert) + { + if(alert.is_valid() && !connection_closed) + { + try + { + writer.send_alert(alert); + } + catch(...) { /* swallow it */ } + } + + if(!connection_closed && (alert.type() == Alert::CLOSE_NOTIFY || alert.is_fatal())) + { + connection_closed = true; + + delete state; + state = nullptr; + + writer.reset(); + } + } + +void Channel::Secure_Renegotiation_State::update(Client_Hello* client_hello) + { + if(initial_handshake) + { + secure_renegotiation = client_hello->secure_renegotiation(); + } + else + { + if(secure_renegotiation != client_hello->secure_renegotiation()) + throw TLS_Exception(Alert::HANDSHAKE_FAILURE, + "Client changed its mind about secure renegotiation"); + } + + if(client_hello->secure_renegotiation()) + { + const std::vector<byte>& data = client_hello->renegotiation_info(); + + if(initial_handshake) + { + if(!data.empty()) + throw TLS_Exception(Alert::HANDSHAKE_FAILURE, + "Client sent renegotiation data on initial handshake"); + } + else + { + if(data != for_client_hello()) + throw TLS_Exception(Alert::HANDSHAKE_FAILURE, + "Client sent bad renegotiation data"); + } + } + } + +void Channel::Secure_Renegotiation_State::update(Server_Hello* server_hello) + { + if(initial_handshake) + { + /* If the client offered but server rejected, then this toggles + * secure_renegotiation to off + */ + secure_renegotiation = server_hello->secure_renegotiation(); + } + else + { + if(secure_renegotiation != server_hello->secure_renegotiation()) + throw TLS_Exception(Alert::HANDSHAKE_FAILURE, + "Server changed its mind about secure renegotiation"); + } + + if(secure_renegotiation) + { + const std::vector<byte>& data = server_hello->renegotiation_info(); + + if(initial_handshake) + { + if(!data.empty()) + throw TLS_Exception(Alert::HANDSHAKE_FAILURE, + "Server sent renegotiation data on initial handshake"); + } + else + { + if(data != for_server_hello()) + throw TLS_Exception(Alert::HANDSHAKE_FAILURE, + "Server sent bad renegotiation data"); + } + } + + initial_handshake = false; + } + +void Channel::Secure_Renegotiation_State::update(Finished* client_finished, + Finished* server_finished) + { + client_verify = client_finished->verify_data(); + server_verify = server_finished->verify_data(); + } + +} + +} + diff --git a/src/tls/tls_channel.h b/src/tls/tls_channel.h new file mode 100644 index 000000000..fc0595064 --- /dev/null +++ b/src/tls/tls_channel.h @@ -0,0 +1,155 @@ +/* +* TLS Channel +* (C) 2011 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#ifndef BOTAN_TLS_CHANNEL_H__ +#define BOTAN_TLS_CHANNEL_H__ + +#include <botan/tls_policy.h> +#include <botan/tls_record.h> +#include <botan/tls_session.h> +#include <botan/tls_alert.h> +#include <botan/x509cert.h> +#include <vector> + +namespace Botan { + +namespace TLS { + +/** +* Generic interface for TLS endpoint +*/ +class BOTAN_DLL Channel + { + public: + /** + * Inject TLS traffic received from counterparty + * @return a hint as the how many more bytes we need to process the + * current record (this may be 0 if on a record boundary) + */ + virtual size_t received_data(const byte buf[], size_t buf_size); + + /** + * Inject plaintext intended for counterparty + */ + virtual void send(const byte buf[], size_t buf_size); + + /** + * Send a close notification alert + */ + void close() { send_alert(Alert(Alert::CLOSE_NOTIFY)); } + + /** + * @return true iff the connection is active for sending application data + */ + bool is_active() const { return handshake_completed && !is_closed(); } + + /** + * @return true iff the connection has been definitely closed + */ + bool is_closed() const { return connection_closed; } + + /** + * Attempt to renegotiate the session + * @param force_full_renegotiation if true, require a full renegotiation, + * otherwise allow session resumption + */ + virtual void renegotiate(bool force_full_renegotiation) = 0; + + /** + * Attempt to send a heartbeat message (if negotiated with counterparty) + * @param payload will be echoed back + * @param countents_size size of payload in bytes + */ + void heartbeat(const byte payload[], size_t payload_size); + + /** + * Attempt to send a heartbeat message (if negotiated with counterparty) + */ + void heartbeat() { heartbeat(nullptr, 0); } + + /** + * @return certificate chain of the peer (may be empty) + */ + std::vector<X509_Certificate> peer_cert_chain() const { return peer_certs; } + + Channel(std::function<void (const byte[], size_t)> socket_output_fn, + std::function<void (const byte[], size_t, Alert)> proc_fn, + std::function<bool (const Session&)> handshake_complete); + + virtual ~Channel(); + protected: + + /** + * Send a TLS alert message. If the alert is fatal, the + * internal state (keys, etc) will be reset + * @param level is warning or fatal + * @param type is the type of alert + */ + void send_alert(const Alert& alert); + + virtual void read_handshake(byte rec_type, + const std::vector<byte>& rec_buf); + + virtual void process_handshake_msg(Handshake_Type type, + const std::vector<byte>& contents) = 0; + + virtual void alert_notify(const Alert& alert) = 0; + + std::function<void (const byte[], size_t, Alert)> proc_fn; + std::function<bool (const Session&)> handshake_fn; + + Record_Writer writer; + Record_Reader reader; + + std::vector<X509_Certificate> peer_certs; + + class Handshake_State* state; + + class Secure_Renegotiation_State + { + public: + Secure_Renegotiation_State() : initial_handshake(true), + secure_renegotiation(false) + {} + + void update(class Client_Hello* client_hello); + void update(class Server_Hello* server_hello); + + void update(class Finished* client_finished, + class Finished* server_finished); + + const std::vector<byte>& for_client_hello() const + { return client_verify; } + + std::vector<byte> for_server_hello() const + { + std::vector<byte> buf = client_verify; + buf += server_verify; + return buf; + } + + bool supported() const { return secure_renegotiation; } + bool renegotiation() const { return !initial_handshake; } + private: + bool initial_handshake; + bool secure_renegotiation; + std::vector<byte> client_verify, server_verify; + }; + + Secure_Renegotiation_State secure_renegotiation; + + bool handshake_completed; + bool connection_closed; + bool m_peer_supports_heartbeats; + bool m_heartbeat_sending_allowed; + }; + +} + +} + +#endif diff --git a/src/tls/tls_ciphersuite.cpp b/src/tls/tls_ciphersuite.cpp new file mode 100644 index 000000000..e3bda06e4 --- /dev/null +++ b/src/tls/tls_ciphersuite.cpp @@ -0,0 +1,104 @@ +/* +* TLS Cipher Suite +* (C) 2004-2010,2012 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#include <botan/tls_ciphersuite.h> +#include <botan/parsing.h> +#include <sstream> +#include <stdexcept> + +namespace Botan { + +namespace TLS { + +Ciphersuite Ciphersuite::by_name(const std::string& name) + { + for(size_t i = 0; i != 65536; ++i) + { + Ciphersuite suite = Ciphersuite::by_id(i); + + if(!suite.valid()) + continue; // not a ciphersuite we know, skip + + if(suite.to_string() == name) + return suite; + } + + return Ciphersuite(); // some unknown ciphersuite + } + +bool Ciphersuite::psk_ciphersuite() const + { + return (kex_algo() == "PSK" || + kex_algo() == "DHE_PSK" || + kex_algo() == "ECDHE_PSK"); + } + +bool Ciphersuite::ecc_ciphersuite() const + { + return (kex_algo() == "ECDH" || sig_algo() == "ECDSA"); + } + +std::string Ciphersuite::to_string() const + { + if(m_cipher_keylen == 0) + throw std::runtime_error("Ciphersuite::to_string - no value set"); + + std::ostringstream out; + + out << "TLS_"; + + if(kex_algo() != "RSA") + { + if(kex_algo() == "DH") + out << "DHE"; + else if(kex_algo() == "ECDH") + out << "ECDHE"; + else + out << kex_algo(); + + out << '_'; + } + + if(sig_algo() == "DSA") + out << "DSS_"; + else if(sig_algo() != "") + out << sig_algo() << '_'; + + out << "WITH_"; + + if(cipher_algo() == "ARC4") + { + out << "RC4_128_"; + } + else + { + if(cipher_algo() == "3DES") + out << "3DES_EDE"; + else if(cipher_algo() == "Camellia") + out << "CAMELLIA_" << std::to_string(8*cipher_keylen()); + else + out << replace_char(cipher_algo(), '-', '_'); + + out << "_CBC_"; + } + + if(mac_algo() == "SHA-1") + out << "SHA"; + else if(mac_algo() == "SHA-256") + out << "SHA256"; + else if(mac_algo() == "SHA-384") + out << "SHA384"; + else + out << mac_algo(); + + return out.str(); + } + +} + +} + diff --git a/src/tls/tls_ciphersuite.h b/src/tls/tls_ciphersuite.h new file mode 100644 index 000000000..dcb4b6a6f --- /dev/null +++ b/src/tls/tls_ciphersuite.h @@ -0,0 +1,73 @@ +/* +* TLS Cipher Suites +* (C) 2004-2011 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#ifndef BOTAN_TLS_CIPHER_SUITES_H__ +#define BOTAN_TLS_CIPHER_SUITES_H__ + +#include <botan/types.h> +#include <string> + +namespace Botan { + +namespace TLS { + +/** +* Ciphersuite Information +*/ +class BOTAN_DLL Ciphersuite + { + public: + /** + * Convert an SSL/TLS ciphersuite to algorithm fields + */ + static Ciphersuite by_id(u16bit suite); + + static Ciphersuite by_name(const std::string& name); + + /** + * Formats the ciphersuite back to an RFC-style ciphersuite string + */ + std::string to_string() const; + + bool psk_ciphersuite() const; + bool ecc_ciphersuite() const; + + std::string kex_algo() const { return m_kex_algo; } + std::string sig_algo() const { return m_sig_algo; } + + std::string cipher_algo() const { return m_cipher_algo; } + std::string mac_algo() const { return m_mac_algo; } + + size_t cipher_keylen() const { return m_cipher_keylen; } + + bool valid() const { return (m_cipher_keylen > 0); } + + Ciphersuite() : m_cipher_keylen(0) {} + + Ciphersuite(const std::string& sig_algo, + const std::string& kex_algo, + const std::string& mac_algo, + const std::string& cipher_algo, + size_t cipher_algo_keylen) : + m_sig_algo(sig_algo), + m_kex_algo(kex_algo), + m_mac_algo(mac_algo), + m_cipher_algo(cipher_algo), + m_cipher_keylen(cipher_algo_keylen) + { + } + + private: + std::string m_sig_algo, m_kex_algo, m_mac_algo, m_cipher_algo; + size_t m_cipher_keylen; + }; + +} + +} + +#endif diff --git a/src/tls/tls_client.cpp b/src/tls/tls_client.cpp new file mode 100644 index 000000000..1ca256f3e --- /dev/null +++ b/src/tls/tls_client.cpp @@ -0,0 +1,486 @@ +/* +* TLS Client +* (C) 2004-2011 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#include <botan/tls_client.h> +#include <botan/internal/tls_handshake_state.h> +#include <botan/internal/tls_messages.h> +#include <botan/internal/stl_util.h> +#include <memory> + +namespace Botan { + +namespace TLS { + +/* +* TLS Client Constructor +*/ +Client::Client(std::function<void (const byte[], size_t)> output_fn, + std::function<void (const byte[], size_t, Alert)> proc_fn, + std::function<bool (const Session&)> handshake_fn, + Session_Manager& session_manager, + Credentials_Manager& creds, + const Policy& policy, + RandomNumberGenerator& rng, + const std::string& hostname, + std::function<std::string (std::vector<std::string>)> next_protocol) : + Channel(output_fn, proc_fn, handshake_fn), + policy(policy), + rng(rng), + session_manager(session_manager), + creds(creds), + m_hostname(hostname) + { + writer.set_version(Protocol_Version::SSL_V3); + + state = new Handshake_State(new Stream_Handshake_Reader); + state->set_expected_next(SERVER_HELLO); + + state->client_npn_cb = next_protocol; + + const std::string srp_identifier = creds.srp_identifier("tls-client", hostname); + + const bool send_npn_request = static_cast<bool>(next_protocol); + + if(hostname != "") + { + Session session_info; + if(session_manager.load_from_host_info(hostname, 0, session_info)) + { + if(session_info.srp_identifier() == srp_identifier) + { + state->client_hello = new Client_Hello( + writer, + state->hash, + policy, + rng, + secure_renegotiation.for_client_hello(), + session_info, + send_npn_request); + + state->resume_master_secret = session_info.master_secret(); + } + } + } + + if(!state->client_hello) // not resuming + { + state->client_hello = new Client_Hello( + writer, + state->hash, + policy, + rng, + secure_renegotiation.for_client_hello(), + send_npn_request, + hostname, + srp_identifier); + } + + secure_renegotiation.update(state->client_hello); + } + +/* +* Send a new client hello to renegotiate +*/ +void Client::renegotiate(bool force_full_renegotiation) + { + if(state && state->client_hello) + return; // currently in active handshake + + delete state; + state = new Handshake_State(new Stream_Handshake_Reader); + + state->set_expected_next(SERVER_HELLO); + + if(!force_full_renegotiation) + { + Session session_info; + if(session_manager.load_from_host_info(m_hostname, 0, session_info)) + { + state->client_hello = new Client_Hello( + writer, + state->hash, + policy, + rng, + secure_renegotiation.for_client_hello(), + session_info); + + state->resume_master_secret = session_info.master_secret(); + } + } + + if(!state->client_hello) + { + state->client_hello = new Client_Hello( + writer, + state->hash, + policy, + rng, + secure_renegotiation.for_client_hello()); + } + + secure_renegotiation.update(state->client_hello); + } + +void Client::alert_notify(const Alert& alert) + { + if(alert.type() == Alert::NO_RENEGOTIATION) + { + if(handshake_completed && state) + { + delete state; + state = nullptr; + } + } + } + +/* +* Process a handshake message +*/ +void Client::process_handshake_msg(Handshake_Type type, + const std::vector<byte>& contents) + { + if(!state) + throw Unexpected_Message("Unexpected handshake message from server"); + + if(type == HELLO_REQUEST) + { + Hello_Request hello_request(contents); + + // Ignore request entirely if we are currently negotiating a handshake + if(state->client_hello) + return; + + if(!secure_renegotiation.supported() && policy.require_secure_renegotiation()) + { + delete state; + state = nullptr; + + // RFC 5746 section 4.2 + send_alert(Alert(Alert::NO_RENEGOTIATION)); + return; + } + + renegotiate(false); + + return; + } + + state->confirm_transition_to(type); + + if(type != HANDSHAKE_CCS && type != FINISHED) + state->hash.update(type, contents); + + if(type == SERVER_HELLO) + { + state->server_hello = new Server_Hello(contents); + + if(!state->client_hello->offered_suite(state->server_hello->ciphersuite())) + { + throw TLS_Exception(Alert::HANDSHAKE_FAILURE, + "Server replied with ciphersuite we didn't send"); + } + + if(!value_exists(state->client_hello->compression_methods(), + state->server_hello->compression_method())) + { + throw TLS_Exception(Alert::HANDSHAKE_FAILURE, + "Server replied with compression method we didn't send"); + } + + if(!state->client_hello->next_protocol_notification() && + state->server_hello->next_protocol_notification()) + { + throw TLS_Exception(Alert::HANDSHAKE_FAILURE, + "Server sent next protocol but we didn't request it"); + } + + if(state->server_hello->supports_session_ticket()) + { + if(!state->client_hello->supports_session_ticket()) + throw TLS_Exception(Alert::HANDSHAKE_FAILURE, + "Server sent session ticket extension but we did not"); + } + + state->set_version(state->server_hello->version()); + + writer.set_version(state->version()); + reader.set_version(state->version()); + + secure_renegotiation.update(state->server_hello); + + m_peer_supports_heartbeats = state->server_hello->supports_heartbeats(); + m_heartbeat_sending_allowed = state->server_hello->peer_can_send_heartbeats(); + + state->suite = Ciphersuite::by_id(state->server_hello->ciphersuite()); + + const bool server_returned_same_session_id = + !state->server_hello->session_id().empty() && + (state->server_hello->session_id() == state->client_hello->session_id()); + + if(server_returned_same_session_id) + { + // successful resumption + + /* + * In this case, we offered the version used in the original + * session, and the server must resume with the same version. + */ + if(state->server_hello->version() != state->client_hello->version()) + throw TLS_Exception(Alert::HANDSHAKE_FAILURE, + "Server resumed session but with wrong version"); + + state->keys = Session_Keys(state, + state->resume_master_secret, + true); + + if(state->server_hello->supports_session_ticket()) + state->set_expected_next(NEW_SESSION_TICKET); + else + state->set_expected_next(HANDSHAKE_CCS); + } + else + { + // new session + + if(state->version() > state->client_hello->version()) + { + throw TLS_Exception(Alert::HANDSHAKE_FAILURE, + "Client: Server replied with bad version"); + } + + if(state->version() < policy.min_version()) + { + throw TLS_Exception(Alert::PROTOCOL_VERSION, + "Client: Server is too old for specified policy"); + } + + if(state->suite.sig_algo() != "") + { + state->set_expected_next(CERTIFICATE); + } + else if(state->suite.kex_algo() == "PSK") + { + /* PSK is anonymous so no certificate/cert req message is + ever sent. The server may or may not send a server kex, + depending on if it has an identity hint for us. + + (EC)DHE_PSK always sends a server key exchange for the + DH exchange portion. + */ + + state->set_expected_next(SERVER_KEX); + state->set_expected_next(SERVER_HELLO_DONE); + } + else if(state->suite.kex_algo() != "RSA") + { + state->set_expected_next(SERVER_KEX); + } + else + { + state->set_expected_next(CERTIFICATE_REQUEST); // optional + state->set_expected_next(SERVER_HELLO_DONE); + } + } + } + else if(type == CERTIFICATE) + { + if(state->suite.kex_algo() != "RSA") + { + state->set_expected_next(SERVER_KEX); + } + else + { + state->set_expected_next(CERTIFICATE_REQUEST); // optional + state->set_expected_next(SERVER_HELLO_DONE); + } + + state->server_certs = new Certificate(contents); + + peer_certs = state->server_certs->cert_chain(); + if(peer_certs.size() == 0) + throw TLS_Exception(Alert::HANDSHAKE_FAILURE, + "Client: No certificates sent by server"); + + try + { + creds.verify_certificate_chain("tls-client", m_hostname, peer_certs); + } + catch(std::exception& e) + { + throw TLS_Exception(Alert::BAD_CERTIFICATE, e.what()); + } + + std::unique_ptr<Public_Key> peer_key(peer_certs[0].subject_public_key()); + + if(peer_key->algo_name() != state->suite.sig_algo()) + throw TLS_Exception(Alert::ILLEGAL_PARAMETER, + "Certificate key type did not match ciphersuite"); + } + else if(type == SERVER_KEX) + { + state->set_expected_next(CERTIFICATE_REQUEST); // optional + state->set_expected_next(SERVER_HELLO_DONE); + + state->server_kex = new Server_Key_Exchange(contents, + state->suite.kex_algo(), + state->suite.sig_algo(), + state->version()); + + if(state->suite.sig_algo() != "") + { + if(!state->server_kex->verify(peer_certs[0], state)) + { + throw TLS_Exception(Alert::DECRYPT_ERROR, + "Bad signature on server key exchange"); + } + } + } + else if(type == CERTIFICATE_REQUEST) + { + state->set_expected_next(SERVER_HELLO_DONE); + state->cert_req = new Certificate_Req(contents, state->version()); + } + else if(type == SERVER_HELLO_DONE) + { + state->server_hello_done = new Server_Hello_Done(contents); + + if(state->received_handshake_msg(CERTIFICATE_REQUEST)) + { + const std::vector<std::string>& types = + state->cert_req->acceptable_cert_types(); + + std::vector<X509_Certificate> client_certs = + creds.cert_chain(types, + "tls-client", + m_hostname); + + state->client_certs = new Certificate(writer, + state->hash, + client_certs); + } + + state->client_kex = + new Client_Key_Exchange(writer, + state, + creds, + peer_certs, + m_hostname, + rng); + + state->keys = Session_Keys(state, + state->client_kex->pre_master_secret(), + false); + + if(state->received_handshake_msg(CERTIFICATE_REQUEST) && + !state->client_certs->empty()) + { + Private_Key* private_key = + creds.private_key_for(state->client_certs->cert_chain()[0], + "tls-client", + m_hostname); + + state->client_verify = new Certificate_Verify(writer, + state, + rng, + private_key); + } + + writer.send(CHANGE_CIPHER_SPEC, 1); + + writer.activate(CLIENT, state->suite, state->keys, + state->server_hello->compression_method()); + + if(state->server_hello->next_protocol_notification()) + { + const std::string protocol = + state->client_npn_cb(state->server_hello->next_protocols()); + + state->next_protocol = new Next_Protocol(writer, state->hash, protocol); + } + + state->client_finished = new Finished(writer, state, CLIENT); + + if(state->server_hello->supports_session_ticket()) + state->set_expected_next(NEW_SESSION_TICKET); + else + state->set_expected_next(HANDSHAKE_CCS); + } + else if(type == NEW_SESSION_TICKET) + { + state->new_session_ticket = new New_Session_Ticket(contents); + + state->set_expected_next(HANDSHAKE_CCS); + } + else if(type == HANDSHAKE_CCS) + { + state->set_expected_next(FINISHED); + + reader.activate(CLIENT, state->suite, state->keys, + state->server_hello->compression_method()); + } + else if(type == FINISHED) + { + state->set_expected_next(HELLO_REQUEST); + + state->server_finished = new Finished(contents); + + if(!state->server_finished->verify(state, SERVER)) + throw TLS_Exception(Alert::DECRYPT_ERROR, + "Finished message didn't verify"); + + state->hash.update(type, contents); + + if(!state->client_finished) // session resume case + { + writer.send(CHANGE_CIPHER_SPEC, 1); + + writer.activate(CLIENT, state->suite, state->keys, + state->server_hello->compression_method()); + + state->client_finished = new Finished(writer, state, CLIENT); + } + + secure_renegotiation.update(state->client_finished, state->server_finished); + + std::vector<byte> session_id = state->server_hello->session_id(); + + const std::vector<byte>& session_ticket = state->session_ticket(); + + if(session_id.empty() && !session_ticket.empty()) + session_id = make_hello_random(rng); + + Session session_info( + session_id, + state->keys.master_secret(), + state->server_hello->version(), + state->server_hello->ciphersuite(), + state->server_hello->compression_method(), + CLIENT, + secure_renegotiation.supported(), + state->server_hello->fragment_size(), + peer_certs, + session_ticket, + m_hostname, + "" + ); + + if(handshake_fn(session_info)) + session_manager.save(session_info); + else + session_manager.remove_entry(session_info.session_id()); + + delete state; + state = nullptr; + handshake_completed = true; + } + else + throw Unexpected_Message("Unknown handshake message received"); + } + +} + +} diff --git a/src/tls/tls_client.h b/src/tls/tls_client.h new file mode 100644 index 000000000..2844780bd --- /dev/null +++ b/src/tls/tls_client.h @@ -0,0 +1,74 @@ +/* +* TLS Client +* (C) 2004-2011 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#ifndef BOTAN_TLS_CLIENT_H__ +#define BOTAN_TLS_CLIENT_H__ + +#include <botan/tls_channel.h> +#include <botan/tls_session_manager.h> +#include <botan/credentials_manager.h> +#include <vector> + +namespace Botan { + +namespace TLS { + +/** +* SSL/TLS Client +*/ +class BOTAN_DLL Client : public Channel + { + public: + /** + * Set up a new TLS client session + * @param socket_output_fn is called with data for the outbound socket + * @param proc_fn is called when new data (application or alerts) is received + * @param handshake_complete is called when a handshake is completed + * @param session_manager manages session state + * @param creds manages application/user credentials + * @param policy specifies other connection policy information + * @param rng a random number generator + * @param servername the server's DNS name, if known + * @param next_protocol allows the client to specify what the next + * protocol will be. For more information read + * http://technotes.googlecode.com/git/nextprotoneg.html. + * + * If the function is not empty, NPN will be negotiated + * and if the server supports NPN the function will be + * called with the list of protocols the server advertised; + * the client should return the protocol it would like to use. + */ + Client(std::function<void (const byte[], size_t)> socket_output_fn, + std::function<void (const byte[], size_t, Alert)> proc_fn, + std::function<bool (const Session&)> handshake_complete, + Session_Manager& session_manager, + Credentials_Manager& creds, + const Policy& policy, + RandomNumberGenerator& rng, + const std::string& servername = "", + std::function<std::string (std::vector<std::string>)> next_protocol = + std::function<std::string (std::vector<std::string>)>()); + + void renegotiate(bool force_full_renegotiation); + private: + void process_handshake_msg(Handshake_Type type, + const std::vector<byte>& contents) override; + + void alert_notify(const Alert& alert); + + const Policy& policy; + RandomNumberGenerator& rng; + Session_Manager& session_manager; + Credentials_Manager& creds; + const std::string m_hostname; + }; + +} + +} + +#endif diff --git a/src/ssl/tls_exceptn.h b/src/tls/tls_exceptn.h index 37b9c0d27..ad19c6c9d 100644 --- a/src/ssl/tls_exceptn.h +++ b/src/tls/tls_exceptn.h @@ -9,24 +9,26 @@ #define BOTAN_TLS_EXCEPTION_H__ #include <botan/exceptn.h> -#include <botan/tls_magic.h> +#include <botan/tls_alert.h> namespace Botan { +namespace TLS { + /** * Exception Base Class */ class BOTAN_DLL TLS_Exception : public Exception { public: - Alert_Type type() const throw() { return alert_type; } + Alert::Type type() const throw() { return alert_type; } - TLS_Exception(Alert_Type type, + TLS_Exception(Alert::Type type, const std::string& err_msg = "Unknown error") : Exception(err_msg), alert_type(type) {} private: - Alert_Type alert_type; + Alert::Type alert_type; }; /** @@ -35,9 +37,11 @@ class BOTAN_DLL TLS_Exception : public Exception struct BOTAN_DLL Unexpected_Message : public TLS_Exception { Unexpected_Message(const std::string& err) : - TLS_Exception(UNEXPECTED_MESSAGE, err) {} + TLS_Exception(Alert::UNEXPECTED_MESSAGE, err) {} }; } +} + #endif diff --git a/src/tls/tls_extensions.cpp b/src/tls/tls_extensions.cpp new file mode 100644 index 000000000..df25c40a5 --- /dev/null +++ b/src/tls/tls_extensions.cpp @@ -0,0 +1,524 @@ +/* +* TLS Extensions +* (C) 2011,2012 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#include <botan/internal/tls_extensions.h> +#include <botan/internal/tls_reader.h> +#include <botan/tls_exceptn.h> + +namespace Botan { + +namespace TLS { + +namespace { + +Extension* make_extension(TLS_Data_Reader& reader, + u16bit code, + u16bit size) + { + switch(code) + { + case TLSEXT_SERVER_NAME_INDICATION: + return new Server_Name_Indicator(reader, size); + + case TLSEXT_MAX_FRAGMENT_LENGTH: + return new Maximum_Fragment_Length(reader, size); + + case TLSEXT_SRP_IDENTIFIER: + return new SRP_Identifier(reader, size); + + case TLSEXT_USABLE_ELLIPTIC_CURVES: + return new Supported_Elliptic_Curves(reader, size); + + case TLSEXT_SAFE_RENEGOTIATION: + return new Renegotation_Extension(reader, size); + + case TLSEXT_SIGNATURE_ALGORITHMS: + return new Signature_Algorithms(reader, size); + + case TLSEXT_NEXT_PROTOCOL: + return new Next_Protocol_Notification(reader, size); + + case TLSEXT_HEARTBEAT_SUPPORT: + return new Heartbeat_Support_Indicator(reader, size); + + case TLSEXT_SESSION_TICKET: + return new Session_Ticket(reader, size); + + default: + return nullptr; // not known + } + } + +} + +Extensions::Extensions(TLS_Data_Reader& reader) + { + if(reader.has_remaining()) + { + const u16bit all_extn_size = reader.get_u16bit(); + + if(reader.remaining_bytes() != all_extn_size) + throw Decoding_Error("Bad extension size"); + + while(reader.has_remaining()) + { + const u16bit extension_code = reader.get_u16bit(); + const u16bit extension_size = reader.get_u16bit(); + + Extension* extn = make_extension(reader, + extension_code, + extension_size); + + if(extn) + this->add(extn); + else // unknown/unhandled extension + reader.discard_next(extension_size); + } + } + } + +std::vector<byte> Extensions::serialize() const + { + std::vector<byte> buf(2); // 2 bytes for length field + + for(std::map<Handshake_Extension_Type, Extension*>::const_iterator i = extensions.begin(); + i != extensions.end(); ++i) + { + if(i->second->empty()) + continue; + + const u16bit extn_code = i->second->type(); + + std::vector<byte> extn_val = i->second->serialize(); + + buf.push_back(get_byte(0, extn_code)); + buf.push_back(get_byte(1, extn_code)); + + buf.push_back(get_byte<u16bit>(0, extn_val.size())); + buf.push_back(get_byte<u16bit>(1, extn_val.size())); + + buf += extn_val; + } + + const u16bit extn_size = buf.size() - 2; + + buf[0] = get_byte(0, extn_size); + buf[1] = get_byte(1, extn_size); + + // avoid sending a completely empty extensions block + if(buf.size() == 2) + return std::vector<byte>(); + + return buf; + } + +Extensions::~Extensions() + { + for(std::map<Handshake_Extension_Type, Extension*>::const_iterator i = extensions.begin(); + i != extensions.end(); ++i) + { + delete i->second; + } + + extensions.clear(); + } + +Server_Name_Indicator::Server_Name_Indicator(TLS_Data_Reader& reader, + u16bit extension_size) + { + /* + * This is used by the server to confirm that it knew the name + */ + if(extension_size == 0) + return; + + u16bit name_bytes = reader.get_u16bit(); + + if(name_bytes + 2 != extension_size) + throw Decoding_Error("Bad encoding of SNI extension"); + + while(name_bytes) + { + byte name_type = reader.get_byte(); + name_bytes--; + + if(name_type == 0) // DNS + { + sni_host_name = reader.get_string(2, 1, 65535); + name_bytes -= (2 + sni_host_name.size()); + } + else // some other unknown name type + { + reader.discard_next(name_bytes); + name_bytes = 0; + } + } + } + +std::vector<byte> Server_Name_Indicator::serialize() const + { + std::vector<byte> buf; + + size_t name_len = sni_host_name.size(); + + buf.push_back(get_byte<u16bit>(0, name_len+3)); + buf.push_back(get_byte<u16bit>(1, name_len+3)); + buf.push_back(0); // DNS + + buf.push_back(get_byte<u16bit>(0, name_len)); + buf.push_back(get_byte<u16bit>(1, name_len)); + + buf += std::make_pair( + reinterpret_cast<const byte*>(sni_host_name.data()), + sni_host_name.size()); + + return buf; + } + +SRP_Identifier::SRP_Identifier(TLS_Data_Reader& reader, + u16bit extension_size) + { + srp_identifier = reader.get_string(1, 1, 255); + + if(srp_identifier.size() + 1 != extension_size) + throw Decoding_Error("Bad encoding for SRP identifier extension"); + } + +std::vector<byte> SRP_Identifier::serialize() const + { + std::vector<byte> buf; + + const byte* srp_bytes = + reinterpret_cast<const byte*>(srp_identifier.data()); + + append_tls_length_value(buf, srp_bytes, srp_identifier.size(), 1); + + return buf; + } + +Renegotation_Extension::Renegotation_Extension(TLS_Data_Reader& reader, + u16bit extension_size) + { + reneg_data = reader.get_range<byte>(1, 0, 255); + + if(reneg_data.size() + 1 != extension_size) + throw Decoding_Error("Bad encoding for secure renegotiation extn"); + } + +std::vector<byte> Renegotation_Extension::serialize() const + { + std::vector<byte> buf; + append_tls_length_value(buf, reneg_data, 1); + return buf; + } + +size_t Maximum_Fragment_Length::fragment_size() const + { + switch(val) + { + case 1: + return 512; + case 2: + return 1024; + case 3: + return 2048; + case 4: + return 4096; + default: + throw TLS_Exception(Alert::ILLEGAL_PARAMETER, + "Bad value in maximum fragment extension"); + } + } + +Maximum_Fragment_Length::Maximum_Fragment_Length(size_t max_fragment) + { + if(max_fragment == 512) + val = 1; + else if(max_fragment == 1024) + val = 2; + else if(max_fragment == 2048) + val = 3; + else if(max_fragment == 4096) + val = 4; + else + throw std::invalid_argument("Bad setting " + + std::to_string(max_fragment) + + " for maximum fragment size"); + } + +Maximum_Fragment_Length::Maximum_Fragment_Length(TLS_Data_Reader& reader, + u16bit extension_size) + { + if(extension_size != 1) + throw Decoding_Error("Bad size for maximum fragment extension"); + val = reader.get_byte(); + } + +Next_Protocol_Notification::Next_Protocol_Notification(TLS_Data_Reader& reader, + u16bit extension_size) + { + if(extension_size == 0) + return; // empty extension + + size_t bytes_remaining = extension_size; + + while(bytes_remaining) + { + const std::string p = reader.get_string(1, 0, 255); + + if(bytes_remaining < p.size() + 1) + throw Decoding_Error("Bad encoding for next protocol extension"); + + bytes_remaining -= (p.size() + 1); + + m_protocols.push_back(p); + } + } + +std::vector<byte> Next_Protocol_Notification::serialize() const + { + std::vector<byte> buf; + + for(size_t i = 0; i != m_protocols.size(); ++i) + { + const std::string p = m_protocols[i]; + + if(p != "") + append_tls_length_value(buf, + reinterpret_cast<const byte*>(p.data()), + p.size(), + 1); + } + + return buf; + } + +std::string Supported_Elliptic_Curves::curve_id_to_name(u16bit id) + { + switch(id) + { + case 15: + return "secp160k1"; + case 16: + return "secp160r1"; + case 17: + return "secp160r2"; + case 18: + return "secp192k1"; + case 19: + return "secp192r1"; + case 20: + return "secp224k1"; + case 21: + return "secp224r1"; + case 22: + return "secp256k1"; + case 23: + return "secp256r1"; + case 24: + return "secp384r1"; + case 25: + return "secp521r1"; + default: + return ""; // something we don't know or support + } + } + +u16bit Supported_Elliptic_Curves::name_to_curve_id(const std::string& name) + { + if(name == "secp160k1") + return 15; + if(name == "secp160r1") + return 16; + if(name == "secp160r2") + return 17; + if(name == "secp192k1") + return 18; + if(name == "secp192r1") + return 19; + if(name == "secp224k1") + return 20; + if(name == "secp224r1") + return 21; + if(name == "secp256k1") + return 22; + if(name == "secp256r1") + return 23; + if(name == "secp384r1") + return 24; + if(name == "secp521r1") + return 25; + + throw Invalid_Argument("name_to_curve_id unknown name " + name); + } + +std::vector<byte> Supported_Elliptic_Curves::serialize() const + { + std::vector<byte> buf(2); + + for(size_t i = 0; i != m_curves.size(); ++i) + { + const u16bit id = name_to_curve_id(m_curves[i]); + buf.push_back(get_byte(0, id)); + buf.push_back(get_byte(1, id)); + } + + buf[0] = get_byte<u16bit>(0, buf.size()-2); + buf[1] = get_byte<u16bit>(1, buf.size()-2); + + return buf; + } + +Supported_Elliptic_Curves::Supported_Elliptic_Curves(TLS_Data_Reader& reader, + u16bit extension_size) + { + u16bit len = reader.get_u16bit(); + + if(len + 2 != extension_size) + throw Decoding_Error("Inconsistent length field in elliptic curve list"); + + if(len % 2 == 1) + throw Decoding_Error("Elliptic curve list of strange size"); + + len /= 2; + + for(size_t i = 0; i != len; ++i) + { + const u16bit id = reader.get_u16bit(); + const std::string name = curve_id_to_name(id); + + if(name != "") + m_curves.push_back(name); + } + } + +std::string Signature_Algorithms::hash_algo_name(byte code) + { + switch(code) + { + // code 1 is MD5 - ignore it + + case 2: + return "SHA-1"; + case 3: + return "SHA-224"; + case 4: + return "SHA-256"; + case 5: + return "SHA-384"; + case 6: + return "SHA-512"; + default: + return ""; + } + } + +byte Signature_Algorithms::hash_algo_code(const std::string& name) + { + if(name == "SHA-1") + return 2; + + if(name == "SHA-224") + return 3; + + if(name == "SHA-256") + return 4; + + if(name == "SHA-384") + return 5; + + if(name == "SHA-512") + return 6; + + throw Internal_Error("Unknown hash ID " + name + " for signature_algorithms"); + } + +std::string Signature_Algorithms::sig_algo_name(byte code) + { + switch(code) + { + case 1: + return "RSA"; + case 2: + return "DSA"; + case 3: + return "ECDSA"; + default: + return ""; + } + } + +byte Signature_Algorithms::sig_algo_code(const std::string& name) + { + if(name == "RSA") + return 1; + + if(name == "DSA") + return 2; + + if(name == "ECDSA") + return 3; + + throw Internal_Error("Unknown sig ID " + name + " for signature_algorithms"); + } + +std::vector<byte> Signature_Algorithms::serialize() const + { + std::vector<byte> buf(2); + + for(size_t i = 0; i != m_supported_algos.size(); ++i) + { + try + { + const byte hash_code = hash_algo_code(m_supported_algos[i].first); + const byte sig_code = sig_algo_code(m_supported_algos[i].second); + + buf.push_back(hash_code); + buf.push_back(sig_code); + } + catch(...) + {} + } + + buf[0] = get_byte<u16bit>(0, buf.size()-2); + buf[1] = get_byte<u16bit>(1, buf.size()-2); + + return buf; + } + +Signature_Algorithms::Signature_Algorithms(TLS_Data_Reader& reader, + u16bit extension_size) + { + u16bit len = reader.get_u16bit(); + + if(len + 2 != extension_size) + throw Decoding_Error("Bad encoding on signature algorithms extension"); + + while(len) + { + const std::string hash_code = hash_algo_name(reader.get_byte()); + const std::string sig_code = sig_algo_name(reader.get_byte()); + + len -= 2; + + // If not something we know, ignore it completely + if(hash_code == "" || sig_code == "") + continue; + + m_supported_algos.push_back(std::make_pair(hash_code, sig_code)); + } + } + +Session_Ticket::Session_Ticket(TLS_Data_Reader& reader, + u16bit extension_size) + { + m_ticket = reader.get_elem<byte, std::vector<byte> >(extension_size); + } + +} + +} diff --git a/src/tls/tls_extensions.h b/src/tls/tls_extensions.h new file mode 100644 index 000000000..542ac0a82 --- /dev/null +++ b/src/tls/tls_extensions.h @@ -0,0 +1,381 @@ +/* +* TLS Extensions +* (C) 2011-2012 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#ifndef BOTAN_TLS_EXTENSIONS_H__ +#define BOTAN_TLS_EXTENSIONS_H__ + +#include <botan/secmem.h> +#include <botan/tls_magic.h> +#include <vector> +#include <string> +#include <map> + +namespace Botan { + +namespace TLS { + +class TLS_Data_Reader; + +enum Handshake_Extension_Type { + TLSEXT_SERVER_NAME_INDICATION = 0, + TLSEXT_MAX_FRAGMENT_LENGTH = 1, + TLSEXT_CLIENT_CERT_URL = 2, + TLSEXT_TRUSTED_CA_KEYS = 3, + TLSEXT_TRUNCATED_HMAC = 4, + + TLSEXT_CERTIFICATE_TYPES = 9, + TLSEXT_USABLE_ELLIPTIC_CURVES = 10, + TLSEXT_EC_POINT_FORMATS = 11, + TLSEXT_SRP_IDENTIFIER = 12, + TLSEXT_SIGNATURE_ALGORITHMS = 13, + TLSEXT_HEARTBEAT_SUPPORT = 15, + + TLSEXT_SESSION_TICKET = 35, + + TLSEXT_NEXT_PROTOCOL = 13172, + + TLSEXT_SAFE_RENEGOTIATION = 65281, +}; + +/** +* Base class representing a TLS extension of some kind +*/ +class Extension + { + public: + virtual Handshake_Extension_Type type() const = 0; + + virtual std::vector<byte> serialize() const = 0; + + virtual bool empty() const = 0; + + virtual ~Extension() {} + }; + +/** +* Server Name Indicator extension (RFC 3546) +*/ +class Server_Name_Indicator : public Extension + { + public: + static Handshake_Extension_Type static_type() + { return TLSEXT_SERVER_NAME_INDICATION; } + + Handshake_Extension_Type type() const { return static_type(); } + + Server_Name_Indicator(const std::string& host_name) : + sni_host_name(host_name) {} + + Server_Name_Indicator(TLS_Data_Reader& reader, + u16bit extension_size); + + std::string host_name() const { return sni_host_name; } + + std::vector<byte> serialize() const; + + bool empty() const { return sni_host_name == ""; } + private: + std::string sni_host_name; + }; + +/** +* SRP identifier extension (RFC 5054) +*/ +class SRP_Identifier : public Extension + { + public: + static Handshake_Extension_Type static_type() + { return TLSEXT_SRP_IDENTIFIER; } + + Handshake_Extension_Type type() const { return static_type(); } + + SRP_Identifier(const std::string& identifier) : + srp_identifier(identifier) {} + + SRP_Identifier(TLS_Data_Reader& reader, + u16bit extension_size); + + std::string identifier() const { return srp_identifier; } + + std::vector<byte> serialize() const; + + bool empty() const { return srp_identifier == ""; } + private: + std::string srp_identifier; + }; + +/** +* Renegotiation Indication Extension (RFC 5746) +*/ +class Renegotation_Extension : public Extension + { + public: + static Handshake_Extension_Type static_type() + { return TLSEXT_SAFE_RENEGOTIATION; } + + Handshake_Extension_Type type() const { return static_type(); } + + Renegotation_Extension() {} + + Renegotation_Extension(const std::vector<byte>& bits) : + reneg_data(bits) {} + + Renegotation_Extension(TLS_Data_Reader& reader, + u16bit extension_size); + + const std::vector<byte>& renegotiation_info() const + { return reneg_data; } + + std::vector<byte> serialize() const; + + bool empty() const { return false; } // always send this + private: + std::vector<byte> reneg_data; + }; + +/** +* Maximum Fragment Length Negotiation Extension (RFC 4366 sec 3.2) +*/ +class Maximum_Fragment_Length : public Extension + { + public: + static Handshake_Extension_Type static_type() + { return TLSEXT_MAX_FRAGMENT_LENGTH; } + + Handshake_Extension_Type type() const { return static_type(); } + + bool empty() const { return val != 0; } + + size_t fragment_size() const; + + std::vector<byte> serialize() const + { + return std::vector<byte>(1, val); + } + + /** + * @param max_fragment specifies what maximum fragment size to + * advertise. Currently must be one of 512, 1024, 2048, or + * 4096. + */ + Maximum_Fragment_Length(size_t max_fragment); + + Maximum_Fragment_Length(TLS_Data_Reader& reader, + u16bit extension_size); + + private: + byte val; + }; + +/** +* Next Protocol Negotiation +* http://technotes.googlecode.com/git/nextprotoneg.html +* +* This implementation requires the semantics defined in the Google +* spec (implemented in Chromium); the internet draft leaves the format +* unspecified. +*/ +class Next_Protocol_Notification : public Extension + { + public: + static Handshake_Extension_Type static_type() + { return TLSEXT_NEXT_PROTOCOL; } + + Handshake_Extension_Type type() const { return static_type(); } + + const std::vector<std::string>& protocols() const + { return m_protocols; } + + /** + * Empty extension, used by client + */ + Next_Protocol_Notification() {} + + /** + * List of protocols, used by server + */ + Next_Protocol_Notification(const std::vector<std::string>& protocols) : + m_protocols(protocols) {} + + Next_Protocol_Notification(TLS_Data_Reader& reader, + u16bit extension_size); + + std::vector<byte> serialize() const; + + bool empty() const { return false; } + private: + std::vector<std::string> m_protocols; + }; + +class Session_Ticket : public Extension + { + public: + static Handshake_Extension_Type static_type() + { return TLSEXT_SESSION_TICKET; } + + Handshake_Extension_Type type() const { return static_type(); } + + const std::vector<byte>& contents() const { return m_ticket; } + + /** + * Create empty extension, used by both client and server + */ + Session_Ticket() {} + + /** + * Extension with ticket, used by client + */ + Session_Ticket(const std::vector<byte>& session_ticket) : + m_ticket(session_ticket) {} + + /** + * Deserialize a session ticket + */ + Session_Ticket(TLS_Data_Reader& reader, u16bit extension_size); + + std::vector<byte> serialize() const { return m_ticket; } + + bool empty() const { return false; } + private: + std::vector<byte> m_ticket; + }; + +/** +* Supported Elliptic Curves Extension (RFC 4492) +*/ +class Supported_Elliptic_Curves : public Extension + { + public: + static Handshake_Extension_Type static_type() + { return TLSEXT_USABLE_ELLIPTIC_CURVES; } + + Handshake_Extension_Type type() const { return static_type(); } + + static std::string curve_id_to_name(u16bit id); + static u16bit name_to_curve_id(const std::string& name); + + const std::vector<std::string>& curves() const { return m_curves; } + + std::vector<byte> serialize() const; + + Supported_Elliptic_Curves(const std::vector<std::string>& curves) : + m_curves(curves) {} + + Supported_Elliptic_Curves(TLS_Data_Reader& reader, + u16bit extension_size); + + bool empty() const { return m_curves.empty(); } + private: + std::vector<std::string> m_curves; + }; + +/** +* Signature Algorithms Extension for TLS 1.2 (RFC 5246) +*/ +class Signature_Algorithms : public Extension + { + public: + static Handshake_Extension_Type static_type() + { return TLSEXT_SIGNATURE_ALGORITHMS; } + + Handshake_Extension_Type type() const { return static_type(); } + + static std::string hash_algo_name(byte code); + static byte hash_algo_code(const std::string& name); + + static std::string sig_algo_name(byte code); + static byte sig_algo_code(const std::string& name); + + std::vector<std::pair<std::string, std::string> > + supported_signature_algorthms() const + { + return m_supported_algos; + } + + std::vector<byte> serialize() const; + + bool empty() const { return false; } + + Signature_Algorithms(const std::vector<std::pair<std::string, std::string> >& algos) : + m_supported_algos(algos) {} + + Signature_Algorithms(TLS_Data_Reader& reader, + u16bit extension_size); + private: + std::vector<std::pair<std::string, std::string> > m_supported_algos; + }; + +/** +* Heartbeat Extension (RFC 6520) +*/ +class Heartbeat_Support_Indicator : public Extension + { + public: + static Handshake_Extension_Type static_type() + { return TLSEXT_HEARTBEAT_SUPPORT; } + + Handshake_Extension_Type type() const { return static_type(); } + + bool peer_allowed_to_send() const { return m_peer_allowed_to_send; } + + std::vector<byte> serialize() const; + + bool empty() const { return false; } + + Heartbeat_Support_Indicator(bool peer_allowed_to_send) : + m_peer_allowed_to_send(peer_allowed_to_send) {} + + Heartbeat_Support_Indicator(TLS_Data_Reader& reader, u16bit extension_size); + + private: + bool m_peer_allowed_to_send; + }; + +/** +* Represents a block of extensions in a hello message +*/ +class Extensions + { + public: + template<typename T> + T* get() const + { + Handshake_Extension_Type type = T::static_type(); + + std::map<Handshake_Extension_Type, Extension*>::const_iterator i = + extensions.find(type); + + if(i != extensions.end()) + return dynamic_cast<T*>(i->second); + return nullptr; + } + + void add(Extension* extn) + { + delete extensions[extn->type()]; // or hard error if already exists? + extensions[extn->type()] = extn; + } + + std::vector<byte> serialize() const; + + Extensions() {} + + Extensions(TLS_Data_Reader& reader); // deserialize + + ~Extensions(); + private: + Extensions(const Extensions&) {} + Extensions& operator=(const Extensions&) { return (*this); } + + std::map<Handshake_Extension_Type, Extension*> extensions; + }; + +} + +} + +#endif diff --git a/src/tls/tls_handshake_hash.cpp b/src/tls/tls_handshake_hash.cpp new file mode 100644 index 000000000..df956e7bb --- /dev/null +++ b/src/tls/tls_handshake_hash.cpp @@ -0,0 +1,103 @@ +/* +* TLS Handshake Hash +* (C) 2004-2006,2011 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#include <botan/internal/tls_handshake_hash.h> +#include <botan/tls_exceptn.h> +#include <botan/libstate.h> +#include <botan/hash.h> +#include <memory> + +namespace Botan { + +namespace TLS { + +void Handshake_Hash::update(Handshake_Type handshake_type, + const std::vector<byte>& handshake_msg) + { + update(static_cast<byte>(handshake_type)); + + const size_t record_length = handshake_msg.size(); + for(size_t i = 0; i != 3; i++) + update(get_byte<u32bit>(i+1, record_length)); + + update(handshake_msg); + } + +/** +* Return a TLS Handshake Hash +*/ +secure_vector<byte> Handshake_Hash::final(Protocol_Version version, + const std::string& mac_algo) + { + Algorithm_Factory& af = global_state().algorithm_factory(); + + std::unique_ptr<HashFunction> hash; + + if(version == Protocol_Version::TLS_V10 || version == Protocol_Version::TLS_V11) + { + hash.reset(af.make_hash_function("TLS.Digest.0")); + } + else if(version == Protocol_Version::TLS_V12) + { + if(mac_algo == "MD5" || mac_algo == "SHA-1" || mac_algo == "SHA-256") + hash.reset(af.make_hash_function("SHA-256")); + else + hash.reset(af.make_hash_function(mac_algo)); + } + else + throw TLS_Exception(Alert::PROTOCOL_VERSION, + "Unknown version for handshake hashes"); + + hash->update(data); + return hash->final(); + } + +/** +* Return a SSLv3 Handshake Hash +*/ +secure_vector<byte> Handshake_Hash::final_ssl3(const secure_vector<byte>& secret) + { + const byte PAD_INNER = 0x36, PAD_OUTER = 0x5C; + + Algorithm_Factory& af = global_state().algorithm_factory(); + + std::unique_ptr<HashFunction> md5(af.make_hash_function("MD5")); + std::unique_ptr<HashFunction> sha1(af.make_hash_function("SHA-1")); + + md5->update(data); + sha1->update(data); + + md5->update(secret); + sha1->update(secret); + + for(size_t i = 0; i != 48; ++i) + md5->update(PAD_INNER); + for(size_t i = 0; i != 40; ++i) + sha1->update(PAD_INNER); + + secure_vector<byte> inner_md5 = md5->final(), inner_sha1 = sha1->final(); + + md5->update(secret); + sha1->update(secret); + + for(size_t i = 0; i != 48; ++i) + md5->update(PAD_OUTER); + for(size_t i = 0; i != 40; ++i) + sha1->update(PAD_OUTER); + + md5->update(inner_md5); + sha1->update(inner_sha1); + + secure_vector<byte> output; + output += md5->final(); + output += sha1->final(); + return output; + } + +} + +} diff --git a/src/tls/tls_handshake_hash.h b/src/tls/tls_handshake_hash.h new file mode 100644 index 000000000..02943977f --- /dev/null +++ b/src/tls/tls_handshake_hash.h @@ -0,0 +1,58 @@ +/* +* TLS Handshake Hash +* (C) 2004-2006,2011 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#ifndef BOTAN_TLS_HANDSHAKE_HASH_H__ +#define BOTAN_TLS_HANDSHAKE_HASH_H__ + +#include <botan/secmem.h> +#include <botan/tls_version.h> +#include <botan/tls_magic.h> + +namespace Botan { + +namespace TLS { + +using namespace Botan; + +/** +* TLS Handshake Hash +*/ +class Handshake_Hash + { + public: + void update(const byte in[], size_t length) + { data += std::make_pair(in, length); } + + void update(const secure_vector<byte>& in) + { data += in; } + + void update(const std::vector<byte>& in) + { data += in; } + + void update(byte in) + { data.push_back(in); } + + void update(Handshake_Type handshake_type, + const std::vector<byte>& handshake_msg); + + secure_vector<byte> final(Protocol_Version version, + const std::string& mac_algo); + + secure_vector<byte> final_ssl3(const secure_vector<byte>& master_secret); + + const secure_vector<byte>& get_contents() const + { return data; } + + private: + secure_vector<byte> data; + }; + +} + +} + +#endif diff --git a/src/tls/tls_handshake_reader.cpp b/src/tls/tls_handshake_reader.cpp new file mode 100644 index 000000000..a3fe48f71 --- /dev/null +++ b/src/tls/tls_handshake_reader.cpp @@ -0,0 +1,66 @@ +/* +* TLS Handshake Reader +* (C) 2012 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#include <botan/internal/tls_handshake_reader.h> +#include <botan/exceptn.h> + +namespace Botan { + +namespace TLS { + +void Stream_Handshake_Reader::add_input(const byte record[], + size_t record_size) + { + m_queue.write(record, record_size); + } + +bool Stream_Handshake_Reader::empty() const + { + return m_queue.empty(); + } + +bool Stream_Handshake_Reader::have_full_record() const + { + if(m_queue.size() >= 4) + { + byte head[4] = { 0 }; + m_queue.peek(head, 4); + + const size_t length = make_u32bit(0, head[1], head[2], head[3]); + + return (m_queue.size() >= length + 4); + } + + return false; + } + +std::pair<Handshake_Type, std::vector<byte> > Stream_Handshake_Reader::get_next_record() + { + if(m_queue.size() >= 4) + { + byte head[4] = { 0 }; + m_queue.peek(head, 4); + + const size_t length = make_u32bit(0, head[1], head[2], head[3]); + + if(m_queue.size() >= length + 4) + { + Handshake_Type type = static_cast<Handshake_Type>(head[0]); + std::vector<byte> contents(length); + m_queue.read(head, 4); // discard + m_queue.read(&contents[0], contents.size()); + + return std::make_pair(type, contents); + } + } + + throw Internal_Error("Stream_Handshake_Reader::get_next_record called without a full record"); + } + +} + +} diff --git a/src/tls/tls_handshake_reader.h b/src/tls/tls_handshake_reader.h new file mode 100644 index 000000000..618e1878a --- /dev/null +++ b/src/tls/tls_handshake_reader.h @@ -0,0 +1,58 @@ +/* +* TLS Handshake Reader +* (C) 2012 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#ifndef BOTAN_TLS_HANDSHAKE_READER_H__ +#define BOTAN_TLS_HANDSHAKE_READER_H__ + +#include <botan/tls_magic.h> +#include <botan/secqueue.h> +#include <botan/loadstor.h> +#include <utility> + +namespace Botan { + +namespace TLS { + +/** +* Handshake Reader Interface +*/ +class Handshake_Reader + { + public: + virtual void add_input(const byte record[], size_t record_size) = 0; + + virtual bool empty() const = 0; + + virtual bool have_full_record() const = 0; + + virtual std::pair<Handshake_Type, std::vector<byte> > get_next_record() = 0; + + virtual ~Handshake_Reader() {} + }; + +/** +* Reader of TLS handshake messages +*/ +class Stream_Handshake_Reader : public Handshake_Reader + { + public: + void add_input(const byte record[], size_t record_size); + + bool empty() const; + + bool have_full_record() const; + + std::pair<Handshake_Type, std::vector<byte> > get_next_record(); + private: + SecureQueue m_queue; + }; + +} + +} + +#endif diff --git a/src/tls/tls_handshake_state.cpp b/src/tls/tls_handshake_state.cpp new file mode 100644 index 000000000..90de7c3f9 --- /dev/null +++ b/src/tls/tls_handshake_state.cpp @@ -0,0 +1,330 @@ +/* +* TLS Handshaking +* (C) 2004-2006,2011 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#include <botan/internal/tls_handshake_state.h> +#include <botan/internal/tls_messages.h> +#include <botan/internal/assert.h> +#include <botan/lookup.h> + +namespace Botan { + +namespace TLS { + +namespace { + +u32bit bitmask_for_handshake_type(Handshake_Type type) + { + switch(type) + { + case HELLO_REQUEST: + return (1 << 0); + + /* + * Same code point for both client hello styles + */ + case CLIENT_HELLO: + case CLIENT_HELLO_SSLV2: + return (1 << 1); + + case SERVER_HELLO: + return (1 << 2); + + case CERTIFICATE: + return (1 << 3); + + case SERVER_KEX: + return (1 << 4); + + case CERTIFICATE_REQUEST: + return (1 << 5); + + case SERVER_HELLO_DONE: + return (1 << 6); + + case CERTIFICATE_VERIFY: + return (1 << 7); + + case CLIENT_KEX: + return (1 << 8); + + case NEXT_PROTOCOL: + return (1 << 9); + + case NEW_SESSION_TICKET: + return (1 << 10); + + case HANDSHAKE_CCS: + return (1 << 11); + + case FINISHED: + return (1 << 12); + + // allow explicitly disabling new handshakes + case HANDSHAKE_NONE: + return 0; + + default: + throw Internal_Error("Unknown handshake type " + + std::to_string(type)); + } + + return 0; + } + +} + +/* +* Initialize the SSL/TLS Handshake State +*/ +Handshake_State::Handshake_State(Handshake_Reader* reader) + { + client_hello = nullptr; + server_hello = nullptr; + server_certs = nullptr; + server_kex = nullptr; + cert_req = nullptr; + server_hello_done = nullptr; + next_protocol = nullptr; + new_session_ticket = nullptr; + + client_certs = nullptr; + client_kex = nullptr; + client_verify = nullptr; + client_finished = nullptr; + server_finished = nullptr; + + m_handshake_reader = reader; + + server_rsa_kex_key = nullptr; + + m_version = Protocol_Version::SSL_V3; + + hand_expecting_mask = 0; + hand_received_mask = 0; + + allow_session_resumption = true; + } + +void Handshake_State::set_version(const Protocol_Version& version) + { + m_version = version; + } + +void Handshake_State::confirm_transition_to(Handshake_Type handshake_msg) + { + const u32bit mask = bitmask_for_handshake_type(handshake_msg); + + hand_received_mask |= mask; + + const bool ok = (hand_expecting_mask & mask); // overlap? + + if(!ok) + throw Unexpected_Message("Unexpected state transition in handshake, got " + + std::to_string(handshake_msg) + " mask is " + + std::to_string(hand_expecting_mask)); + + /* We don't know what to expect next, so force a call to + set_expected_next; if it doesn't happen, the next transition + check will always fail which is what we want. + */ + hand_expecting_mask = 0; + } + +void Handshake_State::set_expected_next(Handshake_Type handshake_msg) + { + hand_expecting_mask |= bitmask_for_handshake_type(handshake_msg); + } + +bool Handshake_State::received_handshake_msg(Handshake_Type handshake_msg) const + { + const u32bit mask = bitmask_for_handshake_type(handshake_msg); + + return (hand_received_mask & mask); + } + +std::string Handshake_State::srp_identifier() const + { + if(suite.valid() && suite.kex_algo() == "SRP_SHA") + return client_hello->srp_identifier(); + + return ""; + } + +const std::vector<byte>& Handshake_State::session_ticket() const + { + if(new_session_ticket && !new_session_ticket->ticket().empty()) + return new_session_ticket->ticket(); + + return client_hello->session_ticket(); + } + +KDF* Handshake_State::protocol_specific_prf() + { + if(version() == Protocol_Version::SSL_V3) + { + return get_kdf("SSL3-PRF"); + } + else if(version() == Protocol_Version::TLS_V10 || version() == Protocol_Version::TLS_V11) + { + return get_kdf("TLS-PRF"); + } + else if(version() == Protocol_Version::TLS_V12) + { + if(suite.mac_algo() == "MD5" || + suite.mac_algo() == "SHA-1" || + suite.mac_algo() == "SHA-256") + { + return get_kdf("TLS-12-PRF(SHA-256)"); + } + + return get_kdf("TLS-12-PRF(" + suite.mac_algo() + ")"); + } + + throw Internal_Error("Unknown version code " + version().to_string()); + } + +std::pair<std::string, Signature_Format> +Handshake_State::choose_sig_format(const Private_Key* key, + std::string& hash_algo_out, + std::string& sig_algo_out, + bool for_client_auth) + { + const std::string sig_algo = key->algo_name(); + + const std::vector<std::pair<std::string, std::string> > supported_algos = + (for_client_auth) ? cert_req->supported_algos() : client_hello->supported_algos(); + + std::string hash_algo; + + for(size_t i = 0; i != supported_algos.size(); ++i) + { + if(supported_algos[i].second == sig_algo) + { + hash_algo = supported_algos[i].first; + break; + } + } + + if(for_client_auth && this->version() == Protocol_Version::SSL_V3) + hash_algo = "Raw"; + + if(hash_algo == "" && this->version() == Protocol_Version::TLS_V12) + hash_algo = "SHA-1"; // TLS 1.2 but no compatible hashes set (?) + + BOTAN_ASSERT(hash_algo != "", "Couldn't figure out hash to use"); + + if(this->version() >= Protocol_Version::TLS_V12) + { + hash_algo_out = hash_algo; + sig_algo_out = sig_algo; + } + + if(sig_algo == "RSA") + { + const std::string padding = "EMSA3(" + hash_algo + ")"; + + return std::make_pair(padding, IEEE_1363); + } + else if(sig_algo == "DSA" || sig_algo == "ECDSA") + { + const std::string padding = "EMSA1(" + hash_algo + ")"; + + return std::make_pair(padding, DER_SEQUENCE); + } + + throw Invalid_Argument(sig_algo + " is invalid/unknown for TLS signatures"); + } + +std::pair<std::string, Signature_Format> +Handshake_State::understand_sig_format(const Public_Key* key, + std::string hash_algo, + std::string sig_algo, + bool for_client_auth) + { + const std::string algo_name = key->algo_name(); + + /* + FIXME: This should check what was sent against the client hello + preferences, or the certificate request, to ensure it was allowed + by those restrictions. + + Or not? + */ + + if(this->version() < Protocol_Version::TLS_V12) + { + if(hash_algo != "" || sig_algo != "") + throw Decoding_Error("Counterparty sent hash/sig IDs with old version"); + } + else + { + if(hash_algo == "") + throw Decoding_Error("Counterparty did not send hash/sig IDS"); + + if(sig_algo != algo_name) + throw Decoding_Error("Counterparty sent inconsistent key and sig types"); + } + + if(algo_name == "RSA") + { + if(for_client_auth && this->version() == Protocol_Version::SSL_V3) + { + hash_algo = "Raw"; + } + else if(this->version() < Protocol_Version::TLS_V12) + { + hash_algo = "TLS.Digest.0"; + } + + const std::string padding = "EMSA3(" + hash_algo + ")"; + return std::make_pair(padding, IEEE_1363); + } + else if(algo_name == "DSA" || algo_name == "ECDSA") + { + if(algo_name == "DSA" && for_client_auth && this->version() == Protocol_Version::SSL_V3) + { + hash_algo = "Raw"; + } + else if(this->version() < Protocol_Version::TLS_V12) + { + hash_algo = "SHA-1"; + } + + const std::string padding = "EMSA1(" + hash_algo + ")"; + + return std::make_pair(padding, DER_SEQUENCE); + } + + throw Invalid_Argument(algo_name + " is invalid/unknown for TLS signatures"); + } + +/* +* Destroy the SSL/TLS Handshake State +*/ +Handshake_State::~Handshake_State() + { + delete client_hello; + delete server_hello; + delete server_certs; + delete server_kex; + delete cert_req; + delete server_hello_done; + delete next_protocol; + delete new_session_ticket; + + delete client_certs; + delete client_kex; + delete client_verify; + delete client_finished; + delete server_finished; + + delete m_handshake_reader; + } + +} + +} diff --git a/src/tls/tls_handshake_state.h b/src/tls/tls_handshake_state.h new file mode 100644 index 000000000..ef8b4ee8f --- /dev/null +++ b/src/tls/tls_handshake_state.h @@ -0,0 +1,112 @@ +/* +* TLS Handshake State +* (C) 2004-2006 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#ifndef BOTAN_TLS_HANDSHAKE_STATE_H__ +#define BOTAN_TLS_HANDSHAKE_STATE_H__ + +#include <botan/internal/tls_handshake_hash.h> +#include <botan/internal/tls_handshake_reader.h> +#include <botan/internal/tls_session_key.h> +#include <botan/pk_keys.h> +#include <botan/pubkey.h> + +#include <functional> +#include <utility> + +namespace Botan { + +class KDF; + +namespace TLS { + +/** +* SSL/TLS Handshake State +*/ +class Handshake_State + { + public: + Handshake_State(Handshake_Reader* reader); + ~Handshake_State(); + + bool received_handshake_msg(Handshake_Type handshake_msg) const; + + void confirm_transition_to(Handshake_Type handshake_msg); + void set_expected_next(Handshake_Type handshake_msg); + + const std::vector<byte>& session_ticket() const; + + std::pair<std::string, Signature_Format> + understand_sig_format(const Public_Key* key, + std::string hash_algo, + std::string sig_algo, + bool for_client_auth); + + std::pair<std::string, Signature_Format> + choose_sig_format(const Private_Key* key, + std::string& hash_algo, + std::string& sig_algo, + bool for_client_auth); + + std::string srp_identifier() const; + + KDF* protocol_specific_prf(); + + Protocol_Version version() const { return m_version; } + + void set_version(const Protocol_Version& version); + + class Client_Hello* client_hello; + class Server_Hello* server_hello; + class Certificate* server_certs; + class Server_Key_Exchange* server_kex; + class Certificate_Req* cert_req; + class Server_Hello_Done* server_hello_done; + + class Certificate* client_certs; + class Client_Key_Exchange* client_kex; + class Certificate_Verify* client_verify; + + class Next_Protocol* next_protocol; + class New_Session_Ticket* new_session_ticket; + + class Finished* client_finished; + class Finished* server_finished; + + // Used by the server only, in case of RSA key exchange + Private_Key* server_rsa_kex_key; + + Ciphersuite suite; + Session_Keys keys; + Handshake_Hash hash; + + /* + * Only used by clients for session resumption + */ + secure_vector<byte> resume_master_secret; + + /* + * + */ + bool allow_session_resumption; + + /** + * Used by client using NPN + */ + std::function<std::string (std::vector<std::string>)> client_npn_cb; + + Handshake_Reader* handshake_reader() { return m_handshake_reader; } + private: + Handshake_Reader* m_handshake_reader; + u32bit hand_expecting_mask, hand_received_mask; + Protocol_Version m_version; + }; + +} + +} + +#endif diff --git a/src/tls/tls_heartbeats.cpp b/src/tls/tls_heartbeats.cpp new file mode 100644 index 000000000..8c129858e --- /dev/null +++ b/src/tls/tls_heartbeats.cpp @@ -0,0 +1,78 @@ +/* +* TLS Heartbeats +* (C) 2012 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#include <botan/internal/tls_heartbeats.h> +#include <botan/internal/tls_extensions.h> +#include <botan/internal/tls_reader.h> +#include <botan/tls_exceptn.h> + +namespace Botan { + +namespace TLS { + +Heartbeat_Message::Heartbeat_Message(const std::vector<byte>& buf) + { + TLS_Data_Reader reader(buf); + + const byte type = reader.get_byte(); + + if(type != 1 && type != 2) + throw TLS_Exception(Alert::ILLEGAL_PARAMETER, + "Unknown heartbeat message type"); + + m_type = static_cast<Type>(type); + + m_payload = reader.get_range<byte>(2, 0, 16*1024); + + // padding follows and is ignored + } + +Heartbeat_Message::Heartbeat_Message(Type type, + const byte payload[], + size_t payload_len) : + m_type(type), + m_payload(payload, payload + payload_len) + { + } + +std::vector<byte> Heartbeat_Message::contents() const + { + std::vector<byte> send_buf(3 + m_payload.size() + 16); + send_buf[0] = m_type; + send_buf[1] = get_byte<u16bit>(0, m_payload.size()); + send_buf[2] = get_byte<u16bit>(1, m_payload.size()); + copy_mem(&send_buf[3], &m_payload[0], m_payload.size()); + // leave padding as all zeros + + return send_buf; + } + +std::vector<byte> Heartbeat_Support_Indicator::serialize() const + { + std::vector<byte> heartbeat(1); + heartbeat[0] = (m_peer_allowed_to_send ? 1 : 2); + return heartbeat; + } + +Heartbeat_Support_Indicator::Heartbeat_Support_Indicator(TLS_Data_Reader& reader, + u16bit extension_size) + { + if(extension_size != 1) + throw Decoding_Error("Strange size for heartbeat extension"); + + const byte code = reader.get_byte(); + + if(code != 1 && code != 2) + throw TLS_Exception(Alert::ILLEGAL_PARAMETER, + "Unknown heartbeat code " + std::to_string(code)); + + m_peer_allowed_to_send = (code == 1); + } + +} + +} diff --git a/src/tls/tls_heartbeats.h b/src/tls/tls_heartbeats.h new file mode 100644 index 000000000..f3cc9ec68 --- /dev/null +++ b/src/tls/tls_heartbeats.h @@ -0,0 +1,40 @@ +/* +* TLS Heartbeats +* (C) 2012 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#ifndef BOTAN_TLS_HEARTBEATS_H__ +#define BOTAN_TLS_HEARTBEATS_H__ + +#include <botan/secmem.h> + +namespace Botan { + +namespace TLS { + +class Heartbeat_Message + { + public: + enum Type { REQUEST = 1, RESPONSE = 2 }; + + std::vector<byte> contents() const; + + const std::vector<byte>& payload() const { return m_payload; } + + bool is_request() const { return m_type == REQUEST; } + + Heartbeat_Message(const std::vector<byte>& buf); + + Heartbeat_Message(Type type, const byte payload[], size_t payload_len); + private: + Type m_type; + std::vector<byte> m_payload; + }; + +} + +} + +#endif diff --git a/src/tls/tls_magic.h b/src/tls/tls_magic.h new file mode 100644 index 000000000..2972321c9 --- /dev/null +++ b/src/tls/tls_magic.h @@ -0,0 +1,69 @@ +/* +* SSL/TLS Protocol Constants +* (C) 2004-2010 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#ifndef BOTAN_TLS_PROTOCOL_MAGIC_H__ +#define BOTAN_TLS_PROTOCOL_MAGIC_H__ + +namespace Botan { + +namespace TLS { + +/** +* Protocol Constants for SSL/TLS +*/ +enum Size_Limits { + TLS_HEADER_SIZE = 5, + MAX_PLAINTEXT_SIZE = 16*1024, + MAX_COMPRESSED_SIZE = MAX_PLAINTEXT_SIZE + 1024, + MAX_CIPHERTEXT_SIZE = MAX_COMPRESSED_SIZE + 1024, + + MAX_TLS_RECORD_SIZE = MAX_CIPHERTEXT_SIZE + TLS_HEADER_SIZE, +}; + +enum Connection_Side { CLIENT = 1, SERVER = 2 }; + +enum Record_Type { + CONNECTION_CLOSED = 0, + + CHANGE_CIPHER_SPEC = 20, + ALERT = 21, + HANDSHAKE = 22, + APPLICATION_DATA = 23, + HEARTBEAT = 24, +}; + +enum Handshake_Type { + HELLO_REQUEST = 0, + CLIENT_HELLO = 1, + CLIENT_HELLO_SSLV2 = 253, // Not a wire value + SERVER_HELLO = 2, + HELLO_VERIFY_REQUEST = 3, + NEW_SESSION_TICKET = 4, // RFC 5077 + CERTIFICATE = 11, + SERVER_KEX = 12, + CERTIFICATE_REQUEST = 13, + SERVER_HELLO_DONE = 14, + CERTIFICATE_VERIFY = 15, + CLIENT_KEX = 16, + FINISHED = 20, + + NEXT_PROTOCOL = 67, + + HANDSHAKE_CCS = 254, // Not a wire value + HANDSHAKE_NONE = 255 // Null value +}; + +enum Compression_Method { + NO_COMPRESSION = 0x00, + DEFLATE_COMPRESSION = 0x01 +}; + +} + +} + +#endif diff --git a/src/tls/tls_messages.h b/src/tls/tls_messages.h new file mode 100644 index 000000000..31c35d901 --- /dev/null +++ b/src/tls/tls_messages.h @@ -0,0 +1,501 @@ +/* +* TLS Messages +* (C) 2004-2011 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#ifndef BOTAN_TLS_MESSAGES_H__ +#define BOTAN_TLS_MESSAGES_H__ + +#include <botan/internal/tls_handshake_state.h> +#include <botan/tls_session.h> +#include <botan/tls_policy.h> +#include <botan/tls_magic.h> +#include <botan/tls_ciphersuite.h> +#include <botan/bigint.h> +#include <botan/pkcs8.h> +#include <botan/x509cert.h> +#include <vector> + +namespace Botan { + +class Credentials_Manager; +class SRP6_Server_Session; + +namespace TLS { + +class Record_Writer; +class Record_Reader; + +/** +* TLS Handshake Message Base Class +*/ +class Handshake_Message + { + public: + virtual std::vector<byte> serialize() const = 0; + virtual Handshake_Type type() const = 0; + + Handshake_Message() {} + virtual ~Handshake_Message() {} + private: + Handshake_Message(const Handshake_Message&) {} + Handshake_Message& operator=(const Handshake_Message&) { return (*this); } + }; + +std::vector<byte> make_hello_random(RandomNumberGenerator& rng); + +/** +* DTLS Hello Verify Request +*/ +class Hello_Verify_Request : public Handshake_Message + { + public: + std::vector<byte> serialize() const; + Handshake_Type type() const { return HELLO_VERIFY_REQUEST; } + + std::vector<byte> cookie() const { return m_cookie; } + + Hello_Verify_Request(const std::vector<byte>& buf); + + Hello_Verify_Request(const std::vector<byte>& client_hello_bits, + const std::string& client_identity, + const SymmetricKey& secret_key); + private: + std::vector<byte> m_cookie; + }; + +/** +* Client Hello Message +*/ +class Client_Hello : public Handshake_Message + { + public: + Handshake_Type type() const { return CLIENT_HELLO; } + + Protocol_Version version() const { return m_version; } + + const std::vector<byte>& session_id() const { return m_session_id; } + + const std::vector<std::pair<std::string, std::string> >& supported_algos() const + { return m_supported_algos; } + + const std::vector<std::string>& supported_ecc_curves() const + { return m_supported_curves; } + + std::vector<u16bit> ciphersuites() const { return m_suites; } + std::vector<byte> compression_methods() const { return m_comp_methods; } + + const std::vector<byte>& random() const { return m_random; } + + std::string sni_hostname() const { return m_hostname; } + + std::string srp_identifier() const { return m_srp_identifier; } + + bool secure_renegotiation() const { return m_secure_renegotiation; } + + const std::vector<byte>& renegotiation_info() + { return m_renegotiation_info; } + + bool offered_suite(u16bit ciphersuite) const; + + bool next_protocol_notification() const { return m_next_protocol; } + + size_t fragment_size() const { return m_fragment_size; } + + bool supports_session_ticket() const { return m_supports_session_ticket; } + + const std::vector<byte>& session_ticket() const + { return m_session_ticket; } + + bool supports_heartbeats() const { return m_supports_heartbeats; } + + bool peer_can_send_heartbeats() const { return m_peer_can_send_heartbeats; } + + Client_Hello(Record_Writer& writer, + Handshake_Hash& hash, + const Policy& policy, + RandomNumberGenerator& rng, + const std::vector<byte>& reneg_info, + bool next_protocol = false, + const std::string& hostname = "", + const std::string& srp_identifier = ""); + + Client_Hello(Record_Writer& writer, + Handshake_Hash& hash, + const Policy& policy, + RandomNumberGenerator& rng, + const std::vector<byte>& reneg_info, + const Session& resumed_session, + bool next_protocol = false); + + Client_Hello(const std::vector<byte>& buf, + Handshake_Type type); + + private: + std::vector<byte> serialize() const; + void deserialize(const std::vector<byte>& buf); + void deserialize_sslv2(const std::vector<byte>& buf); + + Protocol_Version m_version; + std::vector<byte> m_session_id, m_random; + std::vector<u16bit> m_suites; + std::vector<byte> m_comp_methods; + std::string m_hostname; + std::string m_srp_identifier; + bool m_next_protocol; + + size_t m_fragment_size; + bool m_secure_renegotiation; + std::vector<byte> m_renegotiation_info; + + std::vector<std::pair<std::string, std::string> > m_supported_algos; + std::vector<std::string> m_supported_curves; + + bool m_supports_session_ticket; + std::vector<byte> m_session_ticket; + + bool m_supports_heartbeats; + bool m_peer_can_send_heartbeats; + }; + +/** +* Server Hello Message +*/ +class Server_Hello : public Handshake_Message + { + public: + Handshake_Type type() const { return SERVER_HELLO; } + + Protocol_Version version() { return m_version; } + + const std::vector<byte>& random() const { return m_random; } + + const std::vector<byte>& session_id() const { return m_session_id; } + + u16bit ciphersuite() const { return m_ciphersuite; } + + byte compression_method() const { return m_comp_method; } + + bool secure_renegotiation() const { return m_secure_renegotiation; } + + bool next_protocol_notification() const { return m_next_protocol; } + + bool supports_session_ticket() const { return m_supports_session_ticket; } + + const std::vector<std::string>& next_protocols() const + { return m_next_protocols; } + + size_t fragment_size() const { return m_fragment_size; } + + const std::vector<byte>& renegotiation_info() + { return m_renegotiation_info; } + + bool supports_heartbeats() const { return m_supports_heartbeats; } + + bool peer_can_send_heartbeats() const { return m_peer_can_send_heartbeats; } + + Server_Hello(Record_Writer& writer, + Handshake_Hash& hash, + const std::vector<byte>& session_id, + Protocol_Version ver, + u16bit ciphersuite, + byte compression, + size_t max_fragment_size, + bool client_has_secure_renegotiation, + const std::vector<byte>& reneg_info, + bool offer_session_ticket, + bool client_has_npn, + const std::vector<std::string>& next_protocols, + bool client_has_heartbeat, + RandomNumberGenerator& rng); + + Server_Hello(const std::vector<byte>& buf); + private: + std::vector<byte> serialize() const; + + Protocol_Version m_version; + std::vector<byte> m_session_id, m_random; + u16bit m_ciphersuite; + byte m_comp_method; + + size_t m_fragment_size; + bool m_secure_renegotiation; + std::vector<byte> m_renegotiation_info; + + bool m_next_protocol; + std::vector<std::string> m_next_protocols; + bool m_supports_session_ticket; + + bool m_supports_heartbeats; + bool m_peer_can_send_heartbeats; + }; + +/** +* Client Key Exchange Message +*/ +class Client_Key_Exchange : public Handshake_Message + { + public: + Handshake_Type type() const { return CLIENT_KEX; } + + const secure_vector<byte>& pre_master_secret() const + { return pre_master; } + + Client_Key_Exchange(Record_Writer& output, + Handshake_State* state, + Credentials_Manager& creds, + const std::vector<X509_Certificate>& peer_certs, + const std::string& hostname, + RandomNumberGenerator& rng); + + Client_Key_Exchange(const std::vector<byte>& buf, + const Handshake_State* state, + Credentials_Manager& creds, + const Policy& policy, + RandomNumberGenerator& rng); + + private: + std::vector<byte> serialize() const { return key_material; } + + std::vector<byte> key_material; + secure_vector<byte> pre_master; + }; + +/** +* Certificate Message +*/ +class Certificate : public Handshake_Message + { + public: + Handshake_Type type() const { return CERTIFICATE; } + const std::vector<X509_Certificate>& cert_chain() const { return m_certs; } + + size_t count() const { return m_certs.size(); } + bool empty() const { return m_certs.empty(); } + + Certificate(Record_Writer& writer, + Handshake_Hash& hash, + const std::vector<X509_Certificate>& certs); + + Certificate(const std::vector<byte>& buf); + private: + std::vector<byte> serialize() const; + + std::vector<X509_Certificate> m_certs; + }; + +/** +* Certificate Request Message +*/ +class Certificate_Req : public Handshake_Message + { + public: + Handshake_Type type() const { return CERTIFICATE_REQUEST; } + + const std::vector<std::string>& acceptable_cert_types() const + { return cert_key_types; } + + std::vector<X509_DN> acceptable_CAs() const { return names; } + + std::vector<std::pair<std::string, std::string> > supported_algos() const + { return m_supported_algos; } + + Certificate_Req(Record_Writer& writer, + Handshake_Hash& hash, + const Policy& policy, + const std::vector<X509_Certificate>& allowed_cas, + Protocol_Version version); + + Certificate_Req(const std::vector<byte>& buf, + Protocol_Version version); + private: + std::vector<byte> serialize() const; + + std::vector<X509_DN> names; + std::vector<std::string> cert_key_types; + + std::vector<std::pair<std::string, std::string> > m_supported_algos; + }; + +/** +* Certificate Verify Message +*/ +class Certificate_Verify : public Handshake_Message + { + public: + Handshake_Type type() const { return CERTIFICATE_VERIFY; } + + /** + * Check the signature on a certificate verify message + * @param cert the purported certificate + * @param state the handshake state + */ + bool verify(const X509_Certificate& cert, + Handshake_State* state); + + Certificate_Verify(Record_Writer& writer, + Handshake_State* state, + RandomNumberGenerator& rng, + const Private_Key* key); + + Certificate_Verify(const std::vector<byte>& buf, + Protocol_Version version); + private: + std::vector<byte> serialize() const; + + std::string sig_algo; // sig algo used to create signature + std::string hash_algo; // hash used to create signature + std::vector<byte> signature; + }; + +/** +* Finished Message +*/ +class Finished : public Handshake_Message + { + public: + Handshake_Type type() const { return FINISHED; } + + std::vector<byte> verify_data() const + { return verification_data; } + + bool verify(Handshake_State* state, + Connection_Side side); + + Finished(Record_Writer& writer, + Handshake_State* state, + Connection_Side side); + + Finished(const std::vector<byte>& buf); + private: + std::vector<byte> serialize() const; + + Connection_Side side; + std::vector<byte> verification_data; + }; + +/** +* Hello Request Message +*/ +class Hello_Request : public Handshake_Message + { + public: + Handshake_Type type() const { return HELLO_REQUEST; } + + Hello_Request(Record_Writer& writer); + Hello_Request(const std::vector<byte>& buf); + private: + std::vector<byte> serialize() const; + }; + +/** +* Server Key Exchange Message +*/ +class Server_Key_Exchange : public Handshake_Message + { + public: + Handshake_Type type() const { return SERVER_KEX; } + + const std::vector<byte>& params() const { return m_params; } + + bool verify(const X509_Certificate& cert, + Handshake_State* state) const; + + // Only valid for certain kex types + const Private_Key& server_kex_key() const; + + // Only valid for SRP negotiation + SRP6_Server_Session& server_srp_params(); + + Server_Key_Exchange(Record_Writer& writer, + Handshake_State* state, + const Policy& policy, + Credentials_Manager& creds, + RandomNumberGenerator& rng, + const Private_Key* signing_key = nullptr); + + Server_Key_Exchange(const std::vector<byte>& buf, + const std::string& kex_alg, + const std::string& sig_alg, + Protocol_Version version); + + ~Server_Key_Exchange(); + private: + std::vector<byte> serialize() const; + + Private_Key* m_kex_key; + SRP6_Server_Session* m_srp_params; + + std::vector<byte> m_params; + + std::string m_sig_algo; // sig algo used to create signature + std::string m_hash_algo; // hash used to create signature + std::vector<byte> m_signature; + }; + +/** +* Server Hello Done Message +*/ +class Server_Hello_Done : public Handshake_Message + { + public: + Handshake_Type type() const { return SERVER_HELLO_DONE; } + + Server_Hello_Done(Record_Writer& writer, Handshake_Hash& hash); + Server_Hello_Done(const std::vector<byte>& buf); + private: + std::vector<byte> serialize() const; + }; + +/** +* Next Protocol Message +*/ +class Next_Protocol : public Handshake_Message + { + public: + Handshake_Type type() const { return NEXT_PROTOCOL; } + + std::string protocol() const { return m_protocol; } + + Next_Protocol(Record_Writer& writer, + Handshake_Hash& hash, + const std::string& protocol); + + Next_Protocol(const std::vector<byte>& buf); + private: + std::vector<byte> serialize() const; + + std::string m_protocol; + }; + +class New_Session_Ticket : public Handshake_Message + { + public: + Handshake_Type type() const { return NEW_SESSION_TICKET; } + + u32bit ticket_lifetime_hint() const { return m_ticket_lifetime_hint; } + const std::vector<byte>& ticket() const { return m_ticket; } + + New_Session_Ticket(Record_Writer& writer, + Handshake_Hash& hash, + const std::vector<byte>& ticket, + u32bit lifetime); + + New_Session_Ticket(Record_Writer& writer, + Handshake_Hash& hash); + + New_Session_Ticket(const std::vector<byte>& buf); + private: + std::vector<byte> serialize() const; + + u32bit m_ticket_lifetime_hint; + std::vector<byte> m_ticket; + }; + +} + +} + +#endif diff --git a/src/tls/tls_policy.cpp b/src/tls/tls_policy.cpp new file mode 100644 index 000000000..f240bebac --- /dev/null +++ b/src/tls/tls_policy.cpp @@ -0,0 +1,265 @@ +/* +* Policies for TLS +* (C) 2004-2010,2012 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#include <botan/tls_policy.h> +#include <botan/tls_ciphersuite.h> +#include <botan/tls_magic.h> +#include <botan/tls_exceptn.h> +#include <botan/internal/stl_util.h> + +namespace Botan { + +namespace TLS { + +std::vector<std::string> Policy::allowed_ciphers() const + { + std::vector<std::string> allowed; + + allowed.push_back("AES-256"); + allowed.push_back("AES-128"); + allowed.push_back("3DES"); + allowed.push_back("ARC4"); + //allowed.push_back("Camellia"); + //allowed.push_back("SEED"); + + return allowed; + } + +std::vector<std::string> Policy::allowed_hashes() const + { + std::vector<std::string> allowed; + + allowed.push_back("SHA-512"); + allowed.push_back("SHA-384"); + allowed.push_back("SHA-256"); + allowed.push_back("SHA-224"); + allowed.push_back("SHA-1"); + //allowed.push_back("MD5"); + + return allowed; + } + +std::vector<std::string> Policy::allowed_key_exchange_methods() const + { + std::vector<std::string> allowed; + + allowed.push_back("SRP_SHA"); + //allowed.push_back("ECDHE_PSK"); + //allowed.push_back("DHE_PSK"); + //allowed.push_back("PSK"); + + allowed.push_back("ECDH"); + allowed.push_back("DH"); + allowed.push_back("RSA"); + + return allowed; + } + +std::vector<std::string> Policy::allowed_signature_methods() const + { + std::vector<std::string> allowed; + + allowed.push_back("ECDSA"); + allowed.push_back("RSA"); + allowed.push_back("DSA"); + //allowed.push_back(""); + + return allowed; + } + +std::vector<std::string> Policy::allowed_ecc_curves() const + { + std::vector<std::string> curves; + curves.push_back("secp521r1"); + curves.push_back("secp384r1"); + curves.push_back("secp256r1"); + curves.push_back("secp256k1"); + curves.push_back("secp224r1"); + curves.push_back("secp224k1"); + curves.push_back("secp192r1"); + curves.push_back("secp192k1"); + curves.push_back("secp160r2"); + curves.push_back("secp160r1"); + curves.push_back("secp160k1"); + return curves; + } + +/* +* Choose an ECC curve to use +*/ +std::string Policy::choose_curve(const std::vector<std::string>& curve_names) const + { + const std::vector<std::string> our_curves = allowed_ecc_curves(); + + for(size_t i = 0; i != our_curves.size(); ++i) + if(value_exists(curve_names, our_curves[i])) + return our_curves[i]; + + return ""; // no shared curve + } + +DL_Group Policy::dh_group() const + { + return DL_Group("modp/ietf/2048"); + } + +/* +* Return allowed compression algorithms +*/ +std::vector<byte> Policy::compression() const + { + std::vector<byte> algs; + algs.push_back(NO_COMPRESSION); + return algs; + } + +u32bit Policy::session_ticket_lifetime() const + { + return 86400; // 1 day + } + +Protocol_Version Policy::min_version() const + { + return Protocol_Version::SSL_V3; + } + +Protocol_Version Policy::pref_version() const + { + return Protocol_Version::TLS_V12; + } + +namespace { + +class Ciphersuite_Preference_Ordering + { + public: + Ciphersuite_Preference_Ordering(const std::vector<std::string>& ciphers, + const std::vector<std::string>& hashes, + const std::vector<std::string>& kex, + const std::vector<std::string>& sigs) : + m_ciphers(ciphers), m_hashes(hashes), m_kex(kex), m_sigs(sigs) {} + + bool operator()(const Ciphersuite& a, const Ciphersuite& b) const + { + if(a.kex_algo() != b.kex_algo()) + { + for(size_t i = 0; i != m_kex.size(); ++i) + { + if(a.kex_algo() == m_kex[i]) + return true; + if(b.kex_algo() == m_kex[i]) + return false; + } + } + + if(a.cipher_algo() != b.cipher_algo()) + { + for(size_t i = 0; i != m_ciphers.size(); ++i) + { + if(a.cipher_algo() == m_ciphers[i]) + return true; + if(b.cipher_algo() == m_ciphers[i]) + return false; + } + } + + if(a.cipher_keylen() != b.cipher_keylen()) + { + if(a.cipher_keylen() < b.cipher_keylen()) + return false; + if(a.cipher_keylen() > b.cipher_keylen()) + return true; + } + + if(a.sig_algo() != b.sig_algo()) + { + for(size_t i = 0; i != m_sigs.size(); ++i) + { + if(a.sig_algo() == m_sigs[i]) + return true; + if(b.sig_algo() == m_sigs[i]) + return false; + } + } + + if(a.mac_algo() != b.mac_algo()) + { + for(size_t i = 0; i != m_hashes.size(); ++i) + { + if(a.mac_algo() == m_hashes[i]) + return true; + if(b.mac_algo() == m_hashes[i]) + return false; + } + } + + return false; // equal (?!?) + } + private: + std::vector<std::string> m_ciphers, m_hashes, m_kex, m_sigs; + + }; + +} + +std::vector<u16bit> ciphersuite_list(const Policy& policy, + bool have_srp) + { + const std::vector<std::string> ciphers = policy.allowed_ciphers(); + const std::vector<std::string> hashes = policy.allowed_hashes(); + const std::vector<std::string> kex = policy.allowed_key_exchange_methods(); + const std::vector<std::string> sigs = policy.allowed_signature_methods(); + + Ciphersuite_Preference_Ordering order(ciphers, hashes, kex, sigs); + + std::map<Ciphersuite, u16bit, Ciphersuite_Preference_Ordering> + ciphersuites(order); + + for(size_t i = 0; i != 65536; ++i) + { + Ciphersuite suite = Ciphersuite::by_id(i); + + if(!suite.valid()) + continue; // not a ciphersuite we know, skip + + if(!have_srp && suite.kex_algo() == "SRP_SHA") + continue; + + if(!value_exists(kex, suite.kex_algo())) + continue; // unsupported key exchange + + if(!value_exists(ciphers, suite.cipher_algo())) + continue; // unsupported cipher + + if(!value_exists(hashes, suite.mac_algo())) + continue; // unsupported MAC algo + + if(!value_exists(sigs, suite.sig_algo())) + { + // allow if it's an empty sig algo and we want to use PSK + if(suite.sig_algo() != "" || !suite.psk_ciphersuite()) + continue; + } + + // OK, allow it: + ciphersuites[suite] = i; + } + + std::vector<u16bit> ciphersuite_codes; + + for(std::map<Ciphersuite, u16bit, Ciphersuite_Preference_Ordering>::iterator i = ciphersuites.begin(); + i != ciphersuites.end(); ++i) + { + ciphersuite_codes.push_back(i->second); + } + + return ciphersuite_codes; + } + +} + +} diff --git a/src/tls/tls_policy.h b/src/tls/tls_policy.h new file mode 100644 index 000000000..c3a0fc29e --- /dev/null +++ b/src/tls/tls_policy.h @@ -0,0 +1,127 @@ +/* +* Policies +* (C) 2004-2006 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#ifndef BOTAN_TLS_POLICY_H__ +#define BOTAN_TLS_POLICY_H__ + +#include <botan/tls_version.h> +#include <botan/x509cert.h> +#include <botan/dl_group.h> +#include <vector> + +namespace Botan { + +namespace TLS { + +/** +* TLS Policy Base Class +* Inherit and overload as desired to suit local policy concerns +*/ +class BOTAN_DLL Policy + { + public: + + /** + * Returns a list of ciphers we are willing to negotiate, in + * order of preference. Allowed values: any block cipher name, or + * ARC4. + */ + virtual std::vector<std::string> allowed_ciphers() const; + + /** + * Returns a list of hash algorithms we are willing to use, in + * order of preference. This is used for both MACs and signatures. + * Allowed values: any hash name, though currently only MD5, + * SHA-1, and the SHA-2 variants are used. + */ + virtual std::vector<std::string> allowed_hashes() const; + + /** + * Returns a list of key exchange algorithms we are willing to + * use, in order of preference. Allowed values: DH, empty string + * (representing RSA using server certificate key) + */ + virtual std::vector<std::string> allowed_key_exchange_methods() const; + + /** + * Returns a list of signature algorithms we are willing to + * use, in order of preference. Allowed values RSA and DSA. + */ + virtual std::vector<std::string> allowed_signature_methods() const; + + /** + * Return list of ECC curves we are willing to use in order of preference + */ + virtual std::vector<std::string> allowed_ecc_curves() const; + + /** + * Returns a list of signature algorithms we are willing to use, + * in order of preference. Allowed values any value of + * Compression_Method. + */ + virtual std::vector<byte> compression() const; + + /** + * Choose an elliptic curve to use + */ + virtual std::string choose_curve(const std::vector<std::string>& curve_names) const; + + /** + * Require support for RFC 5746 extensions to enable + * renegotiation. + * + * @warning Changing this to false exposes you to injected + * plaintext attacks. Read the RFC for background. + */ + virtual bool require_secure_renegotiation() const { return true; } + + /** + * Return the group to use for ephemeral Diffie-Hellman key agreement + */ + virtual DL_Group dh_group() const; + + /** + * If this function returns false, unknown SRP/PSK identifiers + * will be rejected with an unknown_psk_identifier alert as soon + * as the non-existence is identified. Otherwise, a false + * identifier value will be used and the protocol allowed to + * proceed, causing the handshake to eventually fail without + * revealing that the username does not exist on this system. + */ + virtual bool hide_unknown_users() const { return false; } + + /** + * Return the allowed lifetime of a session ticket. If 0, session + * tickets do not expire until the session ticket key rolls over. + * Expired session tickets cannot be used to resume a session. + */ + virtual u32bit session_ticket_lifetime() const; + + /** + * @return the minimum version that we are willing to negotiate + */ + virtual Protocol_Version min_version() const; + + /** + * @return the version we would prefer to negotiate + */ + virtual Protocol_Version pref_version() const; + + virtual ~Policy() {} + }; + +/** +* Return allowed ciphersuites, in order of preference +*/ +std::vector<u16bit> ciphersuite_list(const Policy& policy, + bool have_srp); + +} + +} + +#endif diff --git a/src/ssl/tls_reader.h b/src/tls/tls_reader.h index 3a45235b5..7440e16b7 100644 --- a/src/ssl/tls_reader.h +++ b/src/tls/tls_reader.h @@ -1,6 +1,6 @@ /* * TLS Data Reader -* (C) 2010 Jack Lloyd +* (C) 2010-2011 Jack Lloyd * * Released under the terms of the Botan license */ @@ -8,20 +8,32 @@ #ifndef BOTAN_TLS_READER_H__ #define BOTAN_TLS_READER_H__ +#include <botan/exceptn.h> #include <botan/secmem.h> #include <botan/loadstor.h> +#include <string> +#include <vector> +#include <stdexcept> namespace Botan { +namespace TLS { + /** * Helper class for decoding TLS protocol messages */ class TLS_Data_Reader { public: - TLS_Data_Reader(const MemoryRegion<byte>& buf_in) : + TLS_Data_Reader(const std::vector<byte>& buf_in) : buf(buf_in), offset(0) {} + void assert_done() const + { + if(has_remaining()) + throw Decoding_Error("Extra bytes at end of message"); + } + size_t remaining_bytes() const { return buf.size() - offset; @@ -38,6 +50,15 @@ class TLS_Data_Reader offset += bytes; } + u16bit get_u32bit() + { + assert_at_least(4); + u16bit result = make_u32bit(buf[offset ], buf[offset+1], + buf[offset+2], buf[offset+3]); + offset += 4; + return result; + } + u16bit get_u16bit() { assert_at_least(2); @@ -70,14 +91,14 @@ class TLS_Data_Reader } template<typename T> - SecureVector<T> get_range(size_t len_bytes, + std::vector<T> get_range(size_t len_bytes, size_t min_elems, size_t max_elems) { const size_t num_elems = get_num_elems(len_bytes, sizeof(T), min_elems, max_elems); - return get_elem<T, SecureVector<T> >(num_elems); + return get_elem<T, std::vector<T> >(num_elems); } template<typename T> @@ -91,10 +112,20 @@ class TLS_Data_Reader return get_elem<T, std::vector<T> >(num_elems); } + std::string get_string(size_t len_bytes, + size_t min_bytes, + size_t max_bytes) + { + std::vector<byte> v = + get_range_vector<byte>(len_bytes, min_bytes, max_bytes); + + return std::string(reinterpret_cast<char*>(&v[0]), v.size()); + } + template<typename T> - SecureVector<T> get_fixed(size_t size) + std::vector<T> get_fixed(size_t size) { - return get_elem<T, SecureVector<T> >(size); + return get_elem<T, std::vector<T> >(size); } private: @@ -131,18 +162,22 @@ class TLS_Data_Reader void assert_at_least(size_t n) const { if(buf.size() - offset < n) - throw Decoding_Error("TLS_Data_Reader: Corrupt packet"); + { + throw Decoding_Error("TLS_Data_Reader: Expected " + std::to_string(n) + + " bytes remaining, only " + std::to_string(buf.size()-offset) + + " left"); + } } - const MemoryRegion<byte>& buf; + const std::vector<byte>& buf; size_t offset; }; /** * Helper function for encoding length-tagged vectors */ -template<typename T> -void append_tls_length_value(MemoryRegion<byte>& buf, +template<typename T, typename Alloc> +void append_tls_length_value(std::vector<byte, Alloc>& buf, const T* vals, size_t vals_size, size_t tag_size) @@ -165,22 +200,27 @@ void append_tls_length_value(MemoryRegion<byte>& buf, buf.push_back(get_byte(j, vals[i])); } -template<typename T> -void append_tls_length_value(MemoryRegion<byte>& buf, - const MemoryRegion<T>& vals, +template<typename T, typename Alloc, typename Alloc2> +void append_tls_length_value(std::vector<byte, Alloc>& buf, + const std::vector<T, Alloc2>& vals, size_t tag_size) { append_tls_length_value(buf, &vals[0], vals.size(), tag_size); } -template<typename T> -void append_tls_length_value(MemoryRegion<byte>& buf, - const std::vector<T>& vals, +template<typename Alloc> +void append_tls_length_value(std::vector<byte, Alloc>& buf, + const std::string& str, size_t tag_size) { - append_tls_length_value(buf, &vals[0], vals.size(), tag_size); + append_tls_length_value(buf, + reinterpret_cast<const byte*>(&str[0]), + str.size(), + tag_size); } } +} + #endif diff --git a/src/tls/tls_record.h b/src/tls/tls_record.h new file mode 100644 index 000000000..a92dcbe9d --- /dev/null +++ b/src/tls/tls_record.h @@ -0,0 +1,136 @@ +/* +* TLS Record Handling +* (C) 2004-2012 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#ifndef BOTAN_TLS_RECORDS_H__ +#define BOTAN_TLS_RECORDS_H__ + +#include <botan/tls_ciphersuite.h> +#include <botan/tls_alert.h> +#include <botan/tls_magic.h> +#include <botan/tls_version.h> +#include <botan/pipe.h> +#include <botan/mac.h> +#include <botan/secqueue.h> +#include <vector> +#include <functional> + +namespace Botan { + +namespace TLS { + +class Session_Keys; + +/** +* TLS Record Writer +*/ +class BOTAN_DLL Record_Writer + { + public: + void send(byte type, const byte input[], size_t length); + void send(byte type, byte val) { send(type, &val, 1); } + + void send(byte type, const std::vector<byte>& input) + { send(type, &input[0], input.size()); } + + std::vector<byte> send(class Handshake_Message& msg); + + void send_alert(const Alert& alert); + + void activate(Connection_Side side, + const Ciphersuite& suite, + const Session_Keys& keys, + byte compression_method); + + void set_version(Protocol_Version version); + + void reset(); + + void set_maximum_fragment_size(size_t max_fragment); + + Record_Writer(std::function<void (const byte[], size_t)> output_fn); + + ~Record_Writer() { delete m_mac; } + private: + Record_Writer(const Record_Writer&) {} + Record_Writer& operator=(const Record_Writer&) { return (*this); } + + void send_record(byte type, const byte input[], size_t length); + + std::function<void (const byte[], size_t)> m_output_fn; + + std::vector<byte> m_writebuf; + + Pipe m_cipher; + MessageAuthenticationCode* m_mac; + + size_t m_block_size, m_mac_size, m_iv_size, m_max_fragment; + + u64bit m_seq_no; + Protocol_Version m_version; + }; + +/** +* TLS Record Reader +*/ +class BOTAN_DLL Record_Reader + { + public: + + /** + * @param input new input data (may be NULL if input_size == 0) + * @param input_size size of input in bytes + * @param input_consumed is set to the number of bytes of input + * that were consumed + * @param msg_type is set to the type of the message just read if + * this function returns 0 + * @param msg is set to the contents of the record + * @return number of bytes still needed (minimum), or 0 if success + */ + size_t add_input(const byte input[], size_t input_size, + size_t& input_consumed, + byte& msg_type, + std::vector<byte>& msg); + + void activate(Connection_Side side, + const Ciphersuite& suite, + const Session_Keys& keys, + byte compression_method); + + void set_version(Protocol_Version version); + + void reset(); + + void set_maximum_fragment_size(size_t max_fragment); + + Record_Reader(); + + ~Record_Reader() { delete m_mac; } + private: + Record_Reader(const Record_Reader&) {} + Record_Reader& operator=(const Record_Reader&) { return (*this); } + + size_t fill_buffer_to(const byte*& input, + size_t& input_size, + size_t& input_consumed, + size_t desired); + + std::vector<byte> m_readbuf; + std::vector<byte> m_macbuf; + size_t m_readbuf_pos; + + Pipe m_cipher; + MessageAuthenticationCode* m_mac; + size_t m_block_size, m_iv_size, m_max_fragment; + u64bit m_seq_no; + Protocol_Version m_version; + }; + +} + +} + +#endif diff --git a/src/tls/tls_server.cpp b/src/tls/tls_server.cpp new file mode 100644 index 000000000..241215d59 --- /dev/null +++ b/src/tls/tls_server.cpp @@ -0,0 +1,620 @@ +/* +* TLS Server +* (C) 2004-2011,2012 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#include <botan/tls_server.h> +#include <botan/internal/tls_handshake_state.h> +#include <botan/internal/tls_messages.h> +#include <botan/internal/stl_util.h> +#include <botan/internal/assert.h> +#include <memory> + +namespace Botan { + +namespace TLS { + +namespace { + +bool check_for_resume(Session& session_info, + Session_Manager& session_manager, + Credentials_Manager& credentials, + Client_Hello* client_hello, + std::chrono::seconds session_ticket_lifetime) + { + const std::vector<byte>& client_session_id = client_hello->session_id(); + const std::vector<byte>& session_ticket = client_hello->session_ticket(); + + if(session_ticket.empty()) + { + if(client_session_id.empty()) // not resuming + return false; + + // not found + if(!session_manager.load_from_session_id(client_session_id, session_info)) + return false; + } + else + { + // If a session ticket was sent, ignore client session ID + try + { + session_info = Session::decrypt( + session_ticket, + credentials.psk("tls-server", "session-ticket", "")); + + if(session_ticket_lifetime != std::chrono::seconds(0) && + session_info.session_age() > session_ticket_lifetime) + return false; // ticket has expired + } + catch(...) + { + return false; + } + } + + // wrong version + if(client_hello->version() != session_info.version()) + return false; + + // client didn't send original ciphersuite + if(!value_exists(client_hello->ciphersuites(), + session_info.ciphersuite_code())) + return false; + + // client didn't send original compression method + if(!value_exists(client_hello->compression_methods(), + session_info.compression_method())) + return false; + + // client sent a different SRP identity + if(client_hello->srp_identifier() != "") + { + if(client_hello->srp_identifier() != session_info.srp_identifier()) + return false; + } + + // client sent a different SNI hostname + if(client_hello->sni_hostname() != "") + { + if(client_hello->sni_hostname() != session_info.sni_hostname()) + return false; + } + + return true; + } + +/* +* Choose which ciphersuite to use +*/ +u16bit choose_ciphersuite( + const Policy& policy, + Credentials_Manager& creds, + const std::map<std::string, std::vector<X509_Certificate> >& cert_chains, + const Client_Hello* client_hello) + { + const bool have_srp = creds.attempt_srp("tls-server", + client_hello->sni_hostname()); + + const std::vector<u16bit> client_suites = client_hello->ciphersuites(); + const std::vector<u16bit> server_suites = ciphersuite_list(policy, have_srp); + + if(server_suites.empty()) + throw Internal_Error("Policy forbids us from negotiating any ciphersuite"); + + const bool have_shared_ecc_curve = + (policy.choose_curve(client_hello->supported_ecc_curves()) != ""); + + // Ordering by our preferences rather than by clients + for(size_t i = 0; i != server_suites.size(); ++i) + { + const u16bit suite_id = server_suites[i]; + + if(!value_exists(client_suites, suite_id)) + continue; + + Ciphersuite suite = Ciphersuite::by_id(suite_id); + + if(!have_shared_ecc_curve && suite.ecc_ciphersuite()) + continue; + + if(cert_chains.count(suite.sig_algo()) == 0) + continue; + + /* + The client may offer SRP cipher suites in the hello message but + omit the SRP extension. If the server would like to select an + SRP cipher suite in this case, the server SHOULD return a fatal + "unknown_psk_identity" alert immediately after processing the + client hello message. + - RFC 5054 section 2.5.1.2 + */ + if(suite.kex_algo() == "SRP_SHA" && client_hello->srp_identifier() == "") + throw TLS_Exception(Alert::UNKNOWN_PSK_IDENTITY, + "Client wanted SRP but did not send username"); + + return suite_id; + } + + throw TLS_Exception(Alert::HANDSHAKE_FAILURE, + "Can't agree on a ciphersuite with client"); + } + + +/* +* Choose which compression algorithm to use +*/ +byte choose_compression(const Policy& policy, + const std::vector<byte>& c_comp) + { + std::vector<byte> s_comp = policy.compression(); + + for(size_t i = 0; i != s_comp.size(); ++i) + for(size_t j = 0; j != c_comp.size(); ++j) + if(s_comp[i] == c_comp[j]) + return s_comp[i]; + + return NO_COMPRESSION; + } + +std::map<std::string, std::vector<X509_Certificate> > +get_server_certs(const std::string& hostname, + Credentials_Manager& creds) + { + const char* cert_types[] = { "RSA", "DSA", "ECDSA", nullptr }; + + std::map<std::string, std::vector<X509_Certificate> > cert_chains; + + for(size_t i = 0; cert_types[i]; ++i) + { + std::vector<X509_Certificate> certs = + creds.cert_chain_single_type(cert_types[i], "tls-server", hostname); + + if(!certs.empty()) + cert_chains[cert_types[i]] = certs; + } + + return cert_chains; + } + +} + +/* +* TLS Server Constructor +*/ +Server::Server(std::function<void (const byte[], size_t)> output_fn, + std::function<void (const byte[], size_t, Alert)> proc_fn, + std::function<bool (const Session&)> handshake_fn, + Session_Manager& session_manager, + Credentials_Manager& creds, + const Policy& policy, + RandomNumberGenerator& rng, + const std::vector<std::string>& next_protocols) : + Channel(output_fn, proc_fn, handshake_fn), + policy(policy), + rng(rng), + session_manager(session_manager), + creds(creds), + m_possible_protocols(next_protocols) + { + } + +/* +* Send a hello request to the client +*/ +void Server::renegotiate(bool force_full_renegotiation) + { + if(state) + return; // currently in handshake + + state = new Handshake_State(new Stream_Handshake_Reader); + + state->allow_session_resumption = !force_full_renegotiation; + state->set_expected_next(CLIENT_HELLO); + Hello_Request hello_req(writer); + } + +void Server::alert_notify(const Alert& alert) + { + if(alert.type() == Alert::NO_RENEGOTIATION) + { + if(handshake_completed && state) + { + delete state; + state = nullptr; + } + } + } + +/* +* Split up and process handshake messages +*/ +void Server::read_handshake(byte rec_type, + const std::vector<byte>& rec_buf) + { + if(rec_type == HANDSHAKE && !state) + { + state = new Handshake_State(new Stream_Handshake_Reader); + state->set_expected_next(CLIENT_HELLO); + } + + Channel::read_handshake(rec_type, rec_buf); + } + +/* +* Process a handshake message +*/ +void Server::process_handshake_msg(Handshake_Type type, + const std::vector<byte>& contents) + { + if(!state) + throw Unexpected_Message("Unexpected handshake message from client"); + + state->confirm_transition_to(type); + + /* + * The change cipher spec message isn't technically a handshake + * message so it's not included in the hash. The finished and + * certificate verify messages are verified based on the current + * state of the hash *before* this message so we delay adding them + * to the hash computation until we've processed them below. + */ + if(type != HANDSHAKE_CCS && type != FINISHED && type != CERTIFICATE_VERIFY) + { + if(type == CLIENT_HELLO_SSLV2) + state->hash.update(contents); + else + state->hash.update(type, contents); + } + + if(type == CLIENT_HELLO || type == CLIENT_HELLO_SSLV2) + { + state->client_hello = new Client_Hello(contents, type); + + if(state->client_hello->sni_hostname() != "") + m_hostname = state->client_hello->sni_hostname(); + + Protocol_Version client_version = state->client_hello->version(); + + if(client_version < policy.min_version()) + throw TLS_Exception(Alert::PROTOCOL_VERSION, + "Client version is unacceptable by policy"); + + if(client_version <= policy.pref_version()) + state->set_version(client_version); + else + state->set_version(policy.pref_version()); + + secure_renegotiation.update(state->client_hello); + + m_peer_supports_heartbeats = state->client_hello->supports_heartbeats(); + m_heartbeat_sending_allowed = state->client_hello->peer_can_send_heartbeats(); + + writer.set_version(state->version()); + reader.set_version(state->version()); + + Session session_info; + const bool resuming = + state->allow_session_resumption && + check_for_resume(session_info, + session_manager, + creds, + state->client_hello, + std::chrono::seconds(policy.session_ticket_lifetime())); + + bool have_session_ticket_key = false; + + try + { + have_session_ticket_key = + creds.psk("tls-server", "session-ticket", "").length() > 0; + } + catch(...) {} + + if(resuming) + { + // resume session + + state->server_hello = new Server_Hello( + writer, + state->hash, + state->client_hello->session_id(), + Protocol_Version(session_info.version()), + session_info.ciphersuite_code(), + session_info.compression_method(), + session_info.fragment_size(), + secure_renegotiation.supported(), + secure_renegotiation.for_server_hello(), + (state->client_hello->supports_session_ticket() && + state->client_hello->session_ticket().empty() && + have_session_ticket_key), + state->client_hello->next_protocol_notification(), + m_possible_protocols, + state->client_hello->supports_heartbeats(), + rng); + + secure_renegotiation.update(state->server_hello); + + if(session_info.fragment_size()) + { + reader.set_maximum_fragment_size(session_info.fragment_size()); + writer.set_maximum_fragment_size(session_info.fragment_size()); + } + + state->suite = Ciphersuite::by_id(state->server_hello->ciphersuite()); + + state->keys = Session_Keys(state, session_info.master_secret(), true); + + if(!handshake_fn(session_info)) + { + session_manager.remove_entry(session_info.session_id()); + + if(state->server_hello->supports_session_ticket()) // send an empty ticket + state->new_session_ticket = new New_Session_Ticket(writer, state->hash); + } + + if(state->server_hello->supports_session_ticket() && !state->new_session_ticket) + { + try + { + const SymmetricKey ticket_key = creds.psk("tls-server", "session-ticket", ""); + + state->new_session_ticket = + new New_Session_Ticket(writer, state->hash, + session_info.encrypt(ticket_key, rng), + policy.session_ticket_lifetime()); + } + catch(...) {} + + if(!state->new_session_ticket) + state->new_session_ticket = new New_Session_Ticket(writer, state->hash); + } + + writer.send(CHANGE_CIPHER_SPEC, 1); + + writer.activate(SERVER, state->suite, state->keys, + state->server_hello->compression_method()); + + state->server_finished = new Finished(writer, state, SERVER); + + state->set_expected_next(HANDSHAKE_CCS); + } + else // new session + { + std::map<std::string, std::vector<X509_Certificate> > cert_chains; + + cert_chains = get_server_certs(m_hostname, creds); + + if(m_hostname != "" && cert_chains.empty()) + { + send_alert(Alert(Alert::UNRECOGNIZED_NAME)); + cert_chains = get_server_certs("", creds); + } + + state->server_hello = new Server_Hello( + writer, + state->hash, + unlock(rng.random_vec(32)), // new session ID + state->version(), + choose_ciphersuite(policy, creds, cert_chains, state->client_hello), + choose_compression(policy, state->client_hello->compression_methods()), + state->client_hello->fragment_size(), + secure_renegotiation.supported(), + secure_renegotiation.for_server_hello(), + state->client_hello->supports_session_ticket() && have_session_ticket_key, + state->client_hello->next_protocol_notification(), + m_possible_protocols, + state->client_hello->supports_heartbeats(), + rng); + + secure_renegotiation.update(state->server_hello); + + if(state->client_hello->fragment_size()) + { + reader.set_maximum_fragment_size(state->client_hello->fragment_size()); + writer.set_maximum_fragment_size(state->client_hello->fragment_size()); + } + + state->suite = Ciphersuite::by_id(state->server_hello->ciphersuite()); + + const std::string sig_algo = state->suite.sig_algo(); + const std::string kex_algo = state->suite.kex_algo(); + + if(sig_algo != "") + { + BOTAN_ASSERT(!cert_chains[sig_algo].empty(), + "Attempting to send empty certificate chain"); + + state->server_certs = new Certificate(writer, + state->hash, + cert_chains[sig_algo]); + } + + Private_Key* private_key = nullptr; + + if(kex_algo == "RSA" || sig_algo != "") + { + private_key = creds.private_key_for(state->server_certs->cert_chain()[0], + "tls-server", + m_hostname); + + if(!private_key) + throw Internal_Error("No private key located for associated server cert"); + } + + if(kex_algo == "RSA") + { + state->server_rsa_kex_key = private_key; + } + else + { + state->server_kex = + new Server_Key_Exchange(writer, state, policy, creds, rng, private_key); + } + + std::vector<X509_Certificate> client_auth_CAs = + creds.trusted_certificate_authorities("tls-server", m_hostname); + + if(!client_auth_CAs.empty() && state->suite.sig_algo() != "") + { + state->cert_req = new Certificate_Req(writer, + state->hash, + policy, + client_auth_CAs, + state->version()); + + state->set_expected_next(CERTIFICATE); + } + + /* + * If the client doesn't have a cert they want to use they are + * allowed to send either an empty cert message or proceed + * directly to the client key exchange, so allow either case. + */ + state->set_expected_next(CLIENT_KEX); + + state->server_hello_done = new Server_Hello_Done(writer, state->hash); + } + } + else if(type == CERTIFICATE) + { + state->client_certs = new Certificate(contents); + + state->set_expected_next(CLIENT_KEX); + } + else if(type == CLIENT_KEX) + { + if(state->received_handshake_msg(CERTIFICATE) && !state->client_certs->empty()) + state->set_expected_next(CERTIFICATE_VERIFY); + else + state->set_expected_next(HANDSHAKE_CCS); + + state->client_kex = new Client_Key_Exchange(contents, state, creds, policy, rng); + + state->keys = Session_Keys(state, state->client_kex->pre_master_secret(), false); + } + else if(type == CERTIFICATE_VERIFY) + { + state->client_verify = new Certificate_Verify(contents, state->version()); + + peer_certs = state->client_certs->cert_chain(); + + const bool sig_valid = + state->client_verify->verify(peer_certs[0], state); + + state->hash.update(type, contents); + + /* + * Using DECRYPT_ERROR looks weird here, but per RFC 4346 is for + * "A handshake cryptographic operation failed, including being + * unable to correctly verify a signature, ..." + */ + if(!sig_valid) + throw TLS_Exception(Alert::DECRYPT_ERROR, "Client cert verify failed"); + + try + { + creds.verify_certificate_chain("tls-server", "", peer_certs); + } + catch(std::exception& e) + { + throw TLS_Exception(Alert::BAD_CERTIFICATE, e.what()); + } + + state->set_expected_next(HANDSHAKE_CCS); + } + else if(type == HANDSHAKE_CCS) + { + if(state->server_hello->next_protocol_notification()) + state->set_expected_next(NEXT_PROTOCOL); + else + state->set_expected_next(FINISHED); + + reader.activate(SERVER, state->suite, state->keys, + state->server_hello->compression_method()); + } + else if(type == NEXT_PROTOCOL) + { + state->set_expected_next(FINISHED); + + state->next_protocol = new Next_Protocol(contents); + + m_next_protocol = state->next_protocol->protocol(); + } + else if(type == FINISHED) + { + state->set_expected_next(HANDSHAKE_NONE); + + state->client_finished = new Finished(contents); + + if(!state->client_finished->verify(state, CLIENT)) + throw TLS_Exception(Alert::DECRYPT_ERROR, + "Finished message didn't verify"); + + if(!state->server_finished) + { + // already sent finished if resuming, so this is a new session + + state->hash.update(type, contents); + + Session session_info( + state->server_hello->session_id(), + state->keys.master_secret(), + state->server_hello->version(), + state->server_hello->ciphersuite(), + state->server_hello->compression_method(), + SERVER, + secure_renegotiation.supported(), + state->server_hello->fragment_size(), + peer_certs, + std::vector<byte>(), + m_hostname, + state->srp_identifier() + ); + + if(handshake_fn(session_info)) + { + if(state->server_hello->supports_session_ticket()) + { + try + { + const SymmetricKey ticket_key = creds.psk("tls-server", "session-ticket", ""); + + state->new_session_ticket = + new New_Session_Ticket(writer, state->hash, + session_info.encrypt(ticket_key, rng), + policy.session_ticket_lifetime()); + } + catch(...) {} + } + else + session_manager.save(session_info); + } + + if(state->server_hello->supports_session_ticket() && !state->new_session_ticket) + state->new_session_ticket = new New_Session_Ticket(writer, state->hash); + + writer.send(CHANGE_CIPHER_SPEC, 1); + + writer.activate(SERVER, state->suite, state->keys, + state->server_hello->compression_method()); + + state->server_finished = new Finished(writer, state, SERVER); + } + + secure_renegotiation.update(state->client_finished, + state->server_finished); + + delete state; + state = nullptr; + handshake_completed = true; + } + else + throw Unexpected_Message("Unknown handshake message received"); + } + +} + +} diff --git a/src/tls/tls_server.h b/src/tls/tls_server.h new file mode 100644 index 000000000..441e03eb2 --- /dev/null +++ b/src/tls/tls_server.h @@ -0,0 +1,74 @@ +/* +* TLS Server +* (C) 2004-2011 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#ifndef BOTAN_TLS_SERVER_H__ +#define BOTAN_TLS_SERVER_H__ + +#include <botan/tls_channel.h> +#include <botan/tls_session_manager.h> +#include <botan/credentials_manager.h> +#include <vector> + +namespace Botan { + +namespace TLS { + +/** +* TLS Server +*/ +class BOTAN_DLL Server : public Channel + { + public: + /** + * Server initialization + */ + Server(std::function<void (const byte[], size_t)> socket_output_fn, + std::function<void (const byte[], size_t, Alert)> proc_fn, + std::function<bool (const Session&)> handshake_complete, + Session_Manager& session_manager, + Credentials_Manager& creds, + const Policy& policy, + RandomNumberGenerator& rng, + const std::vector<std::string>& protocols = + std::vector<std::string>()); + + void renegotiate(bool force_full_renegotiation); + + /** + * Return the server name indicator, if sent by the client + */ + std::string server_name_indicator() const + { return m_hostname; } + + /** + * Return the protocol negotiated with NPN extension + */ + std::string next_protocol() const + { return m_next_protocol; } + + private: + void read_handshake(byte, const std::vector<byte>&); + + void process_handshake_msg(Handshake_Type, const std::vector<byte>&); + + void alert_notify(const Alert& alert); + + const Policy& policy; + RandomNumberGenerator& rng; + Session_Manager& session_manager; + Credentials_Manager& creds; + + std::vector<std::string> m_possible_protocols; + std::string m_hostname; + std::string m_next_protocol; + }; + +} + +} + +#endif diff --git a/src/tls/tls_session.cpp b/src/tls/tls_session.cpp new file mode 100644 index 000000000..d2aae9a7e --- /dev/null +++ b/src/tls/tls_session.cpp @@ -0,0 +1,251 @@ +/* +* TLS Session State +* (C) 2011-2012 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#include <botan/tls_session.h> +#include <botan/der_enc.h> +#include <botan/ber_dec.h> +#include <botan/asn1_str.h> +#include <botan/pem.h> +#include <botan/lookup.h> +#include <botan/loadstor.h> +#include <memory> + +namespace Botan { + +namespace TLS { + +Session::Session(const std::vector<byte>& session_identifier, + const secure_vector<byte>& master_secret, + Protocol_Version version, + u16bit ciphersuite, + byte compression_method, + Connection_Side side, + bool secure_renegotiation_supported, + size_t fragment_size, + const std::vector<X509_Certificate>& certs, + const std::vector<byte>& ticket, + const std::string& sni_hostname, + const std::string& srp_identifier) : + m_start_time(std::chrono::system_clock::now()), + m_identifier(session_identifier), + m_session_ticket(ticket), + m_master_secret(master_secret), + m_version(version), + m_ciphersuite(ciphersuite), + m_compression_method(compression_method), + m_connection_side(side), + m_secure_renegotiation_supported(secure_renegotiation_supported), + m_fragment_size(fragment_size), + m_peer_certs(certs), + m_sni_hostname(sni_hostname), + m_srp_identifier(srp_identifier) + { + } + +Session::Session(const std::string& pem) + { + secure_vector<byte> der = PEM_Code::decode_check_label(pem, "SSL SESSION"); + + *this = Session(&der[0], der.size()); + } + +Session::Session(const byte ber[], size_t ber_len) + { + byte side_code = 0; + ASN1_String sni_hostname_str; + ASN1_String srp_identifier_str; + + byte major_version = 0, minor_version = 0; + + std::vector<byte> peer_cert_bits; + + size_t start_time = 0; + + BER_Decoder(ber, ber_len) + .start_cons(SEQUENCE) + .decode_and_check(static_cast<size_t>(TLS_SESSION_PARAM_STRUCT_VERSION), + "Unknown version in session structure") + .decode_integer_type(start_time) + .decode_integer_type(major_version) + .decode_integer_type(minor_version) + .decode(m_identifier, OCTET_STRING) + .decode(m_session_ticket, OCTET_STRING) + .decode_integer_type(m_ciphersuite) + .decode_integer_type(m_compression_method) + .decode_integer_type(side_code) + .decode_integer_type(m_fragment_size) + .decode(m_secure_renegotiation_supported) + .decode(m_master_secret, OCTET_STRING) + .decode(peer_cert_bits, OCTET_STRING) + .decode(sni_hostname_str) + .decode(srp_identifier_str) + .end_cons() + .verify_end(); + + m_version = Protocol_Version(major_version, minor_version); + m_start_time = std::chrono::system_clock::from_time_t(start_time); + m_sni_hostname = sni_hostname_str.value(); + m_srp_identifier = srp_identifier_str.value(); + m_connection_side = static_cast<Connection_Side>(side_code); + + if(!peer_cert_bits.empty()) + { + DataSource_Memory certs(&peer_cert_bits[0], peer_cert_bits.size()); + + while(!certs.end_of_data()) + m_peer_certs.push_back(X509_Certificate(certs)); + } + } + +secure_vector<byte> Session::DER_encode() const + { + std::vector<byte> peer_cert_bits; + for(size_t i = 0; i != m_peer_certs.size(); ++i) + peer_cert_bits += m_peer_certs[i].BER_encode(); + + return DER_Encoder() + .start_cons(SEQUENCE) + .encode(static_cast<size_t>(TLS_SESSION_PARAM_STRUCT_VERSION)) + .encode(static_cast<size_t>(std::chrono::system_clock::to_time_t(m_start_time))) + .encode(static_cast<size_t>(m_version.major_version())) + .encode(static_cast<size_t>(m_version.minor_version())) + .encode(m_identifier, OCTET_STRING) + .encode(m_session_ticket, OCTET_STRING) + .encode(static_cast<size_t>(m_ciphersuite)) + .encode(static_cast<size_t>(m_compression_method)) + .encode(static_cast<size_t>(m_connection_side)) + .encode(static_cast<size_t>(m_fragment_size)) + .encode(m_secure_renegotiation_supported) + .encode(m_master_secret, OCTET_STRING) + .encode(peer_cert_bits, OCTET_STRING) + .encode(ASN1_String(m_sni_hostname, UTF8_STRING)) + .encode(ASN1_String(m_srp_identifier, UTF8_STRING)) + .end_cons() + .get_contents(); + } + +std::string Session::PEM_encode() const + { + return PEM_Code::encode(this->DER_encode(), "SSL SESSION"); + } + +std::chrono::seconds Session::session_age() const + { + return std::chrono::duration_cast<std::chrono::seconds>( + std::chrono::system_clock::now() - m_start_time); + } + +namespace { + +const u32bit SESSION_CRYPTO_MAGIC = 0x571B0E4E; +const std::string SESSION_CRYPTO_CIPHER = "AES-256/CBC"; +const std::string SESSION_CRYPTO_MAC = "HMAC(SHA-256)"; +const std::string SESSION_CRYPTO_KDF = "KDF2(SHA-256)"; + +const size_t MAGIC_LENGTH = 4; +const size_t MAC_KEY_LENGTH = 32; +const size_t CIPHER_KEY_LENGTH = 32; +const size_t CIPHER_IV_LENGTH = 16; +const size_t MAC_OUTPUT_LENGTH = 32; + +} + +std::vector<byte> +Session::encrypt(const SymmetricKey& master_key, + RandomNumberGenerator& rng) const + { + std::unique_ptr<KDF> kdf(get_kdf(SESSION_CRYPTO_KDF)); + + SymmetricKey cipher_key = + kdf->derive_key(CIPHER_KEY_LENGTH, + master_key.bits_of(), + "tls.session.cipher-key"); + + SymmetricKey mac_key = + kdf->derive_key(MAC_KEY_LENGTH, + master_key.bits_of(), + "tls.session.mac-key"); + + InitializationVector cipher_iv(rng, 16); + + std::unique_ptr<MessageAuthenticationCode> mac(get_mac(SESSION_CRYPTO_MAC)); + mac->set_key(mac_key); + + Pipe pipe(get_cipher(SESSION_CRYPTO_CIPHER, cipher_key, cipher_iv, ENCRYPTION)); + pipe.process_msg(this->DER_encode()); + secure_vector<byte> ctext = pipe.read_all(0); + + std::vector<byte> out(MAGIC_LENGTH); + store_be(SESSION_CRYPTO_MAGIC, &out[0]); + out += cipher_iv.bits_of(); + out += ctext; + + mac->update(out); + + out += mac->final(); + return out; + } + +Session Session::decrypt(const byte buf[], size_t buf_len, + const SymmetricKey& master_key) + { + try + { + const size_t MIN_CTEXT_SIZE = 4 * 16; // due to 48 byte master secret + + if(buf_len < (MAGIC_LENGTH + + CIPHER_IV_LENGTH + + MIN_CTEXT_SIZE + + MAC_OUTPUT_LENGTH)) + throw Decoding_Error("Encrypted TLS session too short to be valid"); + + if(load_be<u32bit>(buf, 0) != SESSION_CRYPTO_MAGIC) + throw Decoding_Error("Unknown header value in encrypted session"); + + std::unique_ptr<KDF> kdf(get_kdf(SESSION_CRYPTO_KDF)); + + SymmetricKey mac_key = + kdf->derive_key(MAC_KEY_LENGTH, + master_key.bits_of(), + "tls.session.mac-key"); + + std::unique_ptr<MessageAuthenticationCode> mac(get_mac(SESSION_CRYPTO_MAC)); + mac->set_key(mac_key); + + mac->update(&buf[0], buf_len - MAC_OUTPUT_LENGTH); + secure_vector<byte> computed_mac = mac->final(); + + if(!same_mem(&buf[buf_len - MAC_OUTPUT_LENGTH], &computed_mac[0], computed_mac.size())) + throw Decoding_Error("MAC verification failed for encrypted session"); + + SymmetricKey cipher_key = + kdf->derive_key(CIPHER_KEY_LENGTH, + master_key.bits_of(), + "tls.session.cipher-key"); + + InitializationVector cipher_iv(&buf[MAGIC_LENGTH], CIPHER_IV_LENGTH); + + const size_t CTEXT_OFFSET = MAGIC_LENGTH + CIPHER_IV_LENGTH; + + Pipe pipe(get_cipher(SESSION_CRYPTO_CIPHER, cipher_key, cipher_iv, DECRYPTION)); + pipe.process_msg(&buf[CTEXT_OFFSET], + buf_len - (MAC_OUTPUT_LENGTH + CTEXT_OFFSET)); + secure_vector<byte> ber = pipe.read_all(); + + return Session(&ber[0], ber.size()); + } + catch(std::exception& e) + { + throw Decoding_Error("Failed to decrypt encrypted session -" + + std::string(e.what())); + } + } + +} + +} + diff --git a/src/tls/tls_session.h b/src/tls/tls_session.h new file mode 100644 index 000000000..2c474bc6a --- /dev/null +++ b/src/tls/tls_session.h @@ -0,0 +1,217 @@ +/* +* TLS Session +* (C) 2011-2012 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#ifndef BOTAN_TLS_SESSION_STATE_H__ +#define BOTAN_TLS_SESSION_STATE_H__ + +#include <botan/x509cert.h> +#include <botan/tls_version.h> +#include <botan/tls_ciphersuite.h> +#include <botan/tls_magic.h> +#include <botan/secmem.h> +#include <botan/symkey.h> +#include <chrono> + +namespace Botan { + +namespace TLS { + +/** +* Class representing a TLS session state +*/ +class BOTAN_DLL Session + { + public: + + /** + * Uninitialized session + */ + Session() : + m_start_time(std::chrono::system_clock::time_point::min()), + m_version(), + m_ciphersuite(0), + m_compression_method(0), + m_connection_side(static_cast<Connection_Side>(0)), + m_secure_renegotiation_supported(false), + m_fragment_size(0) + {} + + /** + * New session (sets session start time) + */ + Session(const std::vector<byte>& session_id, + const secure_vector<byte>& master_secret, + Protocol_Version version, + u16bit ciphersuite, + byte compression_method, + Connection_Side side, + bool secure_renegotiation_supported, + size_t fragment_size, + const std::vector<X509_Certificate>& peer_certs, + const std::vector<byte>& session_ticket, + const std::string& sni_hostname = "", + const std::string& srp_identifier = ""); + + /** + * Load a session from DER representation (created by DER_encode) + */ + Session(const byte ber[], size_t ber_len); + + /** + * Load a session from PEM representation (created by PEM_encode) + */ + Session(const std::string& pem); + + /** + * Encode this session data for storage + * @warning if the master secret is compromised so is the + * session traffic + */ + secure_vector<byte> DER_encode() const; + + /** + * Encrypt a session (useful for serialization or session tickets) + */ + std::vector<byte> encrypt(const SymmetricKey& key, + RandomNumberGenerator& rng) const; + + + /** + * Decrypt a session created by encrypt + * @param ctext the ciphertext returned by encrypt + * @param ctext_size the size of ctext in bytes + * @param key the same key used by the encrypting side + */ + static Session decrypt(const byte ctext[], + size_t ctext_size, + const SymmetricKey& key); + + /** + * Decrypt a session created by encrypt + * @param ctext the ciphertext returned by encrypt + * @param key the same key used by the encrypting side + */ + static inline Session decrypt(const std::vector<byte>& ctext, + const SymmetricKey& key) + { + return Session::decrypt(&ctext[0], ctext.size(), key); + } + + /** + * Encode this session data for storage + * @warning if the master secret is compromised so is the + * session traffic + */ + std::string PEM_encode() const; + + /** + * Get the version of the saved session + */ + Protocol_Version version() const { return m_version; } + + /** + * Get the ciphersuite code of the saved session + */ + u16bit ciphersuite_code() const { return m_ciphersuite; } + + /** + * Get the ciphersuite info of the saved session + */ + Ciphersuite ciphersuite() const { return Ciphersuite::by_id(m_ciphersuite); } + + /** + * Get the compression method used in the saved session + */ + byte compression_method() const { return m_compression_method; } + + /** + * Get which side of the connection the resumed session we are/were + * acting as. + */ + Connection_Side side() const { return m_connection_side; } + + /** + * Get the SNI hostname (if sent by the client in the initial handshake) + */ + std::string sni_hostname() const { return m_sni_hostname; } + + /** + * Get the SRP identity (if sent by the client in the initial handshake) + */ + std::string srp_identifier() const { return m_srp_identifier; } + + /** + * Get the saved master secret + */ + const secure_vector<byte>& master_secret() const + { return m_master_secret; } + + /** + * Get the session identifier + */ + const std::vector<byte>& session_id() const + { return m_identifier; } + + /** + * Get the negotiated maximum fragment size (or 0 if default) + */ + size_t fragment_size() const { return m_fragment_size; } + + /** + * Is secure renegotiation supported? + */ + bool secure_renegotiation() const + { return m_secure_renegotiation_supported; } + + /** + * Return the certificate chain of the peer (possibly empty) + */ + std::vector<X509_Certificate> peer_certs() const { return m_peer_certs; } + + /** + * Get the wall clock time this session began + */ + std::chrono::system_clock::time_point start_time() const + { return m_start_time; } + + /** + * Return how long this session has existed (in seconds) + */ + std::chrono::seconds session_age() const; + + /** + * Return the session ticket the server gave us + */ + const std::vector<byte>& session_ticket() const { return m_session_ticket; } + + private: + enum { TLS_SESSION_PARAM_STRUCT_VERSION = 0x2994e300 }; + + std::chrono::system_clock::time_point m_start_time; + + std::vector<byte> m_identifier; + std::vector<byte> m_session_ticket; // only used by client side + secure_vector<byte> m_master_secret; + + Protocol_Version m_version; + u16bit m_ciphersuite; + byte m_compression_method; + Connection_Side m_connection_side; + + bool m_secure_renegotiation_supported; + size_t m_fragment_size; + + std::vector<X509_Certificate> m_peer_certs; + std::string m_sni_hostname; // optional + std::string m_srp_identifier; // optional + }; + +} + +} + +#endif diff --git a/src/tls/tls_session_key.cpp b/src/tls/tls_session_key.cpp new file mode 100644 index 000000000..0cd74a63a --- /dev/null +++ b/src/tls/tls_session_key.cpp @@ -0,0 +1,89 @@ +/* +* TLS Session Key +* (C) 2004-2006,2011 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#include <botan/internal/tls_session_key.h> +#include <botan/internal/tls_handshake_state.h> +#include <botan/internal/tls_messages.h> +#include <botan/lookup.h> +#include <memory> + +namespace Botan { + +namespace TLS { + +/** +* Session_Keys Constructor +*/ +Session_Keys::Session_Keys(Handshake_State* state, + const secure_vector<byte>& pre_master_secret, + bool resuming) + { + const size_t mac_keylen = output_length_of(state->suite.mac_algo()); + const size_t cipher_keylen = state->suite.cipher_keylen(); + + size_t cipher_ivlen = 0; + if(have_block_cipher(state->suite.cipher_algo())) + cipher_ivlen = block_size_of(state->suite.cipher_algo()); + + const size_t prf_gen = 2 * (mac_keylen + cipher_keylen + cipher_ivlen); + + const byte MASTER_SECRET_MAGIC[] = { + 0x6D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74 }; + + const byte KEY_GEN_MAGIC[] = { + 0x6B, 0x65, 0x79, 0x20, 0x65, 0x78, 0x70, 0x61, 0x6E, 0x73, 0x69, 0x6F, 0x6E }; + + std::unique_ptr<KDF> prf(state->protocol_specific_prf()); + + if(resuming) + { + master_sec = pre_master_secret; + } + else + { + secure_vector<byte> salt; + + if(state->version() != Protocol_Version::SSL_V3) + salt += std::make_pair(MASTER_SECRET_MAGIC, sizeof(MASTER_SECRET_MAGIC)); + + salt += state->client_hello->random(); + salt += state->server_hello->random(); + + master_sec = prf->derive_key(48, pre_master_secret, salt); + } + + secure_vector<byte> salt; + if(state->version() != Protocol_Version::SSL_V3) + salt += std::make_pair(KEY_GEN_MAGIC, sizeof(KEY_GEN_MAGIC)); + salt += state->server_hello->random(); + salt += state->client_hello->random(); + + SymmetricKey keyblock = prf->derive_key(prf_gen, master_sec, salt); + + const byte* key_data = keyblock.begin(); + + c_mac = SymmetricKey(key_data, mac_keylen); + key_data += mac_keylen; + + s_mac = SymmetricKey(key_data, mac_keylen); + key_data += mac_keylen; + + c_cipher = SymmetricKey(key_data, cipher_keylen); + key_data += cipher_keylen; + + s_cipher = SymmetricKey(key_data, cipher_keylen); + key_data += cipher_keylen; + + c_iv = InitializationVector(key_data, cipher_ivlen); + key_data += cipher_ivlen; + + s_iv = InitializationVector(key_data, cipher_ivlen); + } + +} + +} diff --git a/src/tls/tls_session_key.h b/src/tls/tls_session_key.h new file mode 100644 index 000000000..0021694e3 --- /dev/null +++ b/src/tls/tls_session_key.h @@ -0,0 +1,52 @@ +/* +* TLS Session Key +* (C) 2004-2006,2011 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#ifndef BOTAN_TLS_SESSION_KEYS_H__ +#define BOTAN_TLS_SESSION_KEYS_H__ + +#include <botan/tls_ciphersuite.h> +#include <botan/tls_exceptn.h> +#include <botan/symkey.h> + +namespace Botan { + +namespace TLS { + +/** +* TLS Session Keys +*/ +class Session_Keys + { + public: + SymmetricKey client_cipher_key() const { return c_cipher; } + SymmetricKey server_cipher_key() const { return s_cipher; } + + SymmetricKey client_mac_key() const { return c_mac; } + SymmetricKey server_mac_key() const { return s_mac; } + + InitializationVector client_iv() const { return c_iv; } + InitializationVector server_iv() const { return s_iv; } + + const secure_vector<byte>& master_secret() const { return master_sec; } + + Session_Keys() {} + + Session_Keys(class Handshake_State* state, + const secure_vector<byte>& pre_master, + bool resuming); + + private: + secure_vector<byte> master_sec; + SymmetricKey c_cipher, s_cipher, c_mac, s_mac; + InitializationVector c_iv, s_iv; + }; + +} + +} + +#endif diff --git a/src/tls/tls_session_manager.cpp b/src/tls/tls_session_manager.cpp new file mode 100644 index 000000000..72eb83c21 --- /dev/null +++ b/src/tls/tls_session_manager.cpp @@ -0,0 +1,106 @@ +/* +* TLS Session Management +* (C) 2011 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#include <botan/tls_session_manager.h> +#include <botan/hex.h> +#include <chrono> + +namespace Botan { + +namespace TLS { + +bool Session_Manager_In_Memory::load_from_session_str( + const std::string& session_str, Session& session) + { + // assert(lock is held) + + auto i = m_sessions.find(session_str); + + if(i == m_sessions.end()) + return false; + + // if session has expired, remove it + const auto now = std::chrono::system_clock::now(); + + if(i->second.start_time() + session_lifetime() < now) + { + m_sessions.erase(i); + return false; + } + + session = i->second; + return true; + } + +bool Session_Manager_In_Memory::load_from_session_id( + const std::vector<byte>& session_id, Session& session) + { + std::lock_guard<std::mutex> lock(m_mutex); + + return load_from_session_str(hex_encode(session_id), session); + } + +bool Session_Manager_In_Memory::load_from_host_info( + const std::string& hostname, u16bit port, Session& session) + { + std::lock_guard<std::mutex> lock(m_mutex); + + std::map<std::string, std::string>::iterator i; + + if(port > 0) + i = m_host_sessions.find(hostname + ":" + std::to_string(port)); + else + i = m_host_sessions.find(hostname); + + if(i == m_host_sessions.end()) + return false; + + if(load_from_session_str(i->second, session)) + return true; + + // was removed from sessions map, remove m_host_sessions entry + m_host_sessions.erase(i); + + return false; + } + +void Session_Manager_In_Memory::remove_entry( + const std::vector<byte>& session_id) + { + std::lock_guard<std::mutex> lock(m_mutex); + + auto i = m_sessions.find(hex_encode(session_id)); + + if(i != m_sessions.end()) + m_sessions.erase(i); + } + +void Session_Manager_In_Memory::save(const Session& session) + { + std::lock_guard<std::mutex> lock(m_mutex); + + if(m_max_sessions != 0) + { + /* + This removes randomly based on ordering of session ids. + Instead, remove oldest first? + */ + while(m_sessions.size() >= m_max_sessions) + m_sessions.erase(m_sessions.begin()); + } + + const std::string session_id_str = hex_encode(session.session_id()); + + m_sessions[session_id_str] = session; + + if(session.side() == CLIENT && session.sni_hostname() != "") + m_host_sessions[session.sni_hostname()] = session_id_str; + } + +} + +} diff --git a/src/tls/tls_session_manager.h b/src/tls/tls_session_manager.h new file mode 100644 index 000000000..fa1ecae39 --- /dev/null +++ b/src/tls/tls_session_manager.h @@ -0,0 +1,127 @@ +/* +* TLS Session Manager +* (C) 2011 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#ifndef BOTAN_TLS_SESSION_MANAGER_H__ +#define BOTAN_TLS_SESSION_MANAGER_H__ + +#include <botan/tls_session.h> +#include <mutex> +#include <chrono> +#include <map> + +namespace Botan { + +namespace TLS { + +/** +* Session_Manager is an interface to systems which can save +* session parameters for supporting session resumption. +* +* Saving sessions is done on a best-effort basis; an implementation is +* allowed to drop sessions due to space constraints. +* +* Implementations should strive to be thread safe +*/ +class BOTAN_DLL Session_Manager + { + public: + /** + * Try to load a saved session (server side) + * @param session_id the session identifier we are trying to resume + * @param session will be set to the saved session data (if found), + or not modified if not found + * @return true if session was modified + */ + virtual bool load_from_session_id(const std::vector<byte>& session_id, + Session& session) = 0; + + /** + * Try to load a saved session (client side) + * @param hostname of the host we are connecting to + * @param port the port number if we know it, or 0 if unknown + * @param session will be set to the saved session data (if found), + or not modified if not found + * @return true if session was modified + */ + virtual bool load_from_host_info(const std::string& hostname, u16bit port, + Session& session) = 0; + + /** + * Remove this session id from the cache, if it exists + */ + virtual void remove_entry(const std::vector<byte>& session_id) = 0; + + /** + * Save a session on a best effort basis; the manager may not in + * fact be able to save the session for whatever reason; this is + * not an error. Caller cannot assume that calling save followed + * immediately by load_from_* will result in a successful lookup. + * + * @param session to save + */ + virtual void save(const Session& session) = 0; + + /** + * Return the allowed lifetime of a session; beyond this time, + * sessions are not resumed. Returns 0 if unknown/no explicit + * expiration policy. + */ + virtual std::chrono::seconds session_lifetime() const = 0; + + virtual ~Session_Manager() {} + }; + +/** +* A simple implementation of Session_Manager that just saves +* values in memory, with no persistance abilities +*/ +class BOTAN_DLL Session_Manager_In_Memory : public Session_Manager + { + public: + /** + * @param max_sessions a hint on the maximum number of sessions + * to keep in memory at any one time. (If zero, don't cap) + * @param session_lifetime sessions are expired after this many + * seconds have elapsed from initial handshake. + */ + Session_Manager_In_Memory(size_t max_sessions = 1000, + std::chrono::seconds session_lifetime = std::chrono::seconds(7200)) : + m_max_sessions(max_sessions), + m_session_lifetime(session_lifetime) + {} + + bool load_from_session_id(const std::vector<byte>& session_id, + Session& session); + + bool load_from_host_info(const std::string& hostname, u16bit port, + Session& session); + + void remove_entry(const std::vector<byte>& session_id); + + void save(const Session& session_data); + + std::chrono::seconds session_lifetime() const { return m_session_lifetime; } + + private: + bool load_from_session_str(const std::string& session_str, + Session& session); + + std::mutex m_mutex; + + size_t m_max_sessions; + + std::chrono::seconds m_session_lifetime; + + std::map<std::string, Session> m_sessions; // hex(session_id) -> session + std::map<std::string, std::string> m_host_sessions; + }; + +} + +} + +#endif diff --git a/src/tls/tls_suite_info.cpp b/src/tls/tls_suite_info.cpp new file mode 100644 index 000000000..997bda428 --- /dev/null +++ b/src/tls/tls_suite_info.cpp @@ -0,0 +1,317 @@ +/* +* TLS Cipher Suite +* (C) 2004-2010,2012 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#include <botan/tls_ciphersuite.h> + +namespace Botan { + +namespace TLS { + +Ciphersuite Ciphersuite::by_id(u16bit suite) + { + // Automatically generated by a Python script from the IANA values + + switch(suite) + { + case 0x0013: // DHE_DSS_WITH_3DES_EDE_CBC_SHA + return Ciphersuite("DSA", "DH", "SHA-1", "3DES", 24); + + case 0x0032: // DHE_DSS_WITH_AES_128_CBC_SHA + return Ciphersuite("DSA", "DH", "SHA-1", "AES-128", 16); + + case 0x0040: // DHE_DSS_WITH_AES_128_CBC_SHA256 + return Ciphersuite("DSA", "DH", "SHA-256", "AES-128", 16); + + case 0x0038: // DHE_DSS_WITH_AES_256_CBC_SHA + return Ciphersuite("DSA", "DH", "SHA-1", "AES-256", 32); + + case 0x006A: // DHE_DSS_WITH_AES_256_CBC_SHA256 + return Ciphersuite("DSA", "DH", "SHA-256", "AES-256", 32); + + case 0x0044: // DHE_DSS_WITH_CAMELLIA_128_CBC_SHA + return Ciphersuite("DSA", "DH", "SHA-1", "Camellia-128", 16); + + case 0x00BD: // DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256 + return Ciphersuite("DSA", "DH", "SHA-256", "Camellia-128", 16); + + case 0x0087: // DHE_DSS_WITH_CAMELLIA_256_CBC_SHA + return Ciphersuite("DSA", "DH", "SHA-1", "Camellia-256", 32); + + case 0x00C3: // DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256 + return Ciphersuite("DSA", "DH", "SHA-256", "Camellia-256", 32); + + case 0x0066: // DHE_DSS_WITH_RC4_128_SHA + return Ciphersuite("DSA", "DH", "SHA-1", "ARC4", 16); + + case 0x0099: // DHE_DSS_WITH_SEED_CBC_SHA + return Ciphersuite("DSA", "DH", "SHA-1", "SEED", 16); + + case 0x008F: // DHE_PSK_WITH_3DES_EDE_CBC_SHA + return Ciphersuite("", "DHE_PSK", "SHA-1", "3DES", 24); + + case 0x0090: // DHE_PSK_WITH_AES_128_CBC_SHA + return Ciphersuite("", "DHE_PSK", "SHA-1", "AES-128", 16); + + case 0x00B2: // DHE_PSK_WITH_AES_128_CBC_SHA256 + return Ciphersuite("", "DHE_PSK", "SHA-256", "AES-128", 16); + + case 0x0091: // DHE_PSK_WITH_AES_256_CBC_SHA + return Ciphersuite("", "DHE_PSK", "SHA-1", "AES-256", 32); + + case 0x00B3: // DHE_PSK_WITH_AES_256_CBC_SHA384 + return Ciphersuite("", "DHE_PSK", "SHA-384", "AES-256", 32); + + case 0xC096: // DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + return Ciphersuite("", "DHE_PSK", "SHA-256", "Camellia-128", 16); + + case 0xC097: // DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + return Ciphersuite("", "DHE_PSK", "SHA-384", "Camellia-256", 32); + + case 0x008E: // DHE_PSK_WITH_RC4_128_SHA + return Ciphersuite("", "DHE_PSK", "SHA-1", "ARC4", 16); + + case 0x0016: // DHE_RSA_WITH_3DES_EDE_CBC_SHA + return Ciphersuite("RSA", "DH", "SHA-1", "3DES", 24); + + case 0x0033: // DHE_RSA_WITH_AES_128_CBC_SHA + return Ciphersuite("RSA", "DH", "SHA-1", "AES-128", 16); + + case 0x0067: // DHE_RSA_WITH_AES_128_CBC_SHA256 + return Ciphersuite("RSA", "DH", "SHA-256", "AES-128", 16); + + case 0x0039: // DHE_RSA_WITH_AES_256_CBC_SHA + return Ciphersuite("RSA", "DH", "SHA-1", "AES-256", 32); + + case 0x006B: // DHE_RSA_WITH_AES_256_CBC_SHA256 + return Ciphersuite("RSA", "DH", "SHA-256", "AES-256", 32); + + case 0x0045: // DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + return Ciphersuite("RSA", "DH", "SHA-1", "Camellia-128", 16); + + case 0x00BE: // DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + return Ciphersuite("RSA", "DH", "SHA-256", "Camellia-128", 16); + + case 0x0088: // DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + return Ciphersuite("RSA", "DH", "SHA-1", "Camellia-256", 32); + + case 0x00C4: // DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + return Ciphersuite("RSA", "DH", "SHA-256", "Camellia-256", 32); + + case 0x009A: // DHE_RSA_WITH_SEED_CBC_SHA + return Ciphersuite("RSA", "DH", "SHA-1", "SEED", 16); + + case 0x001B: // DH_anon_WITH_3DES_EDE_CBC_SHA + return Ciphersuite("", "DH", "SHA-1", "3DES", 24); + + case 0x0034: // DH_anon_WITH_AES_128_CBC_SHA + return Ciphersuite("", "DH", "SHA-1", "AES-128", 16); + + case 0x006C: // DH_anon_WITH_AES_128_CBC_SHA256 + return Ciphersuite("", "DH", "SHA-256", "AES-128", 16); + + case 0x003A: // DH_anon_WITH_AES_256_CBC_SHA + return Ciphersuite("", "DH", "SHA-1", "AES-256", 32); + + case 0x006D: // DH_anon_WITH_AES_256_CBC_SHA256 + return Ciphersuite("", "DH", "SHA-256", "AES-256", 32); + + case 0x0046: // DH_anon_WITH_CAMELLIA_128_CBC_SHA + return Ciphersuite("", "DH", "SHA-1", "Camellia-128", 16); + + case 0x00BF: // DH_anon_WITH_CAMELLIA_128_CBC_SHA256 + return Ciphersuite("", "DH", "SHA-256", "Camellia-128", 16); + + case 0x0089: // DH_anon_WITH_CAMELLIA_256_CBC_SHA + return Ciphersuite("", "DH", "SHA-1", "Camellia-256", 32); + + case 0x00C5: // DH_anon_WITH_CAMELLIA_256_CBC_SHA256 + return Ciphersuite("", "DH", "SHA-256", "Camellia-256", 32); + + case 0x0018: // DH_anon_WITH_RC4_128_MD5 + return Ciphersuite("", "DH", "MD5", "ARC4", 16); + + case 0x009B: // DH_anon_WITH_SEED_CBC_SHA + return Ciphersuite("", "DH", "SHA-1", "SEED", 16); + + case 0xC008: // ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + return Ciphersuite("ECDSA", "ECDH", "SHA-1", "3DES", 24); + + case 0xC009: // ECDHE_ECDSA_WITH_AES_128_CBC_SHA + return Ciphersuite("ECDSA", "ECDH", "SHA-1", "AES-128", 16); + + case 0xC023: // ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + return Ciphersuite("ECDSA", "ECDH", "SHA-256", "AES-128", 16); + + case 0xC00A: // ECDHE_ECDSA_WITH_AES_256_CBC_SHA + return Ciphersuite("ECDSA", "ECDH", "SHA-1", "AES-256", 32); + + case 0xC024: // ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + return Ciphersuite("ECDSA", "ECDH", "SHA-384", "AES-256", 32); + + case 0xC072: // ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + return Ciphersuite("ECDSA", "ECDH", "SHA-256", "Camellia-128", 16); + + case 0xC073: // ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + return Ciphersuite("ECDSA", "ECDH", "SHA-384", "Camellia-256", 32); + + case 0xC007: // ECDHE_ECDSA_WITH_RC4_128_SHA + return Ciphersuite("ECDSA", "ECDH", "SHA-1", "ARC4", 16); + + case 0xC034: // ECDHE_PSK_WITH_3DES_EDE_CBC_SHA + return Ciphersuite("", "ECDHE_PSK", "SHA-1", "3DES", 24); + + case 0xC035: // ECDHE_PSK_WITH_AES_128_CBC_SHA + return Ciphersuite("", "ECDHE_PSK", "SHA-1", "AES-128", 16); + + case 0xC037: // ECDHE_PSK_WITH_AES_128_CBC_SHA256 + return Ciphersuite("", "ECDHE_PSK", "SHA-256", "AES-128", 16); + + case 0xC036: // ECDHE_PSK_WITH_AES_256_CBC_SHA + return Ciphersuite("", "ECDHE_PSK", "SHA-1", "AES-256", 32); + + case 0xC038: // ECDHE_PSK_WITH_AES_256_CBC_SHA384 + return Ciphersuite("", "ECDHE_PSK", "SHA-384", "AES-256", 32); + + case 0xC09A: // ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + return Ciphersuite("", "ECDHE_PSK", "SHA-256", "Camellia-128", 16); + + case 0xC09B: // ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + return Ciphersuite("", "ECDHE_PSK", "SHA-384", "Camellia-256", 32); + + case 0xC033: // ECDHE_PSK_WITH_RC4_128_SHA + return Ciphersuite("", "ECDHE_PSK", "SHA-1", "ARC4", 16); + + case 0xC012: // ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + return Ciphersuite("RSA", "ECDH", "SHA-1", "3DES", 24); + + case 0xC013: // ECDHE_RSA_WITH_AES_128_CBC_SHA + return Ciphersuite("RSA", "ECDH", "SHA-1", "AES-128", 16); + + case 0xC027: // ECDHE_RSA_WITH_AES_128_CBC_SHA256 + return Ciphersuite("RSA", "ECDH", "SHA-256", "AES-128", 16); + + case 0xC014: // ECDHE_RSA_WITH_AES_256_CBC_SHA + return Ciphersuite("RSA", "ECDH", "SHA-1", "AES-256", 32); + + case 0xC028: // ECDHE_RSA_WITH_AES_256_CBC_SHA384 + return Ciphersuite("RSA", "ECDH", "SHA-384", "AES-256", 32); + + case 0xC076: // ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + return Ciphersuite("RSA", "ECDH", "SHA-256", "Camellia-128", 16); + + case 0xC077: // ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 + return Ciphersuite("RSA", "ECDH", "SHA-384", "Camellia-256", 32); + + case 0xC011: // ECDHE_RSA_WITH_RC4_128_SHA + return Ciphersuite("RSA", "ECDH", "SHA-1", "ARC4", 16); + + case 0xC017: // ECDH_anon_WITH_3DES_EDE_CBC_SHA + return Ciphersuite("", "ECDH", "SHA-1", "3DES", 24); + + case 0xC018: // ECDH_anon_WITH_AES_128_CBC_SHA + return Ciphersuite("", "ECDH", "SHA-1", "AES-128", 16); + + case 0xC019: // ECDH_anon_WITH_AES_256_CBC_SHA + return Ciphersuite("", "ECDH", "SHA-1", "AES-256", 32); + + case 0xC016: // ECDH_anon_WITH_RC4_128_SHA + return Ciphersuite("", "ECDH", "SHA-1", "ARC4", 16); + + case 0x008B: // PSK_WITH_3DES_EDE_CBC_SHA + return Ciphersuite("", "PSK", "SHA-1", "3DES", 24); + + case 0x008C: // PSK_WITH_AES_128_CBC_SHA + return Ciphersuite("", "PSK", "SHA-1", "AES-128", 16); + + case 0x00AE: // PSK_WITH_AES_128_CBC_SHA256 + return Ciphersuite("", "PSK", "SHA-256", "AES-128", 16); + + case 0x008D: // PSK_WITH_AES_256_CBC_SHA + return Ciphersuite("", "PSK", "SHA-1", "AES-256", 32); + + case 0x00AF: // PSK_WITH_AES_256_CBC_SHA384 + return Ciphersuite("", "PSK", "SHA-384", "AES-256", 32); + + case 0xC094: // PSK_WITH_CAMELLIA_128_CBC_SHA256 + return Ciphersuite("", "PSK", "SHA-256", "Camellia-128", 16); + + case 0xC095: // PSK_WITH_CAMELLIA_256_CBC_SHA384 + return Ciphersuite("", "PSK", "SHA-384", "Camellia-256", 32); + + case 0x008A: // PSK_WITH_RC4_128_SHA + return Ciphersuite("", "PSK", "SHA-1", "ARC4", 16); + + case 0x000A: // RSA_WITH_3DES_EDE_CBC_SHA + return Ciphersuite("RSA", "RSA", "SHA-1", "3DES", 24); + + case 0x002F: // RSA_WITH_AES_128_CBC_SHA + return Ciphersuite("RSA", "RSA", "SHA-1", "AES-128", 16); + + case 0x003C: // RSA_WITH_AES_128_CBC_SHA256 + return Ciphersuite("RSA", "RSA", "SHA-256", "AES-128", 16); + + case 0x0035: // RSA_WITH_AES_256_CBC_SHA + return Ciphersuite("RSA", "RSA", "SHA-1", "AES-256", 32); + + case 0x003D: // RSA_WITH_AES_256_CBC_SHA256 + return Ciphersuite("RSA", "RSA", "SHA-256", "AES-256", 32); + + case 0x0041: // RSA_WITH_CAMELLIA_128_CBC_SHA + return Ciphersuite("RSA", "RSA", "SHA-1", "Camellia-128", 16); + + case 0x00BA: // RSA_WITH_CAMELLIA_128_CBC_SHA256 + return Ciphersuite("RSA", "RSA", "SHA-256", "Camellia-128", 16); + + case 0x0084: // RSA_WITH_CAMELLIA_256_CBC_SHA + return Ciphersuite("RSA", "RSA", "SHA-1", "Camellia-256", 32); + + case 0x00C0: // RSA_WITH_CAMELLIA_256_CBC_SHA256 + return Ciphersuite("RSA", "RSA", "SHA-256", "Camellia-256", 32); + + case 0x0004: // RSA_WITH_RC4_128_MD5 + return Ciphersuite("RSA", "RSA", "MD5", "ARC4", 16); + + case 0x0005: // RSA_WITH_RC4_128_SHA + return Ciphersuite("RSA", "RSA", "SHA-1", "ARC4", 16); + + case 0x0096: // RSA_WITH_SEED_CBC_SHA + return Ciphersuite("RSA", "RSA", "SHA-1", "SEED", 16); + + case 0xC01C: // SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA + return Ciphersuite("DSA", "SRP_SHA", "SHA-1", "3DES", 24); + + case 0xC01F: // SRP_SHA_DSS_WITH_AES_128_CBC_SHA + return Ciphersuite("DSA", "SRP_SHA", "SHA-1", "AES-128", 16); + + case 0xC022: // SRP_SHA_DSS_WITH_AES_256_CBC_SHA + return Ciphersuite("DSA", "SRP_SHA", "SHA-1", "AES-256", 32); + + case 0xC01B: // SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA + return Ciphersuite("RSA", "SRP_SHA", "SHA-1", "3DES", 24); + + case 0xC01E: // SRP_SHA_RSA_WITH_AES_128_CBC_SHA + return Ciphersuite("RSA", "SRP_SHA", "SHA-1", "AES-128", 16); + + case 0xC021: // SRP_SHA_RSA_WITH_AES_256_CBC_SHA + return Ciphersuite("RSA", "SRP_SHA", "SHA-1", "AES-256", 32); + + case 0xC01A: // SRP_SHA_WITH_3DES_EDE_CBC_SHA + return Ciphersuite("", "SRP_SHA", "SHA-1", "3DES", 24); + + case 0xC01D: // SRP_SHA_WITH_AES_128_CBC_SHA + return Ciphersuite("", "SRP_SHA", "SHA-1", "AES-128", 16); + + case 0xC020: // SRP_SHA_WITH_AES_256_CBC_SHA + return Ciphersuite("", "SRP_SHA", "SHA-1", "AES-256", 32); + } + + return Ciphersuite(); // some unknown ciphersuite + } + +} + +} diff --git a/src/tls/tls_version.cpp b/src/tls/tls_version.cpp new file mode 100644 index 000000000..82dce0be9 --- /dev/null +++ b/src/tls/tls_version.cpp @@ -0,0 +1,33 @@ +/* +* TLS Protocol Version Management +* (C) 2012 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#include <botan/tls_version.h> +#include <botan/parsing.h> + +namespace Botan { + +namespace TLS { + +std::string Protocol_Version::to_string() const + { + const byte maj = major_version(); + const byte min = minor_version(); + + // Some very new or very old protocol? + if(maj != 3) + return "Protocol " + std::to_string(maj) + "." + std::to_string(min); + + if(maj == 3 && min == 0) + return "SSL v3"; + + // The TLS v1.[0123...] case + return "TLS v1." + std::to_string(min-1); + } + +} + +} diff --git a/src/tls/tls_version.h b/src/tls/tls_version.h new file mode 100644 index 000000000..aa689b300 --- /dev/null +++ b/src/tls/tls_version.h @@ -0,0 +1,87 @@ +/* +* TLS Protocol Version Management +* (C) 2012 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#ifndef BOTAN_TLS_PROTOCOL_VERSION_H__ +#define BOTAN_TLS_PROTOCOL_VERSION_H__ + +#include <botan/get_byte.h> +#include <string> + +namespace Botan { + +namespace TLS { + +class BOTAN_DLL Protocol_Version + { + public: + enum Version_Code { + SSL_V3 = 0x0300, + TLS_V10 = 0x0301, + TLS_V11 = 0x0302, + TLS_V12 = 0x0303 + }; + + Protocol_Version() : m_version(0) {} + + Protocol_Version(Version_Code named_version) : + m_version(static_cast<u16bit>(named_version)) {} + + Protocol_Version(byte major, byte minor) : + m_version((static_cast<u16bit>(major) << 8) | minor) {} + + /** + * Get the major version of the protocol version + */ + byte major_version() const { return get_byte(0, m_version); } + + /** + * Get the minor version of the protocol version + */ + byte minor_version() const { return get_byte(1, m_version); } + + bool operator==(const Protocol_Version& other) const + { + return (m_version == other.m_version); + } + + bool operator!=(const Protocol_Version& other) const + { + return (m_version != other.m_version); + } + + bool operator>=(const Protocol_Version& other) const + { + return (m_version >= other.m_version); + } + + bool operator>(const Protocol_Version& other) const + { + return (m_version > other.m_version); + } + + bool operator<=(const Protocol_Version& other) const + { + return (m_version <= other.m_version); + } + + bool operator<(const Protocol_Version& other) const + { + return (m_version < other.m_version); + } + + std::string to_string() const; + + private: + u16bit m_version; + }; + +} + +} + +#endif + diff --git a/src/utils/assert.cpp b/src/utils/assert.cpp index 29af831d8..3747912d6 100644 --- a/src/utils/assert.cpp +++ b/src/utils/assert.cpp @@ -21,7 +21,7 @@ void assertion_failure(const char* expr_str, format << "Assertion " << expr_str << " failed "; - if(msg) + if(msg && msg[0] != 0) format << "(" << msg << ") "; if(func) diff --git a/src/utils/assert.h b/src/utils/assert.h index 67ca665e3..d68f683a6 100644 --- a/src/utils/assert.h +++ b/src/utils/assert.h @@ -36,6 +36,16 @@ void assertion_failure(const char* expr_str, __LINE__); \ } while(0) +#define BOTAN_ASSERT_NONNULL(ptr) \ + do { \ + if(static_cast<bool>(ptr) == false) \ + Botan::assertion_failure(#ptr " is not null", \ + "", \ + BOTAN_ASSERT_FUNCTION, \ + __FILE__, \ + __LINE__); \ + } while(0) + /* * Unfortunately getting the function name from the preprocessor * isn't standard in C++98 (C++0x uses C99's __func__) diff --git a/src/utils/calendar.cpp b/src/utils/calendar.cpp new file mode 100644 index 000000000..14f0113f2 --- /dev/null +++ b/src/utils/calendar.cpp @@ -0,0 +1,52 @@ +/* +* Calendar Functions +* (C) 1999-2010 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/calendar.h> +#include <botan/exceptn.h> +#include <ctime> + +namespace Botan { + +namespace { + +std::tm do_gmtime(std::time_t time_val) + { + std::tm tm; + +#if defined(BOTAN_TARGET_OS_HAS_GMTIME_S) + gmtime_s(&tm, &time_val); // Windows +#elif defined(BOTAN_TARGET_OS_HAS_GMTIME_R) + gmtime_r(&time_val, &tm); // Unix/SUSv2 +#else + std::tm* tm_p = std::gmtime(&time_val); + if (tm_p == 0) + throw Encoding_Error("time_t_to_tm could not convert"); + tm = *tm_p; +#endif + + return tm; + } + +} + +/* +* Convert a time_point to a calendar_point +*/ +calendar_point calendar_value( + const std::chrono::system_clock::time_point& time_point) + { + std::tm tm = do_gmtime(std::chrono::system_clock::to_time_t(time_point)); + + return calendar_point(tm.tm_year + 1900, + tm.tm_mon + 1, + tm.tm_mday, + tm.tm_hour, + tm.tm_min, + tm.tm_sec); + } + +} diff --git a/src/utils/time.h b/src/utils/calendar.h index fcc956df2..d617cc9a0 100644 --- a/src/utils/time.h +++ b/src/utils/calendar.h @@ -1,14 +1,15 @@ /* -* Time Functions +* Calendar Functions * (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ -#ifndef BOTAN_TIME_H__ -#define BOTAN_TIME_H__ +#ifndef BOTAN_CALENDAR_H__ +#define BOTAN_CALENDAR_H__ #include <botan/types.h> +#include <chrono> namespace Botan { @@ -50,21 +51,12 @@ struct BOTAN_DLL calendar_point year(y), month(mon), day(d), hour(h), minutes(min), seconds(sec) {} }; -/** +/* * @param time_point a time point from the system clock * @return calendar_point object representing this time point */ -BOTAN_DLL calendar_point calendar_value(u64bit time_point); - -/** -* @return seconds resolution timestamp, unknown epoch -*/ -BOTAN_DLL u64bit system_time(); - -/** -* @return nanoseconds resolution timestamp, unknown epoch -*/ -BOTAN_DLL u64bit get_nanoseconds_clock(); +BOTAN_DLL calendar_point calendar_value( + const std::chrono::system_clock::time_point& time_point); } diff --git a/src/utils/charset.cpp b/src/utils/charset.cpp index 8e20e6492..7ee637f80 100644 --- a/src/utils/charset.cpp +++ b/src/utils/charset.cpp @@ -119,7 +119,7 @@ std::string transcode(const std::string& str, return ucs2_to_latin1(str); throw Invalid_Argument("Unknown transcoding operation from " + - to_string(from) + " to " + to_string(to)); + std::to_string(from) + " to " + std::to_string(to)); } /* diff --git a/src/utils/cpuid.h b/src/utils/cpuid.h index ad85ac4fe..cdc6417ec 100644 --- a/src/utils/cpuid.h +++ b/src/utils/cpuid.h @@ -103,7 +103,7 @@ class BOTAN_DLL CPUID CPUID_MOVBE_BIT = 54, CPUID_AESNI_BIT = 57, CPUID_AVX_BIT = 60, - CPUID_RDRAND_BIT = 61 + CPUID_RDRAND_BIT = 62 }; static bool x86_processor_flags_has(u64bit bit) diff --git a/src/utils/datastor/datastor.cpp b/src/utils/datastor/datastor.cpp index 49e7b2dda..d65b3f1ac 100644 --- a/src/utils/datastor/datastor.cpp +++ b/src/utils/datastor/datastor.cpp @@ -14,16 +14,6 @@ namespace Botan { /* -* Default Matcher transform operation (identity) -*/ -std::pair<std::string, std::string> -Data_Store::Matcher::transform(const std::string& key, - const std::string& value) const - { - return std::make_pair(key, value); - } - -/* * Data_Store Equality Comparison */ bool Data_Store::operator==(const Data_Store& other) const @@ -42,26 +32,14 @@ bool Data_Store::has_value(const std::string& key) const /* * Search based on an arbitrary predicate */ -std::multimap<std::string, std::string> -Data_Store::search_with(const Matcher& matcher) const +std::multimap<std::string, std::string> Data_Store::search_for( + std::function<bool (std::string, std::string)> predicate) const { std::multimap<std::string, std::string> out; - std::multimap<std::string, std::string>::const_iterator i = - contents.begin(); - - while(i != contents.end()) - { - if(matcher(i->first, i->second)) - { - std::pair<std::string, std::string> p( - matcher.transform(i->first, i->second)); - - multimap_insert(out, p.first, p.second); - } - - ++i; - } + for(auto i = contents.begin(); i != contents.end(); ++i) + if(predicate(i->first, i->second)) + out.insert(std::make_pair(i->first, i->second)); return out; } @@ -71,12 +49,9 @@ Data_Store::search_with(const Matcher& matcher) const */ std::vector<std::string> Data_Store::get(const std::string& looking_for) const { - typedef std::multimap<std::string, std::string>::const_iterator iter; - - std::pair<iter, iter> range = contents.equal_range(looking_for); - std::vector<std::string> out; - for(iter i = range.first; i != range.second; ++i) + auto range = contents.equal_range(looking_for); + for(auto i = range.first; i != range.second; ++i) out.push_back(i->second); return out; } @@ -97,21 +72,21 @@ std::string Data_Store::get1(const std::string& key) const } /* -* Get a single MemoryVector atom +* Get a single std::vector atom */ -MemoryVector<byte> +std::vector<byte> Data_Store::get1_memvec(const std::string& key) const { std::vector<std::string> vals = get(key); if(vals.empty()) - return MemoryVector<byte>(); + return std::vector<byte>(); if(vals.size() > 1) throw Invalid_State("Data_Store::get1_memvec: Multiple values for " + key); - return hex_decode(vals[0]); + return unlock(hex_decode(vals[0])); } /* @@ -144,13 +119,18 @@ void Data_Store::add(const std::string& key, const std::string& val) */ void Data_Store::add(const std::string& key, u32bit val) { - add(key, to_string(val)); + add(key, std::to_string(val)); } /* * Insert a single key and value */ -void Data_Store::add(const std::string& key, const MemoryRegion<byte>& val) +void Data_Store::add(const std::string& key, const secure_vector<byte>& val) + { + add(key, hex_encode(&val[0], val.size())); + } + +void Data_Store::add(const std::string& key, const std::vector<byte>& val) { add(key, hex_encode(&val[0], val.size())); } diff --git a/src/utils/datastor/datastor.h b/src/utils/datastor/datastor.h index 8d41b07a8..b471f85e1 100644 --- a/src/utils/datastor/datastor.h +++ b/src/utils/datastor/datastor.h @@ -9,6 +9,7 @@ #define BOTAN_DATA_STORE_H__ #include <botan/secmem.h> +#include <functional> #include <utility> #include <string> #include <vector> @@ -25,28 +26,16 @@ class BOTAN_DLL Data_Store /** * A search function */ - class BOTAN_DLL Matcher - { - public: - virtual bool operator()(const std::string&, - const std::string&) const = 0; - - virtual std::pair<std::string, std::string> - transform(const std::string&, const std::string&) const; - - virtual ~Matcher() {} - }; - bool operator==(const Data_Store&) const; - std::multimap<std::string, std::string> - search_with(const Matcher&) const; + std::multimap<std::string, std::string> search_for( + std::function<bool (std::string, std::string)> predicate) const; std::vector<std::string> get(const std::string&) const; std::string get1(const std::string&) const; - MemoryVector<byte> get1_memvec(const std::string&) const; + std::vector<byte> get1_memvec(const std::string&) const; u32bit get1_u32bit(const std::string&, u32bit = 0) const; bool has_value(const std::string&) const; @@ -54,7 +43,8 @@ class BOTAN_DLL Data_Store void add(const std::multimap<std::string, std::string>&); void add(const std::string&, const std::string&); void add(const std::string&, u32bit); - void add(const std::string&, const MemoryRegion<byte>&); + void add(const std::string&, const secure_vector<byte>&); + void add(const std::string&, const std::vector<byte>&); private: std::multimap<std::string, std::string> contents; }; diff --git a/src/utils/dyn_load/dyn_load.cpp b/src/utils/dyn_load/dyn_load.cpp index 06b8c5df3..51afb1afe 100644 --- a/src/utils/dyn_load/dyn_load.cpp +++ b/src/utils/dyn_load/dyn_load.cpp @@ -30,7 +30,7 @@ void raise_runtime_loader_exception(const std::string& lib_name, Dynamically_Loaded_Library::Dynamically_Loaded_Library( const std::string& library) : - lib_name(library), lib(0) + lib_name(library), lib(nullptr) { #if defined(BOTAN_TARGET_OS_HAS_DLOPEN) lib = ::dlopen(lib_name.c_str(), RTLD_LAZY); @@ -60,7 +60,7 @@ Dynamically_Loaded_Library::~Dynamically_Loaded_Library() void* Dynamically_Loaded_Library::resolve_symbol(const std::string& symbol) { - void* addr = 0; + void* addr = nullptr; #if defined(BOTAN_TARGET_OS_HAS_DLOPEN) addr = ::dlsym(lib, symbol.c_str()); diff --git a/src/utils/dyn_load/dyn_load.h b/src/utils/dyn_load/dyn_load.h index b37a52e84..4d5cfb296 100644 --- a/src/utils/dyn_load/dyn_load.h +++ b/src/utils/dyn_load/dyn_load.h @@ -59,6 +59,9 @@ class Dynamically_Loaded_Library } private: + Dynamically_Loaded_Library(const Dynamically_Loaded_Library&); + Dynamically_Loaded_Library& operator=(const Dynamically_Loaded_Library&); + std::string lib_name; void* lib; }; diff --git a/src/utils/exceptn.h b/src/utils/exceptn.h index 3797a5478..02fb16a66 100644 --- a/src/utils/exceptn.h +++ b/src/utils/exceptn.h @@ -56,7 +56,7 @@ struct BOTAN_DLL Invalid_Key_Length : public Invalid_Argument { Invalid_Key_Length(const std::string& name, size_t length) : Invalid_Argument(name + " cannot accept a key of length " + - to_string(length)) + std::to_string(length)) {} }; @@ -78,7 +78,7 @@ struct BOTAN_DLL Invalid_Block_Size : public Invalid_Argument struct BOTAN_DLL Invalid_IV_Length : public Invalid_Argument { Invalid_IV_Length(const std::string& mode, size_t bad_len) : - Invalid_Argument("IV length " + to_string(bad_len) + + Invalid_Argument("IV length " + std::to_string(bad_len) + " is invalid for " + mode) {} }; diff --git a/src/utils/info.txt b/src/utils/info.txt index fcf16bd5a..a1079d47b 100644 --- a/src/utils/info.txt +++ b/src/utils/info.txt @@ -4,19 +4,16 @@ load_on always <source> assert.cpp +calendar.cpp charset.cpp cpuid.cpp -mlock.cpp parsing.cpp -time.cpp -ui.cpp version.cpp </source> <header:internal> assert.h bit_ops.h -mlock.h prefetch.h rounding.h stl_util.h @@ -25,6 +22,7 @@ xor_buf.h <header:public> bswap.h +calendar.h charset.h cpuid.h exceptn.h @@ -32,9 +30,7 @@ loadstor.h mem_ops.h parsing.h rotate.h -time.h types.h -ui.h version.h get_byte.h </header:public> diff --git a/src/utils/mlock.cpp b/src/utils/mlock.cpp deleted file mode 100644 index 800425665..000000000 --- a/src/utils/mlock.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* -* Memory Locking Functions -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/internal/mlock.h> - -#if defined(BOTAN_TARGET_OS_HAS_POSIX_MLOCK) - #include <sys/types.h> - #include <sys/mman.h> -#elif defined(BOTAN_TARGET_OS_HAS_WIN32_VIRTUAL_LOCK) - #include <windows.h> -#endif - -namespace Botan { - -bool has_mlock() - { - byte buf[4096]; - if(!lock_mem(&buf, sizeof(buf))) - return false; - unlock_mem(&buf, sizeof(buf)); - return true; - } - -/* -* Lock an area of memory into RAM -*/ -bool lock_mem(void* ptr, size_t bytes) - { -#if defined(BOTAN_TARGET_OS_HAS_POSIX_MLOCK) - return (::mlock(static_cast<char*>(ptr), bytes) == 0); -#elif defined(BOTAN_TARGET_OS_HAS_WIN32_VIRTUAL_LOCK) - return (::VirtualLock(ptr, bytes) != 0); -#else - return false; -#endif - } - -/* -* Unlock a previously locked region of memory -*/ -void unlock_mem(void* ptr, size_t bytes) - { -#if defined(BOTAN_TARGET_OS_HAS_POSIX_MLOCK) - ::munlock(static_cast<char*>(ptr), bytes); -#elif defined(BOTAN_TARGET_OS_HAS_WIN32_VIRTUAL_LOCK) - ::VirtualUnlock(ptr, bytes); -#endif - } - -} diff --git a/src/utils/mlock.h b/src/utils/mlock.h deleted file mode 100644 index 88788472d..000000000 --- a/src/utils/mlock.h +++ /dev/null @@ -1,37 +0,0 @@ -/* -* Memory Locking Functions -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_MLOCK_H__ -#define BOTAN_MLOCK_H__ - -#include <botan/types.h> - -namespace Botan { - -/** -* Check if we can at least potentially lock memory -*/ -bool has_mlock(); - -/** -* Lock memory into RAM if possible -* @param addr the start of the memory block -* @param length the length of the memory block in bytes -* @returns true if successful, false otherwise -*/ -bool lock_mem(void* addr, size_t length); - -/** -* Unlock memory locked with lock_mem() -* @param addr the start of the memory block -* @param length the length of the memory block in bytes -*/ -void unlock_mem(void* addr, size_t length); - -} - -#endif diff --git a/src/utils/parsing.cpp b/src/utils/parsing.cpp index 9ec00040c..c3d7f00f7 100644 --- a/src/utils/parsing.cpp +++ b/src/utils/parsing.cpp @@ -13,53 +13,6 @@ namespace Botan { /* -* Convert a string into an integer -*/ -u32bit to_u32bit(const std::string& number) - { - u32bit n = 0; - - for(std::string::const_iterator i = number.begin(); i != number.end(); ++i) - { - const u32bit OVERFLOW_MARK = 0xFFFFFFFF / 10; - - if(*i == ' ') - continue; - - byte digit = Charset::char2digit(*i); - - if((n > OVERFLOW_MARK) || (n == OVERFLOW_MARK && digit > 5)) - throw Decoding_Error("to_u32bit: Integer overflow"); - n *= 10; - n += digit; - } - return n; - } - -/* -* Convert an integer into a string -*/ -std::string to_string(u64bit n, size_t min_len) - { - std::string lenstr; - if(n) - { - while(n > 0) - { - lenstr = Charset::digit2char(n % 10) + lenstr; - n /= 10; - } - } - else - lenstr = "0"; - - while(lenstr.size() < min_len) - lenstr = "0" + lenstr; - - return lenstr; - } - -/* * Convert a string into a time duration */ u32bit timespec_to_u32bit(const std::string& timespec) @@ -106,7 +59,7 @@ std::vector<std::string> parse_algorithm_name(const std::string& namex) elems.push_back(name.substr(0, name.find('('))); name = name.substr(name.find('(')); - for(std::string::const_iterator i = name.begin(); i != name.end(); ++i) + for(auto i = name.begin(); i != name.end(); ++i) { char c = *i; @@ -155,7 +108,7 @@ std::vector<std::string> split_on(const std::string& str, char delim) if(str == "") return elems; std::string substr; - for(std::string::const_iterator i = str.begin(); i != str.end(); ++i) + for(auto i = str.begin(); i != str.end(); ++i) { if(*i == delim) { @@ -175,6 +128,23 @@ std::vector<std::string> split_on(const std::string& str, char delim) } /* +* Join a string +*/ +std::string string_join(const std::vector<std::string>& strs, char delim) + { + std::string out = ""; + + for(size_t i = 0; i != strs.size(); ++i) + { + if(i != 0) + out += delim; + out += strs[i]; + } + + return out; + } + +/* * Parse an ASN.1 OID string */ std::vector<u32bit> parse_asn1_oid(const std::string& oid) @@ -182,7 +152,7 @@ std::vector<u32bit> parse_asn1_oid(const std::string& oid) std::string substring; std::vector<u32bit> oid_elems; - for(std::string::const_iterator i = oid.begin(); i != oid.end(); ++i) + for(auto i = oid.begin(); i != oid.end(); ++i) { char c = *i; @@ -212,8 +182,8 @@ std::vector<u32bit> parse_asn1_oid(const std::string& oid) */ bool x500_name_cmp(const std::string& name1, const std::string& name2) { - std::string::const_iterator p1 = name1.begin(); - std::string::const_iterator p2 = name2.begin(); + auto p1 = name1.begin(); + auto p2 = name2.begin(); while((p1 != name1.end()) && Charset::is_space(*p1)) ++p1; while((p2 != name2.end()) && Charset::is_space(*p2)) ++p2; @@ -258,9 +228,9 @@ u32bit string_to_ipv4(const std::string& str) u32bit ip = 0; - for(size_t i = 0; i != parts.size(); ++i) + for(auto part = parts.begin(); part != parts.end(); ++part) { - u32bit octet = to_u32bit(parts[i]); + u32bit octet = to_u32bit(*part); if(octet > 255) throw Decoding_Error("Invalid IP string " + str); @@ -282,10 +252,23 @@ std::string ipv4_to_string(u32bit ip) { if(i) str += "."; - str += to_string(get_byte(i, ip)); + str += std::to_string(get_byte(i, ip)); } return str; } +std::string replace_char(const std::string& str, + char from_char, + char to_char) + { + std::string out = str; + + for(size_t i = 0; i != out.size(); ++i) + if(out[i] == from_char) + out[i] = to_char; + + return out; + } + } diff --git a/src/utils/parsing.h b/src/utils/parsing.h index 12370bf2b..12a31a7dd 100644 --- a/src/utils/parsing.h +++ b/src/utils/parsing.h @@ -32,6 +32,25 @@ BOTAN_DLL std::vector<std::string> split_on( const std::string& str, char delim); /** +* Replace a character in a string +* @param str the input string +* @param from_char the character to replace +* @return to_char the character to replace it with +*/ +BOTAN_DLL std::string replace_char(const std::string& str, + char from_char, + char to_char); + +/** +* Join a string +* @param strs strings to join +* @param delim the delimitor +* @return string joined by delim +*/ +BOTAN_DLL std::string string_join(const std::vector<std::string>& strs, + char delim); + +/** * Parse an ASN.1 OID * @param oid the OID in string form * @return OID components @@ -48,19 +67,12 @@ BOTAN_DLL bool x500_name_cmp(const std::string& name1, const std::string& name2); /** -* Convert a number to a string -* @param n the integer to convert to a string -* @param min_len the min length of the output string -* @return n convert to a string -*/ -BOTAN_DLL std::string to_string(u64bit n, size_t min_len = 0); - -/** * Convert a string to a number * @param str the string to convert * @return number value of the string */ -BOTAN_DLL u32bit to_u32bit(const std::string& str); +inline u32bit to_u32bit(const std::string& str) + { return std::stoul(str); } /** * Convert a time specification to a number diff --git a/src/utils/rounding.h b/src/utils/rounding.h index c77ab9b52..4ddd7a432 100644 --- a/src/utils/rounding.h +++ b/src/utils/rounding.h @@ -21,6 +21,9 @@ namespace Botan { template<typename T> inline T round_up(T n, T align_to) { + if(align_to == 0) + return n; + if(n % align_to || n == 0) n += align_to - (n % align_to); return n; @@ -35,9 +38,24 @@ inline T round_up(T n, T align_to) template<typename T> inline T round_down(T n, T align_to) { + if(align_to == 0) + return n; + return (n - (n % align_to)); } +/** +* Clamp +*/ +inline size_t clamp(size_t n, size_t lower_bound, size_t upper_bound) + { + if(n < lower_bound) + return lower_bound; + if(n > upper_bound) + return upper_bound; + return n; + } + } #endif diff --git a/src/utils/stl_util.h b/src/utils/stl_util.h index 0e0617d5b..1a62e8fe7 100644 --- a/src/utils/stl_util.h +++ b/src/utils/stl_util.h @@ -8,31 +8,12 @@ #ifndef BOTAN_STL_UTIL_H__ #define BOTAN_STL_UTIL_H__ +#include <vector> #include <map> namespace Botan { -/** -* Copy-on-Predicate Algorithm -* @param current the first iterator value -* @param end the final iterator value -* @param dest an output iterator -* @param copy_p the predicate -*/ -template<typename InputIterator, typename OutputIterator, typename Predicate> -OutputIterator copy_if(InputIterator current, InputIterator end, - OutputIterator dest, Predicate copy_p) - { - while(current != end) - { - if(copy_p(*current)) - *dest++ = *current; - ++current; - } - return dest; - } - -/** +/* * Searching through a std::map * @param mapping the map to search * @param key is what to look for @@ -44,32 +25,23 @@ inline V search_map(const std::map<K, V>& mapping, const K& key, const V& null_result = V()) { - typename std::map<K, V>::const_iterator i = mapping.find(key); + auto i = mapping.find(key); if(i == mapping.end()) return null_result; return i->second; } -/** -* Function adaptor for delete operation -*/ -template<class T> -class del_fun : public std::unary_function<T, void> - { - public: - void operator()(T* ptr) { delete ptr; } - }; - -/** -* Delete the second half of a pair of objects -*/ -template<typename Pair> -void delete2nd(Pair& pair) +template<typename K, typename V, typename R> +inline R search_map(const std::map<K, V>& mapping, const K& key, + const R& null_result, const R& found_result) { - delete pair.second; + auto i = mapping.find(key); + if(i == mapping.end()) + return null_result; + return found_result; } -/** +/* * Insert a key/value pair into a multimap */ template<typename K, typename V> @@ -84,6 +56,19 @@ void multimap_insert(std::multimap<K, V>& multimap, #endif } +/** +* Existence check for values +*/ +template<typename T> +bool value_exists(const std::vector<T>& vec, + const T& val) + { + for(size_t i = 0; i != vec.size(); ++i) + if(vec[i] == val) + return true; + return false; + } + } #endif diff --git a/src/utils/time.cpp b/src/utils/time.cpp deleted file mode 100644 index 65e808c04..000000000 --- a/src/utils/time.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/* -* Time Functions -* (C) 1999-2010 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/time.h> -#include <botan/exceptn.h> -#include <ctime> - -#if defined(BOTAN_TARGET_OS_HAS_WIN32_GET_SYSTEMTIME) - #include <windows.h> -#endif - -#if defined(BOTAN_TARGET_OS_HAS_GETTIMEOFDAY) - #include <sys/time.h> -#endif - -#if defined(BOTAN_TARGET_OS_HAS_CLOCK_GETTIME) - - #ifndef _POSIX_C_SOURCE - #define _POSIX_C_SOURCE 199309 - #endif - - #include <time.h> - - #ifndef CLOCK_REALTIME - #define CLOCK_REALTIME 0 - #endif - -#endif - -namespace Botan { - -namespace { - -/* -* Combine a two time values into a single one -*/ -u64bit combine_timers(u32bit seconds, u32bit parts, u32bit parts_hz) - { - static const u64bit NANOSECONDS_UNITS = 1000000000; - - u64bit res = seconds * NANOSECONDS_UNITS; - res += parts * (NANOSECONDS_UNITS / parts_hz); - return res; - } - -std::tm do_gmtime(time_t time_val) - { - std::tm tm; - -#if defined(BOTAN_TARGET_OS_HAS_GMTIME_S) - gmtime_s(&tm, &time_val); // Windows -#elif defined(BOTAN_TARGET_OS_HAS_GMTIME_R) - gmtime_r(&time_val, &tm); // Unix/SUSv2 -#else - std::tm* tm_p = std::gmtime(&time_val); - if (tm_p == 0) - throw Encoding_Error("time_t_to_tm could not convert"); - tm = *tm_p; -#endif - - return tm; - } - -} - -/* -* Get the system clock -*/ -u64bit system_time() - { - return static_cast<u64bit>(std::time(0)); - } - -/* -* Convert a time_point to a calendar_point -*/ -calendar_point calendar_value(u64bit a_time_t) - { - std::tm tm = do_gmtime(static_cast<std::time_t>(a_time_t)); - - return calendar_point(tm.tm_year + 1900, - tm.tm_mon + 1, - tm.tm_mday, - tm.tm_hour, - tm.tm_min, - tm.tm_sec); - } - -u64bit get_nanoseconds_clock() - { -#if defined(BOTAN_TARGET_OS_HAS_CLOCK_GETTIME) - - struct ::timespec tv; - ::clock_gettime(CLOCK_REALTIME, &tv); - return combine_timers(tv.tv_sec, tv.tv_nsec, 1000000000); - -#elif defined(BOTAN_TARGET_OS_HAS_GETTIMEOFDAY) - - struct ::timeval tv; - ::gettimeofday(&tv, 0); - return combine_timers(tv.tv_sec, tv.tv_usec, 1000000); - -#elif defined(BOTAN_TARGET_OS_HAS_WIN32_GET_SYSTEMTIME) - - // Returns time since January 1, 1601 in 100-ns increments - ::FILETIME tv; - ::GetSystemTimeAsFileTime(&tv); - u64bit tstamp = (static_cast<u64bit>(tv.dwHighDateTime) << 32) | - tv.dwLowDateTime; - - return (tstamp * 100); // Scale to 1 nanosecond units - -#else - - return combine_timers(static_cast<u32bit>(std::time(0)), - std::clock(), CLOCKS_PER_SEC); - -#endif - } - -} diff --git a/src/utils/types.h b/src/utils/types.h index 61a55368c..255311580 100644 --- a/src/utils/types.h +++ b/src/utils/types.h @@ -39,15 +39,7 @@ typedef signed int s32bit; /** * Typedef representing an unsigned 64-bit quantity */ -#if defined(_MSC_VER) || defined(__BORLANDC__) - typedef unsigned __int64 u64bit; -#elif defined(__KCC) - typedef unsigned __long_long u64bit; -#elif defined(__GNUG__) - __extension__ typedef unsigned long long u64bit; -#else - typedef unsigned long long u64bit; -#endif +typedef unsigned long long u64bit; /** * A default buffer size; typically a memory page diff --git a/src/utils/ui.cpp b/src/utils/ui.cpp deleted file mode 100644 index e6c3430ff..000000000 --- a/src/utils/ui.cpp +++ /dev/null @@ -1,36 +0,0 @@ -/* -* User Interface -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/ui.h> - -namespace Botan { - -/* -* Get a passphrase from the user -*/ -std::string User_Interface::get_passphrase(const std::string&, - const std::string&, - UI_Result& action) const - { - action = OK; - - if(!first_try) - action = CANCEL_ACTION; - - return preset_passphrase; - } - -/* -* User_Interface Constructor -*/ -User_Interface::User_Interface(const std::string& preset) : - preset_passphrase(preset) - { - first_try = true; - } - -} diff --git a/src/utils/ui.h b/src/utils/ui.h deleted file mode 100644 index f69bb2c6d..000000000 --- a/src/utils/ui.h +++ /dev/null @@ -1,37 +0,0 @@ -/* -* User Interface -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_UI_H__ -#define BOTAN_UI_H__ - -#include <botan/build.h> -#include <string> - -namespace Botan { - -/** -* User Interface -* Only really used for callbacks for PKCS #8 decryption -*/ -class BOTAN_DLL User_Interface - { - public: - enum UI_Result { OK, CANCEL_ACTION }; - - virtual std::string get_passphrase(const std::string&, - const std::string&, - UI_Result&) const; - User_Interface(const std::string& = ""); - virtual ~User_Interface() {} - protected: - std::string preset_passphrase; - mutable bool first_try; - }; - -} - -#endif diff --git a/src/utils/xor_buf.h b/src/utils/xor_buf.h index 3c96dea70..b67d84c50 100644 --- a/src/utils/xor_buf.h +++ b/src/utils/xor_buf.h @@ -9,6 +9,7 @@ #define BOTAN_XOR_BUF_H__ #include <botan/types.h> +#include <vector> namespace Botan { @@ -70,6 +71,31 @@ inline void xor_buf(byte out[], out[i] = in[i] ^ in2[i]; } +template<typename Alloc, typename Alloc2> +void xor_buf(std::vector<byte, Alloc>& out, + const std::vector<byte, Alloc2>& in, + size_t n) + { + xor_buf(&out[0], &in[0], n); + } + +template<typename Alloc> +void xor_buf(std::vector<byte, Alloc>& out, + const byte* in, + size_t n) + { + xor_buf(&out[0], in, n); + } + +template<typename Alloc, typename Alloc2> +void xor_buf(std::vector<byte, Alloc>& out, + const byte* in, + const std::vector<byte, Alloc2>& in2, + size_t n) + { + xor_buf(&out[0], &in[0], &in2[0], n); + } + } #endif diff --git a/src/wrap/python/core.cpp b/src/wrap/python/core.cpp index 7dac7be7f..6dcceee74 100644 --- a/src/wrap/python/core.cpp +++ b/src/wrap/python/core.cpp @@ -178,7 +178,7 @@ std::string python_kdf2(const std::string& param, const std::string& masterkey, u32bit outputlength) { - std::auto_ptr<KDF> kdf(get_kdf("KDF2(SHA-1)")); + std::unique_ptr<KDF> kdf(get_kdf("KDF2(SHA-1)")); return make_string( kdf->derive_key(outputlength, diff --git a/src/wrap/python/filter.cpp b/src/wrap/python/filter.cpp index e329ed708..eef8b202c 100644 --- a/src/wrap/python/filter.cpp +++ b/src/wrap/python/filter.cpp @@ -107,19 +107,19 @@ Filter* make_filter4(const std::string& name, name); } -void append_filter(Pipe& pipe, std::auto_ptr<Filter> filter) +void append_filter(Pipe& pipe, std::unique_ptr<Filter> filter) { pipe.append(filter.get()); filter.release(); } -void prepend_filter(Pipe& pipe, std::auto_ptr<Filter> filter) +void prepend_filter(Pipe& pipe, std::unique_ptr<Filter> filter) { pipe.prepend(filter.get()); filter.release(); } -void do_send(std::auto_ptr<FilterWrapper> filter, const std::string& data) +void do_send(std::unique_ptr<FilterWrapper> filter, const std::string& data) { filter->send_str(data); } @@ -128,7 +128,7 @@ BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(rallas_ovls, read_all_as_string, 0, 1) void export_filters() { - class_<Filter, std::auto_ptr<Filter>, boost::noncopyable> + class_<Filter, std::unique_ptr<Filter>, boost::noncopyable> ("__Internal_FilterObj", no_init); def("make_filter", make_filter1, @@ -142,7 +142,7 @@ void export_filters() // This might not work - Pipe will delete the filter, but Python // might have allocated the space with malloc() or who-knows-what -> bad - class_<FilterWrapper, std::auto_ptr<FilterWrapper>, + class_<FilterWrapper, std::unique_ptr<FilterWrapper>, bases<Filter>, boost::noncopyable> ("FilterObj") .def("write", pure_virtual(&Py_Filter::write_str)) @@ -150,8 +150,8 @@ void export_filters() .def("start_msg", &Filter::start_msg, &FilterWrapper::default_start_msg) .def("end_msg", &Filter::end_msg, &FilterWrapper::default_end_msg); - implicitly_convertible<std::auto_ptr<FilterWrapper>, - std::auto_ptr<Filter> >(); + implicitly_convertible<std::unique_ptr<FilterWrapper>, + std::unique_ptr<Filter> >(); void (Pipe::*pipe_write_str)(const std::string&) = &Pipe::write; void (Pipe::*pipe_process_str)(const std::string&) = &Pipe::process_msg; diff --git a/src/wrap/python/python_botan.h b/src/wrap/python/python_botan.h index a7a2e505e..03bdd9156 100644 --- a/src/wrap/python/python_botan.h +++ b/src/wrap/python/python_botan.h @@ -24,7 +24,8 @@ class Bad_Size : public Exception public: Bad_Size(u32bit got, u32bit expected) : Exception("Bad size detected in Python/C++ conversion layer: got " + - to_string(got) + " bytes, expected " + to_string(expected)) + std::to_string(got) + " bytes, expected " + + std::to_string(expected)) {} }; @@ -33,7 +34,7 @@ inline std::string make_string(const byte input[], u32bit length) return std::string((const char*)input, length); } -inline std::string make_string(const MemoryRegion<byte>& in) +inline std::string make_string(const secure_vector<byte>& in) { return make_string(in.begin(), in.size()); } diff --git a/src/wrap/python/rsa.cpp b/src/wrap/python/rsa.cpp index dc6053503..3ff1edb07 100644 --- a/src/wrap/python/rsa.cpp +++ b/src/wrap/python/rsa.cpp @@ -40,7 +40,7 @@ class Py_RSA_PrivateKey std::string to_ber() const { - SecureVector<byte> bits = PKCS8::BER_encode(*rsa_key); + secure_vector<byte> bits = PKCS8::BER_encode(*rsa_key); return std::string(reinterpret_cast<const char*>(&bits[0]), bits.size()); @@ -140,7 +140,7 @@ class Py_RSA_PublicKey std::string to_ber() const { - SecureVector<byte> bits = X509::BER_encode(*rsa_key); + secure_vector<byte> bits = X509::BER_encode(*rsa_key); return std::string(reinterpret_cast<const char*>(&bits[0]), bits.size()); diff --git a/src/wrap/python/x509.cpp b/src/wrap/python/x509.cpp index 4c248890d..0a29ad83a 100644 --- a/src/wrap/python/x509.cpp +++ b/src/wrap/python/x509.cpp @@ -63,7 +63,7 @@ void export_x509() { vector_to_list<std::string>(); vector_to_list<X509_Certificate>(); - memvec_to_hexstr<MemoryVector<byte> >(); + memvec_to_hexstr<std::vector<byte> >(); python::class_<X509_Certificate> ("X509_Certificate", python::init<std::string>()) |