diff options
192 files changed, 4457 insertions, 8671 deletions
diff --git a/checks/check.cpp b/checks/check.cpp index 03579b51a..1f46b5b4c 100644 --- a/checks/check.cpp +++ b/checks/check.cpp @@ -186,15 +186,9 @@ int run_test_suite(RandomNumberGenerator& rng) errors += do_pk_validation_tests(PK_VALIDATION_FILE, rng); //errors += do_cvc_tests(rng); } - catch(Botan::Exception& e) - { - std::cout << "Exception caught: " << e.what() << std::endl; - return 1; - } catch(std::exception& e) { - std::cout << "Standard library exception caught: " - << e.what() << std::endl; + std::cout << "Exception: " << e.what() << std::endl; return 1; } catch(...) diff --git a/checks/common.h b/checks/common.h index 5b8f0a5d0..b849ce721 100644 --- a/checks/common.h +++ b/checks/common.h @@ -25,8 +25,7 @@ std::string hex_encode(const byte in[], u32bit len); Botan::SecureVector<byte> decode_hex(const std::string&); Botan::Filter* lookup(const std::string& algname, - const std::vector<std::string>& params, - const std::string& section); + const std::vector<std::string>& params); Botan::Filter* lookup_block(const std::string&, const std::string&); Botan::Filter* lookup_cipher(const std::string&, const std::string&, diff --git a/checks/cvc_tests.cpp b/checks/cvc_tests.cpp index d041569ba..68b669996 100644 --- a/checks/cvc_tests.cpp +++ b/checks/cvc_tests.cpp @@ -1,10 +1,9 @@ -/****************************************************** -* CVC EAC1.1 tests * -* * -* (C) 2008 Falko Strenzke * -* [email protected] * -* 2008 Jack Lloyd * -******************************************************/ +/* +* CVC EAC1.1 tests +* +* (C) 2008 Falko Strenzke ([email protected]) +* 2008 Jack Lloyd +*/ #include "validate.h" #include <botan/build.h> @@ -24,7 +23,6 @@ #include <botan/x509cert.h> #include <botan/x509self.h> #include <botan/oids.h> -#include <botan/look_pk.h> #include <botan/cvc_self.h> #include <botan/cvc_cert.h> #include <botan/cvc_ado.h> @@ -79,7 +77,7 @@ bool helper_files_equal(std::string const& file_path1, std::string const& file_p void test_enc_gen_selfsigned(RandomNumberGenerator& rng) { - std::cout << "." << std::flush; + std::cout << '.' << std::flush; EAC1_1_CVC_Options opts; //opts.cpi = 0; @@ -579,6 +577,8 @@ void test_cvc_chain(RandomNumberGenerator& rng) u32bit do_cvc_tests(Botan::RandomNumberGenerator& rng) { + std::cout << "Testing CVC: " << std::flush; + test_enc_gen_selfsigned(rng); test_enc_gen_req(rng); test_cvc_req_ext(rng); @@ -591,6 +591,7 @@ u32bit do_cvc_tests(Botan::RandomNumberGenerator& rng) test_eac_str_illegal_values(rng); test_tmp_eac_str_enc(rng); test_cvc_chain(rng); + std::cout << std::endl; return 0; } diff --git a/checks/dolook.cpp b/checks/dolook.cpp index aa2d58e1f..e9be25614 100644 --- a/checks/dolook.cpp +++ b/checks/dolook.cpp @@ -11,7 +11,6 @@ #include <botan/filters.h> #include <botan/libstate.h> #include <botan/hmac.h> -#include <botan/aes.h> #include <botan/sha2_32.h> #include <botan/sha2_64.h> #include <botan/parsing.h> @@ -36,9 +35,16 @@ #include <botan/hmac_rng.h> #endif +#if defined(BOTAN_HAS_AES) + #include <botan/aes.h> +#endif + +#if defined(BOTAN_HAS_DES) + #include <botan/des.h> +#endif + #if defined(BOTAN_HAS_X931_RNG) #include <botan/x931_rng.h> - #include <botan/des.h> #endif #if defined(BOTAN_HAS_AUTO_SEEDING_RNG) @@ -156,10 +162,15 @@ Filter* lookup_rng(const std::string& algname, #endif #if defined(BOTAN_HAS_X931_RNG) + +#if defined(BOTAN_HAS_DES) if(algname == "X9.31-RNG(TripleDES)") prng = new ANSI_X931_RNG(new TripleDES, new Fixed_Output_RNG(decode_hex(key))); - else if(algname == "X9.31-RNG(AES-128)") +#endif + +#if defined(BOTAN_HAS_AES) + if(algname == "X9.31-RNG(AES-128)") prng = new ANSI_X931_RNG(new AES_128, new Fixed_Output_RNG(decode_hex(key))); else if(algname == "X9.31-RNG(AES-192)") @@ -170,7 +181,9 @@ Filter* lookup_rng(const std::string& algname, new Fixed_Output_RNG(decode_hex(key))); #endif -#if defined(BOTAN_HAS_RANDPOOL) +#endif + +#if defined(BOTAN_HAS_RANDPOOL) && defined(BOTAN_HAS_AES) if(algname == "Randpool") { prng = new Randpool(new AES_256, new HMAC(new SHA_256)); diff --git a/checks/ec_tests.cpp b/checks/ec_tests.cpp index 2d23a3033..485639e76 100644 --- a/checks/ec_tests.cpp +++ b/checks/ec_tests.cpp @@ -741,7 +741,7 @@ void test_cdc_curve_33() { p_G.check_invariants(); } - catch (std::exception& e) + catch (std::exception) { exc = true; } @@ -847,84 +847,6 @@ void test_curve_cp_ctor() CurveGFp curve(dom_pars.get_curve()); } -/** -* The following test checks assignment operator and copy ctor for ec keys -*/ -void test_ec_key_cp_and_assignment(RandomNumberGenerator& rng) - { - std::cout << "." << std::flush; - - - std::string g_secp("024a96b5688ef573284664698968c38bb913cbfc82"); - SecureVector<byte> sv_g_secp = decode_hex ( g_secp); - BigInt bi_p_secp("0xffffffffffffffffffffffffffffffff7fffffff"); - BigInt bi_a_secp("0xffffffffffffffffffffffffffffffff7ffffffc"); - BigInt bi_b_secp("0x1c97befc54bd7a8b65acf89f81d4d4adc565fa45"); - BigInt order = BigInt("0x0100000000000000000001f4c8f927aed3ca752257"); - CurveGFp curve(bi_p_secp, bi_a_secp, bi_b_secp); - - BigInt cofactor = BigInt(1); - PointGFp p_G = OS2ECP ( sv_g_secp, curve ); - - EC_Domain_Params dom_pars = EC_Domain_Params(curve, p_G, order, cofactor); - ECDSA_PrivateKey my_priv_key(rng, dom_pars); - - std::string str_message = ("12345678901234567890abcdef12"); - SecureVector<byte> sv_message = decode_hex(str_message); - - // sign with the original key - SecureVector<byte> signature = my_priv_key.sign(sv_message.begin(), sv_message.size(), rng); - bool ver_success = my_priv_key.verify(sv_message.begin(), sv_message.size(), signature.begin(), signature.size()); - CHECK_MESSAGE(ver_success, "generated signature could not be verified positively"); - - // make a copy and sign - ECDSA_PrivateKey cp_key(my_priv_key); - SecureVector<byte> cp_sig = cp_key.sign(sv_message.begin(), sv_message.size(), rng); - - // now cross verify... - CHECK(my_priv_key.verify(sv_message.begin(), sv_message.size(), cp_sig.begin(), cp_sig.size())); - CHECK(cp_key.verify(sv_message.begin(), sv_message.size(), signature.begin(), signature.size())); - - // make an copy assignment and verify - ECDSA_PrivateKey ass_key = my_priv_key; - SecureVector<byte> ass_sig = ass_key.sign(sv_message.begin(), sv_message.size(), rng); - - // now cross verify... - CHECK(my_priv_key.verify(sv_message.begin(), sv_message.size(), ass_sig.begin(), ass_sig.size())); - CHECK(ass_key.verify(sv_message.begin(), sv_message.size(), signature.begin(), signature.size())); - } - -void test_ec_key_cast(RandomNumberGenerator& rng) - { - std::cout << "." << std::flush; - - std::string g_secp("024a96b5688ef573284664698968c38bb913cbfc82"); - SecureVector<byte> sv_g_secp = decode_hex ( g_secp); - BigInt bi_p_secp("0xffffffffffffffffffffffffffffffff7fffffff"); - BigInt bi_a_secp("0xffffffffffffffffffffffffffffffff7ffffffc"); - BigInt bi_b_secp("0x1c97befc54bd7a8b65acf89f81d4d4adc565fa45"); - BigInt order = BigInt("0x0100000000000000000001f4c8f927aed3ca752257"); - CurveGFp curve(bi_p_secp, bi_a_secp, bi_b_secp); - BigInt cofactor = BigInt(1); - PointGFp p_G = OS2ECP ( sv_g_secp, curve ); - - EC_Domain_Params dom_pars = EC_Domain_Params(curve, p_G, order, cofactor); - ECDSA_PrivateKey my_priv_key(rng, dom_pars); - ECDSA_PublicKey my_ecdsa_pub_key = my_priv_key; - - Public_Key* my_pubkey = static_cast<Public_Key*>(&my_ecdsa_pub_key); - ECDSA_PublicKey* ec_cast_back = dynamic_cast<ECDSA_PublicKey*>(my_pubkey); - - std::string str_message = ("12345678901234567890abcdef12"); - SecureVector<byte> sv_message = decode_hex(str_message); - - // sign with the original key - SecureVector<byte> signature = my_priv_key.sign(sv_message.begin(), sv_message.size(), rng); - - bool ver_success = ec_cast_back->verify(sv_message.begin(), sv_message.size(), signature.begin(), signature.size()); - CHECK_MESSAGE(ver_success, "generated signature could not be verified positively"); - } - } void do_ec_tests(RandomNumberGenerator& rng) @@ -955,8 +877,6 @@ void do_ec_tests(RandomNumberGenerator& rng) test_point_swap(rng); test_mult_sec_mass(rng); test_curve_cp_ctor(); - test_ec_key_cp_and_assignment(rng); - test_ec_key_cast(rng); std::cout << std::endl; } diff --git a/checks/ecdh.cpp b/checks/ecdh.cpp new file mode 100644 index 000000000..a63742f2f --- /dev/null +++ b/checks/ecdh.cpp @@ -0,0 +1,130 @@ +/* +* ECDH tests +* +* (C) 2007 Manuel Hartl ([email protected]) +* 2008 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/build.h> + +#include "validate.h" +#include "common.h" + +#if defined(BOTAN_HAS_ECDH) + +#include <iostream> +#include <fstream> + +#include <botan/pubkey.h> +#include <botan/ecdh.h> +#include <botan/x509self.h> +#include <botan/der_enc.h> + +using namespace Botan; + +#define CHECK_MESSAGE(expr, print) try { if(!(expr)) std::cout << print << "\n"; } catch(std::exception& e) { std::cout << __FUNCTION__ << ": " << e.what() << "\n"; } +#define CHECK(expr) try { if(!(expr)) std::cout << #expr << "\n"; } catch(std::exception& e) { std::cout << __FUNCTION__ << ": " << e.what() << "\n"; } + +namespace { + +void test_ecdh_normal_derivation(RandomNumberGenerator& rng) + { + std::cout << "." << std::flush; + + EC_Domain_Params dom_pars(OID("1.3.132.0.8")); + + ECDH_PrivateKey private_a(rng, dom_pars); + + ECDH_PrivateKey private_b(rng, dom_pars); //public_a.getCurve() + + PK_Key_Agreement ka(private_a, "KDF2(SHA-1)"); + PK_Key_Agreement kb(private_b, "KDF2(SHA-1)"); + + SymmetricKey alice_key = ka.derive_key(32, private_b.public_value()); + SymmetricKey bob_key = kb.derive_key(32, private_a.public_value()); + + if(alice_key != bob_key) + { + std::cout << "The two keys didn't match!\n"; + std::cout << "Alice's key was: " << alice_key.as_string() << "\n"; + std::cout << "Bob's key was: " << bob_key.as_string() << "\n"; + } + } + +void test_ecdh_some_dp(RandomNumberGenerator& rng) + { + std::vector<std::string> oids; + oids.push_back("1.2.840.10045.3.1.7"); + oids.push_back("1.3.132.0.8"); + oids.push_back("1.2.840.10045.3.1.1"); + + for(u32bit i = 0; i< oids.size(); i++) + { + std::cout << "." << std::flush; + + OID oid(oids[i]); + EC_Domain_Params dom_pars(oid); + + ECDH_PrivateKey private_a(rng, dom_pars); + ECDH_PrivateKey private_b(rng, dom_pars); + + PK_Key_Agreement ka(private_a, "KDF2(SHA-1)"); + PK_Key_Agreement kb(private_b, "KDF2(SHA-1)"); + + SymmetricKey alice_key = ka.derive_key(32, private_b.public_value()); + SymmetricKey bob_key = kb.derive_key(32, private_a.public_value()); + + CHECK_MESSAGE(alice_key == bob_key, "different keys - " << "Alice's key was: " << alice_key.as_string() << ", Bob's key was: " << bob_key.as_string()); + } + + } + +void test_ecdh_der_derivation(RandomNumberGenerator& rng) + { + std::vector<std::string> oids; + oids.push_back("1.2.840.10045.3.1.7"); + oids.push_back("1.3.132.0.8"); + oids.push_back("1.2.840.10045.3.1.1"); + + for(u32bit i = 0; i< oids.size(); i++) + { + OID oid(oids[i]); + EC_Domain_Params dom_pars(oid); + + 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(); + + PK_Key_Agreement ka(private_a, "KDF2(SHA-1)"); + PK_Key_Agreement kb(private_b, "KDF2(SHA-1)"); + + SymmetricKey alice_key = ka.derive_key(32, key_b); + SymmetricKey bob_key = kb.derive_key(32, key_a); + + CHECK_MESSAGE(alice_key == bob_key, "different keys - " << "Alice's key was: " << alice_key.as_string() << ", Bob's key was: " << bob_key.as_string()); + //cout << "key: " << alice_key.as_string() << endl; + } + } + +} + +u32bit do_ecdh_tests(RandomNumberGenerator& rng) + { + std::cout << "Testing ECDH (InSiTo unit tests): "; + + test_ecdh_normal_derivation(rng); + test_ecdh_some_dp(rng); + test_ecdh_der_derivation(rng); + + std::cout << std::endl; + + return 0; + } + +#else +u32bit do_ecdh_tests(RandomNumberGenerator&) { return 0; } +#endif diff --git a/checks/ecdsa.cpp b/checks/ecdsa.cpp index 6767db154..7e585b584 100644 --- a/checks/ecdsa.cpp +++ b/checks/ecdsa.cpp @@ -11,7 +11,7 @@ #if defined(BOTAN_HAS_ECDSA) #include <botan/botan.h> -#include <botan/look_pk.h> +#include <botan/pubkey.h> #include <botan/ecdsa.h> #include <botan/rsa.h> #include <botan/x509cert.h> @@ -70,12 +70,12 @@ void test_hash_larger_than_n(RandomNumberGenerator& rng) { format = "EMSA1_BSI(SHA-1)"; } - std::unique_ptr<PK_Signer> pk_signer(get_pk_signer(priv_key, format)); + PK_Signer pk_signer(priv_key, format); SecureVector<byte> signature; bool sig_exc = false; try { - signature = pk_signer->sign_message(message, rng); + signature = pk_signer.sign_message(message, rng); } catch(Encoding_Error e) { @@ -90,11 +90,10 @@ void test_hash_larger_than_n(RandomNumberGenerator& rng) CHECK(!sig_exc); } - if(i==0) // makes no sense to check for sha224 { - std::unique_ptr<PK_Verifier> pk_verifier(get_pk_verifier(priv_key, format)); - bool ver = pk_verifier->verify_message(message, signature); + PK_Verifier pk_verifier(priv_key, format); + bool ver = pk_verifier.verify_message(message, signature); CHECK(ver); } @@ -103,54 +102,25 @@ void test_hash_larger_than_n(RandomNumberGenerator& rng) // now check that verification alone fails // sign it with the normal EMSA1 - std::unique_ptr<PK_Signer> pk_signer(get_pk_signer(priv_key, "EMSA1(SHA-224)")); - SecureVector<byte> signature = pk_signer->sign_message(message, rng); + PK_Signer pk_signer(priv_key, "EMSA1(SHA-224)"); + SecureVector<byte> signature = pk_signer.sign_message(message, rng); - std::unique_ptr<PK_Verifier> pk_verifier(get_pk_verifier(priv_key, "EMSA1_BSI(SHA-224)")); + PK_Verifier pk_verifier(priv_key, "EMSA1_BSI(SHA-224)"); // verify against EMSA1_BSI // we make sure it doesn't fail because of the invalid signature, // but because of the Encoding_Error - if(pk_verifier->verify_message(message, signature)) + if(pk_verifier.verify_message(message, signature)) std::cout << "Corrupt ECDSA signature verified, should not have\n"; } -/** -* Tests whether the the signing routine will work correctly in case the integer e -* that is constructed from the message is larger than n, the order of the base point -*/ -void test_message_larger_than_n(RandomNumberGenerator& rng) - { - std::cout << "." << std::flush; - - EC_Domain_Params dom_pars(OID("1.3.132.0.8")); - ECDSA_PrivateKey priv_key(rng, dom_pars); - std::string str_message = ("12345678901234567890abcdef1212345678901234567890abcdef1212345678901234567890abcdef12"); - - SecureVector<byte> sv_message = decode_hex(str_message); - bool thrn = false; - SecureVector<byte> signature; - try - { - signature = priv_key.sign(sv_message.begin(), sv_message.size(), rng); - } - catch (Invalid_Argument e) - { - thrn = true; - } - //cout << "signature = " << hex_encode(signature.begin(), signature.size()) << "\n"; - bool ver_success = priv_key.verify(sv_message.begin(), sv_message.size(), signature.begin(), signature.size()); - CHECK_MESSAGE(ver_success, "generated signature could not be verified positively"); - //CHECK_MESSAGE(thrn, "no exception was thrown although message to sign was too long"); - } - void test_decode_ecdsa_X509() { std::cout << "." << std::flush; X509_Certificate cert(TEST_DATA_DIR "/CSCA.CSCA.csca-germany.1.crt"); - CHECK_MESSAGE(OIDS::lookup(cert.signature_algorithm().oid) == "ECDSA/EMSA1_BSI(SHA-224)", "error reading signature algorithm from x509 ecdsa certificate"); + CHECK_MESSAGE(OIDS::lookup(cert.signature_algorithm().oid) == "ECDSA/EMSA1(SHA-224)", "error reading signature algorithm from x509 ecdsa certificate"); CHECK_MESSAGE(to_hex(cert.serial_number()) == "01", "error reading serial from x509 ecdsa certificate"); CHECK_MESSAGE(to_hex(cert.authority_key_id()) == "0096452DE588F966C4CCDF161DD1F3F5341B71E7", "error reading authority key id from x509 ecdsa certificate"); @@ -187,30 +157,28 @@ void test_decode_ver_link_SHA1() void test_sign_then_ver(RandomNumberGenerator& rng) { - std::cout << "." << std::flush; + std::cout << '.' << std::flush; - std::string g_secp("024a96b5688ef573284664698968c38bb913cbfc82"); - SecureVector<byte> sv_g_secp = decode_hex(g_secp); - BigInt bi_p_secp("0xffffffffffffffffffffffffffffffff7fffffff"); - BigInt bi_a_secp("0xffffffffffffffffffffffffffffffff7ffffffc"); - BigInt bi_b_secp("0x1c97befc54bd7a8b65acf89f81d4d4adc565fa45"); - BigInt order = BigInt("0x0100000000000000000001f4c8f927aed3ca752257"); - CurveGFp curve(bi_p_secp, bi_a_secp, bi_b_secp); - BigInt cofactor = BigInt(1); - PointGFp p_G = OS2ECP ( sv_g_secp, curve ); - - EC_Domain_Params dom_pars = EC_Domain_Params(curve, p_G, order, cofactor); - ECDSA_PrivateKey my_priv_key(rng, dom_pars); - - std::string str_message = ("12345678901234567890abcdef12"); - SecureVector<byte> sv_message = decode_hex(str_message); - SecureVector<byte> signature = my_priv_key.sign(sv_message.begin(), sv_message.size(), rng); - //cout << "signature = " << hex_encode(signature.begin(), signature.size()) << "\n"; - bool ver_success = my_priv_key.verify(sv_message.begin(), sv_message.size(), signature.begin(), signature.size()); - CHECK_MESSAGE(ver_success, "generated signature could not be verified positively"); - signature[signature.size()-1] += 0x01; - bool ver_must_fail = my_priv_key.verify(sv_message.begin(), sv_message.size(), signature.begin(), signature.size()); - CHECK_MESSAGE(!ver_must_fail, "corrupted signature could be verified positively"); + EC_Domain_Params dom_pars(OID("1.3.132.0.8")); + ECDSA_PrivateKey ecdsa(rng, dom_pars); + + PK_Signer signer(ecdsa, "EMSA1(SHA-1)"); + + SecureVector<byte> msg = decode_hex("12345678901234567890abcdef12"); + SecureVector<byte> sig = signer.sign_message(msg, rng); + + PK_Verifier verifier(ecdsa, "EMSA1(SHA-1)"); + + bool ok = verifier.verify_message(msg, sig); + + if(!ok) + std::cout << "ERROR: Could not verify ECDSA signature\n"; + + sig[0]++; + ok = verifier.verify_message(msg, sig); + + if(ok) + std::cout << "ERROR: Bogus ECDSA signature verified anyway\n"; } bool test_ec_sign(RandomNumberGenerator& rng) @@ -223,16 +191,16 @@ bool test_ec_sign(RandomNumberGenerator& rng) ECDSA_PrivateKey priv_key(rng, dom_pars); std::string pem_encoded_key = PKCS8::PEM_encode(priv_key); - std::unique_ptr<PK_Signer> signer(get_pk_signer(priv_key, "EMSA1(SHA-224)")); - std::unique_ptr<PK_Verifier> verifier(get_pk_verifier(priv_key, "EMSA1(SHA-224)")); + PK_Signer signer(priv_key, "EMSA1(SHA-224)"); + PK_Verifier verifier(priv_key, "EMSA1(SHA-224)"); for(u32bit i = 0; i != 256; ++i) - signer->update((byte)i); - SecureVector<byte> sig = signer->signature(rng); + signer.update((byte)i); + SecureVector<byte> sig = signer.signature(rng); for(u32bit i = 0; i != 256; ++i) - verifier->update((byte)i); - if(!verifier->check_signature(sig)) + verifier.update((byte)i); + if(!verifier.check_signature(sig)) { std::cout << "ECDSA self-test failed!"; return false; @@ -240,9 +208,9 @@ bool test_ec_sign(RandomNumberGenerator& rng) // now check valid signature, different input for(u32bit i = 1; i != 256; ++i) //starting from 1 - verifier->update((byte)i); + verifier.update((byte)i); - if(verifier->check_signature(sig)) + if(verifier.check_signature(sig)) { std::cout << "ECDSA with bad input passed validation"; return false; @@ -252,9 +220,9 @@ bool test_ec_sign(RandomNumberGenerator& rng) sig[sig.size()/2]++; for(u32bit i = 0; i != 256; ++i) - verifier->update((byte)i); + verifier.update((byte)i); - if(verifier->check_signature(sig)) + if(verifier.check_signature(sig)) { std::cout << "ECDSA with bad signature passed validation"; return false; @@ -392,13 +360,16 @@ void test_curve_registry(RandomNumberGenerator& rng) OID oid(oids[i]); EC_Domain_Params dom_pars(oid); dom_pars.get_base_point().check_invariants(); - ECDSA_PrivateKey key(rng, dom_pars); + ECDSA_PrivateKey ecdsa(rng, dom_pars); + + PK_Signer signer(ecdsa, "EMSA1(SHA-1)"); + PK_Verifier verifier(ecdsa, "EMSA1(SHA-1)"); + + SecureVector<byte> msg = decode_hex("12345678901234567890abcdef12"); + SecureVector<byte> sig = signer.sign_message(msg, rng); - std::string str_message = ("12345678901234567890abcdef12"); - SecureVector<byte> sv_message = decode_hex(str_message); - SecureVector<byte> signature = key.sign(sv_message.begin(), sv_message.size(), rng); - bool ver_success = key.verify(sv_message.begin(), sv_message.size(), signature.begin(), signature.size()); - CHECK_MESSAGE(ver_success, "generated signature could not be verified positively"); + if(!verifier.verify_message(msg, sig)) + std::cout << "Failed testing ECDSA sig for curve " << oids[i] << "\n"; } catch(Invalid_Argument& e) { @@ -411,112 +382,57 @@ void test_curve_registry(RandomNumberGenerator& rng) void test_read_pkcs8(RandomNumberGenerator& rng) { std::cout << "." << std::flush; + + SecureVector<byte> msg = decode_hex("12345678901234567890abcdef12"); + try { - 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::string str_message = ("12345678901234567890abcdef12"); - SecureVector<byte> sv_message = decode_hex(str_message); - SecureVector<byte> signature = loaded_ec_key->sign(sv_message.begin(), sv_message.size(), rng); - //cout << "signature = " << hex_encode(signature.begin(), signature.size()) << "\n"; - bool ver_success = loaded_ec_key->verify(sv_message.begin(), sv_message.size(), signature.begin(), signature.size()); - CHECK_MESSAGE(ver_success, "generated signature could not be verified positively"); - - 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* loaded_ec_key_nodp = dynamic_cast<ECDSA_PrivateKey*>(loaded_key_nodp.get()); - CHECK_MESSAGE(loaded_ec_key_nodp, "the loaded key could not be converted into an ECDSA_PrivateKey"); + std::auto_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"); - SecureVector<byte> signature_nodp = loaded_ec_key_nodp->sign(sv_message.begin(), sv_message.size(), rng); - //cout << "signature = " << hex_encode(signature.begin(), signature.size()) << "\n"; - bool ver_success_nodp = loaded_ec_key_nodp->verify(sv_message.begin(), sv_message.size(), signature_nodp.begin(), signature_nodp.size()); - CHECK_MESSAGE(ver_success_nodp, "generated signature could not be verified positively (no_dom)"); - try - { - std::unique_ptr<PKCS8_PrivateKey> loaded_key_withdp(PKCS8::load_key(TEST_DATA_DIR "/withdompar_private.pkcs8.pem", rng)); + PK_Signer signer(*ecdsa, "EMSA1(SHA-1)"); - std::cout << "Unexpected success: loaded key with unknown OID\n"; - } - catch (std::exception& e) { /* OK */ } + SecureVector<byte> sig = signer.sign_message(msg, rng); + + PK_Verifier verifier(*ecdsa, "EMSA1(SHA-1)"); + + CHECK_MESSAGE(verifier.verify_message(msg, sig), + "generated sig could not be verified positively"); } catch (std::exception& e) { std::cout << "Exception in test_read_pkcs8 - " << e.what() << "\n"; } - } - -/** -* The following test tests the copy ctors and and copy-assignment operators -*/ -void test_cp_and_as_ctors(RandomNumberGenerator& rng) - { - std::cout << "." << std::flush; - - 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::string str_message = ("12345678901234567890abcdef12"); - SecureVector<byte> sv_message = decode_hex(str_message); - SecureVector<byte> signature_1 = loaded_ec_key->sign(sv_message.begin(), sv_message.size(), rng); - //cout << "signature = " << hex_encode(signature.begin(), signature.size()) << "\n"; - ECDSA_PrivateKey cp_priv_key(*loaded_ec_key); // priv-key, cp-ctor - SecureVector<byte> signature_2 = cp_priv_key.sign(sv_message.begin(), sv_message.size(), rng); - - ECDSA_PrivateKey as_priv_key = *loaded_ec_key; //priv-key, as-op - SecureVector<byte> signature_3 = as_priv_key.sign(sv_message.begin(), sv_message.size(), rng); - - ECDSA_PublicKey pk_1 = cp_priv_key; // pub-key, as-op - ECDSA_PublicKey pk_2(pk_1); // pub-key, cp-ctor - ECDSA_PublicKey pk_3; - pk_3 = pk_2; // pub-key, as-op - - bool ver_success_1 = pk_1.verify(sv_message.begin(), sv_message.size(), signature_1.begin(), signature_1.size()); + try + { + std::auto_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"); - bool ver_success_2 = pk_2.verify(sv_message.begin(), sv_message.size(), signature_2.begin(), signature_2.size()); + PK_Signer signer(*ecdsa_nodp, "EMSA1(SHA-1)"); + PK_Verifier verifier(*ecdsa_nodp, "EMSA1(SHA-1)"); - bool ver_success_3 = pk_3.verify(sv_message.begin(), sv_message.size(), signature_3.begin(), signature_3.size()); + SecureVector<byte> signature_nodp = signer.sign_message(msg, rng); - CHECK_MESSAGE((ver_success_1 && ver_success_2 && ver_success_3), "different results for copied keys"); - } + CHECK_MESSAGE(verifier.verify_message(msg, signature_nodp), + "generated signature could not be verified positively (no_dom)"); -/** -* The following test tests whether ECDSA keys exhibit correct behaviour when it is -* attempted to use them in an uninitialized state -*/ -void test_non_init_ecdsa_keys(RandomNumberGenerator& rng) - { - std::cout << "." << std::flush; - - std::unique_ptr<PKCS8_PrivateKey> loaded_key(PKCS8::load_key(TEST_DATA_DIR "/wo_dompar_private.pkcs8.pem", rng)); - - std::string str_message = ("12345678901234567890abcdef12"); - ECDSA_PrivateKey empty_priv; - ECDSA_PublicKey empty_pub; - SecureVector<byte> sv_message = decode_hex(str_message); - bool exc1 = false; - try - { - SecureVector<byte> signature_1 = empty_priv.sign(sv_message.begin(), sv_message.size(), rng); - } - catch (std::exception e) - { - exc1 = true; - } - CHECK_MESSAGE(exc1, "there was no exception thrown when attempting to use an uninitialized ECDSA key"); + try + { + std::auto_ptr<PKCS8_PrivateKey> loaded_key_withdp( + PKCS8::load_key(TEST_DATA_DIR "/withdompar_private.pkcs8.pem", rng)); - bool exc2 = false; - try - { - empty_pub.verify(sv_message.begin(), sv_message.size(), sv_message.begin(), sv_message.size()); + std::cout << "Unexpected success: loaded key with unknown OID\n"; + } + catch (std::exception) { /* OK */ } } - catch (std::exception e) + catch (std::exception& e) { - exc2 = true; + std::cout << "Exception in test_read_pkcs8 - " << e.what() << "\n"; } - CHECK_MESSAGE(exc2, "there was no exception thrown when attempting to use an uninitialized ECDSA key"); } } @@ -525,8 +441,6 @@ u32bit do_ecdsa_tests(Botan::RandomNumberGenerator& rng) { std::cout << "Testing ECDSA (InSiTo unit tests): "; - test_hash_larger_than_n(rng); - //test_message_larger_than_n(); test_decode_ecdsa_X509(); test_decode_ver_link_SHA256(); test_decode_ver_link_SHA1(); @@ -536,8 +450,6 @@ u32bit do_ecdsa_tests(Botan::RandomNumberGenerator& rng) test_create_and_verify(rng); test_curve_registry(rng); test_read_pkcs8(rng); - test_cp_and_as_ctors(rng); - test_non_init_ecdsa_keys(rng); std::cout << std::endl; diff --git a/checks/eckaeg.cpp b/checks/eckaeg.cpp deleted file mode 100644 index bc7945a7b..000000000 --- a/checks/eckaeg.cpp +++ /dev/null @@ -1,286 +0,0 @@ -/* -* ECDH tests -* -* (C) 2007 Manuel Hartl ([email protected]) -* 2008 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/build.h> - -#include "validate.h" -#include "common.h" - -#if defined(BOTAN_HAS_ECDH) - -#include <iostream> -#include <fstream> - -#include <botan/symkey.h> -#include <botan/dh.h> -#include <botan/ecdh.h> -#include <botan/x509self.h> -#include <botan/der_enc.h> - -using namespace Botan; - -#define CHECK_MESSAGE(expr, print) try { if(!(expr)) std::cout << print << "\n"; } catch(std::exception& e) { std::cout << __FUNCTION__ << ": " << e.what() << "\n"; } -#define CHECK(expr) try { if(!(expr)) std::cout << #expr << "\n"; } catch(std::exception& e) { std::cout << __FUNCTION__ << ": " << e.what() << "\n"; } - -namespace { - -void test_eckaeg_normal_derivation(RandomNumberGenerator& rng) - { - std::cout << "." << std::flush; - - /* - std::string p_secp = "ffffffffffffffffffffffffffffffff7fffffff"; - std::string a_secp = "ffffffffffffffffffffffffffffffff7ffffffc"; - std::string b_secp = "1c97befc54bd7a8b65acf89f81d4d4adc565fa45"; - std::string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82"; - ::Botan::SecureVector<byte> sv_p_secp = decode_hex(p_secp); - ::Botan::SecureVector<byte> sv_a_secp = decode_hex(a_secp); - ::Botan::SecureVector<byte> sv_b_secp = decode_hex(b_secp); - ::Botan::SecureVector<byte> sv_G_secp_comp = decode_hex(G_secp_comp); - BigInt bi_p_secp = BigInt::decode(sv_p_secp.begin(), sv_p_secp.size()); - BigInt bi_a_secp = BigInt::decode(sv_a_secp.begin(), sv_a_secp.size()); - BigInt bi_b_secp = BigInt::decode(sv_b_secp.begin(), sv_b_secp.size()); - CurveGFp secp160r1(GFpElement(bi_p_secp,bi_a_secp), GFpElement(bi_p_secp, bi_b_secp), bi_p_secp); - */ - - std::string g_secp("024a96b5688ef573284664698968c38bb913cbfc82"); - Botan::SecureVector<Botan::byte> sv_g_secp = decode_hex(g_secp); - BigInt bi_p_secp("0xffffffffffffffffffffffffffffffff7fffffff"); - BigInt bi_a_secp("0xffffffffffffffffffffffffffffffff7ffffffc"); - BigInt bi_b_secp("0x1c97befc54bd7a8b65acf89f81d4d4adc565fa45"); - BigInt order = BigInt("0x0100000000000000000001f4c8f927aed3ca752257"); - CurveGFp curve(bi_p_secp, bi_a_secp, bi_b_secp); - - BigInt cofactor = BigInt(1); - PointGFp p_G = OS2ECP ( sv_g_secp, curve ); - Botan::EC_Domain_Params dom_pars = Botan::EC_Domain_Params(curve, p_G, order, cofactor); - - /** - * begin ECDH - */ - // alices key (a key constructed by domain parameters IS an ephimeral key!) - Botan::ECDH_PrivateKey private_a(rng, dom_pars); - Botan::ECDH_PublicKey public_a = private_a; // Bob gets this - - // Bob creates a key with a matching group - Botan::ECDH_PrivateKey private_b(rng, dom_pars); //public_a.getCurve() - - // Bob sends the key back to Alice - Botan::ECDH_PublicKey public_b = private_b; // Alice gets this - - // Both of them create a key using their private key and the other's - // public key - Botan::SymmetricKey alice_key = private_a.derive_key(public_b); - Botan::SymmetricKey bob_key = private_b.derive_key(public_a); - - if(alice_key != bob_key) - { - std::cout << "The two keys didn't match!\n"; - std::cout << "Alice's key was: " << alice_key.as_string() << "\n"; - std::cout << "Bob's key was: " << bob_key.as_string() << "\n"; - } - } - -void test_eckaeg_some_dp(RandomNumberGenerator& rng) - { - std::vector<std::string> oids; - oids.push_back("1.2.840.10045.3.1.7"); - oids.push_back("1.3.132.0.8"); - oids.push_back("1.2.840.10045.3.1.1"); - - for(Botan::u32bit i = 0; i< oids.size(); i++) - { - std::cout << "." << std::flush; - - Botan::OID oid(oids[i]); - Botan::EC_Domain_Params dom_pars(oid); - Botan::ECDH_PrivateKey private_a(rng, dom_pars); - Botan::ECDH_PublicKey public_a = private_a; - /*unique_ptr<Botan::X509_Encoder> x509_key_enc = public_a.x509_encoder(); - Botan::MemoryVector<Botan::byte> enc_key_a = Botan::DER_Encoder() - .start_cons(Botan::SEQUENCE) - .encode(x509_key_enc->alg_id()) - .encode(x509_key_enc->key_bits(), Botan::BIT_STRING) - .end_cons() - .get_contents();*/ - - Botan::ECDH_PrivateKey private_b(rng, dom_pars); - Botan::ECDH_PublicKey public_b = private_b; - // to test the equivalence, we - // use the direct derivation method here - - Botan::SymmetricKey alice_key = private_a.derive_key(public_b); - - //cout << "encoded key = " << hex_encode(enc_key_a.begin(), enc_key_a.size()) << endl; - - Botan::SymmetricKey bob_key = private_b.derive_key(public_a); - CHECK_MESSAGE(alice_key == bob_key, "different keys - " << "Alice's key was: " << alice_key.as_string() << ", Bob's key was: " << bob_key.as_string()); - //cout << "key: " << alice_key.as_string() << endl; - } - - } - -void test_eckaeg_der_derivation(RandomNumberGenerator& rng) - { - std::vector<std::string> oids; - oids.push_back("1.2.840.10045.3.1.7"); - oids.push_back("1.3.132.0.8"); - oids.push_back("1.2.840.10045.3.1.1"); - - for(Botan::u32bit i = 0; i< oids.size(); i++) - { - Botan::OID oid(oids[i]); - Botan::EC_Domain_Params dom_pars(oid); - - Botan::ECDH_PrivateKey private_a(rng, dom_pars); - Botan::ECDH_PublicKey public_a = private_a; - - Botan::ECDH_PrivateKey private_b(rng, dom_pars); - Botan::ECDH_PublicKey public_b = private_b; - - Botan::MemoryVector<Botan::byte> key_der_a = private_a.public_value(); - Botan::MemoryVector<Botan::byte> key_der_b = private_b.public_value(); - Botan::SymmetricKey alice_key = private_a.derive_key(key_der_b.begin(), key_der_b.size()); - Botan::SymmetricKey bob_key = private_b.derive_key(key_der_a.begin(), key_der_a.size()); - CHECK_MESSAGE(alice_key == bob_key, "different keys - " << "Alice's key was: " << alice_key.as_string() << ", Bob's key was: " << bob_key.as_string()); - //cout << "key: " << alice_key.as_string() << endl; - } - } - -/** -* The following test tests the copy ctors and and copy-assignment operators -*/ -void test_eckaeg_cp_ctor_as_op(RandomNumberGenerator& rng) - { - std::cout << "." << std::flush; - - std::string g_secp("024a96b5688ef573284664698968c38bb913cbfc82"); - Botan::SecureVector<Botan::byte> sv_g_secp = decode_hex(g_secp); - BigInt bi_p_secp("0xffffffffffffffffffffffffffffffff7fffffff"); - BigInt bi_a_secp("0xffffffffffffffffffffffffffffffff7ffffffc"); - BigInt bi_b_secp("0x1c97befc54bd7a8b65acf89f81d4d4adc565fa45"); - BigInt order = BigInt("0x0100000000000000000001f4c8f927aed3ca752257"); - CurveGFp curve(bi_p_secp, bi_a_secp, bi_b_secp); - BigInt cofactor = BigInt(1); - PointGFp p_G = OS2ECP ( sv_g_secp, curve ); - Botan::EC_Domain_Params dom_pars = Botan::EC_Domain_Params(curve, p_G, order, cofactor); - - /** - * begin ECDH - */ - // alices key (a key constructed by domain parameters IS an ephimeral key!) - Botan::ECDH_PrivateKey private_a(rng, dom_pars); - Botan::ECDH_PrivateKey private_a2(private_a); - Botan::ECDH_PrivateKey private_a3; - private_a3 = private_a2; - - Botan::DH_PrivateKey dh_pr_empty; - Botan::DH_PublicKey dh_pub_empty; - - Botan::ECDH_PublicKey public_a = private_a; // Bob gets this - Botan::ECDH_PublicKey public_a2(public_a); - Botan::ECDH_PublicKey public_a3; - public_a3 = public_a; - // Bob creates a key with a matching group - Botan::ECDH_PrivateKey private_b(rng, dom_pars); //public_a.getCurve() - - // Bob sends the key back to Alice - Botan::ECDH_PublicKey public_b = private_b; // Alice gets this - - // Both of them create a key using their private key and the other's - // public key - Botan::SymmetricKey alice_key = private_a.derive_key(public_b); - Botan::SymmetricKey alice_key_2 = private_a2.derive_key(public_b); - Botan::SymmetricKey alice_key_3 = private_a3.derive_key(public_b); - - Botan::SymmetricKey bob_key = private_b.derive_key(public_a); - Botan::SymmetricKey bob_key_2 = private_b.derive_key(public_a2); - Botan::SymmetricKey bob_key_3 = private_b.derive_key(public_a3); - - CHECK_MESSAGE(alice_key == bob_key, "different keys - " << "Alice's key was: " << alice_key.as_string() << ", Bob's key was: " << bob_key.as_string()); - CHECK_MESSAGE(alice_key_2 == bob_key_2, "different keys - " << "Alice's key was: " << alice_key.as_string() << ", Bob's key was: " << bob_key.as_string()); - CHECK_MESSAGE(alice_key_3 == bob_key_3, "different keys - " << "Alice's key was: " << alice_key.as_string() << ", Bob's key was: " << bob_key.as_string()); - CHECK_MESSAGE(alice_key == bob_key_2, "different keys - " << "Alice's key was: " << alice_key.as_string() << ", Bob's key was: " << bob_key.as_string()); - CHECK_MESSAGE(alice_key_2 == bob_key_3, "different keys - " << "Alice's key was: " << alice_key.as_string() << ", Bob's key was: " << bob_key.as_string()); - } - -/** -* The following test tests whether ECDH keys exhibit correct behaviour when it is -* attempted to use them in an uninitialized state -*/ -void test_non_init_eckaeg_keys(RandomNumberGenerator& rng) - { - std::cout << "." << std::flush; - - // set up dom pars - std::string g_secp("024a96b5688ef573284664698968c38bb913cbfc82"); - Botan::SecureVector<Botan::byte> sv_g_secp = decode_hex(g_secp); - BigInt bi_p_secp("0xffffffffffffffffffffffffffffffff7fffffff"); - BigInt bi_a_secp("0xffffffffffffffffffffffffffffffff7ffffffc"); - BigInt bi_b_secp("0x1c97befc54bd7a8b65acf89f81d4d4adc565fa45"); - BigInt order = BigInt("0x0100000000000000000001f4c8f927aed3ca752257"); - CurveGFp curve(bi_p_secp, bi_a_secp, bi_b_secp); - BigInt cofactor = BigInt(1); - PointGFp p_G = OS2ECP ( sv_g_secp, curve ); - Botan::EC_Domain_Params dom_pars = Botan::EC_Domain_Params(curve, p_G, order, cofactor); - - // alices key (a key constructed by domain parameters IS an emphemeral key!) - Botan::ECDH_PrivateKey private_a(rng, dom_pars); - Botan::ECDH_PrivateKey private_b(rng, dom_pars); - - Botan::ECDH_PublicKey public_b; - - Botan::ECDH_PrivateKey private_empty; - Botan::ECDH_PublicKey public_empty; - - bool exc1 = false; - try - { - Botan::SymmetricKey void_key = private_empty.derive_key(public_b); - } - catch (Botan::Exception e) - { - exc1 = true; - } - - CHECK_MESSAGE(exc1, "there was no exception thrown when attempting to use an uninitialized ECDH key"); - - bool exc2 = false; - try - { - Botan::SymmetricKey void_key = private_a.derive_key(public_empty); - } - catch (Botan::Exception e) - { - exc2 = true; - } - - CHECK_MESSAGE(exc2, "there was no exception thrown when attempting to use an uninitialized ECDH key"); - } - -} - -u32bit do_eckaeg_tests(Botan::RandomNumberGenerator& rng) - { - std::cout << "Testing ECDH (InSiTo unit tests): "; - - test_eckaeg_normal_derivation(rng); - test_eckaeg_some_dp(rng); - test_eckaeg_der_derivation(rng); - test_eckaeg_cp_ctor_as_op(rng); - test_non_init_eckaeg_keys(rng); - - std::cout << std::endl; - - return 0; - } - -#else -u32bit do_eckaeg_tests(Botan::RandomNumberGenerator&) { return 0; } -#endif diff --git a/checks/pk.cpp b/checks/pk.cpp index b50ce17da..da6c6277d 100644 --- a/checks/pk.cpp +++ b/checks/pk.cpp @@ -12,6 +12,7 @@ #include <memory> #include <botan/botan.h> +#include <botan/oids.h> #if defined(BOTAN_HAS_RSA) #include <botan/rsa.h> @@ -37,13 +38,24 @@ #include <botan/elgamal.h> #endif +#if defined(BOTAN_HAS_ECDSA) + #include <botan/ecdsa.h> +#endif + +#if defined(BOTAN_HAS_ECDH) + #include <botan/ecdh.h> +#endif + +#if defined(BOTAN_HAS_GOST_34_10_2001) + #include <botan/gost_3410.h> +#endif + #if defined(BOTAN_HAS_DLIES) #include <botan/dlies.h> #include <botan/kdf.h> #endif #include <botan/filters.h> -#include <botan/look_pk.h> #include <botan/numthry.h> using namespace Botan; @@ -58,12 +70,6 @@ BigInt to_bigint(const std::string& h) h.length(), BigInt::Hexadecimal); } -} - -#define DEBUG 0 - -namespace { - void dump_data(const SecureVector<byte>& out, const SecureVector<byte>& expected) { @@ -75,22 +81,66 @@ void dump_data(const SecureVector<byte>& out, std::cout << "Exp: " << pipe.read_all_as_string(1) << std::endl; } -void validate_decryption(PK_Decryptor* d, const std::string& algo, +void validate_save_and_load(const Private_Key* priv_key, + RandomNumberGenerator& rng) + { + std::string name = priv_key->algo_name(); + + std::string pub_pem = X509::PEM_encode(*priv_key); + + try + { + DataSource_Memory input_pub(pub_pem); + std::auto_ptr<Public_Key> restored_pub(X509::load_key(input_pub)); + + if(restored_pub.get() == 0) + 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"; + } + catch(std::exception& e) + { + std::cout << "Exception during load of " << name + << " key: " << e.what() << "\n"; + std::cout << "PEM for pubkey was:\n" << pub_pem << "\n"; + } + + std::string priv_pem = PKCS8::PEM_encode(*priv_key); + + try + { + DataSource_Memory input_priv(priv_pem); + std::auto_ptr<Private_Key> restored_priv( + PKCS8::load_key(input_priv, rng)); + + if(restored_priv.get() == 0) + 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"; + } + catch(std::exception& e) + { + std::cout << "Exception during load of " << name + << " key: " << e.what() << "\n"; + std::cout << "PEM for privkey was:\n" << priv_pem << "\n"; + } + } + +void validate_decryption(PK_Decryptor& d, const std::string& algo, const SecureVector<byte> ctext, const SecureVector<byte> ptext, bool& failure) { - SecureVector<byte> decrypted = d->decrypt(ctext); + SecureVector<byte> decrypted = d.decrypt(ctext); if(decrypted != ptext) { std::cout << "FAILED (decrypt): " << algo << std::endl; dump_data(decrypted, ptext); failure = true; } - delete d; } -void validate_encryption(PK_Encryptor* e, PK_Decryptor* d, +void validate_encryption(PK_Encryptor& e, PK_Decryptor& d, const std::string& algo, const std::string& input, const std::string& random, const std::string& exp, bool& failure) @@ -99,7 +149,7 @@ void validate_encryption(PK_Encryptor* e, PK_Decryptor* d, SecureVector<byte> expected = decode_hex(exp); Fixed_Output_RNG rng(decode_hex(random)); - SecureVector<byte> out = e->encrypt(message, rng); + SecureVector<byte> out = e.encrypt(message, rng); if(out != expected) { std::cout << "FAILED (encrypt): " << algo << std::endl; @@ -108,19 +158,18 @@ void validate_encryption(PK_Encryptor* e, PK_Decryptor* d, } validate_decryption(d, algo, out, message, failure); - delete e; } -void validate_signature(PK_Verifier* v, PK_Signer* s, const std::string& algo, - const std::string& input, const std::string& random, +void validate_signature(PK_Verifier& v, PK_Signer& s, const std::string& algo, + const std::string& input, + RandomNumberGenerator& rng, const std::string& exp, bool& failure) { SecureVector<byte> message = decode_hex(input); SecureVector<byte> expected = decode_hex(exp); - Fixed_Output_RNG rng(decode_hex(random)); - SecureVector<byte> sig = s->sign_message(message, message.size(), rng); + SecureVector<byte> sig = s.sign_message(message, message.size(), rng); if(sig != expected) { @@ -129,7 +178,7 @@ void validate_signature(PK_Verifier* v, PK_Signer* s, const std::string& algo, failure = true; } - if(!v->verify_message(message, message.size(), sig, sig.size())) + if(!v.verify_message(message, message.size(), sig, sig.size())) { std::cout << "FAILED (verify): " << algo << std::endl; failure = true; @@ -138,24 +187,31 @@ void validate_signature(PK_Verifier* v, PK_Signer* s, const std::string& algo, /* This isn't a very thorough testing method, but it will hopefully catch any really horrible errors */ sig[0]++; - if(v->verify_message(message, message.size(), sig, sig.size())) + if(v.verify_message(message, message.size(), sig, sig.size())) { std::cout << "FAILED (accepted bad sig): " << algo << std::endl; failure = true; } + } - delete v; - delete s; +void validate_signature(PK_Verifier& v, PK_Signer& s, const std::string& algo, + const std::string& input, + const std::string& random, + const std::string& exp, bool& failure) + { + Fixed_Output_RNG rng(decode_hex(random)); + + validate_signature(v, s, algo, input, rng, exp, failure); } -void validate_kas(PK_Key_Agreement* kas, const std::string& algo, +void validate_kas(PK_Key_Agreement& kas, const std::string& algo, const SecureVector<byte>& pubkey, const std::string& output, u32bit keylen, bool& failure) { SecureVector<byte> expected = decode_hex(output); - SecureVector<byte> got = kas->derive_key(keylen, - pubkey, pubkey.size()).bits_of(); + SecureVector<byte> got = kas.derive_key(keylen, + pubkey, pubkey.size()).bits_of(); if(got != expected) { @@ -163,8 +219,6 @@ void validate_kas(PK_Key_Agreement* kas, const std::string& algo, dump_data(got, expected); failure = true; } - - delete kas; } u32bit validate_rsa_enc_pkcs8(const std::string& algo, @@ -194,8 +248,8 @@ u32bit validate_rsa_enc_pkcs8(const std::string& algo, std::string eme = algo.substr(12, std::string::npos); - PK_Encryptor* e = get_pk_encryptor(*rsapub, eme); - PK_Decryptor* d = get_pk_decryptor(*rsapriv, eme); + PK_Encryptor_EME e(*rsapub, eme); + PK_Decryptor_EME d(*rsapriv, eme); bool failure = false; validate_encryption(e, d, algo, str[1], str[2], str[3], failure); @@ -212,7 +266,6 @@ u32bit validate_rsa_enc(const std::string& algo, if(str.size() != 6) throw std::runtime_error("Invalid input from pk_valid.dat"); - #if defined(BOTAN_HAS_RSA) RSA_PrivateKey privkey(rng, to_bigint(str[1]), to_bigint(str[2]), @@ -222,8 +275,8 @@ u32bit validate_rsa_enc(const std::string& algo, std::string eme = algo.substr(6, std::string::npos); - PK_Encryptor* e = get_pk_encryptor(pubkey, eme); - PK_Decryptor* d = get_pk_decryptor(privkey, eme); + PK_Encryptor_EME e(pubkey, eme); + PK_Decryptor_EME d(privkey, eme); bool failure = false; validate_encryption(e, d, algo, str[3], str[4], str[5], failure); @@ -248,12 +301,12 @@ u32bit validate_elg_enc(const std::string& algo, std::string eme = algo.substr(8, std::string::npos); - PK_Decryptor* d = get_pk_decryptor(privkey, eme); + PK_Decryptor_EME d(privkey, eme); bool failure = false; if(str.size() == 7) { - PK_Encryptor* e = get_pk_encryptor(pubkey, eme); + PK_Encryptor_EME e(pubkey, eme); validate_encryption(e, d, algo, str[4], str[5], str[6], failure); } else @@ -282,8 +335,8 @@ u32bit validate_rsa_sig(const std::string& algo, std::string emsa = algo.substr(7, std::string::npos); - PK_Verifier* v = get_pk_verifier(pubkey, emsa); - PK_Signer* s = get_pk_signer(privkey, emsa); + PK_Verifier v(pubkey, emsa); + PK_Signer s(privkey, emsa); bool failure = false; validate_signature(v, s, algo, str[3], str[4], str[5], failure); return (failure ? 1 : 0); @@ -303,13 +356,13 @@ u32bit validate_rsa_ver(const std::string& algo, std::string emsa = algo.substr(6, std::string::npos); - std::unique_ptr<PK_Verifier> v(get_pk_verifier(key, emsa)); + PK_Verifier v(key, emsa); SecureVector<byte> msg = decode_hex(str[2]); SecureVector<byte> sig = decode_hex(str[3]); bool passed = true; - passed = v->verify_message(msg, msg.size(), sig, sig.size()); + passed = v.verify_message(msg, msg.size(), sig, sig.size()); return (passed ? 0 : 1); #endif @@ -335,12 +388,12 @@ u32bit validate_rsa_ver_x509(const std::string& algo, std::string emsa = algo.substr(11, std::string::npos); - std::unique_ptr<PK_Verifier> v(get_pk_verifier(*rsakey, emsa)); + PK_Verifier v(*rsakey, emsa); SecureVector<byte> msg = decode_hex(str[1]); SecureVector<byte> sig = decode_hex(str[2]); - bool passed = v->verify_message(msg, msg.size(), sig, sig.size()); + bool passed = v.verify_message(msg, msg.size(), sig, sig.size()); return (passed ? 0 : 1); #endif @@ -354,20 +407,18 @@ u32bit validate_rw_ver(const std::string& algo, if(str.size() != 5) throw std::runtime_error("Invalid input from pk_valid.dat"); - - #if defined(BOTAN_HAS_RW) RW_PublicKey key(to_bigint(str[1]), to_bigint(str[0])); std::string emsa = algo.substr(5, std::string::npos); - std::unique_ptr<PK_Verifier> v(get_pk_verifier(key, emsa)); + PK_Verifier v(key, emsa); SecureVector<byte> msg = decode_hex(str[2]); SecureVector<byte> sig = decode_hex(str[3]); bool passed = true; - passed = v->verify_message(msg, msg.size(), sig, sig.size()); + passed = v.verify_message(msg, msg.size(), sig, sig.size()); return (passed ? 0 : 1); #endif @@ -378,10 +429,9 @@ u32bit validate_rw_sig(const std::string& algo, const std::vector<std::string>& str, RandomNumberGenerator& rng) { - if(str.size() != 6) + if(str.size() != 5) throw std::runtime_error("Invalid input from pk_valid.dat"); - #if defined(BOTAN_HAS_RW) RW_PrivateKey privkey(rng, to_bigint(str[1]), to_bigint(str[2]), to_bigint(str[0])); @@ -389,11 +439,11 @@ u32bit validate_rw_sig(const std::string& algo, std::string emsa = algo.substr(3, std::string::npos); - PK_Verifier* v = get_pk_verifier(pubkey, emsa); - PK_Signer* s = get_pk_signer(privkey, emsa); + PK_Verifier v(pubkey, emsa); + PK_Signer s(privkey, emsa); bool failure = false; - validate_signature(v, s, algo, str[3], str[4], str[5], failure); + validate_signature(v, s, algo, str[3], rng, str[4], failure); return (failure ? 1 : 0); #endif @@ -427,8 +477,8 @@ u32bit validate_dsa_sig(const std::string& algo, std::string emsa = algo.substr(4, std::string::npos); - PK_Verifier* v = get_pk_verifier(*dsapub, emsa); - PK_Signer* s = get_pk_signer(*dsapriv, emsa); + PK_Verifier v(*dsapub, emsa); + PK_Signer s(*dsapriv, emsa); bool failure = false; validate_signature(v, s, algo, str[1], str[2], str[3], failure); @@ -438,6 +488,30 @@ u32bit validate_dsa_sig(const std::string& algo, return 2; } +u32bit validate_ecdsa_sig(const std::string& algo, + const std::vector<std::string>& str) + { + if(str.size() != 5) + throw std::runtime_error("Invalid input from pk_valid.dat"); + +#if defined(BOTAN_HAS_ECDSA) + + EC_Domain_Params group(OIDS::lookup(str[0])); + ECDSA_PrivateKey ecdsa(group, to_bigint(str[1])); + + std::string emsa = algo.substr(6, std::string::npos); + + PK_Verifier v(ecdsa, emsa); + PK_Signer s(ecdsa, emsa); + + bool failure = false; + validate_signature(v, s, algo, str[2], str[3], str[4], failure); + return (failure ? 1 : 0); +#endif + + return 2; + } + u32bit validate_dsa_ver(const std::string& algo, const std::vector<std::string>& str) { @@ -458,13 +532,13 @@ u32bit validate_dsa_ver(const std::string& algo, std::string emsa = algo.substr(7, std::string::npos); - std::unique_ptr<PK_Verifier> v(get_pk_verifier(*dsakey, emsa)); + PK_Verifier v(*dsakey, emsa); SecureVector<byte> msg = decode_hex(str[1]); SecureVector<byte> sig = decode_hex(str[2]); - v->set_input_format(DER_SEQUENCE); - bool passed = v->verify_message(msg, msg.size(), sig, sig.size()); + v.set_input_format(DER_SEQUENCE); + bool passed = v.verify_message(msg, msg.size(), sig, sig.size()); return (passed ? 0 : 1); #endif @@ -487,8 +561,8 @@ u32bit validate_nr_sig(const std::string& algo, std::string emsa = algo.substr(3, std::string::npos); - PK_Verifier* v = get_pk_verifier(pubkey, emsa); - PK_Signer* s = get_pk_signer(privkey, emsa); + PK_Verifier v(pubkey, emsa); + PK_Signer s(privkey, emsa); bool failure = false; validate_signature(v, s, algo, str[5], str[6], str[7], failure); @@ -518,7 +592,7 @@ u32bit validate_dh(const std::string& algo, if(str.size() == 6) keylen = to_u32bit(str[5]); - PK_Key_Agreement* kas = get_pk_kas(mykey, kdf); + PK_Key_Agreement kas(mykey, kdf); bool failure = false; validate_kas(kas, algo, otherkey.public_value(), @@ -552,17 +626,15 @@ u32bit validate_dlies(const std::string& algo, MessageAuthenticationCode* mac = get_mac(options[1]); u32bit mac_key_len = to_u32bit(options[2]); - PK_Decryptor* d = - new DLIES_Decryptor(to, - get_kdf(options[0]), - mac->clone(), mac_key_len); + DLIES_Encryptor e(from, + get_kdf(options[0]), + mac, mac_key_len); - DLIES_Encryptor* e = - new DLIES_Encryptor(from, - get_kdf(options[0]), - mac, mac_key_len); + DLIES_Decryptor d(to, + get_kdf(options[0]), + mac->clone(), mac_key_len); - e->set_other_key(to.public_value()); + e.set_other_key(to.public_value()); std::string empty = ""; bool failure = false; @@ -577,24 +649,19 @@ void do_pk_keygen_tests(RandomNumberGenerator& rng) { std::cout << "Testing PK key generation: " << std::flush; -#define DL_SIG_KEY(TYPE, GROUP) \ - { \ - TYPE key(rng, DL_Group(GROUP)); \ - key.check_key(rng, true); \ - std::cout << '.' << std::flush; \ - } - -#define DL_ENC_KEY(TYPE, GROUP) \ +#define DL_KEY(TYPE, GROUP) \ { \ TYPE key(rng, DL_Group(GROUP)); \ key.check_key(rng, true); \ + validate_save_and_load(&key, rng); \ std::cout << '.' << std::flush; \ } -#define DL_KEY(TYPE, GROUP) \ +#define EC_KEY(TYPE, GROUP) \ { \ - TYPE key(rng, DL_Group(GROUP)); \ + TYPE key(rng, EC_Domain_Params(OIDS::lookup(GROUP))); \ key.check_key(rng, true); \ + validate_save_and_load(&key, rng); \ std::cout << '.' << std::flush; \ } @@ -602,6 +669,7 @@ void do_pk_keygen_tests(RandomNumberGenerator& rng) { RSA_PrivateKey rsa1024(rng, 1024); rsa1024.check_key(rng, true); + validate_save_and_load(&rsa1024, rng); std::cout << '.' << std::flush; } #endif @@ -610,32 +678,64 @@ void do_pk_keygen_tests(RandomNumberGenerator& rng) { RW_PrivateKey rw1024(rng, 1024); rw1024.check_key(rng, true); + validate_save_and_load(&rw1024, rng); std::cout << '.' << std::flush; } #endif #if defined(BOTAN_HAS_DSA) - DL_SIG_KEY(DSA_PrivateKey, "dsa/jce/512"); - DL_SIG_KEY(DSA_PrivateKey, "dsa/jce/768"); - DL_SIG_KEY(DSA_PrivateKey, "dsa/jce/1024"); + DL_KEY(DSA_PrivateKey, "dsa/jce/512"); + DL_KEY(DSA_PrivateKey, "dsa/jce/768"); + DL_KEY(DSA_PrivateKey, "dsa/jce/1024"); + DL_KEY(DSA_PrivateKey, "dsa/botan/2048"); + DL_KEY(DSA_PrivateKey, "dsa/botan/3072"); #endif #if defined(BOTAN_HAS_DIFFIE_HELLMAN) DL_KEY(DH_PrivateKey, "modp/ietf/768"); + DL_KEY(DH_PrivateKey, "modp/ietf/1024"); DL_KEY(DH_PrivateKey, "modp/ietf/2048"); + DL_KEY(DH_PrivateKey, "modp/ietf/4096"); DL_KEY(DH_PrivateKey, "dsa/jce/1024"); #endif #if defined(BOTAN_HAS_NYBERG_RUEPPEL) - DL_SIG_KEY(NR_PrivateKey, "dsa/jce/512"); - DL_SIG_KEY(NR_PrivateKey, "dsa/jce/768"); - DL_SIG_KEY(NR_PrivateKey, "dsa/jce/1024"); + DL_KEY(NR_PrivateKey, "dsa/jce/512"); + DL_KEY(NR_PrivateKey, "dsa/jce/768"); + DL_KEY(NR_PrivateKey, "dsa/jce/1024"); + DL_KEY(NR_PrivateKey, "dsa/botan/2048"); + DL_KEY(NR_PrivateKey, "dsa/botan/3072"); #endif #if defined(BOTAN_HAS_ELGAMAL) - DL_ENC_KEY(ElGamal_PrivateKey, "modp/ietf/768"); - DL_ENC_KEY(ElGamal_PrivateKey, "modp/ietf/1024"); - DL_ENC_KEY(ElGamal_PrivateKey, "dsa/jce/1024"); + DL_KEY(ElGamal_PrivateKey, "modp/ietf/768"); + DL_KEY(ElGamal_PrivateKey, "modp/ietf/1024"); + DL_KEY(ElGamal_PrivateKey, "dsa/jce/1024"); + DL_KEY(ElGamal_PrivateKey, "dsa/botan/2048"); + DL_KEY(ElGamal_PrivateKey, "dsa/botan/3072"); +#endif + +#if defined(BOTAN_HAS_ECDSA) + EC_KEY(ECDSA_PrivateKey, "secp112r1"); + EC_KEY(ECDSA_PrivateKey, "secp128r1"); + EC_KEY(ECDSA_PrivateKey, "secp160r1"); + EC_KEY(ECDSA_PrivateKey, "secp192r1"); + EC_KEY(ECDSA_PrivateKey, "secp224r1"); + EC_KEY(ECDSA_PrivateKey, "secp256r1"); + EC_KEY(ECDSA_PrivateKey, "secp384r1"); + EC_KEY(ECDSA_PrivateKey, "secp521r1"); +#endif + +#if defined(BOTAN_HAS_GOST_34_10_2001) + EC_KEY(GOST_3410_PrivateKey, "gost_256A"); + EC_KEY(GOST_3410_PrivateKey, "secp112r1"); + EC_KEY(GOST_3410_PrivateKey, "secp128r1"); + EC_KEY(GOST_3410_PrivateKey, "secp160r1"); + EC_KEY(GOST_3410_PrivateKey, "secp192r1"); + EC_KEY(GOST_3410_PrivateKey, "secp224r1"); + EC_KEY(GOST_3410_PrivateKey, "secp256r1"); + EC_KEY(GOST_3410_PrivateKey, "secp384r1"); + EC_KEY(GOST_3410_PrivateKey, "secp521r1"); #endif std::cout << std::endl; @@ -703,7 +803,7 @@ u32bit do_pk_validation_tests(const std::string& filename, std::vector<std::string> substr = parse(line); -#if DEBUG +#if 0 std::cout << "Testing: " << print_algorithm << std::endl; #endif @@ -712,33 +812,36 @@ u32bit do_pk_validation_tests(const std::string& filename, try { - if(algorithm.find("DSA/") != std::string::npos) + if(algorithm.find("DSA/") == 0) new_errors = validate_dsa_sig(algorithm, substr, rng); - else if(algorithm.find("DSA_VA/") != std::string::npos) + else if(algorithm.find("DSA_VA/") == 0) new_errors = validate_dsa_ver(algorithm, substr); - else if(algorithm.find("RSAES_PKCS8/") != std::string::npos) + else if(algorithm.find("ECDSA/") == 0) + new_errors = validate_ecdsa_sig(algorithm, substr); + + else if(algorithm.find("RSAES_PKCS8/") == 0) new_errors = validate_rsa_enc_pkcs8(algorithm, substr, rng); - else if(algorithm.find("RSAVA_X509/") != std::string::npos) + else if(algorithm.find("RSAVA_X509/") == 0) new_errors = validate_rsa_ver_x509(algorithm, substr); - else if(algorithm.find("RSAES/") != std::string::npos) + else if(algorithm.find("RSAES/") == 0) new_errors = validate_rsa_enc(algorithm, substr, rng); - else if(algorithm.find("RSASSA/") != std::string::npos) + else if(algorithm.find("RSASSA/") == 0) new_errors = validate_rsa_sig(algorithm, substr, rng); - else if(algorithm.find("RSAVA/") != std::string::npos) + else if(algorithm.find("RSAVA/") == 0) new_errors = validate_rsa_ver(algorithm, substr); - else if(algorithm.find("RWVA/") != std::string::npos) + else if(algorithm.find("RWVA/") == 0) new_errors = validate_rw_ver(algorithm, substr); - else if(algorithm.find("RW/") != std::string::npos) + else if(algorithm.find("RW/") == 0) new_errors = validate_rw_sig(algorithm, substr, rng); - else if(algorithm.find("NR/") != std::string::npos) + else if(algorithm.find("NR/") == 0) new_errors = validate_nr_sig(algorithm, substr, rng); - else if(algorithm.find("ElGamal/") != std::string::npos) + else if(algorithm.find("ElGamal/") == 0) new_errors = validate_elg_enc(algorithm, substr, rng); - else if(algorithm.find("DH/") != std::string::npos) + else if(algorithm.find("DH/") == 0) new_errors = validate_dh(algorithm, substr, rng); - else if(algorithm.find("DLIES/") != std::string::npos) + else if(algorithm.find("DLIES/") == 0) new_errors = validate_dlies(algorithm, substr, rng); else std::cout << "WARNING: Unknown PK algorithm " @@ -771,7 +874,7 @@ u32bit do_pk_validation_tests(const std::string& filename, do_ec_tests(rng); errors += do_ecdsa_tests(rng); - errors += do_eckaeg_tests(rng); + errors += do_ecdh_tests(rng); do_pk_keygen_tests(rng); do_x509_tests(rng); diff --git a/checks/pk_bench.cpp b/checks/pk_bench.cpp index 84eba79e2..a180778a6 100644 --- a/checks/pk_bench.cpp +++ b/checks/pk_bench.cpp @@ -6,7 +6,6 @@ #include <botan/pkcs8.h> #include <botan/mem_ops.h> -#include <botan/look_pk.h> #include <botan/libstate.h> #include <botan/parsing.h> @@ -49,6 +48,10 @@ #include <botan/ecdh.h> #endif +#if defined(BOTAN_HAS_GOST_34_10_2001) + #include <botan/gost_3410.h> +#endif + using namespace Botan; #include "common.h" @@ -211,13 +214,16 @@ void benchmark_rsa(RandomNumberGenerator& rng, while(verify_timer.seconds() < seconds || sig_timer.seconds() < seconds) { - std::unique_ptr<PK_Encryptor> enc(get_pk_encryptor(key, enc_padding)); - std::unique_ptr<PK_Decryptor> dec(get_pk_decryptor(key, enc_padding)); - benchmark_enc_dec(*enc, *dec, enc_timer, dec_timer, rng, 10000, seconds); + PK_Encryptor_EME enc(key, enc_padding); + PK_Decryptor_EME dec(key, enc_padding); + + benchmark_enc_dec(enc, dec, enc_timer, dec_timer, + rng, 10000, seconds); + + PK_Signer sig(key, sig_padding); + PK_Verifier ver(key, sig_padding); - std::unique_ptr<PK_Signer> sig(get_pk_signer(key, sig_padding)); - std::unique_ptr<PK_Verifier> ver(get_pk_verifier(key, sig_padding)); - benchmark_sig_ver(*ver, *sig, verify_timer, + benchmark_sig_ver(ver, sig, verify_timer, sig_timer, rng, 10000, seconds); } @@ -266,10 +272,11 @@ void benchmark_rw(RandomNumberGenerator& rng, RW_PrivateKey key(rng, keylen); keygen_timer.stop(); - std::unique_ptr<PK_Signer> sig(get_pk_signer(key, padding)); - std::unique_ptr<PK_Verifier> ver(get_pk_verifier(key, padding)); + PK_Signer sig(key, padding); + PK_Verifier ver(key, padding); - benchmark_sig_ver(*ver, *sig, verify_timer, sig_timer, rng, 10000, seconds); + benchmark_sig_ver(ver, sig, verify_timer, sig_timer, + rng, 10000, seconds); } const std::string nm = "RW-" + std::to_string(keylen); @@ -321,10 +328,10 @@ void benchmark_ecdsa(RandomNumberGenerator& rng, ECDSA_PrivateKey key(rng, params); keygen_timer.stop(); - std::unique_ptr<PK_Signer> sig(get_pk_signer(key, padding)); - std::unique_ptr<PK_Verifier> ver(get_pk_verifier(key, padding)); + PK_Signer sig(key, padding); + PK_Verifier ver(key, padding); - benchmark_sig_ver(*ver, *sig, verify_timer, + benchmark_sig_ver(ver, sig, verify_timer, sig_timer, rng, 1000, seconds); } @@ -338,11 +345,70 @@ void benchmark_ecdsa(RandomNumberGenerator& rng, #endif +#if defined(BOTAN_HAS_GOST_34_10_2001) + +void benchmark_gost_3410(RandomNumberGenerator& rng, + double seconds, + Benchmark_Report& report) + { + const char* domains[] = { "1.3.132.0.6", // secp112r1 + "1.3.132.0.28", // secp128r1 + "1.3.132.0.30", // secp160r2 + "1.3.132.0.33", // secp224r1 + "1.2.643.2.2.35.1", // gost 256p + "1.3.132.0.34", // secp384r1 + "1.3.132.0.35", // secp512r1 + NULL }; + + for(size_t j = 0; domains[j]; j++) + { + OID oid(domains[j]); + EC_Domain_Params params(oid); + + u32bit pbits = params.get_curve().get_p().bits(); + + u32bit hashbits = pbits; + + if(hashbits < 160) + hashbits = 160; + if(hashbits == 521) + hashbits = 512; + + const std::string padding = "EMSA1(SHA-" + to_string(hashbits) + ")"; + + Timer keygen_timer("keygen"); + Timer verify_timer(padding + " verify"); + Timer sig_timer(padding + " signature"); + + while(verify_timer.seconds() < seconds || + sig_timer.seconds() < seconds) + { + keygen_timer.start(); + GOST_3410_PrivateKey key(rng, params); + keygen_timer.stop(); + + PK_Signer sig(key, padding); + PK_Verifier ver(key, padding); + + benchmark_sig_ver(ver, sig, verify_timer, + sig_timer, rng, 1000, seconds); + } + + const std::string nm = "GOST-34.10-" + to_string(pbits); + + report.report(nm, keygen_timer); + report.report(nm, verify_timer); + report.report(nm, sig_timer); + } + } + +#endif + #if defined(BOTAN_HAS_ECDH) -void benchmark_eckaeg(RandomNumberGenerator& rng, - double seconds, - Benchmark_Report& report) +void benchmark_ecdh(RandomNumberGenerator& rng, + double seconds, + Benchmark_Report& report) { const char* domains[] = { "1.3.132.0.6", // secp112r1 "1.3.132.0.28", // secp128r1 @@ -365,17 +431,17 @@ void benchmark_eckaeg(RandomNumberGenerator& rng, while(kex_timer.seconds() < seconds) { keygen_timer.start(); - ECDH_PrivateKey eckaeg1(rng, params); + ECDH_PrivateKey ecdh1(rng, params); keygen_timer.stop(); keygen_timer.start(); - ECDH_PrivateKey eckaeg2(rng, params); + ECDH_PrivateKey ecdh2(rng, params); keygen_timer.stop(); - ECDH_PublicKey pub1(eckaeg1); - ECDH_PublicKey pub2(eckaeg2); + PK_Key_Agreement ka1(ecdh1, "KDF2(SHA-1)"); + PK_Key_Agreement ka2(ecdh2, "KDF2(SHA-1)"); - SecureVector<byte> secret1, secret2; + SymmetricKey secret1, secret2; for(u32bit i = 0; i != 1000; ++i) { @@ -383,15 +449,15 @@ void benchmark_eckaeg(RandomNumberGenerator& rng, break; kex_timer.start(); - secret1 = eckaeg1.derive_key(pub2); + secret1 = ka1.derive_key(32, ecdh2.public_value()); kex_timer.stop(); kex_timer.start(); - secret2 = eckaeg2.derive_key(pub1); + secret2 = ka2.derive_key(32, ecdh1.public_value()); kex_timer.stop(); if(secret1 != secret2) - std::cerr << "ECDH secrets did not match, bug in the library!?!\n"; + std::cerr << "ECDH secrets did not match\n"; } } @@ -416,7 +482,7 @@ void benchmark_dsa_nr(RandomNumberGenerator& rng, "dsa/botan/3072", NULL }; - const std::string algo_name = PRIV_KEY_TYPE().algo_name(); + std::string algo_name; for(size_t j = 0; domains[j]; j++) { @@ -436,12 +502,13 @@ void benchmark_dsa_nr(RandomNumberGenerator& rng, keygen_timer.start(); PRIV_KEY_TYPE key(rng, group); + algo_name = key.algo_name(); keygen_timer.stop(); - std::unique_ptr<PK_Signer> sig(get_pk_signer(key, padding)); - std::unique_ptr<PK_Verifier> ver(get_pk_verifier(key, padding)); + PK_Signer sig(key, padding); + PK_Verifier ver(key, padding); - benchmark_sig_ver(*ver, *sig, verify_timer, + benchmark_sig_ver(ver, sig, verify_timer, sig_timer, rng, 1000, seconds); } @@ -484,10 +551,10 @@ void benchmark_dh(RandomNumberGenerator& rng, DH_PrivateKey dh2(rng, group); keygen_timer.stop(); - DH_PublicKey pub1(dh1); - DH_PublicKey pub2(dh2); + PK_Key_Agreement ka1(dh1, "KDF2(SHA-1)"); + PK_Key_Agreement ka2(dh2, "KDF2(SHA-1)"); - SecureVector<byte> secret1, secret2; + SymmetricKey secret1, secret2; for(u32bit i = 0; i != 1000; ++i) { @@ -495,15 +562,15 @@ void benchmark_dh(RandomNumberGenerator& rng, break; kex_timer.start(); - secret1 = dh1.derive_key(pub2); + secret1 = ka1.derive_key(32, dh2.public_value()); kex_timer.stop(); kex_timer.start(); - secret2 = dh2.derive_key(pub1); + secret2 = ka2.derive_key(32, dh1.public_value()); kex_timer.stop(); if(secret1 != secret2) - std::cerr << "DH secrets did not match, bug in the library!?!\n"; + std::cerr << "DH secrets did not match\n"; } } @@ -608,10 +675,11 @@ void benchmark_elg(RandomNumberGenerator& rng, ElGamal_PrivateKey key(rng, group); keygen_timer.stop(); - std::unique_ptr<PK_Decryptor> dec(get_pk_decryptor(key, padding)); - std::unique_ptr<PK_Encryptor> enc(get_pk_encryptor(key, padding)); + PK_Decryptor_EME dec(key, padding); + PK_Encryptor_EME enc(key, padding); - benchmark_enc_dec(*enc, *dec, enc_timer, dec_timer, rng, 1000, seconds); + benchmark_enc_dec(enc, dec, enc_timer, dec_timer, + rng, 1000, seconds); } const std::string nm = algo_name + "-" + std::to_string(pbits); @@ -674,7 +742,12 @@ void bench_pk(RandomNumberGenerator& rng, #if defined(BOTAN_HAS_ECDH) if(algo == "All" || algo == "ECDH") - benchmark_eckaeg(rng, seconds, report); + benchmark_ecdh(rng, seconds, report); +#endif + +#if defined(BOTAN_HAS_GOST_34_10_2001) + if(algo == "All" || algo == "GOST-34.10") + benchmark_gost_3410(rng, seconds, report); #endif #if defined(BOTAN_HAS_DIFFIE_HELLMAN) diff --git a/checks/pk_valid.dat b/checks/pk_valid.dat index 1e2a84c19..40bd830c2 100644 --- a/checks/pk_valid.dat +++ b/checks/pk_valid.dat @@ -3642,12 +3642,12 @@ D2F20D5BB1E28D6A0D3D722B2F044670B20530FD1F7983513D7F3527A662571A3AE98E1DAFF9403\ 5EFFC02FD41C583E1CBDA53C1821BB79FB392D68A4524B0F65EBB64FF6656C52BF54D5774DF2D91\ 6C9B793E206E0D5351D7B4D18DE3CA4CCFA8F7A3ABFB36048C9297F7512B3FDA70F7 -# RW Format: exponent:p:q:message:nonce:output +# RW Format: exponent:p:q:message:output [RW/EMSA2(SHA-1)] 2:\ F21624A28732743BBE9B1A2B320CA31EF4A127456547ACDF5C523995E25A990B:\ BC6EDE730E7CEC8993A6E6296EA8DFBBC7D46615122F23F635FF988E284E31CF:\ -5075752E::\ +5075752E:\ 44CB3C6CD992A656AC2D8C92E044FCCC60FAA1B47FE153E7BA4B647136DA4A42\ 88BD50FB0935E3B9180AF477F8B88E1EA1106569CCAB8D354E0A7E3AC92D70B3 @@ -3655,7 +3655,7 @@ BC6EDE730E7CEC8993A6E6296EA8DFBBC7D46615122F23F635FF988E284E31CF:\ F2E5CDF6CA7387C132242CE031CEC8FE2CEAFA8530EC9795F16605B1CBD97BCB:\ DA330E4440FE5CD00A37A738DDFBDD5623A31FAE273AD98E41DA0D3DB937CEBF:\ 4C6F7665207375636B732E20556E7265717569746564206C6F7665207375636B\ -73206D6F72652E::\ +73206D6F72652E:\ 5AB035B8E6415D691951DBCEACC6A61987599000A590A414363BF52FB95C5BAB\ C12812152C5BCBC6A443C68B971EE0AA5E864C9FF9ABE0A85BB86FA544239958 @@ -3663,21 +3663,21 @@ C12812152C5BCBC6A443C68B971EE0AA5E864C9FF9ABE0A85BB86FA544239958 13CE5CDF6CA7387C132242CE031CEC8FE2CEAFA8530EC9795F16605B1CBD978A3:\ 14FE360AA550965F93CE76E4B01F55FBFDD7A049B2761817505CB6959A73A4C07:\ 4C6F7665207375636B732E20556E7265717569746564206C6F7665207375636B7\ -3206D6F72652E::\ +3206D6F72652E:\ 0085AC363AEA57F36E348936599A77167BAF17194D250787F347C710019558A9F\ 773DDC25A2216DA694D38E03CAA4F7423BDF03DB0E75161221906222FC9E0F23D 2:\ 1947A060ECFEFA3F8DDED8AE580D45B02D82DE108496AFC322FFD14EA02B7BFE3:\ 1E1384A66A21500DEE4DC2B36F43EF398B1C50BDEE7600CD4340B663471F0F16F:\ -4A65737369652048616E68616D20697320612064616D6E2063757465206769726C::\ +4A65737369652048616E68616D20697320612064616D6E2063757465206769726C:\ 00BE5B2A5EE3CB613ABE4548C856F6C8F8B4B9EAD3795675E59E4DDC4A015D019\ 2F29B6352CDD913C289961BE57F84005F0BBD3AE7E2BBE73DABC50B2201923CC0 2:\ 1AA83F51426F2BDA398221C48E8D322EF66D59098D0418E0C2B06DE6EA2F97D33:\ 1E4C7924C9E6D7ABDB372B112601D4C091FAE6C8FEB518595DF436FE9B354E26F:\ -492077616E742061206472696E6B2E204E6F772E::\ +492077616E742061206472696E6B2E204E6F772E:\ 010E8838216B05B4C2739B65AB2A7ABC114A046E3CD37CF1E97815ECA53750B1B\ F486A9BA684B9FE2D983BBA5F9D97565F0DCF6A5176C169EC67B6BB6C9616CEA6 @@ -3685,7 +3685,7 @@ F486A9BA684B9FE2D983BBA5F9D97565F0DCF6A5176C169EC67B6BB6C9616CEA6 22C9D42C6803B9AC87F641E9465D300DE8898694427D138761C4A5B121B0632DB:\ 25DA5C05701C99EDDF0FBAA61DCDBA404C05D860DD539E06B0AECA7E56354DEA7:\ 54657374696E6720766172696F7573206B657973697A657320666F72205257207\ -369676E6174757265733A2035313220746F203531392C20616E642031303234::\ +369676E6174757265733A2035313220746F203531392C20616E642031303234:\ 0191F1BA45BC571445612D8C1A7818B52DFF78566E6CCFF7AB55B2F35FA21210C\ 951F171E27A2921032718AE01BB4F209164BA0B21A5842D1925B35D09C7538050 @@ -3693,7 +3693,7 @@ F486A9BA684B9FE2D983BBA5F9D97565F0DCF6A5176C169EC67B6BB6C9616CEA6 388F732F05B06F5BA10816242E8F75A000E235C97174F57931E8D845442147F8B:\ 2F3758EBE44182841FB1743D3BA6AEEC0AEC5758660E1DB37C818199B90A1A307:\ 54657374696E6720766172696F7573206B657973697A657320666F72205257207\ -369676E6174757265733A2035313220746F203531392C20616E642031303234::\ +369676E6174757265733A2035313220746F203531392C20616E642031303234:\ 046C31E4EA320DF130FE1F361184DDC03713BBAC169E08266B91655B42A01F39E\ 1E3FF781B04B2F44B2504F37ACC9688C1ADD7EB94A998779EFCDFBEB9FAFFC82D @@ -3701,14 +3701,14 @@ F486A9BA684B9FE2D983BBA5F9D97565F0DCF6A5176C169EC67B6BB6C9616CEA6 4AE4F716610D77E35A6FA2FEAAAC3E92706B996414C012EF72BCBE86E3F1A97BB:\ 5145D9E08DA9021E87080C437BE1835B06E5C9ECCDA8E7CF7E30F682D0CB1A9F7:\ 54657374696E6720766172696F7573206B657973697A657320666F72205257207\ -369676E6174757265733A2035313220746F203531392C20616E642031303234::\ +369676E6174757265733A2035313220746F203531392C20616E642031303234:\ 01BF0E20BF646E5E427B8D28CBAF696D7AA6B6DE878BB91C295D5559B1FA9A94F\ 114FF61C11C0BC97066C2FC919815B0FD150CE70F63D696CEA4D5D1D7BDEDC035 2:\ 6AA3DB8710567A30D7E9E61956962D4E4D50BC0510C2238D9136A93CC5DC3A73B:\ 6CAC9FF49F1035D179668B399927A610608788A8C884B76A94A6DDBCA94A52327:\ -57414E5445443A2043757465204A6170616E657365206769726C667269656E64::\ +57414E5445443A2043757465204A6170616E657365206769726C667269656E64:\ 1695A91578EBC67ED86C20EC4886B2E3895E11A7647D22FFB41091E1C7A3CA0DC\ E091A1FCBACB859C4A5C8B3B841C0F0F7039BEFEA790A423114F35F9D809DBCD2 @@ -3716,7 +3716,7 @@ E091A1FCBACB859C4A5C8B3B841C0F0F7039BEFEA790A423114F35F9D809DBCD2 9EADA4F7D1BEC405BC2BFB4F836E19A488E079030F8C09DE76810B9E63FB41873:\ AD5DEBCF83372200B106812A6A7CF3A702C35BAF4FC095617794314EBCAC4DE47:\ 476F6C642073747564733F213F204576656E20746865204D544120756E6465727\ -374616E647320746865206E65656420666F722074686520424C494E472D424C494E4721::\ +374616E647320746865206E65656420666F722074686520424C494E472D424C494E4721:\ 203FCE80570CA0DA3C2D50634A33BAACEA6D397618F36620EE10DE4E6A51018C0\ BADE98DF220E47DBA140AEAE910A28F3177D4349740EC05A5EB7BA280D7BF8F34 @@ -3727,7 +3727,7 @@ CDC7D5FE3805572EA3FF554C086C7DD4020A3CE48DF5A09A5CEB75E6AABCD338\ F800F362448E87CE7E1A55331ADF2BBF3A22B3E6134035FDA52D9578FD3F72F7:\ 57687920696E20746865206E616D65206F6620616C6C20746861742069732067\ 6F6F6420616E6420686F6C792061726520796F752072656164696E6720746869\ -733F213F21::\ +733F213F21:\ 05BDC911B3F19F2201EDF6CCC792A68BCEC40506F00112A6DCAEEAA2D7A62192\ 931D8968F7312EBFE7F7646CED6A8948E58327862527EFD960F15CD8EC74D1DF\ 1FDC37F369A4A844D15DB7ACC6DB5ADA884B119148929439D5305B6916D0A081\ @@ -3738,7 +3738,7 @@ EF86DD7AF3F32CDE8A9F6564E43A559A0C9F8BAD36CC25330548B347AC158A34\ 5631FA90F7B873C36EFFAE2F7823227A3F580B5DD18304D5932751E743E9281B:\ F5BB4289C389D9019C36F96C6B81FFFBF20BE0620C6343E2B800AEFB1B55A330\ 8CC1402DA7A2A558579A2A5146B30CB08E3F20B501081248F2F1DE36CDFCE9DF:\ -2CA039854B55688740E3::\ +2CA039854B55688740E3:\ 1AF029CBEC9C692CE5096E73E4E9A52EC9A28D207A5511CCEC7681E5E3D867A4\ AE2E22DE4909D89196A272F1B50DE6FA3248BCA334D46E0D57171A790B6F4697\ E7BA7047DB79DECD47BD21995243DEBBF25915DDBC93C45875C14DE953792257\ @@ -3749,7 +3749,7 @@ EF86DD7AF3F32CDE8A9F6564E43A559A0C9F8BAD36CC25330548B347AC158A34\ 5631FA90F7B873C36EFFAE2F7823227A3F580B5DD18304D5932751E743E9281B:\ F5BB4289C389D9019C36F96C6B81FFFBF20BE0620C6343E2B800AEFB1B55A330\ 8CC1402DA7A2A558579A2A5146B30CB08E3F20B501081248F2F1DE36CDFCE9DF:\ -2119A954F1AC0F3DCDB2::\ +2119A954F1AC0F3DCDB2:\ 60C3CCF4F086B15B7F850B445F384333F7AE5A4B5EDE2820C7233239E1B86D6E\ 4B4FCA4F50B087CE1DF17DA5D62672A17F2CF87A2875BBD9B138CAF6863821D6\ A4D553E9EB64C9254A8F9A6B960E57E39069D65E3F561AA1FA91643D42FEEFB9\ @@ -3760,7 +3760,7 @@ EF86DD7AF3F32CDE8A9F6564E43A559A0C9F8BAD36CC25330548B347AC158A34\ 5631FA90F7B873C36EFFAE2F7823227A3F580B5DD18304D5932751E743E9281B:\ F5BB4289C389D9019C36F96C6B81FFFBF20BE0620C6343E2B800AEFB1B55A330\ 8CC1402DA7A2A558579A2A5146B30CB08E3F20B501081248F2F1DE36CDFCE9DF:\ -7A4C634DE6F16315BD5F::\ +7A4C634DE6F16315BD5F:\ 308A5D65224201BED626CC83FB901EC84874EE03B2E7AB4E752EDBDE024C754E\ 3CC9841CA062100A8843DE9183354B4E0596E8C68F1605828287884F0F9BA696\ 8FC7A9F0CA09418A8485B90465E5D3F96CE4995A5FC7A6E5ABD9CC06BB8A2C3C\ @@ -3771,7 +3771,7 @@ F5BB4289C389D9019C36F96C6B81FFFBF20BE0620C6343E2B800AEFB1B55A330\ 976C3B14FBD253F0F988C354725289F2897D7FB62C5C74AF7D597A1E22AAFBA1D3:\ 0F816BF0ADD559AFDA38B008E4087F6A38B575C56FFF453056EAAAB3381C9552\ 0969546F954D458D48E44850938B1DB471CF4B40AFC47E067FB5BCE67BA98BE8D7:\ -EF0F1D56F4E5D587C212::\ +EF0F1D56F4E5D587C212:\ 3E544FEBB6623F5D392003B729FE2BFC20E2CB3ECAC22734DFCA55150254E616\ A41C5E54CE3B50FBC2FE2363EE9AF9B15C70615497B0A458F8AB6D850992EEEB\ 56D65F87EA1BD6E2B4B7E40A0F5E1635C7DDB17110C61039CF712D3524C9C2C1\ @@ -3782,7 +3782,7 @@ F35D9163BE5C70276F46634514BE16EC09602782E88FE74EAEB2F50CBB0E3B5C4A 976C3B14FBD253F0F988C354725289F2897D7FB62C5C74AF7D597A1E22AAFBA1D3:\ 0F816BF0ADD559AFDA38B008E4087F6A38B575C56FFF453056EAAAB3381C9552\ 0969546F954D458D48E44850938B1DB471CF4B40AFC47E067FB5BCE67BA98BE8D7:\ -EC5CC4228C3C70EE8F35::\ +EC5CC4228C3C70EE8F35:\ 228BAA85062F10DCC9D99A23D340BC4B9E463D8AB86A6781A6D2143564303E2D\ C78772BF68449BE1E2711A68D5A15CF04A23573FB3870454308F583BBB5F2467\ 069EF1395431E70F91BD56D846DC8DB2E88AB3D26A9770660B87A76D6C3575DE\ @@ -3793,7 +3793,7 @@ C78772BF68449BE1E2711A68D5A15CF04A23573FB3870454308F583BBB5F2467\ 976C3B14FBD253F0F988C354725289F2897D7FB62C5C74AF7D597A1E22AAFBA1D3:\ 0F816BF0ADD559AFDA38B008E4087F6A38B575C56FFF453056EAAAB3381C9552\ 0969546F954D458D48E44850938B1DB471CF4B40AFC47E067FB5BCE67BA98BE8D7:\ -FEF5EE07C74118DA30B9::\ +FEF5EE07C74118DA30B9:\ 2637E16E2599B6EC2F4728C73D3B29F483C2B881F1E1969C426027605EF080E9\ B17D258D5E1EBC6472A2501E04CF19C144537FCB38A1DA00D948EBD39FA11322\ D9230B62E2C12AEDB366BD85A2089588A8D52E941FD986D89828A342B83438A9\ @@ -3808,7 +3808,7 @@ BADCC718DD2D761C4893C4831D56ADA30FC5C7C148D473BEDF7615B7E821B92F\ 319676CE278349F1309FB3D264C1A22BDE71B221354C7A4D31117B3EC3C9D480\ 2E0A26BD8EC05D28B6502C65F35C687AF7F8396B963ED029A2C5AE38DD7C5C96\ 2A953C113C0F590957AB19A6E2AFDA6DB84F22C0C31AE243DEBD2920FBE9FBDF:\ -15E7B7B7ED0F176B6799::\ +15E7B7B7ED0F176B6799:\ 39FF4B5FA50AE498F3C91A655E6865840D1FC401EE02DBC8460A59DEB8816E66\ 80F712B7BAF8D4DC11A3B54BF906BE698306F0449BB43F3F223B944D930A1A3C\ 718E8A9E2EEDEC5A07AB817C26A80CC2A2EE2846A597EAB8A999D38DB9849016\ @@ -3827,7 +3827,7 @@ BADCC718DD2D761C4893C4831D56ADA30FC5C7C148D473BEDF7615B7E821B92F\ 319676CE278349F1309FB3D264C1A22BDE71B221354C7A4D31117B3EC3C9D480\ 2E0A26BD8EC05D28B6502C65F35C687AF7F8396B963ED029A2C5AE38DD7C5C96\ 2A953C113C0F590957AB19A6E2AFDA6DB84F22C0C31AE243DEBD2920FBE9FBDF:\ -B36724C92954C38D0288::\ +B36724C92954C38D0288:\ 3C8CD3614555568BBECA99174B7B203D0BC6FABE9E6FFE0C41EB4D9A2C601D23\ 93CA1E01B7D7E99337758AC914C9F151311E5AE6708DAF1D8C825DA471652C6E\ 13A8FE5802D7AE097BFC899A4EC8CA235B5982B9058C53AAD52823ACF692290E\ @@ -4182,6 +4182,24 @@ MIG6AgEAMIGhBgcqhkjOOAQBMIGVAkAA8HR2W1fHj8t8G9/BzpO5z1Ea5YnMTwMS\ 25ECC0ED4CE7118A72D133704D002A:\ 14593FBF63EAC64976987524044D8B11AB9A95B4B75A760FE22C45A3EFD6: +# ECDSA format is group name:private key:message:nonce:signature +[ECDSA/EMSA1(SHA-1)] + +# From ANSI X9.62 +secp192r1:\ +1A8D598FC15BF0FD89030B5CB1111AEB92AE8BAF5EA475FB:\ +616263:\ +FA6DE29746BBEB7F8BB1E761F85F7DFB2983169D82FA2F4E:\ +885052380FF147B734C330C43D39B2C4A89F29B0F749FEAD\ +E9ECC78106DEF82BF1070CF1D4D804C3CB390046951DF686 + +x962_p239v1:\ +7EF7C6FABEFFFDEA864206E80B0B08A9331ED93E698561B64CA0F7777F3D:\ +616263:\ +656C7196BF87DCC5D1F1020906DF2782360D36B2DE7A17ECE37D503784AF:\ +2CB7F36803EBB9C427C58D8265F11FC5084747133078FC279DE874FBECB0\ +2EEAE988104E9C2234A3C2BEB1F53BFA5DC11FF36A875D1E3CCB1F7E45CF + # NR Format: p:q:g:y:x:message:k:output [NR/EMSA1(SHA-1)] # Trickiness: in some of these, we put a leading 0 digit on the nonce (k). This diff --git a/checks/validate.cpp b/checks/validate.cpp index 093d5e3b7..68035f293 100644 --- a/checks/validate.cpp +++ b/checks/validate.cpp @@ -54,18 +54,6 @@ u32bit random_word(Botan::RandomNumberGenerator& rng, #endif } -} - -Botan::Filter* lookup(const std::string&, const std::vector<std::string>&); - -bool failed_test(const std::string&, std::vector<std::string>, bool, bool, - std::string&, - Botan::RandomNumberGenerator& rng); - -std::vector<std::string> parse(const std::string&); -void strip(std::string&); -Botan::SecureVector<byte> decode_hex(const std::string&); - bool test_passhash(RandomNumberGenerator& rng) { #if defined(BOTAN_HAS_PASSHASH9) @@ -95,6 +83,16 @@ bool test_passhash(RandomNumberGenerator& rng) return true; } +} + +bool failed_test(const std::string&, std::vector<std::string>, bool, bool, + std::string&, + Botan::RandomNumberGenerator& rng); + +std::vector<std::string> parse(const std::string&); +void strip(std::string&); +Botan::SecureVector<byte> decode_hex(const std::string&); + u32bit do_validation_tests(const std::string& filename, RandomNumberGenerator& rng, bool should_pass) diff --git a/checks/validate.dat b/checks/validate.dat index 0998348ec..bdadad40e 100644 --- a/checks/validate.dat +++ b/checks/validate.dat @@ -42920,6 +42920,88 @@ AFDF1195:\ 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F:\ 0000000000000000 +# XSalsa20, from NaCl via Crypto++ +0000000000000000000000000000000000000000000000000000000000000000\ +0000000000000000000000000000000000000000000000000000000000000000\ +0000000000000000000000000000000000000000000000000000000000000000\ +0000000000000000000000000000000000000000000000000000000000000000\ +0000000000000000000000:\ +EEA6A7251C1E72916D11C2CB214D3C252539121D8E234E652D651FA4C8CFF880\ +309E645A74E9E0A60D8243ACD9177AB51A1BEB8D5A2F5D700C093C5E55855796\ +25337BD3AB619D615760D8C5B224A85B1D0EFE0EB8A7EE163ABB0376529FCC09\ +BAB506C618E13CE777D82C3AE9D1A6F972D4160287CBFE60BF2130FC0A6FF604\ +9D0A5C8A82F429231F0080:\ +1B27556473E985D462CD51197A9A46C76009549EAC6474F206C4EE0844F68389:\ +69696EE955B62B73CD62BDA875FC73D68219E0036B7A0B37 + +093C5E5585579625337BD3AB619D615760D8C5B224A85B1D0EFE0EB8A7EE163A\ +BB0376529FCC09BAB506C618E13CE777D82C3AE9D1A6F972D4160287CBFE60BF\ +2130FC0A6FF6049D0A5C8A82F429231F008082E845D7E189D37F9ED2B464E6B9\ +19E6523A8C1210BD52A02A4C3FE406D3085F5068D1909EEECA6369ABC981A42E\ +87FE665583F0AB85AE71F6F84F528E6B397AF86F6917D9754B7320DBDC2FEA81\ +496F2732F532AC78C4E9C6CFB18F8E9BDF74622EB126141416776971A84F94D1\ +56BEAF67AECBF2AD412E76E66E8FAD7633F5B6D7F3D64B5C6C69CE29003C6024\ +465AE3B89BE78E915D88B4B5621D:\ +B2AF688E7D8FC4B508C05CC39DD583D6714322C64D7F3E63147AEDE2D9534934\ +B04FF6F337B031815CD094BDBC6D7A92077DCE709412286822EF0737EE47F6B7\ +FFA22F9D53F11DD2B0A3BB9FC01D9A88F9D53C26E9365C2C3C063BC4840BFC81\ +2E4B80463E69D179530B25C158F543191CFF993106511AA036043BBC75866AB7\ +E34AFC57E2CCE4934A5FAAE6EABE4F221770183DD060467827C27A354159A081\ +275A291F69D946D6FE28ED0B9CE08206CF484925A51B9498DBDE178DDD3AE91A\ +8581B91682D860F840782F6EEA49DBB9BD721501D2C67122DEA3B7283848C5F1\ +3E0C0DE876BD227A856E4DE593A3:\ +A6A7251C1E72916D11C2CB214D3C252539121D8E234E652D651FA4C8CFF88030:\ +9E645A74E9E0A60D8243ACD9177AB51A1BEB8D5A2F5D700C + +093C5E5585579625337BD3AB619D615760D8C5B224A85B1D0EFE0EB8A7EE163A\ +BB0376529FCC09BAB506C618E13CE777D82C3AE9D1A6F972D4160287CBFE60BF\ +2130FC0A6FF6049D0A5C8A82F429231F008082E845D7E189D37F9ED2B464E6B9\ +19E6523A8C1210BD52A02A4C3FE406D3085F5068D1909EEECA6369ABC981A42E\ +87FE665583F0AB85AE71F6F84F528E6B397AF86F6917D9754B7320DBDC2FEA81\ +496F2732F532AC78C4E9C6CFB18F8E9BDF74622EB126141416776971A84F94D1\ +56BEAF67AECBF2AD412E76E66E8FAD7633F5B6D7F3D64B5C6C69CE29003C6024\ +465AE3B89BE78E915D88B4B5621D:\ +418078FE843F5984DD3C7975D1FF51AF4DCEDA640999AAA3C28618AE286CA150\ +51CB4D55F9DA22A213EF14A2B905B52C99A557854C7F2A6D6ED6F69C1C6649F3\ +FB67B8628468029B3367920C2E1148AA1F3B9C695CB1426F09CE84045842946E\ +0454E41AB1EDB32CAE4B95669DE4E2CCAF00BA86FFEAE6A9C5FCE4153BADDB0D\ +8998A600537A9649939CB7D7A9C4E8CBCA0FAB77963ABD516699879DE0B1971D\ +C7328668111FF5B77C253B9E6346D1A2CE6E390CD736156AD7F44B339CFB141F\ +00E7A766C06E130B0C31D88980D2AD8814A2D641599162AB8AF25D93067F06A4\ +9637EAF6523806B8FA07D56628BB:\ +A6A7251C1E72916D11C2CB214D3C252539121D8E234E652D651FA4C8CFF88030:\ +B2AF688E7D8FC4B508C05CC39DD583D6714322C64D7F3E63 + +FEAC9D54FC8C115AE247D9A7E919DD76CFCBC72D32CAE4944860817CBDFB8C04\ +E6B1DF76A16517CD33CCF1ACDA9206389E9E318F5966C093CFB3EC2D9EE2DE85\ +6437ED581F552F26AC2907609DF8C613B9E33D44BFC21FF79153E9EF81A9D66C\ +C317857F752CC175FD8891FEFEBB7D041E6517C3162D197E2112837D3BC41043\ +12AD35B75EA686E7C70D4EC04746B52FF09C421451459FB59F:\ +2C261A2F4E61A62E1B27689916BF03453FCBC97BB2AF6F329391EF063B5A219B\ +F984D07D70F602D85F6DB61474E9D9F5A2DEECB4FCD90184D16F3B5B5E168EE0\ +3EA8C93F3933A22BC3D1A5AE8C2D8B02757C87C073409052A2A8A41E7F487E04\ +1F9A49A0997B540E18621CAD3A24F0A56D9B19227929057AB3BA950F6274B121\ +F193E32E06E5388781A1CB57317C0BA6305E910961D01002F0:\ +9E1DA239D155F52AD37F75C7368A536668B051952923AD44F57E75AB588E475A:\ +AF06F17859DFFA799891C4288F6635B5C5A45EEE9017FD72 + +F4EA120B47D15466ADE07DF0F2FF508759D9CB1035CEEAB43920E9094FA50B86\ +8673B07173557D4B994B1E9D35078C1C7369DF6B6ADB2EC0E6BFD280FEA8AC31\ +DB44BEB0C2A4DDC6198957BD0592E3E587D304863B893FF8EEE0EFC70CED5D71\ +2651C3E9DD1A0DE0480FD8CCCBAE4C50DCCBACB83DCDC3E2CEF7DBC645F0AF46\ +8163FB0E015EF48AD74694DFBCE2DB8430A6E91645FD16ADBB72E21A0FBAEDF5\ +ECFF829CEA9CBC22F82902748AA52DA5CE903D9F2BDE77EFEF5FA3970C720E89\ +F25DD05157247BF0DE2D2129C3F856238D4FAD:\ +46F396F0D2D54189968BF56B5B2F35588C3AD851E00FAC6507598F3EA0193A58\ +6C00B18677811CC305B0261D9AEBBB9C0485A5800C940AA4F09C4FBDEDE12553\ +824C429C7954E0B8DAD889203D292517B98A64E8D7A37C1364EB0934751323D9\ +B9F8498F50D729E977FB742880222F22AC5D7BFEBE6905A4C344D82027398A70\ +C334635792DEB0F20B83861B05E731F5627AEE17DF20413C79957556E66A9700\ +85E9AD40A73D9A964381584976C6F111619A916FBB5F5D305DF862D5A56BAC9F\ +F9B436F31C85F34FF890B5AD3299EDA2B8642D:\ +3070F0DB09C523507D36404DAC79038A393E9F0E3CF5F870B16D2A06DA68DCD3:\ +4AFE87BF79EB938D786BA54C26FD6D7E62261EEAE8B62202 + [Turing] 0000000000000000000000000000000000000000:\ 696626BBDC6E09F6DA9ABAB5B56C14878246DF18:\ diff --git a/checks/validate.h b/checks/validate.h index b0e3565f8..9e34d64fb 100644 --- a/checks/validate.h +++ b/checks/validate.h @@ -23,7 +23,7 @@ u32bit do_pk_validation_tests(const std::string&, void do_ec_tests(RandomNumberGenerator& rng); u32bit do_ecdsa_tests(RandomNumberGenerator& rng); -u32bit do_eckaeg_tests(RandomNumberGenerator& rng); +u32bit do_ecdh_tests(RandomNumberGenerator& rng); u32bit do_cvc_tests(RandomNumberGenerator& rng); void do_x509_tests(RandomNumberGenerator&); diff --git a/checks/x509.cpp b/checks/x509.cpp index a86df7691..96d99eee2 100644 --- a/checks/x509.cpp +++ b/checks/x509.cpp @@ -40,15 +40,11 @@ namespace { u64bit key_id(const Public_Key* key) { - std::unique_ptr<X509_Encoder> encoder(key->x509_encoder()); - if(!encoder.get()) - throw Internal_Error("Public_Key:key_id: No encoder found"); - Pipe pipe(new Hash_Filter("SHA-1", 8)); pipe.start_msg(); pipe.write(key->algo_name()); - pipe.write(encoder->alg_id().parameters); - pipe.write(encoder->key_bits()); + pipe.write(key->algorithm_identifier().parameters); + pipe.write(key->x509_subject_public_key()); pipe.end_msg(); SecureVector<byte> output = pipe.read_all(); diff --git a/configure.py b/configure.py index 4388cb0a0..ed4c94e2f 100755 --- a/configure.py +++ b/configure.py @@ -961,6 +961,8 @@ def create_template_vars(build_config, options, modules, cc, arch, osinfo): build_commands(build_config.check_sources, build_config.checkobj_dir, 'CHECK')), + 'python_obj_dir': build_config.pyobject_dir, + 'python_objs': makefile_list( objectfile_list(build_config.python_sources, build_config.pyobject_dir)), diff --git a/doc/examples/bench.cpp b/doc/examples/bench.cpp index 724c258e4..7054d8563 100644 --- a/doc/examples/bench.cpp +++ b/doc/examples/bench.cpp @@ -13,6 +13,8 @@ using namespace Botan; #include <iostream> +namespace { + const std::string algos[] = { "AES-128", "AES-192", diff --git a/doc/examples/cpuid.cpp b/doc/examples/cpuid.cpp index 8adc8be6c..62b565edf 100644 --- a/doc/examples/cpuid.cpp +++ b/doc/examples/cpuid.cpp @@ -9,6 +9,8 @@ using namespace Botan; +namespace { + void print_if_feature(const std::string& feature_name, bool exists) { if(exists) @@ -17,6 +19,8 @@ void print_if_feature(const std::string& feature_name, bool exists) std::cout << '[' << feature_name << ']' << '\n'; } +} + int main() { std::cout << "Cache line size = " << CPUID::cache_line_size() << "\n"; diff --git a/doc/examples/dh.cpp b/doc/examples/dh.cpp index 4c6961234..652c7b136 100644 --- a/doc/examples/dh.cpp +++ b/doc/examples/dh.cpp @@ -1,12 +1,12 @@ /* -* (C) 2009 Jack Lloyd +* (C) 2009-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ #include <botan/botan.h> #include <botan/dh.h> -#include <botan/rng.h> +#include <botan/pubkey.h> using namespace Botan; #include <iostream> @@ -15,25 +15,40 @@ using namespace Botan; int main() { Botan::LibraryInitializer init; - + try { AutoSeeded_RNG rng; + // Alice and Bob agree on a DH domain to use + DL_Group shared_domain("modp/ietf/1024"); + // Alice creates a DH key and sends (the public part) to Bob - DH_PrivateKey private_a(rng, DL_Group("modp/ietf/1024")); - DH_PublicKey public_a = private_a; // Bob gets this + DH_PrivateKey private_a(rng, shared_domain); + + // Alice sends to Bob her public key: + MemoryVector<byte> public_a = private_a.public_value(); // Bob creates a key with a matching group - DH_PrivateKey private_b(rng, public_a.get_domain()); + DH_PrivateKey private_b(rng, shared_domain); + + // Bob sends his public key to Alice + MemoryVector<byte> public_b = private_b.public_value(); + + PK_Key_Agreement ka1(private_a, "KDF2(SHA-1)"); + PK_Key_Agreement ka2(private_b, "KDF2(SHA-1)"); - // Bob sends the key back to Alice - DH_PublicKey public_b = private_b; // Alice gets this + /* + * Preferably, include some salt or parameter that binds this key + * generation to the current session (for instance a session + * identifier, if guaranteed unique, would be a good choice). Or + * anything else that both sides can agree on that will never + * repeat. + */ + const std::string ka_salt = "alice and bob agree on a key"; - // Both of them create a key using their private key and the other's - // public key - SymmetricKey alice_key = private_a.derive_key(public_b); - SymmetricKey bob_key = private_b.derive_key(public_a); + SymmetricKey alice_key = ka1.derive_key(32, public_b, ka_salt); + SymmetricKey bob_key = ka2.derive_key(32, public_a, ka_salt); if(alice_key == bob_key) { @@ -42,12 +57,12 @@ int main() } else { - std::cout << "The two keys didn't match!\n"; + std::cout << "The two keys didn't match! Hmmm...\n"; std::cout << "Alice's key was: " << alice_key.as_string() << "\n"; std::cout << "Bob's key was: " << bob_key.as_string() << "\n"; } - // Now Alice and Bob hash the key and use it for something + // Now use the shared key for encryption or MACing or whatever } catch(std::exception& e) { diff --git a/doc/examples/dsa_sign.cpp b/doc/examples/dsa_sign.cpp index abc22d0de..ea23907cf 100644 --- a/doc/examples/dsa_sign.cpp +++ b/doc/examples/dsa_sign.cpp @@ -12,7 +12,7 @@ #include <memory> #include <botan/botan.h> -#include <botan/look_pk.h> +#include <botan/pubkey.h> #include <botan/dsa.h> using namespace Botan; @@ -62,7 +62,7 @@ int main(int argc, char* argv[]) return 1; } - PK_Signer signer(*dsakey, get_emsa("EMSA1(SHA-1)")); + PK_Signer signer(*dsakey, "EMSA1(SHA-1)"); DataSource_Stream in(message); byte buf[4096] = { 0 }; diff --git a/doc/examples/dsa_ver.cpp b/doc/examples/dsa_ver.cpp index 4a2f62ce4..b30208559 100644 --- a/doc/examples/dsa_ver.cpp +++ b/doc/examples/dsa_ver.cpp @@ -21,10 +21,12 @@ signature format, encoded into base64 with a trailing newline. #include <memory> #include <botan/botan.h> -#include <botan/look_pk.h> +#include <botan/pubkey.h> #include <botan/dsa.h> using namespace Botan; +namespace { + SecureVector<byte> b64_decode(const std::string& in) { Pipe pipe(new Base64_Decoder); @@ -32,6 +34,8 @@ SecureVector<byte> b64_decode(const std::string& in) return pipe.read_all(); } +} + int main(int argc, char* argv[]) { if(argc != 4) @@ -71,14 +75,14 @@ int main(int argc, char* argv[]) SecureVector<byte> sig = b64_decode(sigstr); - std::auto_ptr<PK_Verifier> ver(get_pk_verifier(*dsakey, "EMSA1(SHA-1)")); + PK_Verifier ver(*dsakey, "EMSA1(SHA-1)"); DataSource_Stream in(message); byte buf[4096] = { 0 }; while(u32bit got = in.read(buf, sizeof(buf))) - ver->update(buf, got); + ver.update(buf, got); - bool ok = ver->check_signature(sig); + bool ok = ver.check_signature(sig); if(ok) std::cout << "Signature verified\n"; diff --git a/doc/examples/eax_test.cpp b/doc/examples/eax_test.cpp index 3f7dbcbc8..32311800d 100644 --- a/doc/examples/eax_test.cpp +++ b/doc/examples/eax_test.cpp @@ -14,7 +14,9 @@ using namespace Botan; -unsigned to_string(const std::string& s) +namespace { + +unsigned from_string(const std::string& s) { std::istringstream stream(s); unsigned n; @@ -211,7 +213,7 @@ void run_tests(std::istream& in) if(boost::regex_match(line, what, vec_regex, boost::match_extra)) { - unsigned n = to_string(what[1]); + unsigned n = from_string(what[1]); std::string ciphertext = what[2]; std::string tag = what[3]; @@ -230,6 +232,8 @@ void run_tests(std::istream& in) } +} + int main() { std::ifstream in("eax_tv.txt"); diff --git a/doc/examples/ecdsa.cpp b/doc/examples/ecdsa.cpp index f55005544..df1e1b93a 100644 --- a/doc/examples/ecdsa.cpp +++ b/doc/examples/ecdsa.cpp @@ -7,7 +7,6 @@ #include <botan/botan.h> #include <botan/ecdsa.h> #include <botan/pubkey.h> -#include <botan/look_pk.h> #include <memory> #include <iostream> @@ -22,7 +21,7 @@ int main() { AutoSeeded_RNG rng; - EC_Domain_Params params = get_EC_Dom_Pars_by_oid("1.3.132.0.8"); + EC_Domain_Params params("1.3.132.0.8"); ECDSA_PrivateKey ecdsa(rng, params); @@ -35,22 +34,21 @@ int main() std::cout << PKCS8::PEM_encode(ecdsa); */ - std::auto_ptr<PK_Signer> signer(get_pk_signer(ecdsa, "EMSA1(SHA-256)")); + PK_Signer signer(ecdsa, "EMSA1(SHA-256)"); const char* message = "Hello World"; - signer->update((const byte*)message, strlen(message)); + signer.update((const byte*)message, strlen(message)); - SecureVector<byte> sig = signer->signature(rng); + SecureVector<byte> sig = signer.signature(rng); std::cout << sig.size() << "\n"; - std::auto_ptr<PK_Verifier> verifier( - get_pk_verifier(ecdsa_pub, "EMSA1(SHA-256)")); + PK_Verifier verifier(ecdsa_pub, "EMSA1(SHA-256)"); - verifier->update((const byte*)message, strlen(message)); + verifier.update((const byte*)message, strlen(message)); - bool ok = verifier->check_signature(sig); + bool ok = verifier.check_signature(sig); if(ok) std::cout << "Signature valid\n"; else diff --git a/doc/examples/factor.cpp b/doc/examples/factor.cpp index 7700d9b2d..b0105426b 100644 --- a/doc/examples/factor.cpp +++ b/doc/examples/factor.cpp @@ -17,11 +17,14 @@ using namespace Botan; #include <iostream> #include <memory> -// Pollard's Rho algorithm, as described in the MIT algorithms book -// We use (x^2+x) mod n instead of (x*2-1) mod n as the random function, -// it _seems_ to lead to faster factorization for the values I tried. +namespace { +/* +* Pollard's Rho algorithm, as described in the MIT algorithms book. We +* use (x^2+x) mod n instead of (x*2-1) mod n as the random function, +* it _seems_ to lead to faster factorization for the values I tried. +*/ BigInt rho(const BigInt& n, RandomNumberGenerator& rng) { BigInt x = BigInt::random_integer(rng, 0, n-1); @@ -117,6 +120,8 @@ std::vector<BigInt> factorize(const BigInt& n_in, return factors; } +} + int main(int argc, char* argv[]) { if(argc != 2) diff --git a/doc/examples/fpe.cpp b/doc/examples/fpe.cpp index 73773994b..9b18d4879 100644 --- a/doc/examples/fpe.cpp +++ b/doc/examples/fpe.cpp @@ -18,6 +18,8 @@ using namespace Botan; #include <iostream> #include <stdexcept> +namespace { + byte luhn_checksum(u64bit cc_number) { byte sum = 0; @@ -109,6 +111,8 @@ u64bit decrypt_cc_number(u64bit enc_cc, return cc_derank(dec_cc); } +} + int main(int argc, char* argv[]) { LibraryInitializer init; diff --git a/doc/examples/gen_certs.cpp b/doc/examples/gen_certs.cpp index b267d8791..73d667edb 100644 --- a/doc/examples/gen_certs.cpp +++ b/doc/examples/gen_certs.cpp @@ -20,6 +20,8 @@ using namespace Botan; #include <iostream> #include <fstream> +namespace { + void fill_commoninfo(X509_Cert_Options& opts) { opts.country = "US"; diff --git a/doc/examples/hash_quickly.cpp b/doc/examples/hash_quickly.cpp index a5236b381..1af0e8f45 100644 --- a/doc/examples/hash_quickly.cpp +++ b/doc/examples/hash_quickly.cpp @@ -4,16 +4,6 @@ * Distributed under the terms of the Botan license */ -#include <botan/botan.h> -#include <botan/benchmark.h> -#include <botan/filters.h> - -#include <iostream> -#include <fstream> -#include <string> -#include <map> -#include <cstdlib> - /* Try to find the fastest SHA-1 implementation and use it to hash files. In most programs this isn't worth the bother and @@ -25,6 +15,18 @@ Of course you could also just do this once and save it as an application config, which is probably the smart thing to do. */ +#include <botan/botan.h> +#include <botan/benchmark.h> +#include <botan/filters.h> + +#include <iostream> +#include <fstream> +#include <string> +#include <map> +#include <cstdlib> + +namespace { + void set_fastest_implementation(const std::string& algo, Botan::RandomNumberGenerator& rng, double ms = 30) @@ -54,6 +56,8 @@ void set_fastest_implementation(const std::string& algo, af.set_preferred_provider(algo, fastest_provider); } +} + int main(int argc, char* argv[]) { if(argc <= 1) diff --git a/doc/examples/package.cpp b/doc/examples/package.cpp index 14d215f73..bdb5b78c0 100644 --- a/doc/examples/package.cpp +++ b/doc/examples/package.cpp @@ -4,7 +4,6 @@ * Distributed under the terms of the Botan license */ - #include <botan/botan.h> #include <botan/serpent.h> #include <botan/package.h> @@ -15,6 +14,8 @@ using namespace Botan; +namespace { + std::vector<byte> slurp_file(const std::string& filename) { std::ifstream in(filename.c_str()); @@ -33,6 +34,8 @@ std::vector<byte> slurp_file(const std::string& filename) return out; } +} + int main(int argc, char* argv[]) { if(argc != 2) diff --git a/doc/examples/pqg_gen.cpp b/doc/examples/pqg_gen.cpp index e797233f9..c033dac3b 100644 --- a/doc/examples/pqg_gen.cpp +++ b/doc/examples/pqg_gen.cpp @@ -13,7 +13,6 @@ #include <botan/botan.h> #include <botan/auto_rng.h> -#include <botan/look_pk.h> #include <botan/dsa.h> #include <botan/numthry.h> #include <botan/dl_group.h> diff --git a/doc/examples/read_ssh.cpp b/doc/examples/read_ssh.cpp index 52c758ceb..f6299a29d 100644 --- a/doc/examples/read_ssh.cpp +++ b/doc/examples/read_ssh.cpp @@ -17,6 +17,8 @@ using namespace Botan; +namespace { + u32bit read_u32bit(Pipe& pipe) { byte out[4] = { 0 }; @@ -104,6 +106,8 @@ Public_Key* read_ssh_pubkey(const std::string& file) return 0; } +} + #include <botan/init.h> #include <iostream> diff --git a/doc/examples/ressol.cpp b/doc/examples/ressol.cpp deleted file mode 100644 index 286377fc6..000000000 --- a/doc/examples/ressol.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* -* (C) 2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/numthry.h> -#include <botan/auto_rng.h> -#include <botan/botan.h> - -using namespace Botan; - -#include <iostream> - -void test_ressol(const BigInt& p, RandomNumberGenerator& rng) - { - std::cout << p << std::endl; - - // const BigInt p_16 = p / 16; - - int noroot = 0, false_result = 0; - - for(int j = 0; j != 1000; ++j) - { - BigInt x = BigInt::random_integer(rng, 0, p); - //if(x % p_16 == 0) - //std::cout << "p = " << p << " x = " << x << "\n"; - - BigInt sqrt_x = ressol(x, p); - - if(sqrt_x < 0) - { - ++noroot; - continue; - } - - BigInt check = square(sqrt_x) % p; - - if(check != x % p) - { - std::cout << "FAIL " - << "x = " << x << "; " - << "p = " << p << "; " - << "s = " << sqrt_x << "; " - << "s^2%p = " << check << "\n"; - ++false_result; - } - } - /* - std::cout << "nomatch=" << nomatch << " " - << "noroot=" << noroot << " " - << "false=" << false_result << "\n"; - */ - } - -int main() - { - Botan::LibraryInitializer init; - AutoSeeded_RNG rng; - -#if 0 - std::cout << ressol(8, 17) << "\n"; - std::cout << ressol_orig(8, 17) << "\n"; -#endif - -#if 1 - for(int j = 16; j != 1024; ++j) - { - std::cout << "Round " << j << "\n"; - BigInt p = random_prime(rng, j); - test_ressol(p, rng); - //printf("%d\n", j); - - - } -#endif - /* - for(u32bit j = 9; j != PRIME_TABLE_SIZE; ++j) - { - std::cout << "PRIME[" << j << "] == " << PRIMES[j] << std::endl; - //printf("%d - ", PRIMES[j]); - test_ressol(PRIMES[j], rng); - //printf("\n"); - } - */ - } diff --git a/doc/examples/rng_test.cpp b/doc/examples/rng_test.cpp index 05f2c28a4..3d96b7a42 100644 --- a/doc/examples/rng_test.cpp +++ b/doc/examples/rng_test.cpp @@ -11,12 +11,12 @@ #include <iostream> #include <fstream> -#include <boost/algorithm/string.hpp> +#include <deque> #include <stdexcept> using namespace Botan; -std::vector<std::pair<std::string, std::string> > read_file(const std::string&); +namespace { SecureVector<byte> decode_hex(const std::string& in) { @@ -109,18 +109,6 @@ void x931_tests(std::vector<std::pair<std::string, std::string> > vecs, } -int main() - { - Botan::LibraryInitializer init; - - x931_tests(read_file("ANSI931_AES128VST.txt.vst"), "AES-128"); - x931_tests(read_file("ANSI931_AES192VST.txt.vst"), "AES-192"); - x931_tests(read_file("ANSI931_AES256VST.txt.vst"), "AES-256"); - x931_tests(read_file("ANSI931_TDES2VST.txt.vst"), "TripleDES"); - x931_tests(read_file("ANSI931_TDES3VST.txt.vst"), "TripleDES"); - } - - std::vector<std::pair<std::string, std::string> > read_file(const std::string& fsname) { @@ -136,8 +124,7 @@ read_file(const std::string& fsname) if(line == "") break; - std::vector<std::string> l; - boost::split(l, line, boost::is_any_of(":")); + std::vector<std::string> l = split_on(line, ':'); if(l.size() != 2) throw std::runtime_error("Bad line " + line); @@ -147,3 +134,16 @@ read_file(const std::string& fsname) return out; } + +} + +int main() + { + Botan::LibraryInitializer init; + + x931_tests(read_file("ANSI931_AES128VST.txt.vst"), "AES-128"); + x931_tests(read_file("ANSI931_AES192VST.txt.vst"), "AES-192"); + x931_tests(read_file("ANSI931_AES256VST.txt.vst"), "AES-256"); + x931_tests(read_file("ANSI931_TDES2VST.txt.vst"), "TripleDES"); + x931_tests(read_file("ANSI931_TDES3VST.txt.vst"), "TripleDES"); + } diff --git a/doc/examples/rsa_dec.cpp b/doc/examples/rsa_dec.cpp index 1e789d748..8353b0449 100644 --- a/doc/examples/rsa_dec.cpp +++ b/doc/examples/rsa_dec.cpp @@ -1,5 +1,5 @@ /* -* (C) 2002 Jack Lloyd +* (C) 2002-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -16,7 +16,7 @@ same key format as that generated by rsa_kgen. #include <memory> #include <botan/botan.h> -#include <botan/look_pk.h> // for get_kdf +#include <botan/pubkey.h> #include <botan/rsa.h> using namespace Botan; @@ -75,9 +75,9 @@ int main(int argc, char* argv[]) SecureVector<byte> enc_masterkey = b64_decode(enc_masterkey_str); - std::auto_ptr<PK_Decryptor> decryptor(get_pk_decryptor(*rsakey, - "EME1(SHA-1)")); - SecureVector<byte> masterkey = decryptor->decrypt(enc_masterkey); + PK_Decryptor_EME decryptor(*rsakey, "EME1(SHA-1)"); + + SecureVector<byte> masterkey = decryptor.decrypt(enc_masterkey); SymmetricKey cast_key = derive_key("CAST", masterkey, 16); InitializationVector iv = derive_key("IV", masterkey, 8); diff --git a/doc/examples/rsa_enc.cpp b/doc/examples/rsa_enc.cpp index 904b1e379..6cf555e70 100644 --- a/doc/examples/rsa_enc.cpp +++ b/doc/examples/rsa_enc.cpp @@ -32,7 +32,7 @@ #include <memory> #include <botan/botan.h> -#include <botan/look_pk.h> +#include <botan/pubkey.h> #include <botan/rsa.h> using namespace Botan; @@ -77,8 +77,7 @@ int main(int argc, char* argv[]) AutoSeeded_RNG rng; - std::auto_ptr<PK_Encryptor> encryptor(get_pk_encryptor(*rsakey, - "EME1(SHA-1)")); + PK_Encryptor_EME encryptor(*rsakey, "EME1(SHA-1)"); /* Generate the master key (the other keys are derived from this) @@ -92,14 +91,14 @@ int main(int argc, char* argv[]) a problem. */ SymmetricKey masterkey(rng, - std::min(32U, encryptor->maximum_input_size())); + std::min(32U, encryptor.maximum_input_size())); SymmetricKey cast_key = derive_key("CAST", masterkey, 16); SymmetricKey mac_key = derive_key("MAC", masterkey, 16); SymmetricKey iv = derive_key("IV", masterkey, 8); SecureVector<byte> encrypted_key = - encryptor->encrypt(masterkey.bits_of(), rng); + encryptor.encrypt(masterkey.bits_of(), rng); ciphertext << b64_encode(encrypted_key) << std::endl; diff --git a/doc/examples/sig_gen.cpp b/doc/examples/sig_gen.cpp index fca069862..cf273216a 100644 --- a/doc/examples/sig_gen.cpp +++ b/doc/examples/sig_gen.cpp @@ -12,8 +12,8 @@ #include <memory> #include <botan/botan.h> -#include <botan/look_pk.h> #include <botan/dsa.h> +#include <botan/pubkey.h> using namespace Botan; bool check(std::map<std::string, std::string>); @@ -90,7 +90,7 @@ bool check(std::map<std::string, std::string> inputs) pipe.write(inputs["S"] ); pipe.end_msg(); - std::auto_ptr<PK_Verifier> verify(get_pk_verifier(key, "EMSA1(SHA-1)")); + PK_Verifier verifier(key, "EMSA1(SHA-1)"); - return verify->verify_message(pipe.read_all(0), pipe.read_all(1)); + return verifier.verify_message(pipe.read_all(0), pipe.read_all(1)); } diff --git a/doc/examples/tls_client.cpp b/doc/examples/tls_client.cpp index 9e6b510f2..b60941eb2 100644 --- a/doc/examples/tls_client.cpp +++ b/doc/examples/tls_client.cpp @@ -38,7 +38,7 @@ int main() byte buf[16+1] = { 0 }; u32bit got = tls.read(buf, sizeof(buf)-1); - printf("%s", buf); + printf("Got %d bytes: %s", got, buf); fflush(0); } } diff --git a/doc/examples/x509info.cpp b/doc/examples/x509info.cpp index 8f4d83c45..52cc4afbd 100644 --- a/doc/examples/x509info.cpp +++ b/doc/examples/x509info.cpp @@ -14,6 +14,8 @@ using namespace Botan; #include <iterator> #include <algorithm> +namespace { + std::string to_hex(const SecureVector<byte>& bin) { Pipe pipe(new Hex_Encoder); @@ -46,6 +48,8 @@ void do_issuer(const X509_Certificate& cert, const std::string& what) do_print(what, cert.issuer_info(what)); } +} + int main(int argc, char* argv[]) { if(argc != 2) diff --git a/doc/log.txt b/doc/log.txt index da624f223..472a87a3c 100644 --- a/doc/log.txt +++ b/doc/log.txt @@ -1,20 +1,24 @@ * 1.9.4-dev, ????-??-?? - - Add the Ajisai SSL/TLS implementation + - Add the Ajisai SSLv3/TLSv1.0 implementation - Add GOST 34.10-2001 public key signature scheme - Add SIMD implementation of Noekeon - Add SSE2 implementation of IDEA + - Extend Salsa20 to support longer IVs (XSalsa20) - Perform XTS encryption and decryption in parallel where possible - Perform CBC decryption in parallel where possible - Add SQLite3 db encryption codec, contributed by Olivier de Gaalon - Add a block cipher cascade construction - Add support for password hashing for authentication (passhash9.h) - Add support for Win32 high resolution system timers + - Major refactoring and API changes in the public key code + - Use consistency checking (anti-fault attack) for all signature schemes - Changed S2K interface: derive_key now takes salt, iteration count - Remove dependency on TR1 for ECC and CVC code - Renamed ECKAEG to its more usual name, ECDH - Fix crash in GMP_Engine if library is shutdown and reinitialized - Fix an invalid memory read in MD4 + - Fix Visual C++ static builds - Remove Timer class entirely - Switch default PKCS #8 encryption algorithm from 3DES to AES-256 - New option --gen-amalgamation for creating a SQLite-style amalgamation diff --git a/doc/python/cryptobox.py b/doc/python/cryptobox.py index 1968b40e1..f76ed6bc3 100755 --- a/doc/python/cryptobox.py +++ b/doc/python/cryptobox.py @@ -8,7 +8,7 @@ def main(args = None): args = sys.argv if len(args) != 3: - raise Exception("Bad usage") + raise Exception("Usage: <password> <input>"); password = args[1] input = ''.join(open(args[2]).readlines()) @@ -24,10 +24,12 @@ def main(args = None): try: plaintext = botan.cryptobox_decrypt(ciphertext, password + 'FAIL') except Exception, e: - print "Oops -- ", e + print "Good news: bad password caused exception: " + print e plaintext = botan.cryptobox_decrypt(ciphertext, password) + print "Original input was: " print plaintext if __name__ == '__main__': diff --git a/doc/python/rsa.py b/doc/python/rsa.py index 15ffcffa3..09ca22314 100755 --- a/doc/python/rsa.py +++ b/doc/python/rsa.py @@ -26,6 +26,9 @@ print plaintext == key signature = rsa_priv.sign(key, 'EMSA4(SHA-256)', rng) -key = key.replace('a', 'b') +print rsa_pub.verify(key, signature, 'EMSA4(SHA-256)') + +# Corrupt the signature, make sure it doesn't verify +signature = signature.replace(signature[0], '0') print rsa_pub.verify(key, signature, 'EMSA4(SHA-256)') diff --git a/doc/scripts/configure.pl b/doc/scripts/configure.pl deleted file mode 100755 index 1ce01e2b4..000000000 --- a/doc/scripts/configure.pl +++ /dev/null @@ -1,2340 +0,0 @@ -#!/usr/bin/perl -w - -require 5.006; - -use strict; - -use Config; -use Getopt::Long; -use File::Spec; -use File::Copy; -use File::Find; -use Sys::Hostname; - -my $MAJOR_VERSION = 1; -my $MINOR_VERSION = 8; -my $PATCH_VERSION = 8; - -my $VERSION_SUFFIX = ''; - -my $SO_PATCH_VERSION = 2; - -my $VERSION_STRING = "$MAJOR_VERSION.$MINOR_VERSION.$PATCH_VERSION$VERSION_SUFFIX"; -my $SO_VERSION_STRING = "$MAJOR_VERSION.$MINOR_VERSION.$SO_PATCH_VERSION$VERSION_SUFFIX"; - -################################################## -# Data # -################################################## -my (%CPU, %OPERATING_SYSTEM, %COMPILER, %MODULES); - -my @DOCS = ( - 'api.pdf', 'tutorial.pdf', 'fips140.pdf', - 'api.tex', 'tutorial.tex', 'fips140.tex', - 'credits.txt', 'license.txt', 'log.txt', - 'thanks.txt', 'todo.txt', 'pgpkeys.asc'); - -my $TRACING = 0; - -################################################## -# Run main() and Quit # -################################################## -my $config = {}; - -main(); -exit; - -sub exec_uname { - # Only exec it if we think it might actually work - if(-f '/bin/uname' || -f '/usr/bin/uname' || -f '/bin/sh') { - my $uname = `uname -a`; - if($uname) { - chomp $uname; - return $uname; - } - } - - return ''; -} - -sub deprecation_warning { - warning("$0 is deprecated; migration to ./configure.py strongly recommended"); -} - -################################################## -# Main Driver # -################################################## -sub main { - my $base_dir = where_am_i(); - - deprecation_warning(); - - $$config{'uname'} = exec_uname(); - - $$config{'base-dir'} = $base_dir; - $$config{'src-dir'} = File::Spec->catdir($base_dir, 'src'); - $$config{'checks-dir'} = File::Spec->catdir($base_dir, 'checks'); - $$config{'doc_src_dir'} = File::Spec->catdir($base_dir, 'doc'); - - $$config{'config-dir'} = - File::Spec->catdir($$config{'src-dir'}, 'build-data'); - - $$config{'command_line'} = $0 . ' ' . join(' ', @ARGV); - $$config{'timestamp'} = gmtime; - $$config{'user'} = getlogin || getpwuid($<) || ''; - $$config{'hostname'} = hostname; - - %CPU = read_info_files($config, 'arch', \&get_arch_info); - %OPERATING_SYSTEM = read_info_files($config, 'os', \&get_os_info); - %COMPILER = read_info_files($config, 'cc', \&get_cc_info); - %MODULES = read_module_files($config); - - add_to($config, { - 'version_major' => $MAJOR_VERSION, - 'version_minor' => $MINOR_VERSION, - 'version_patch' => $PATCH_VERSION, - 'version' => $VERSION_STRING, - 'so_version' => $SO_VERSION_STRING, - }); - - get_options($config); - - my $default_value_is = sub { - my ($var, $val) = @_; - $$config{$var} = $val if not defined($$config{$var}); - }; - - &$default_value_is('gcc_bug', 0); - &$default_value_is('autoconfig', 1); - &$default_value_is('debug', 0); - &$default_value_is('shared', 'yes'); - &$default_value_is('local_config', ''); - - # Goes into build-specific dirs (maybe) - - $$config{'build_dir'} = 'build'; - $$config{'botan_config'} = File::Spec->catfile( - $$config{'build_dir'}, 'botan-config'); - - $$config{'botan_pkgconfig'} = File::Spec->catfile( - $$config{'build_dir'}, - 'botan-' . $MAJOR_VERSION . '.' . $MINOR_VERSION . '.pc'); - - $$config{'makefile'} = 'Makefile'; - $$config{'check_prefix'} = ''; - $$config{'lib_prefix'} = ''; - - if(defined($$config{'with_build_dir'})) { - for my $var ('build_dir', - 'botan_config', - 'botan_pkgconfig', - 'makefile', - 'check_prefix', - 'lib_prefix') - { - $$config{$var} = File::Spec->catfile($$config{'with_build_dir'}, - $$config{$var}); - } - } - else { - } - - choose_target($config); - - my $os = $$config{'os'}; - my $cc = $$config{'compiler'}; - - &$default_value_is('prefix', os_info_for($os, 'install_root')); - &$default_value_is('libdir', os_info_for($os, 'lib_dir')); - &$default_value_is('docdir', os_info_for($os, 'doc_dir')); - &$default_value_is('make_style', $COMPILER{$cc}{'makefile_style'}); - - scan_modules($config); - - print_enabled_modules($config); - - add_to($config, { - 'includedir' => os_info_for($os, 'header_dir'), - - 'build_lib' => File::Spec->catdir($$config{'build_dir'}, 'lib'), - 'build_check' => File::Spec->catdir($$config{'build_dir'}, 'checks'), - 'build_include' => - File::Spec->catdir($$config{'build_dir'}, 'include'), - 'build_include_botan' => - File::Spec->catdir($$config{'build_dir'}, 'include', 'botan'), - - 'mp_bits' => find_mp_bits($config), - 'mod_libs' => [ using_libs($config) ], - - 'sources' => { }, - 'includes' => { }, - - 'check_src' => { - map_to($$config{'checks-dir'}, - grep { $_ ne 'keys' and !m@\.(dat|h)$@ } - dir_list($$config{'checks-dir'})) - } - }); - - load_modules($config); - - my @dirs = mkdirs($$config{'build_dir'}, - $$config{'build_include'}, - $$config{'build_include_botan'}, - $$config{'build_lib'}, - $$config{'build_check'}); - - #autoconfig('Created ' . join(' ', @dirs)) if @dirs; - - write_pkg_config($config); - - determine_config($config); - - process_template(File::Spec->catfile($$config{'config-dir'}, 'buildh.in'), - File::Spec->catfile($$config{'build_dir'}, 'build.h'), - $config); - - process_template(File::Spec->catfile( - $$config{'config-dir'}, 'botan.doxy.in'), - File::Spec->catfile($$config{'doc_src_dir'}, 'botan.doxy'), - $config); - - $$config{'includes'}{'build.h'} = $$config{'build_dir'}; - - generate_makefile($config); - - copy_include_files($config); - - deprecation_warning(); -} - -sub where_am_i { - my ($volume,$dir,$file) = File::Spec->splitpath($0); - my $src_dir = File::Spec->catpath($volume, $dir, ''); - return $src_dir if $src_dir; - return File::Spec->curdir(); -} - -################################################## -# Diagnostics # -################################################## -sub with_diagnostic { - my ($type, @args) = @_; - - my $args = join('', @args); - my $str = "($type): "; - while(length($str) < 14) { $str = ' ' . $str; } - - $str .= $args . "\n"; - return $str; -} - -sub croak { - die with_diagnostic('error', @_); -} - -sub warning { - warn with_diagnostic('warning', @_); -} - -sub autoconfig { - print with_diagnostic('autoconfig', @_); -} - -sub emit_help { - print join('', @_); - exit; -} - -sub trace { - return unless $TRACING; - - my (undef, undef, $line) = caller(0); - my (undef, undef, undef, $func) = caller(1); - - $func =~ s/main:://; - - print with_diagnostic('trace', "at $func:$line - ", @_); -} - -################################################## -# Display Help and Quit # -################################################## -sub display_help { - sub module_sets { - my %modsets; - for my $name (sort keys %MODULES) { - my %info = %{$MODULES{$name}}; - next unless (defined($info{'modset'})); - - for my $s (split(/,/, $info{'modset'})) { - $modsets{$s} = undef; - } - } - - return sort keys %modsets; - } - - my $sets = join(' ', module_sets()); - - my $listing = sub { - my (@list) = @_; - - return '' if (@list == 0); - - my ($output, $len) = ('', 0); - - my $append = sub { - my ($to_append) = @_; - $output .= $to_append; - $len += length $to_append; - }; - - foreach my $name (sort @list) { - next if $name eq 'defaults'; - if($len > 58) { - $output .= "\n "; - $len = 8; - } - &$append($name . ' '); - } - chop $output; - return $output; - }; - - #my $modules = &$listing(keys %MODULES); - my $compilers = &$listing(keys %COMPILER); - my $oses = &$listing(keys %OPERATING_SYSTEM); - my $cpus = &$listing(keys %CPU); - - my $helptxt = <<ENDOFHELP; -This is $0 from Botan $VERSION_STRING - -To select the compiler, use - - --cc=[$compilers] - -To select the OS and processor to target, use these options. By -default, autodetection will be attempted. - - --os=[generic $oses] - --cpu=[generic $cpus] - - --with-endian=[little big none] - --with-unaligned-mem=[yes no] - -To change build options: - - --with-tr1={none,system,boost} enable (or disable) using a TR1 implementation - --with-build-dir=DIR setup the build in DIR - --with-local-config=FILE include the contents of FILE into build.h - - --disable-debug don't worry about debugging - --enable-debug set compiler flags for debugging - - --enable-shared enable shared libraries - --disable-shared don't build shared libararies - -To change where the library is installed: - - --prefix=PATH set the base installation directory - --libdir=PATH install library files in \${prefix}/\${libdir} - --docdir=PATH install documentation in \${prefix}/\${docdir} - -To change what modules to use: - - --enable-modules=[module,[module[,...]]] - --disable-modules=[module,[module[,...]]] - -To get diagnostic and debug output: - - --module-info display more information about modules - - --show-arch-info=CPU show more information about a particular CPU - [$cpus] - - --help display this help - --version display the version of Botan - --quiet display only warnings and errors - --trace enable runtime tracing of this program - -See doc/building.pdf for more information about this program. - -ENDOFHELP - - emit_help($helptxt); -} - -################################################## -# Display Further Information about Modules # -################################################## -sub module_info { - - my $info = ''; - foreach my $mod (sort keys %MODULES) { - my $modinfo = $MODULES{$mod}; - my $fullname = $$modinfo{'realname'}; - - while(length($mod) < 10) { $mod .= ' '; } - $info .= "$mod - $fullname\n"; - } - - return $info; -} - -################################################## -# -################################################## -sub choose_target { - my ($config) = @_; - - my $cc = $$config{'compiler'}; - my $os = $$config{'os'}; - my $cpu = $$config{'cpu'}; - - autoconfig("Setting up build for Botan $VERSION_STRING"); - - $cpu = guess_cpu() if not defined($cpu); - $cc = guess_compiler() if not defined($cc); - $os = guess_os() if not defined($os); - - display_help() - unless(defined($cc) and defined($os) and defined($cpu)); - - croak("Compiler $cc isn't known (try --help)") - unless defined($COMPILER{$cc}); - - my %ccinfo = %{$COMPILER{$cc}}; - - if(defined($ccinfo{'compiler_has_tr1'})) { - unless(defined($$config{'tr1'})) { - autoconfig('Assuming compiler ', $cc, ' has TR1 headers. ', - 'Use --with-tr1=none to disable'); - $$config{'tr1'} = 'system'; - } - } - - $os = os_alias($os); - croak("OS $os isn't known (try --help)") unless - ($os eq 'generic' or defined($OPERATING_SYSTEM{$os})); - - my ($arch, $submodel) = figure_out_arch($cpu); - - # hacks - if($cc eq 'gcc') { - $ccinfo{'binary_name'} = 'c++' if($os eq 'darwin'); - - if($$config{'gcc_bug'} != 1) { - my $binary = $ccinfo{'binary_name'}; - - my $gcc_version = `$binary -v 2>&1`; - - $gcc_version = '' if not defined $gcc_version; - - my $has_ll_bug = 0; - $has_ll_bug = 1 if($gcc_version =~ /4\.[01234]/); - $has_ll_bug = 1 if($gcc_version =~ /3\.[34]/); - $has_ll_bug = 1 if($gcc_version =~ /2\.95\.[0-4]/); - $has_ll_bug = 1 if($gcc_version eq ''); - - $has_ll_bug = 0 if($arch eq 'alpha' or $arch =~ /.*64$/); - - if($has_ll_bug) - { - warning('Enabling -fpermissive to work around ', - 'possible GCC bug'); - - $$config{'gcc_bug'} = 1; - } - - warning('GCC 2.95.x issues many spurious warnings') - if($gcc_version =~ /2\.95\.[0-4]/); - } - } - - trace("using $cc $os $arch $submodel"); - - add_to($config, { - 'compiler' => $cc, - 'os' => $os, - 'arch' => $arch, - 'submodel' => $submodel, - }); -} - -sub module_runs_on { - my ($config, $modinfo, $mod, $noisy) = @_; - - my $cc = $$config{'compiler'}; - my $os = $$config{'os'}; - my $submodel = $$config{'submodel'}; - my $arch = $$config{'arch'}; - - my %modinfo = %{$modinfo}; - - my $realname = $modinfo{'realname'}; - - my @arch_list = @{ $modinfo{'arch'} }; - if(scalar @arch_list > 0 && !in_array($arch, \@arch_list) && - !in_array($submodel, \@arch_list)) - { - autoconfig("$mod ($realname): skipping, " . - "not compatible with " . realname($arch) . - "/" . $submodel) if $noisy; - return 0; - } - - my @os_list = @{ $modinfo{'os'} }; - if(scalar @os_list > 0 && !in_array($os, \@os_list)) - { - autoconfig("$mod ($realname): " . - "skipping, not compatible with " . realname($os)) if $noisy; - return 0; - } - - my @cc_list = @{ $modinfo{'cc'} }; - if(scalar @cc_list > 0 && !in_array($cc, \@cc_list)) { - autoconfig("$mod ($realname): " . - "skipping, not compatible with " . realname($cc)) if $noisy; - return 0; - } - - - if($modinfo{'uses_tr1'} eq 'yes') { - return 0 unless defined($$config{'tr1'}); - - my $tr1 = $$config{'tr1'}; - return 0 unless($tr1 eq 'system' or $tr1 eq 'boost'); - } - - return 1; -} - -sub scan_modules { - my ($config) = @_; - - foreach my $mod (sort keys %MODULES) { - my %modinfo = %{ $MODULES{$mod} }; - - next if(defined($$config{'modules'}{$mod}) && $$config{'modules'}{$mod} < 0); - - next unless(module_runs_on($config, \%modinfo, $mod, 0)); - - if($modinfo{'load_on'} eq 'auto' or - $modinfo{'load_on'} eq 'always' or - ($modinfo{'load_on'} eq 'asm_ok' and $$config{'asm_ok'})) { - - my %maybe_load = (); - my $all_deps_found = 1; - - LINE: foreach (@{$modinfo{'requires'}}) { - for my $req_mod (split(/\|/, $_)) { - next unless defined $MODULES{$req_mod}; - - next if(defined($$config{'modules'}{$req_mod}) && $$config{'modules'}{$req_mod} < 0); - next unless(module_runs_on($config, $MODULES{$req_mod}, $req_mod, 0)); - - $maybe_load{$req_mod} = 1; - next LINE; - } - $all_deps_found = 0; - } - - if($all_deps_found) { - foreach my $depmod (keys %maybe_load) - { $$config{'modules'}{$depmod} = 1; } - $$config{'modules'}{$mod} = 1; - } - } - } -} - -sub print_enabled_modules { - my ($config) = @_; - - return unless($$config{'verbose'}); - - my %by_type; - - foreach my $mod (sort keys %MODULES) { - my $type = $MODULES{$mod}{'type'}; - - my $n = 0; - $n = 1 if($$config{'modules'}{$mod} && $$config{'modules'}{$mod} > 0); - - $by_type{$type}{$mod} = $n; - } - - for my $type (sort keys %by_type) { - my %mods = %{$by_type{$type}}; - - my @load_lines; - - if(keys %mods == 1) { - my $on = $mods{$type}; - - if($on > 0) { - print with_diagnostic('loading', $type); - } - else { - print with_diagnostic('loading', '[', $type , ']'); - } - } - else { - my $s = $type . ': '; - - for my $mod (sort keys %mods) { - my $on = $mods{$mod}; - - if($s eq '') { - $s = ' ' x (length($type) + 16); - } - - if($on > 0) { - $s .= $mod . ' '; - } - else { - $s .= '[' . $mod . '] '; - } - - if(length($s) > 60) { - push @load_lines, $s; - $s = ''; - } - } - - #print "Last1 '$s'\n"; - - $s =~ s/\s*$//m; # strip trailing whitespace - - push @load_lines, $s if($s ne ''); - - - print with_diagnostic('loading', join("\n", @load_lines)); - } - } -} - -sub get_options { - my ($config) = @_; - - my $save_option = sub { - my ($opt, $val) = @_; - $opt =~ s/-/_/g; - $$config{$opt} = $val; - }; - - $$config{'verbose'} = 1; - $$config{'asm_ok'} = 1; - $$config{'tr1'} = undef; # not enabled by default - $$config{'modules'} = {}; - - sub arch_info { - my $arg = $_[0]; - - my $arch = find_arch($arg); - - unless(defined($arch) and defined($CPU{$arch})) { - warning("Unknown arch '$arg' passed to --arch-info (try --help)"); - return ''; - } - - my %info = %{ $CPU{$arch} }; - - my $out = "Information for $arg ($arch)\n--------\n"; - - if(@{$info{'aliases'}}) { - $out .= 'Aliases: ' . join(' ', @{$info{'aliases'}}) . "\n"; - } - - if(@{$info{'submodels'}}) { - $out .= 'Submodels: ' . join(' ', @{$info{'submodels'}}) . "\n"; - } - - foreach my $k (keys %{$info{'submodel_aliases'}}) { - $out .= "Alias '$k' -> '" . $info{'submodel_aliases'}{$k} . "'\n"; - } - - if(defined($info{'endian'})) { - $out .= 'Default endian: ' . $info{'endian'} . "\n"; - } - - if(defined($info{'unaligned'})) { - $out .= 'Unaligned memory access: ' . $info{'unaligned'} . "\n"; - } - - return $out; - } - - sub add_modules { - my ($config,$mods) = @_; - - foreach my $mod (split(/,/, $mods)) { - # -1 means disabled by user, do not load - $$config{'modules'}{$mod} = 1 unless( - defined($$config{'modules'}{$mod}) && - $$config{'modules'}{$mod} == -1); - } - } - - sub disable_modules { - my ($config,$mods) = @_; - - foreach my $mod (split(/,/, $mods)) { - # -1 means disabled by user, do not load - $$config{'modules'}{$mod} = -1; - } - } - - sub add_module_sets { - my ($config,$sets) = @_; - - foreach my $set (split(/,/, $sets)) { - for my $mod (sort keys %MODULES) { - my %info = %{$MODULES{$mod}}; - - next unless (defined($info{'modset'})); - - for my $s (split(/,/, $info{'modset'})) { - if($s eq $set) { - $$config{'modules'}{$mod} = 1 - unless($$config{'modules'}{$mod} == -1); - } - } - } - } - } - - exit 1 unless GetOptions( - 'prefix=s' => sub { &$save_option(@_); }, - 'exec-prefix=s' => sub { &$save_option(@_); }, - - 'bindir=s' => sub { &$save_option(@_); }, - 'datadir' => sub { &$save_option(@_); }, - 'datarootdir' => sub { &$save_option(@_); }, - 'docdir=s' => sub { &$save_option(@_); }, - 'dvidir' => sub { &$save_option(@_); }, - 'htmldir' => sub { &$save_option(@_); }, - 'includedir' => sub { &$save_option(@_); }, - 'infodir' => sub { &$save_option(@_); }, - 'libdir=s' => sub { &$save_option(@_); }, - 'libexecdir' => sub { &$save_option(@_); }, - 'localedir' => sub { &$save_option(@_); }, - 'localstatedir' => sub { &$save_option(@_); }, - 'mandir' => sub { &$save_option(@_); }, - 'oldincludedir' => sub { &$save_option(@_); }, - 'pdfdir' => sub { &$save_option(@_); }, - 'psdir' => sub { &$save_option(@_); }, - 'sbindir=s' => sub { &$save_option(@_); }, - 'sharedstatedir' => sub { &$save_option(@_); }, - 'sysconfdir' => sub { &$save_option(@_); }, - - 'cc=s' => sub { &$save_option('compiler', $_[1]) }, - 'os=s' => sub { &$save_option(@_) }, - 'cpu=s' => sub { &$save_option(@_) }, - - 'help' => sub { display_help(); }, - 'module-info' => sub { emit_help(module_info()); }, - 'version' => sub { emit_help("$VERSION_STRING\n") }, - 'so-version' => sub { emit_help("$SO_VERSION_STRING\n") }, - - 'with-tr1-implementation=s' => sub { $$config{'tr1'} = $_[1]; }, - - 'quiet' => sub { $$config{'verbose'} = 0; }, - 'trace' => sub { $TRACING = 1; }, - - 'enable-asm' => sub { $$config{'asm_ok'} = 1; }, - 'disable-asm' => sub { $$config{'asm_ok'} = 0; }, - - 'enable-autoconfig' => sub { $$config{'autoconfig'} = 1; }, - 'disable-autoconfig' => sub { $$config{'autoconfig'} = 0; }, - - 'enable-shared' => sub { $$config{'shared'} = 'yes'; }, - 'disable-shared' => sub { $$config{'shared'} = 'no'; }, - - 'enable-debug' => sub { &$save_option('debug', 1); }, - 'disable-debug' => sub { &$save_option('debug', 0); }, - - 'enable-modules:s' => sub { add_modules($config, $_[1]); }, - 'disable-modules:s' => sub { disable_modules($config, $_[1]); }, - - 'with-openssl' => sub { add_modules($config, 'openssl'); }, - 'without-openssl' => sub { disable_modules($config, 'openssl'); }, - 'with-gnump' => sub { add_modules($config, 'gnump'); }, - 'without-gnump' => sub { disable_modules($config, 'gnump'); }, - 'with-bzip2' => sub { add_modules($config, 'bzip2'); }, - 'without-bzip2' => sub { disable_modules($config, 'bzip2'); }, - 'with-zlib' => sub { add_modules($config, 'zlib'); }, - 'without-zlib' => sub { disable_modules($config, 'zlib'); }, - - 'use-module-set=s' => sub { add_module_sets($config, $_[1]); }, - - 'with-build-dir=s' => sub { &$save_option(@_); }, - 'with-endian=s' => sub { &$save_option(@_); }, - 'with-unaligned-mem=s' => sub { &$save_option(@_); }, - 'with-local-config=s' => - sub { &$save_option('local_config', slurp_file($_[1])); }, - - 'modules=s' => sub { add_modules($config, $_[1]); }, - 'show-arch-info=s' => sub { emit_help(arch_info($_[1])); }, - 'make-style=s' => sub { &$save_option(@_); }, - 'dumb-gcc|gcc295x' => sub { $$config{'gcc_bug'} = 1; } - ); - - # All arguments should now be consumed - croak("Unknown option $ARGV[0] (try --help)") unless($#ARGV == -1); -} - -################################################## -# Functions to search the info tables # -################################################## -sub find_arch { - my $name = $_[0]; - - foreach my $arch (keys %CPU) { - my %info = %{$CPU{$arch}}; - - return $arch if($name eq $arch); - - foreach my $alias (@{$info{'aliases'}}) { - return $arch if($name eq $alias); - } - - foreach my $submodel (@{$info{'submodels'}}) { - return $arch if($name eq $submodel); - } - - foreach my $submodel (keys %{$info{'submodel_aliases'}}) { - return $arch if($name eq $submodel); - } - } - return undef; -}; - -sub figure_out_arch { - my ($name) = @_; - - return ('generic', 'generic') if($name eq 'generic'); - - my $submodel_alias = sub { - my ($name,$info) = @_; - - my %info = %{$info}; - - foreach my $submodel (@{$info{'submodels'}}) { - return $submodel if($name eq $submodel); - } - - return '' unless defined $info{'submodel_aliases'}; - my %sm_aliases = %{$info{'submodel_aliases'}}; - - foreach my $alias (keys %sm_aliases) { - my $official = $sm_aliases{$alias}; - return $official if($alias eq $name); - } - return ''; - }; - - my $arch = find_arch($name); - croak("Arch type $name isn't known (try --help)") unless defined $arch; - trace("mapped name '$name' to arch '$arch'"); - - my %archinfo = %{ $CPU{$arch} }; - - my $submodel = &$submodel_alias($name, \%archinfo); - - if($submodel eq '') { - $submodel = $archinfo{'default_submodel'}; - - autoconfig("Using $submodel as default type for family ", - realname($arch)) if($submodel ne $arch); - } - - trace("mapped name '$name' to submodel '$submodel'"); - - croak("Couldn't figure out arch type of $name") - unless defined($arch) and defined($submodel); - - return ($arch,$submodel); -} - -sub os_alias { - my $name = $_[0]; - - foreach my $os (keys %OPERATING_SYSTEM) { - foreach my $alias (@{$OPERATING_SYSTEM{$os}{'aliases'}}) { - if($alias eq $name) { - trace("os_alias($name) -> $os"); - return $os; - } - } - } - - return $name; -} - -sub os_info_for { - my ($os,$what) = @_; - - die unless defined($os); - - croak('os_info_for called with an os of defaults (internal problem)') - if($os eq 'defaults'); - - my $result = ''; - - if(defined($OPERATING_SYSTEM{$os})) { - my %osinfo = %{$OPERATING_SYSTEM{$os}}; - $result = $osinfo{$what}; - } - - if(!defined($result) or $result eq '') { - $result = $OPERATING_SYSTEM{'defaults'}{$what}; - } - - croak("os_info_for: No info for $what on $os") unless defined $result; - - return $result; -} - -sub my_compiler { - my ($config) = @_; - my $cc = $$config{'compiler'}; - - croak('my_compiler called, but no compiler set in config') - unless defined $cc and $cc ne ''; - - croak("unknown compiler $cc") unless defined $COMPILER{$cc}; - - return %{$COMPILER{$cc}}; -} - -sub mach_opt { - my ($config) = @_; - - my %ccinfo = my_compiler($config); - - # Nothing we can do in that case - return '' unless $ccinfo{'mach_opt_flags'}; - - my $submodel = $$config{'submodel'}; - my $arch = $$config{'arch'}; - if(defined($ccinfo{'mach_opt_flags'}{$submodel})) - { - return $ccinfo{'mach_opt_flags'}{$submodel}; - } - elsif(defined($ccinfo{'mach_opt_flags'}{$arch})) { - my $mach_opt_flags = $ccinfo{'mach_opt_flags'}{$arch}; - my $processed_modelname = $submodel; - - my $remove = ''; - if(defined($ccinfo{'mach_opt_re'}) and - defined($ccinfo{'mach_opt_re'}{$arch})) { - $remove = $ccinfo{'mach_opt_re'}{$arch}; - } - - $processed_modelname =~ s/$remove//; - $mach_opt_flags =~ s/SUBMODEL/$processed_modelname/g; - return $mach_opt_flags; - } - return ''; -} - -################################################## -# # -################################################## -sub using_libs { - my ($config) = @_; - - my $os = $$config{'os'}; - my %libs; - - foreach my $mod (sort keys %{$$config{'modules'}}) { - next if ${$$config{'modules'}}{$mod} < 0; - - my %MOD_LIBS = %{ $MODULES{$mod}{'libs'} }; - - foreach my $mod_os (keys %MOD_LIBS) - { - next if($mod_os =~ /^all!$os$/); - next if($mod_os =~ /^all!$os,/); - #next if($mod_os =~ /^all!.*,${os}$/); - next if($mod_os =~ /^all!.*,$os,.*/); - next unless($mod_os eq $os or ($mod_os =~ /^all.*/)); - my @liblist = split(/,/, $MOD_LIBS{$mod_os}); - foreach my $lib (@liblist) { $libs{$lib} = 1; } - } - } - - return sort keys %libs; -} - -sub libs { - my ($prefix,$suffix,@libs) = @_; - my $output = ''; - foreach my $lib (@libs) { - $output .= ' ' if($output ne ''); - $output .= $prefix . $lib . $suffix; - } - return $output; -} - -################################################## -# Path and file manipulation utilities # -################################################## -sub portable_symlink { - my ($from, $to_dir, $to_fname) = @_; - - #trace("portable_symlink($from, $to_dir, $to_fname)"); - - my $can_symlink = 0; - my $can_link = 0; - - unless($^O eq 'MSWin32' or $^O eq 'dos' or $^O eq 'cygwin') { - $can_symlink = eval { symlink("",""); 1 }; - $can_link = eval { link("",""); 1 }; - } - - chdir $to_dir or croak("Can't chdir to $to_dir ($!)"); - - if($can_symlink) { - symlink $from, $to_fname or - croak("Can't symlink $from to $to_fname ($!)"); - } - elsif($can_link) { - link $from, $to_fname or - croak("Can't link $from to $to_fname ($!)"); - } - else { - copy ($from, $to_fname) or - croak("Can't copy $from to $to_fname ($!)"); - } - - my $go_up = File::Spec->splitdir($to_dir); - for(my $j = 0; $j != $go_up; $j++) # return to where we were - { - chdir File::Spec->updir(); - } -} - -sub copy_include_files { - my ($config) = @_; - - my $include_dir = $$config{'build_include_botan'}; - - trace('Copying to ', $include_dir); - - foreach my $file (dir_list($include_dir)) { - my $path = File::Spec->catfile($include_dir, $file); - unlink $path or croak("Could not unlink $path ($!)"); - } - - my $link_up = sub { - my ($dir, $file) = @_; - my $updir = File::Spec->updir(); - portable_symlink(File::Spec->catfile($updir, $updir, $updir, - $dir, $file), - $include_dir, $file); - }; - - my $files = $$config{'includes'}; - - foreach my $file (keys %$files) { - &$link_up($$files{$file}, $file); - } -} - -sub dir_list { - my ($dir) = @_; - opendir(DIR, $dir) or croak("Couldn't read directory '$dir' ($!)"); - - my @listing = grep { !/#/ and -f File::Spec->catfile($dir, $_) and - $_ ne File::Spec->curdir() and - $_ ne File::Spec->updir() } readdir DIR; - - closedir DIR; - return @listing; -} - -sub mkdirs { - my (@dirs) = @_; - - my @created; - foreach my $dir (@dirs) { - next if( -e $dir and -d $dir ); # skip it if it's already there - mkdir($dir, 0777) or - croak("Could not create directory $dir ($!)"); - push @created, $dir; - } - return @created; -} - -sub slurp_file { - my $file = $_[0]; - - return '' if(!defined($file) or $file eq ''); - - croak("'$file': No such file") unless(-e $file); - croak("'$file': Not a regular file") unless(-f $file); - - open FILE, "<$file" or croak("Couldn't read $file ($!)"); - - my $output = ''; - while(<FILE>) { $output .= $_; } - close FILE; - - return $output; -} - -sub which -{ - my $file = $_[0]; - my @paths = split(/:/, $ENV{PATH}); - foreach my $path (@paths) - { - my $file_path = File::Spec->catfile($path, $file); - return $file_path if(-e $file_path and -r $file_path); - } - return ''; -} - -# Return a hash mapping every var in a list to a constant value -sub map_to { - my $var = shift; - return map { $_ => $var } @_; -} - -sub in_array { - my($target, $array) = @_; - return 0 unless defined($array); - foreach (@$array) { return 1 if($_ eq $target); } - return 0; -} - -sub add_to { - my ($to,$from) = @_; - - foreach my $key (keys %$from) { - $$to{$key} = $$from{$key}; - } -} - -################################################## -# # -################################################## -sub find_mp_bits { - my(@modules_list) = @_; - my $mp_bits = 32; # default, good for most systems - - my $seen_mp_module = undef; - - foreach my $modname (sort keys %{$$config{'modules'}}) { - croak("Unknown module $modname") unless defined $MODULES{$modname}; - - next if $$config{'modules'}{$modname} < 0; - - my %modinfo = %{ $MODULES{$modname} }; - if($modinfo{'mp_bits'}) { - if(defined($seen_mp_module) and $modinfo{'mp_bits'} != $mp_bits) { - croak('Inconsistent mp_bits requests from modules ', - $seen_mp_module, ' and ', $modname); - } - - $seen_mp_module = $modname; - $mp_bits = $modinfo{'mp_bits'}; - } - } - return $mp_bits; -} - -################################################## -# # -################################################## -sub realname { - my $arg = $_[0]; - - return $COMPILER{$arg}{'realname'} - if defined $COMPILER{$arg}; - - return $OPERATING_SYSTEM{$arg}{'realname'} - if defined $OPERATING_SYSTEM{$arg}; - - return $CPU{$arg}{'realname'} - if defined $CPU{$arg}; - - return $arg; -} - -################################################## -# # -################################################## - -sub load_module { - my ($config, $modname) = @_; - - #trace("load_module($modname)"); - - croak("Unknown module $modname") unless defined($MODULES{$modname}); - - my %module = %{$MODULES{$modname}}; - - my $works_on = sub { - my ($what, $lst_ref) = @_; - my @lst = @{$lst_ref}; - return 1 if not @lst; # empty list -> no restrictions - return 1 if $what eq 'generic'; # trust the user - return in_array($what, \@lst); - }; - - # Check to see if everything is OK WRT system requirements - my $os = $$config{'os'}; - - croak("Module '$modname' does not run on $os") - unless(&$works_on($os, $module{'os'})); - - my $arch = $$config{'arch'}; - my $sub = $$config{'submodel'}; - - croak("Module '$modname' does not run on $arch/$sub") - unless(&$works_on($arch, $module{'arch'}) or - &$works_on($sub, $module{'arch'})); - - my $cc = $$config{'compiler'}; - - croak("Module '$modname' does not work with $cc") - unless(&$works_on($cc, $module{'cc'})); - - my $handle_files = sub { - my($lst, $func) = @_; - return unless defined($lst); - - foreach (sort @$lst) { - &$func($module{'moddirs'}, $config, $_); - } - }; - - &$handle_files($module{'ignore'}, \&ignore_file); - &$handle_files($module{'add'}, \&add_file); - &$handle_files($module{'replace'}, - sub { ignore_file(@_); add_file(@_); }); - - warning($modname, ': ', $module{'note'}) - if(defined($module{'note'})); -} - -sub load_modules { - my ($config) = @_; - - my @mod_names; - - foreach my $mod (sort keys %{$$config{'modules'}}) { - next unless($$config{'modules'}{$mod} > 0); - - load_module($config, $mod); - - push @mod_names, $mod; - } - - $$config{'mod_list'} = join("\n", @mod_names); - - my $unaligned_ok = 0; - - my $target_os_defines = sub { - my @macro_list; - - my $os = $$config{'os'}; - if($os ne 'generic') { - push @macro_list, '#define BOTAN_TARGET_OS_IS_' . uc $os; - - my @features = @{$OPERATING_SYSTEM{$os}{'target_features'}}; - - for my $feature (@features) { - push @macro_list, '#define BOTAN_TARGET_OS_HAS_' . uc $feature; - } - - } - return join("\n", @macro_list); - }; - - $$config{'target_os_defines'} = &$target_os_defines(); - - my $target_cpu_defines = sub { - my @macro_list; - - my $arch = $$config{'arch'}; - if($arch ne 'generic') { - my %cpu_info = %{$CPU{$arch}}; - my $endian = $cpu_info{'endian'}; - - if(defined($$config{'with_endian'})) { - $endian = $$config{'with_endian'}; - $endian = undef unless($endian eq 'little' || - $endian eq 'big'); - } - elsif(defined($endian)) { - autoconfig("Since arch is $arch, assuming $endian endian mode"); - } - - push @macro_list, "#define BOTAN_TARGET_ARCH_IS_" . (uc $arch); - - my $submodel = $$config{'submodel'}; - if($arch ne $submodel) { - $submodel = uc $submodel; - $submodel =~ tr/-/_/; - $submodel =~ tr/.//; - - push @macro_list, "#define BOTAN_TARGET_CPU_IS_$submodel"; - } - - if(defined($endian)) { - $endian = uc $endian; - push @macro_list, - "#define BOTAN_TARGET_CPU_IS_${endian}_ENDIAN"; - - # See if the user set --with-unaligned-mem - if(defined($$config{'with_unaligned_mem'})) { - my $spec = $$config{'with_unaligned_mem'}; - - if($spec eq 'yes') { - $unaligned_ok = 1; - } - elsif($spec eq 'no') { - $unaligned_ok = 0; - } - else { - warning('Unknown arg to --with-unaligned-mem (' . - $spec . ') will ignore'); - $unaligned_ok = 0; - } - } - # Otherwise, see if the CPU has a default setting - elsif(defined($cpu_info{'unaligned'}) and - $cpu_info{'unaligned'} eq 'ok') - { - autoconfig("Since arch is $arch, " . - 'assuming unaligned memory access is OK'); - $unaligned_ok = 1; - } - } - } - - # variable is always set (one or zero) - push @macro_list, - "#define BOTAN_TARGET_UNALIGNED_LOADSTOR_OK $unaligned_ok"; - return join("\n", @macro_list); - }; - - $$config{'target_cpu_defines'} = &$target_cpu_defines(); - - my $target_compiler_defines = sub { - my @macro_list; - - if(defined($$config{'tr1'})) { - my $tr1 = $$config{'tr1'}; - - if($tr1 eq 'system') { - push @macro_list, '#define BOTAN_USE_STD_TR1'; - } - elsif($tr1 eq 'boost') { - push @macro_list, '#define BOTAN_USE_BOOST_TR1'; - } - elsif($tr1 ne 'none') { - croak("Unknown --with-tr1= option value '$tr1' (try --help)"); - } - } - - return join("\n", @macro_list); - }; - - $$config{'target_compiler_defines'} = &$target_compiler_defines(); - - my $gen_defines = sub { - my @macro_list; - - my %defines; - - foreach my $mod (sort keys %{$$config{'modules'}}) { - next unless $$config{'modules'}{$mod} > 0; - - my $defs = $MODULES{$mod}{'define'}; - next unless $defs; - - push @{$defines{$MODULES{$mod}{'type'}}}, split(/,/, $defs); - } - - foreach my $type (sort keys %defines) { - push @macro_list, "\n/* $type */"; - - for my $macro (@{$defines{$type}}) { - die unless(defined $macro and $macro ne ''); - push @macro_list, "#define BOTAN_HAS_$macro"; - } - } - - return join("\n", @macro_list); - }; - - $$config{'module_defines'} = &$gen_defines(); -} - -################################################## -# # -################################################## -sub file_type { - my ($file) = @_; - - return 'sources' - if($file =~ /\.cpp$/ or $file =~ /\.c$/ or $file =~ /\.S$/); - return 'includes' if($file =~ /\.h$/); - - croak('file_type() - don\'t know what sort of file ', $file, ' is'); -} - -sub add_file { - my ($mod_dir, $config, $file) = @_; - - check_for_file($config, $file, $mod_dir, $mod_dir); - - my $do_add_file = sub { - my ($type) = @_; - - croak("File $file already added from ", $$config{$type}{$file}) - if(defined($$config{$type}{$file})); - - if($file =~ /(.*):(.*)/) { - my @dirs = File::Spec->splitdir($mod_dir); - - $dirs[$#dirs-1] = $1; - - $$config{$type}{$2} = File::Spec->catdir(@dirs); - } - else { - $$config{$type}{$file} = $mod_dir; - } - }; - - &$do_add_file(file_type($file)); -} - -sub ignore_file { - my ($mod_dir, $config, $file) = @_; - check_for_file($config, $file, undef, $mod_dir); - - my $do_ignore_file = sub { - my ($type, $ok_if_from) = @_; - - if(defined ($$config{$type}{$file})) { - - croak("$mod_dir - File $file modified from ", - $$config{$type}{$file}) - if($$config{$type}{$file} ne $ok_if_from); - - delete $$config{$type}{$file}; - } - }; - - &$do_ignore_file(file_type($file)); -} - -sub check_for_file { - my ($config, $file, $added_from, $mod_dir) = @_; - - #trace("check_for_file($file, $added_from, $mod_dir)"); - - my $full_path = sub { - my ($file,$mod_dir) = @_; - - if($file =~ /(.*):(.*)/) { - return File::Spec->catfile($mod_dir, '..', $1, $2); - } else { - return File::Spec->catfile($mod_dir, $file) if(defined($mod_dir)); - - my @typeinfo = file_type($config, $file); - return File::Spec->catfile($typeinfo[1], $file); - } - }; - - $file = &$full_path($file, $added_from); - - croak("Module $mod_dir requires that file $file exist. This error\n ", - 'should never occur; please contact the maintainers with details.') - unless(-e $file); -} - -################################################## -# # -################################################## -sub process_template { - my ($in, $out, $config) = @_; - - trace("process_template: $in -> $out"); - - my $contents = slurp_file($in); - - foreach my $name (keys %$config) { - my $val = $$config{$name}; - - unless(defined $val) { - trace("Undefined variable $name in $in"); - next; - } - - $contents =~ s/\%\{$name\}/$val/g; - } - - if($contents =~ /\%\{([a-z_]*)\}/) { - - sub summarize { - my ($n, $s) = @_; - - $s =~ s/\n/\\n/; # escape newlines - - return $s if(length($s) <= $n); - - return substr($s, 0, 57) . '...'; - } - - foreach my $key (sort keys %$config) { - print with_diagnostic("debug", - "In %config:", $key, " -> ", - summarize(60, $$config{$key})); - } - - croak("Unbound variable '$1' in $in"); - } - - open OUT, ">$out" or croak("Couldn't write $out ($!)"); - print OUT $contents; - close OUT; -} - -################################################## -# # -################################################## -sub read_list { - my ($line, $reader, $marker, $func) = @_; - - if($line =~ m@^<$marker>$@) { - while(1) { - $line = &$reader(); - - die "EOF while searching for $marker" unless $line; - last if($line =~ m@^</$marker>$@); - &$func($line); - } - } -} - -sub list_push { - my ($listref) = @_; - return sub { push @$listref, $_[0]; } -} - -sub match_any_of { - my ($line, $hash, $quoted, @any_of) = @_; - - $quoted = ($quoted eq 'quoted') ? 1 : 0; - - foreach my $what (@any_of) { - $$hash{$what} = $1 if(not $quoted and $line =~ /^$what (.*)/); - $$hash{$what} = $1 if($quoted and $line =~ /^$what \"(.*)\"/); - } -} - -################################################## -# # -################################################## -sub make_reader { - my $filename = $_[0]; - - croak("make_reader(): Arg was undef") if not defined $filename; - - open FILE, "<$filename" or - croak("Couldn't read $filename ($!)"); - - return sub { - my $line = ''; - while(1) { - my $line = <FILE>; - last unless defined($line); - - chomp($line); - $line =~ s/#.*//; - $line =~ s/^\s*//; - $line =~ s/\s*$//; - $line =~ s/\s\s*/ /; - $line =~ s/\t/ /; - return $line if $line ne ''; - } - close FILE; - return undef; - } -} - -################################################## -# # -################################################## -sub read_info_files { - my ($config, $dir, $func) = @_; - - $dir = File::Spec->catdir($$config{'config-dir'}, $dir); - - my %allinfo; - foreach my $file (dir_list($dir)) { - my $fullpath = File::Spec->catfile($dir, $file); - - $file =~ s/.txt//; - - trace("reading $fullpath"); - %{$allinfo{$file}} = &$func($file, $fullpath); - } - - return %allinfo; -} - -sub read_module_files { - my ($config) = @_; - - my %allinfo; - - my @modinfos; - - File::Find::find( - { wanted => sub - { if(-f $_ && /^info\.txt\z/s) { - my $name = $File::Find::name; - push @modinfos, $name; - } - } - }, - $$config{'src-dir'}); - - foreach my $modfile (@modinfos) { - trace("reading $modfile"); - - my ($volume,$dirs,$file) = File::Spec->splitpath($modfile); - - my @dirs = File::Spec->splitdir($dirs); - my $moddir = $dirs[$#dirs-1]; - - trace("module $moddir in $dirs $modfile"); - - %{$allinfo{$moddir}} = get_module_info($dirs, $moddir, $modfile); - } - - return %allinfo; -} - -################################################## -# # -################################################## - -sub get_module_info { - my ($dirs, $name, $modfile) = @_; - my $reader = make_reader($modfile); - - my %info; - - $info{'name'} = $name; - $info{'modinfo'} = $modfile; - $info{'moddirs'} = $dirs; - - # Default module settings - $info{'load_on'} = 'request'; # default unless specified - $info{'uses_tr1'} = 'no'; - $info{'libs'} = {}; - $info{'use'} = 'no'; - - my @dir_arr = File::Spec->splitdir($dirs); - $info{'type'} = $dir_arr[$#dir_arr-2]; # cipher, hash, ... - if($info{'type'} eq 'src') { $info{'type'} = $dir_arr[$#dir_arr-1]; } - - while($_ = &$reader()) { - match_any_of($_, \%info, 'quoted', 'realname', 'note', 'type'); - match_any_of($_, \%info, 'unquoted', 'define', 'mp_bits', - 'modset', 'load_on', 'uses_tr1'); - - read_list($_, $reader, 'arch', list_push(\@{$info{'arch'}})); - read_list($_, $reader, 'cc', list_push(\@{$info{'cc'}})); - read_list($_, $reader, 'os', list_push(\@{$info{'os'}})); - read_list($_, $reader, 'add', list_push(\@{$info{'add'}})); - read_list($_, $reader, 'replace', list_push(\@{$info{'replace'}})); - read_list($_, $reader, 'ignore', list_push(\@{$info{'ignore'}})); - read_list($_, $reader, 'requires', list_push(\@{$info{'requires'}})); - - read_list($_, $reader, 'libs', - sub { - my $line = $_[0]; - $line =~ m/^([\w!,]*) -> ([\w.,-]*)$/; - $info{'libs'}{$1} = $2; - }); - - if(/^require_version /) { - if(/^require_version (\d+)\.(\d+)\.(\d+)$/) { - my $version = "$1.$2.$3"; - my $needed_version = 100*$1 + 10*$2 + $3; - - my $have_version = - 100*$MAJOR_VERSION + 10*$MINOR_VERSION + $PATCH_VERSION; - - if($needed_version > $have_version) { - warning("Module $name needs v$version; disabling"); - return (); - } - } - else { - croak("In module $name, bad version requirement '$_'"); - } - } - } - - return %info; -} - -################################################## -# # -################################################## -sub get_arch_info { - my ($name,$file) = @_; - my $reader = make_reader($file); - - my %info; - $info{'name'} = $name; - - while($_ = &$reader()) { - match_any_of($_, \%info, 'quoted', 'realname'); - match_any_of($_, \%info, 'unquoted', - 'default_submodel', 'endian', 'unaligned'); - - read_list($_, $reader, 'aliases', list_push(\@{$info{'aliases'}})); - read_list($_, $reader, 'submodels', list_push(\@{$info{'submodels'}})); - - read_list($_, $reader, 'submodel_aliases', - sub { - my $line = $_[0]; - $line =~ m/^(\S*) -> (\S*)$/; - $info{'submodel_aliases'}{$1} = $2; - }); - } - return %info; -} - -################################################## -# # -################################################## -sub get_os_info { - my ($name,$file) = @_; - my $reader = make_reader($file); - - my %info; - $info{'name'} = $name; - - while($_ = &$reader()) { - match_any_of($_, \%info, - 'quoted', 'realname', 'ar_command', - 'install_cmd_data', 'install_cmd_exec'); - - match_any_of($_, \%info, 'unquoted', - 'os_type', - 'obj_suffix', - 'so_suffix', - 'static_suffix', - 'install_root', - 'header_dir', - 'lib_dir', 'doc_dir', - 'ar_needs_ranlib'); - - read_list($_, $reader, 'aliases', list_push(\@{$info{'aliases'}})); - - read_list($_, $reader, 'target_features', - list_push(\@{$info{'target_features'}})); - - read_list($_, $reader, 'supports_shared', - list_push(\@{$info{'supports_shared'}})); - } - return %info; -} - -################################################## -# Read a file from misc/config/cc and set the values from -# there into a hash for later reference -################################################## -sub get_cc_info { - my ($name,$file) = @_; - my $reader = make_reader($file); - - my %info; - $info{'name'} = $name; - - while($_ = &$reader()) { - match_any_of($_, \%info, 'quoted', - 'realname', - 'binary_name', - 'compile_option', - 'output_to_option', - 'add_include_dir_option', - 'add_lib_dir_option', - 'add_lib_option', - 'lib_opt_flags', - 'check_opt_flags', - 'dll_import_flags', - 'dll_export_flags', - 'lang_flags', - 'warning_flags', - 'shared_flags', - 'ar_command', - 'debug_flags', - 'no_debug_flags'); - - match_any_of($_, \%info, 'unquoted', - 'makefile_style', - 'compiler_has_tr1'); - - sub quoted_mapping { - my $hashref = $_[0]; - return sub { - my $line = $_[0]; - $line =~ m/^(\S*) -> \"(.*)\"$/; - $$hashref{$1} = $2; - } - } - - read_list($_, $reader, 'mach_abi_linking', - quoted_mapping(\%{$info{'mach_abi_linking'}})); - read_list($_, $reader, 'so_link_flags', - quoted_mapping(\%{$info{'so_link_flags'}})); - - read_list($_, $reader, 'mach_opt', - sub { - my $line = $_[0]; - $line =~ m/^(\S*) -> \"(.*)\" ?(.*)?$/; - $info{'mach_opt_flags'}{$1} = $2; - $info{'mach_opt_re'}{$1} = $3; - }); - - } - return %info; -} - -################################################## -# # -################################################## -sub write_pkg_config { - my ($config) = @_; - - return if($$config{'os'} eq 'generic' or - $$config{'os'} eq 'windows'); - - $$config{'link_to'} = libs('-l', '', 'm', @{$$config{'mod_libs'}}); - - my $botan_config = $$config{'botan_config'}; - - process_template( - File::Spec->catfile($$config{'config-dir'}, 'botan-config.in'), - $botan_config, $config); - chmod 0755, $botan_config; - - process_template( - File::Spec->catfile($$config{'config-dir'}, 'botan.pc.in'), - $$config{'botan_pkgconfig'}, $config); - - delete $$config{'link_to'}; -} - -################################################## -# # -################################################## -sub file_list { - my ($put_in, $from, $to, %files) = @_; - - my $list = ''; - - my $spaces = 16; - - foreach (sort keys %files) { - my $file = $_; - - $file =~ s/$from/$to/ if(defined($from) and defined($to)); - - my $dir = $files{$_}; - $dir = $put_in if defined $put_in; - - if(defined($dir)) { - $list .= File::Spec->catfile ($dir, $file); - } - else { - $list .= $file; - } - - $list .= " \\\n "; - } - - $list =~ s/\\\n +$//; # remove trailing escape - - return $list; -} - -sub build_cmds { - my ($config, $dir, $flags, $files) = @_; - - my $obj_suffix = $$config{'obj_suffix'}; - - my %ccinfo = my_compiler($config); - - my $inc = $ccinfo{'add_include_dir_option'}; - my $from = $ccinfo{'compile_option'}; - my $to = $ccinfo{'output_to_option'}; - - my $inc_dir = $$config{'build_include'}; - - # Probably replace by defaults to -I -c -o - croak('undef value found in build_cmds') - unless defined($inc) and defined($from) and defined($to); - - my $bld_line = "\t\$(CXX) $inc$inc_dir $flags $from\$? $to\$@"; - - my @output_lines; - - foreach (sort keys %$files) { - my $src_file = File::Spec->catfile($$files{$_}, $_); - my $obj_file = File::Spec->catfile($dir, $_); - - $obj_file =~ s/\.cpp$/.$obj_suffix/; - $obj_file =~ s/\.c$/.$obj_suffix/; - $obj_file =~ s/\.S$/.$obj_suffix/; - - push @output_lines, "$obj_file: $src_file\n$bld_line"; - } - - return join("\n\n", @output_lines); -} - -sub determine_config { - my ($config) = @_; - - sub os_ar_command { - return os_info_for(shift, 'ar_command'); - } - - sub append_if { - my($var,$addme,$cond) = @_; - - croak('append_if: reference was undef') unless defined $var; - - if($cond and $addme ne '') { - $$var .= ' ' unless($$var eq '' or $$var =~ / $/); - $$var .= $addme; - } - } - - sub append_ifdef { - my($var,$addme) = @_; - append_if($var, $addme, defined($addme)); - } - - my $empty_if_nil = sub { - my $val = $_[0]; - return $val if defined($val); - return ''; - }; - - my %ccinfo = my_compiler($config); - - my $lang_flags = ''; - append_ifdef(\$lang_flags, $ccinfo{'lang_flags'}); - append_if(\$lang_flags, "-fpermissive", $$config{'gcc_bug'}); - - my $debug = $$config{'debug'}; - - my $lib_opt_flags = ''; - append_ifdef(\$lib_opt_flags, $ccinfo{'lib_opt_flags'}); - append_ifdef(\$lib_opt_flags, $ccinfo{'debug_flags'}) if($debug); - append_ifdef(\$lib_opt_flags, $ccinfo{'no_debug_flags'}) if(!$debug); - - # This is a default that works on most Unix and Unix-like systems - my $ar_command = 'ar crs'; - my $ranlib_command = 'true'; # almost no systems need it anymore - - # See if there are any over-riding methods. We presume if CC is creating - # the static libs, it knows how to create the index itself. - - my $os = $$config{'os'}; - - if($ccinfo{'ar_command'}) { - $ar_command = $ccinfo{'ar_command'}; - } - elsif(os_ar_command($os)) - { - $ar_command = os_ar_command($os); - $ranlib_command = 'ranlib' - if(os_info_for($os, 'ar_needs_ranlib') eq 'yes'); - } - - my $arch = $$config{'arch'}; - - my $abi_opts = ''; - append_ifdef(\$abi_opts, $ccinfo{'mach_abi_linking'}{$arch}); - append_ifdef(\$abi_opts, $ccinfo{'mach_abi_linking'}{$os}); - append_ifdef(\$abi_opts, $ccinfo{'mach_abi_linking'}{'all'}); - $abi_opts = ' ' . $abi_opts if($abi_opts ne ''); - - if($$config{'shared'} eq 'yes' and - (in_array('all', $OPERATING_SYSTEM{$os}{'supports_shared'}) or - in_array($$config{'compiler'}, - $OPERATING_SYSTEM{$os}{'supports_shared'}))) { - - $$config{'shared_flags'} = &$empty_if_nil($ccinfo{'shared_flags'}); - $$config{'so_link'} = &$empty_if_nil($ccinfo{'so_link_flags'}{$os}); - - if($$config{'so_link'} eq '') { - $$config{'so_link'} = - &$empty_if_nil($ccinfo{'so_link_flags'}{'default'}) - } - - if($$config{'shared_flags'} eq '' and $$config{'so_link'} eq '') { - $$config{'shared'} = 'no'; - - warning($$config{'compiler'}, ' has no shared object flags set ', - "for $os; disabling shared"); - } - } - else { - autoconfig("No shared library generated with " . - $$config{'compiler'} . " on " . $$config{'os'}); - - $$config{'shared'} = 'no'; - $$config{'shared_flags'} = ''; - $$config{'so_link'} = ''; - } - - add_to($config, { - 'cc' => $ccinfo{'binary_name'} . $abi_opts, - 'lib_opt' => $lib_opt_flags, - 'check_opt' => &$empty_if_nil($ccinfo{'check_opt_flags'}), - 'mach_opt' => mach_opt($config), - 'lang_flags' => $lang_flags, - 'warn_flags' => &$empty_if_nil($ccinfo{'warning_flags'}), - - 'ar_command' => $ar_command, - 'ranlib_command' => $ranlib_command, - 'static_suffix' => os_info_for($os, 'static_suffix'), - 'so_suffix' => os_info_for($os, 'so_suffix'), - 'obj_suffix' => os_info_for($os, 'obj_suffix'), - - 'dll_export_flags' => $ccinfo{'dll_export_flags'}, - 'dll_import_flags' => $ccinfo{'dll_import_flags'}, - - 'install_cmd_exec' => os_info_for($os, 'install_cmd_exec'), - 'install_cmd_data' => os_info_for($os, 'install_cmd_data'), - }); -} - -sub generate_makefile { - my ($config) = @_; - - my $is_in_doc_dir = - sub { -e File::Spec->catfile($$config{'doc_src_dir'}, $_[0]) }; - - my $docs = file_list(undef, undef, undef, - map_to($$config{'doc_src_dir'}, - grep { &$is_in_doc_dir($_); } @DOCS)); - - $docs .= File::Spec->catfile($$config{'base-dir'}, 'readme.txt'); - - my $includes = file_list(undef, undef, undef, - map_to($$config{'build_include_botan'}, - keys %{$$config{'includes'}})); - - my $lib_objs = file_list($$config{'build_lib'}, '(\.cpp$|\.c$|\.S$)', - '.' . $$config{'obj_suffix'}, - %{$$config{'sources'}}); - - my $check_objs = file_list($$config{'build_check'}, '.cpp', - '.' . $$config{'obj_suffix'}, - %{$$config{'check_src'}}), - - my $lib_build_cmds = build_cmds($config, $$config{'build_lib'}, - '$(LIB_FLAGS)', $$config{'sources'}); - - my $check_build_cmds = build_cmds($config, $$config{'build_check'}, - '$(CHECK_FLAGS)', $$config{'check_src'}); - - add_to($config, { - 'lib_objs' => $lib_objs, - 'check_objs' => $check_objs, - 'lib_build_cmds' => $lib_build_cmds, - 'check_build_cmds' => $check_build_cmds, - - 'doc_files' => $docs, - 'include_files' => $includes - }); - - my $template_dir = File::Spec->catdir($$config{'config-dir'}, 'makefile'); - my $template = undef; - - my $make_style = $$config{'make_style'}; - - if($make_style eq 'unix') { - $template = File::Spec->catfile($template_dir, 'unix.in'); - - $template = File::Spec->catfile($template_dir, 'unix_shr.in') - if($$config{'shared'} eq 'yes'); - - add_to($config, { - 'link_to' => libs('-l', '', 'm', @{$$config{'mod_libs'}}), - }); - } - elsif($make_style eq 'nmake') { - $template = File::Spec->catfile($template_dir, 'nmake.in'); - - add_to($config, { - 'shared' => 'no', - 'link_to' => libs('', '', '', @{$$config{'mod_libs'}}), - }); - } - - croak("Don't know about makefile format '$make_style'") - unless defined $template; - - trace("'$make_style' -> '$template'"); - - process_template($template, $$config{'makefile'}, $config); - - autoconfig("Wrote ${make_style}-style makefile in $$config{'makefile'}"); -} - -################################################## -# Configuration Guessing # -################################################## -sub guess_cpu_from_this -{ - my $cpuinfo = lc $_[0]; - - $cpuinfo =~ s/\(r\)//g; - $cpuinfo =~ s/\(tm\)//g; - $cpuinfo =~ s/ //g; - - trace("guess_cpu_from_this($cpuinfo)"); - - # The 32-bit SPARC stuff is impossible to match to arch type easily, and - # anyway the uname stuff will pick up that it's a SPARC so it doesn't - # matter. If it's an Ultra, assume a 32-bit userspace, no 64-bit code - # possible; that's the most common setup right now anyway - return 'sparc32-v9' if($cpuinfo =~ /ultrasparc/); - - # Should probably do this once and cache it - my @names; - my %all_alias; - - foreach my $arch (keys %CPU) { - my %info = %{$CPU{$arch}}; - - foreach my $submodel (@{$info{'submodels'}}) { - push @names, $submodel; - } - - if(defined($info{'submodel_aliases'})) { - my %submodel_aliases = %{$info{'submodel_aliases'}}; - foreach my $sm_alias (keys %submodel_aliases) { - push @names, $sm_alias; - $all_alias{$sm_alias} = $submodel_aliases{$sm_alias}; - } - } - } - - @names = sort { length($b) <=> length($a) } @names; - - foreach my $name (@names) { - if($cpuinfo =~ $name) { - trace("Matched '$cpuinfo' against '$name'"); - - return $all_alias{$name} if defined($all_alias{$name}); - - return $name; - } - } - - trace("Couldn't match $cpuinfo against any submodels"); - - # No match? Try arch names. Reset @names - @names = (); - - foreach my $arch (keys %CPU) { - my %info = %{$CPU{$arch}}; - - push @names, $info{'name'}; - - foreach my $alias (@{$info{'aliases'}}) { - push @names, $alias; - } - } - - @names = sort { length($b) <=> length($a) } @names; - - foreach my $name (@names) { - if($cpuinfo =~ $name) { - trace("Matched '$cpuinfo' against '$name'"); - return $name; - } - } - - return ''; -} - -# Do some WAGing and see if we can figure out what system we are. Think about -# this as a really moronic config.guess -sub guess_compiler -{ - my @CCS = ('gcc', 'msvc', 'icc', 'compaq', 'kai'); - - # First try the CC enviornmental variable, if it's set - if(defined($ENV{CC})) - { - my @new_CCS = ($ENV{CC}); - foreach my $cc (@CCS) { push @new_CCS, $cc; } - @CCS = @new_CCS; - } - - foreach (@CCS) - { - my $bin_name = $COMPILER{$_}{'binary_name'}; - if(which($bin_name) ne '') { - autoconfig("Guessing to use $_ as the compiler " . - "(use --cc to set)"); - return $_; - } - } - - croak( - "Can't find a usable C++ compiler, is PATH right?\n" . - "You might need to run with the --cc option (try $0 --help)\n"); -} - -sub guess_os -{ - sub recognize_os - { - my $os = os_alias($_[0]); - if(defined($OPERATING_SYSTEM{$os})) { - autoconfig("Guessing operating system is $os (use --os to set)"); - return $os; - } - return undef; - } - - my $guess = recognize_os($^O); - return $guess if $guess; - - trace("Can't guess os from $^O"); - - my $uname = $$config{'uname'}; - - if($uname ne '') { - $guess = recognize_os($uname); - return $guess if $guess; - trace("Can't guess os from $uname"); - } - - warning("Unknown OS ('$^O', '$uname'), falling back to generic code"); - return 'generic'; -} - -sub guess_cpu -{ - # If we have /proc/cpuinfo, try to get nice specific information about - # what kind of CPU we're running on. - my $cpuinfo = '/proc/cpuinfo'; - - if(defined($ENV{'CPUINFO'})) { - my $cpuinfo_env = $ENV{'CPUINFO'}; - - if(-e $cpuinfo_env and -r $cpuinfo_env) { - autoconfig("Will use $cpuinfo_env as /proc/cpuinfo"); - $cpuinfo = $cpuinfo_env; - } else { - warn("Could not read from ENV /proc/cpuinfo ($cpuinfo_env)"); - } - } - - if(-e $cpuinfo and -r $cpuinfo) - { - open CPUINFO, $cpuinfo or die "Could not read $cpuinfo\n"; - - while(<CPUINFO>) { - - chomp; - $_ =~ s/\t/ /g; - $_ =~ s/ +/ /g; - - if($_ =~ /^cpu +: (.*)/ or - $_ =~ /^model name +: (.*)/) - { - my $cpu = guess_cpu_from_this($1); - if($cpu ne '') { - autoconfig("Guessing CPU using $cpuinfo line '$_'"); - autoconfig("Guessing CPU is a $cpu (use --cpu to set)"); - return $cpu; - } - } - } - - autoconfig("*** Could not figure out CPU based on $cpuinfo"); - autoconfig("*** Please mail contents to lloyd\@randombit.net"); - } - - sub known_arch { - my ($name) = @_; - - foreach my $arch (keys %CPU) { - my %info = %{$CPU{$arch}}; - - return 1 if $name eq $info{'name'}; - foreach my $submodel (@{$info{'submodels'}}) { - return 1 if $name eq $submodel; - } - - foreach my $alias (@{$info{'aliases'}}) { - return 1 if $name eq $alias; - } - - if(defined($info{'submodel_aliases'})) { - my %submodel_aliases = %{$info{'submodel_aliases'}}; - foreach my $sm_alias (keys %submodel_aliases) { - return 1 if $name eq $sm_alias; - } - } - } - - my $guess = guess_cpu_from_this($name); - - return 0 if($guess eq $name or $guess eq ''); - - return known_arch($guess); - } - - my $uname = $$config{'uname'}; - if($uname ne '') { - my $cpu = guess_cpu_from_this($uname); - - if($cpu ne '') - { - autoconfig("Guessing CPU using uname output '$uname'"); - autoconfig("Guessing CPU is a $cpu (use --cpu to set)"); - - return $cpu if known_arch($cpu); - } - } - - my $config_archname = $Config{'archname'}; - my $cpu = guess_cpu_from_this($config_archname); - - if($cpu ne '') - { - autoconfig("Guessing CPU using Config{archname} '$config_archname'"); - autoconfig("Guessing CPU is a $cpu (use --cpu to set)"); - - return $cpu if known_arch($cpu); - } - - warning("Could not determine CPU type (try --cpu option)"); - return 'generic'; -} diff --git a/doc/tutorial.tex b/doc/tutorial.tex index 9229cb853..4023ab20d 100644 --- a/doc/tutorial.tex +++ b/doc/tutorial.tex @@ -510,9 +510,7 @@ near future. In these examples, we punt on the problem, and hard-code using EMSA1 with SHA-256. \begin{verbatim} - PK_Signing_Key* key = dynamic_cast<PK_Signing_Key*>(privkey); - if(!key) - error(); + Public_Key* key = /* loaded or generated somehow */ PK_Signer* signer = get_pk_signer(*key, "EMSA1(SHA-256)"); byte msg[] = { /* ... */ }; diff --git a/src/asn1/asn1_oid.cpp b/src/asn1/asn1_oid.cpp index 425df645c..4f2c70231 100644 --- a/src/asn1/asn1_oid.cpp +++ b/src/asn1/asn1_oid.cpp @@ -20,7 +20,15 @@ OID::OID(const std::string& oid_str) { if(oid_str != "") { - id = parse_asn1_oid(oid_str); + try + { + id = parse_asn1_oid(oid_str); + } + catch(...) + { + throw Invalid_OID(oid_str); + } + if(id.size() < 2 || id[0] > 2) throw Invalid_OID(oid_str); if((id[0] == 0 || id[0] == 1) && id[1] > 39) diff --git a/src/build-data/buildh.in b/src/build-data/buildh.in index 6412d8a6a..724801040 100644 --- a/src/build-data/buildh.in +++ b/src/build-data/buildh.in @@ -20,7 +20,6 @@ #define BOTAN_MP_WORD_BITS %{mp_bits} #define BOTAN_KARAT_MUL_THRESHOLD 32 #define BOTAN_KARAT_SQR_THRESHOLD 32 -#define BOTAN_PRIVATE_KEY_OP_BLINDING_BITS 64 /* PK key consistency checking toggles */ #define BOTAN_PUBLIC_KEY_STRONG_CHECKS_ON_LOAD 1 diff --git a/src/build-data/cc/gcc.txt b/src/build-data/cc/gcc.txt index 1b9f51620..14701718c 100644 --- a/src/build-data/cc/gcc.txt +++ b/src/build-data/cc/gcc.txt @@ -10,7 +10,7 @@ add_lib_option -l lang_flags "-ansi -std=c++0x" warning_flags "-W -Wall" -#warning_flags "-Wextra -Wall -Wstrict-aliasing -Wstrict-overflow=5 -Wcast-align -Wmissing-declarations -Wno-unused-parameter" +#warning_flags "-Werror -Wextra -Wall -Wstrict-aliasing -Wstrict-overflow=5 -Wcast-align -Wmissing-declarations -Wno-unused-parameter" lib_opt_flags "-O3" check_opt_flags "-O2" diff --git a/src/build-data/cc/msvc.txt b/src/build-data/cc/msvc.txt index 36437e6a2..df8d94671 100644 --- a/src/build-data/cc/msvc.txt +++ b/src/build-data/cc/msvc.txt @@ -14,7 +14,7 @@ check_opt_flags "/O2 /D_CONSOLE" lang_flags "/EHsc /GR" warning_flags "/W3" -shared_flags "/DBOTAN_DLL=__declspec(dllexport)" +shared_flags "/DBOTAN_DLL=__declspec(dllexport) /wd4275" dll_import_flags "__declspec(dllimport)" ar_command lib diff --git a/src/build-data/makefile/nmake.in b/src/build-data/makefile/nmake.in index 2d89850fd..212825131 100644 --- a/src/build-data/makefile/nmake.in +++ b/src/build-data/makefile/nmake.in @@ -64,7 +64,11 @@ $(CHECK): $(LIBRARIES) $(CHECKOBJS) $(CXX) /Fe$@ $(CHECKOBJS) $(BOTAN_LIB) $(LINK_TO) $(BOTAN_LIB): $(LIBOBJS) +!If "$(SO_OBJ_FLAGS)" == "" + $(AR) /OUT:$(BOTAN_LIB) $(LIBOBJS) +!Else $(LIB_LINK_CMD) /Fe$(LIBNAME) $(LIBOBJS) $(LINK_TO) +!Endif ### Fake Targets clean: @@ -73,7 +77,9 @@ clean: distclean: clean $(RM_R) %{build_dir} - $(RMDIR) %{build_dir}\include\botan %{build_dir}\include + $(RMDIR) %{build_dir}\include\botan\internal + $(RMDIR) %{build_dir}\include\botan + $(RMDIR) %{build_dir}\include $(RMDIR) %{build_dir}\lib %{build_dir}\checks $(RMDIR) %{build_dir} $(RM) Makefile $(LIBNAME).* $(CHECK).* diff --git a/src/build-data/makefile/python.in b/src/build-data/makefile/python.in index 9658c70ce..d3b4a122b 100644 --- a/src/build-data/makefile/python.in +++ b/src/build-data/makefile/python.in @@ -6,17 +6,15 @@ PYTHON_SITE_PACKAGE_DIR = /usr/lib/python%{python_version}/site-packages/ PYTHON_FLAGS = -Isrc/wrap/python -Os -fPIC -ftemplate-depth-255 -Wall -Wno-unused $(PYTHON_INC) -PYTHON_OBJS = %{python_objs} +BOTAN_PYTHON_MODDIR = %{python_obj_dir} -BOTAN_PYTHON_MODDIR = build/botan-python +PYTHON_OBJS = %{python_objs} all: $(BOTAN_PYTHON_MODDIR)/_botan.so %{python_build_cmds} $(BOTAN_PYTHON_MODDIR)/_botan.so: $(PYTHON_OBJS) - rm -rf $(BOTAN_PYTHON_MODDIR) - mkdir $(BOTAN_PYTHON_MODDIR) cp src/wrap/python/*.py $(BOTAN_PYTHON_MODDIR) $(CXX) -shared -o $@ $(PYTHON_OBJS) -L. -L$(PYTHON_ROOT) -lbotan -lboost_python -Wl,-rpath-link,. -Wl,-soname,$@ @@ -25,5 +23,5 @@ clean: install: mkdir -p $(PYTHON_SITE_PACKAGE_DIR)/botan - cp $(BOTAN_PYTHON_MODDIR)/* $(PYTHON_SITE_PACKAGE_DIR)/botan + cp $(BOTAN_PYTHON_MODDIR)/_botan.so $(BOTAN_PYTHON_MODDIR)/*.py $(PYTHON_SITE_PACKAGE_DIR)/botan chmod -R u=rwX,go=rX $(PYTHON_SITE_PACKAGE_DIR)/botan diff --git a/src/cert/cvc/cvc_ado.cpp b/src/cert/cvc/cvc_ado.cpp index fd5b80f13..8c38e90ae 100644 --- a/src/cert/cvc/cvc_ado.cpp +++ b/src/cert/cvc/cvc_ado.cpp @@ -45,13 +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, - RandomNumberGenerator& rng) +MemoryVector<byte> EAC1_1_ADO::make_signed(PK_Signer& signer, + const MemoryRegion<byte>& tbs_bits, + RandomNumberGenerator& rng) { - SecureVector<byte> concat_sig = - EAC1_1_obj<EAC1_1_ADO>::make_signature(signer, tbs_bits, rng); + SecureVector<byte> concat_sig = signer.sign_message(tbs_bits, rng); return DER_Encoder() .start_cons(ASN1_Tag(7), APPLICATION) diff --git a/src/cert/cvc/cvc_ado.h b/src/cert/cvc/cvc_ado.h index 100888d29..230ee8b8d 100644 --- a/src/cert/cvc/cvc_ado.h +++ b/src/cert/cvc/cvc_ado.h @@ -8,11 +8,8 @@ #ifndef BOTAN_EAC_CVC_ADO_H__ #define BOTAN_EAC_CVC_ADO_H__ -#include <botan/x509_key.h> -#include <botan/pubkey_enums.h> -#include <botan/pubkey.h> -#include <botan/ecdsa.h> #include <botan/eac_obj.h> +#include <botan/eac_asn_obj.h> #include <botan/cvc_req.h> #include <string> diff --git a/src/cert/cvc/cvc_ca.cpp b/src/cert/cvc/cvc_ca.cpp deleted file mode 100644 index af40fcd05..000000000 --- a/src/cert/cvc/cvc_ca.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#include <botan/cvc_ca.h> -#include <botan/cvc_cert.h> -#include <botan/der_enc.h> -#include <botan/oids.h> -namespace Botan { - -EAC1_1_CVC EAC1_1_CVC_CA::make_cert(PK_Signer& signer, - MemoryRegion<byte> const& public_key, - ASN1_Car const& car, - ASN1_Chr const& chr, - byte holder_auth_templ, - ASN1_Ced ced, - ASN1_Cex cex, - RandomNumberGenerator& rng) - { - OID chat_oid(OIDS::lookup("CertificateHolderAuthorizationTemplate")); - MemoryVector<byte> enc_chat_val; - enc_chat_val.append(holder_auth_templ); - - MemoryVector<byte> enc_cpi; - enc_cpi.append(0x00); - MemoryVector<byte> tbs = DER_Encoder() - .encode(enc_cpi, OCTET_STRING, ASN1_Tag(41), APPLICATION) // cpi - .encode(car) - .raw_bytes(public_key) - .encode(chr) - .start_cons(ASN1_Tag(76), APPLICATION) - .encode(chat_oid) - .encode(enc_chat_val, OCTET_STRING, ASN1_Tag(19), APPLICATION) - .end_cons() - .encode(ced) - .encode(cex) - .get_contents(); - - MemoryVector<byte> signed_cert = - EAC1_1_CVC::make_signed(signer, - EAC1_1_CVC::build_cert_body(tbs), - rng); - - DataSource_Memory source(signed_cert); - return EAC1_1_CVC(source); - } - -} diff --git a/src/cert/cvc/cvc_ca.h b/src/cert/cvc/cvc_ca.h deleted file mode 100644 index 87699808f..000000000 --- a/src/cert/cvc/cvc_ca.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -* EAC1.1 CVC Certificate Authority -* (C) 2007 FlexSecure GmbH -* 2008 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_CVC_CA_H__ -#define BOTAN_CVC_CA_H__ - -#include <botan/pkcs8.h> -#include <botan/pkcs10.h> -#include <botan/pubkey.h> -#include <botan/cvc_cert.h> - -namespace Botan { - -/** -* This class represents a CVC CA. -*/ -class BOTAN_DLL EAC1_1_CVC_CA - { - public: - - /** - * Create an arbitrary EAC 1.1 CVC. - * The desired key encoding must be set within the key (if applicable). - * @param signer the signer used to sign the certificate - * @param public_key the DER encoded public key to appear in - * the certificate - * @param car the CAR of the certificate - * @param chr the CHR of the certificate - * @param holder_auth_templ the holder authorization value byte to - * appear in the CHAT of the certificate - * @param ced the CED to appear in the certificate - * @param ced the CEX to appear in the certificate - */ - static EAC1_1_CVC make_cert(PK_Signer& signer, - MemoryRegion<byte> const& public_key, - ASN1_Car const& car, - ASN1_Chr const& chr, - byte holder_auth_templ, - ASN1_Ced ced, - ASN1_Cex cex, - RandomNumberGenerator& rng); - }; - -} - -#endif diff --git a/src/cert/cvc/cvc_cert.cpp b/src/cert/cvc/cvc_cert.cpp index 4274e143b..9cc2bb7e5 100644 --- a/src/cert/cvc/cvc_cert.cpp +++ b/src/cert/cvc/cvc_cert.cpp @@ -1,13 +1,12 @@ /* (C) 2007 FlexSecure GmbH - 2008 Jack Lloyd + 2008-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ #include <botan/cvc_cert.h> -#include <botan/cvc_key.h> -#include <botan/ecdsa.h> +#include <botan/oids.h> namespace Botan { @@ -58,21 +57,11 @@ void EAC1_1_CVC::force_decode() if(cpi != 0) throw Decoding_Error("EAC1_1 certificate's cpi was not 0"); - // FIXME: PK algos have no notion of EAC encoder/decoder currently -#if 0 - ECDSA_PublicKey tmp_pk; - std::unique_ptr<EAC1_1_CVC_Decoder> dec = tmp_pk.cvc_eac1_1_decoder(); - sig_algo = dec->public_key(enc_pk); + m_pk = decode_eac1_1_key(enc_pk, sig_algo); - - m_pk = tmp_pk; m_chat_val = enc_chat_val[0]; - self_signed = false; - if(m_car.iso_8859() == m_chr.iso_8859()) - { - self_signed= true; - } -#endif + + self_signed = (m_car.iso_8859() == m_chr.iso_8859()); } /* @@ -99,4 +88,48 @@ 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>&, + AlgorithmIdentifier&) + { + throw Internal_Error("decode_eac1_1_key: Unimplemented"); + return 0; + } + +EAC1_1_CVC make_cvc_cert(PK_Signer& signer, + MemoryRegion<byte> const& public_key, + ASN1_Car const& car, + ASN1_Chr const& chr, + byte holder_auth_templ, + ASN1_Ced ced, + ASN1_Cex cex, + RandomNumberGenerator& rng) + { + OID chat_oid(OIDS::lookup("CertificateHolderAuthorizationTemplate")); + MemoryVector<byte> enc_chat_val; + enc_chat_val.append(holder_auth_templ); + + MemoryVector<byte> enc_cpi; + enc_cpi.append(0x00); + MemoryVector<byte> tbs = DER_Encoder() + .encode(enc_cpi, OCTET_STRING, ASN1_Tag(41), APPLICATION) // cpi + .encode(car) + .raw_bytes(public_key) + .encode(chr) + .start_cons(ASN1_Tag(76), APPLICATION) + .encode(chat_oid) + .encode(enc_chat_val, OCTET_STRING, ASN1_Tag(19), APPLICATION) + .end_cons() + .encode(ced) + .encode(cex) + .get_contents(); + + MemoryVector<byte> signed_cert = + EAC1_1_CVC::make_signed(signer, + EAC1_1_CVC::build_cert_body(tbs), + rng); + + DataSource_Memory source(signed_cert); + return EAC1_1_CVC(source); + } + } diff --git a/src/cert/cvc/cvc_cert.h b/src/cert/cvc/cvc_cert.h index ae0c21d7b..12bc41a9c 100644 --- a/src/cert/cvc/cvc_cert.h +++ b/src/cert/cvc/cvc_cert.h @@ -9,14 +9,8 @@ #ifndef BOTAN_CVC_EAC_H__ #define BOTAN_CVC_EAC_H__ -#include <botan/x509_key.h> -#include <botan/pubkey_enums.h> -#include <botan/signed_obj.h> -#include <botan/pubkey.h> -#include <botan/ecdsa.h> -#include <botan/ecdsa_sig.h> -#include <botan/eac_obj.h> #include <botan/cvc_gen_cert.h> +#include <botan/ecdsa.h> #include <string> namespace Botan { @@ -70,7 +64,6 @@ class BOTAN_DLL EAC1_1_CVC : public EAC1_1_gen_CVC<EAC1_1_CVC>//Signed_Object virtual ~EAC1_1_CVC() {} private: void force_decode(); - friend class EAC1_1_CVC_CA; EAC1_1_CVC() {} ASN1_Car m_car; @@ -88,6 +81,34 @@ inline bool operator!=(EAC1_1_CVC const& lhs, EAC1_1_CVC const& rhs) return !(lhs == rhs); } +/** +* Create an arbitrary EAC 1.1 CVC. +* The desired key encoding must be set within the key (if applicable). +* @param signer the signer used to sign the certificate +* @param public_key the DER encoded public key to appear in +* the certificate +* @param car the CAR of the certificate +* @param chr the CHR of the certificate +* @param holder_auth_templ the holder authorization value byte to +* appear in the CHAT of the certificate +* @param ced the CED to appear in the certificate +* @param ced the CEX to appear in the certificate +*/ +EAC1_1_CVC BOTAN_DLL make_cvc_cert(PK_Signer& signer, + const MemoryRegion<byte>& public_key, + ASN1_Car const& car, + ASN1_Chr const& chr, + byte holder_auth_templ, + ASN1_Ced ced, + ASN1_Cex cex, + RandomNumberGenerator& rng); + +/** +* Decode an EAC encoding ECDSA key +*/ +BOTAN_DLL ECDSA_PublicKey* decode_eac1_1_key(const MemoryRegion<byte>& enc_key, + AlgorithmIdentifier& sig_algo); + } #endif diff --git a/src/cert/cvc/cvc_gen_cert.h b/src/cert/cvc/cvc_gen_cert.h index ab6e22ff0..8c3b1b989 100644 --- a/src/cert/cvc/cvc_gen_cert.h +++ b/src/cert/cvc/cvc_gen_cert.h @@ -1,7 +1,7 @@ /* * EAC1_1 general CVC * (C) 2008 Falko Strenzke -* 2008 Jack Lloyd +* 2008-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -9,13 +9,11 @@ #ifndef BOTAN_EAC_CVC_GEN_CERT_H__ #define BOTAN_EAC_CVC_GEN_CERT_H__ -#include <botan/x509_key.h> +#include <botan/eac_obj.h> #include <botan/eac_asn_obj.h> -#include <botan/pubkey_enums.h> -#include <botan/pubkey.h> #include <botan/ecdsa.h> -#include <botan/ecdsa_sig.h> -#include <string> +#include <botan/pubkey.h> +#include <memory> namespace Botan { @@ -23,7 +21,7 @@ namespace Botan { * This class represents TR03110 (EAC) v1.1 generalized CV Certificates */ template<typename Derived> -class BOTAN_DLL EAC1_1_gen_CVC : public EAC1_1_obj<Derived> // CRTP continuation from EAC1_1_obj +class EAC1_1_gen_CVC : public EAC1_1_obj<Derived> // CRTP continuation from EAC1_1_obj { friend class EAC1_1_obj<EAC1_1_gen_CVC>; @@ -78,11 +76,12 @@ class BOTAN_DLL EAC1_1_gen_CVC : public EAC1_1_obj<Derived> // CRTP continuation PK_Signer& signer, const MemoryRegion<byte>& tbs_bits, RandomNumberGenerator& rng); + virtual ~EAC1_1_gen_CVC<Derived>() - {} + { delete m_pk; } protected: - ECDSA_PublicKey m_pk; // public key + ECDSA_PublicKey* m_pk; ASN1_Chr m_chr; bool self_signed; @@ -102,12 +101,13 @@ template<typename Derived> bool EAC1_1_gen_CVC<Derived>::is_self_signed() const return self_signed; } -template<typename Derived> MemoryVector<byte> EAC1_1_gen_CVC<Derived>::make_signed( +template<typename Derived> +MemoryVector<byte> EAC1_1_gen_CVC<Derived>::make_signed( PK_Signer& signer, const MemoryRegion<byte>& tbs_bits, RandomNumberGenerator& rng) // static { - SecureVector<byte> concat_sig = EAC1_1_obj<Derived>::make_signature(signer, tbs_bits, rng); + SecureVector<byte> concat_sig = signer.sign_message(tbs_bits, rng); return DER_Encoder() .start_cons(ASN1_Tag(33), APPLICATION) @@ -117,9 +117,10 @@ template<typename Derived> MemoryVector<byte> EAC1_1_gen_CVC<Derived>::make_sign .get_contents(); } -template<typename Derived> std::unique_ptr<Public_Key> EAC1_1_gen_CVC<Derived>::subject_public_key() const +template<typename Derived> +std::unique_ptr<Public_Key> EAC1_1_gen_CVC<Derived>::subject_public_key() const { - return std::unique_ptr<Public_Key>(new ECDSA_PublicKey(m_pk)); + return std::unique_ptr<Public_Key>(new ECDSA_PublicKey(*m_pk)); } template<typename Derived> SecureVector<byte> EAC1_1_gen_CVC<Derived>::build_cert_body(MemoryRegion<byte> const& tbs) diff --git a/src/cert/cvc/cvc_key.h b/src/cert/cvc/cvc_key.h deleted file mode 100644 index a81660597..000000000 --- a/src/cert/cvc/cvc_key.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -* EAC CVC Public Key -* (C) 2008 FlexSecure Gmbh -* Falko Strenzke -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_EAC1_1_CVC_PUBLIC_KEY_H__ -#define BOTAN_EAC1_1_CVC_PUBLIC_KEY_H__ - -#include <botan/pipe.h> -#include <botan/pk_keys.h> -#include <botan/alg_id.h> - -namespace Botan { - -/** -* This class represents EAC 1.1 CVC public key encoders. -*/ -class BOTAN_DLL EAC1_1_CVC_Encoder - { - public: - /** - * Get the DER encoded CVC public key. - * @param alg_id the algorithm identifier to use in the encoding - * @return the DER encoded public key - */ - virtual MemoryVector<byte> - public_key(const AlgorithmIdentifier& enc) const = 0; - - virtual ~EAC1_1_CVC_Encoder() {} - }; - -/** -* This class represents EAC 1.1 CVC public key decoders. -*/ -class BOTAN_DLL EAC1_1_CVC_Decoder - { - public: - /** - * Decode a CVC public key. - * @param enc the DER encoded public key to decode - * @return the algorithm identifier found in the encoded public key - */ - virtual AlgorithmIdentifier const - public_key(const MemoryRegion<byte>& enc) = 0; - - virtual ~EAC1_1_CVC_Decoder() {} - }; -} - -#endif diff --git a/src/cert/cvc/cvc_req.cpp b/src/cert/cvc/cvc_req.cpp index 6df6157ad..0a33d4dca 100644 --- a/src/cert/cvc/cvc_req.cpp +++ b/src/cert/cvc/cvc_req.cpp @@ -1,19 +1,13 @@ /* (C) 2007 FlexSecure GmbH - 2008 Jack Lloyd + 2008-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ +#include <botan/cvc_req.h> #include <botan/cvc_cert.h> -#include <botan/der_enc.h> #include <botan/ber_dec.h> -#include <botan/pem.h> -#include <botan/parsing.h> -#include <botan/cvc_key.h> -#include <botan/oids.h> -#include <botan/look_pk.h> -#include <botan/cvc_req.h> namespace Botan { @@ -38,13 +32,7 @@ void EAC1_1_Req::force_decode() if(cpi != 0) throw Decoding_Error("EAC1_1 requests cpi was not 0"); - // FIXME: No EAC support in ECDSA -#if 0 - ECDSA_PublicKey tmp_pk; - std::unique_ptr<EAC1_1_CVC_Decoder> dec = tmp_pk.cvc_eac1_1_decoder(); - sig_algo = dec->public_key(enc_pk); - m_pk = tmp_pk; -#endif + m_pk = decode_eac1_1_key(enc_pk, sig_algo); } EAC1_1_Req::EAC1_1_Req(DataSource& in) diff --git a/src/cert/cvc/cvc_req.h b/src/cert/cvc/cvc_req.h index 2abc72c9a..1e8cea7f8 100644 --- a/src/cert/cvc/cvc_req.h +++ b/src/cert/cvc/cvc_req.h @@ -1,6 +1,7 @@ /* * EAC1_1 CVC Request * (C) 2008 Falko Strenzke +* 2010 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -8,10 +9,7 @@ #ifndef BOTAN_EAC_CVC_REQ_H__ #define BOTAN_EAC_CVC_REQ_H__ -#include <botan/x509_key.h> -#include <botan/pubkey_enums.h> #include <botan/cvc_gen_cert.h> -#include <botan/cvc_req.h> namespace Botan { @@ -21,7 +19,6 @@ namespace Botan { class BOTAN_DLL EAC1_1_Req : public EAC1_1_gen_CVC<EAC1_1_Req> { public: - friend class EAC1_1_Req_CA; friend class EAC1_1_ADO; friend class EAC1_1_obj<EAC1_1_Req>; diff --git a/src/cert/cvc/cvc_self.cpp b/src/cert/cvc/cvc_self.cpp index 1d06acd66..0c765347f 100644 --- a/src/cert/cvc/cvc_self.cpp +++ b/src/cert/cvc/cvc_self.cpp @@ -1,22 +1,16 @@ /* (C) 2007 FlexSecure GmbH - 2008 Jack Lloyd + 2008-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ #include <botan/cvc_self.h> -#include <botan/cvc_cert.h> -#include <botan/cvc_ca.h> -#include <botan/alg_id.h> -#include <botan/cvc_key.h> +#include <botan/ecc_key.h> +#include <botan/point_gfp.h> +#include <botan/time.h> #include <botan/oids.h> -#include <botan/look_pk.h> -#include <botan/cvc_req.h> -#include <botan/cvc_ado.h> -#include <chrono> #include <sstream> -#include <assert.h> namespace Botan { @@ -35,49 +29,73 @@ enum CHAT_values{ FINGERPRINT = 0x01 }; -std::string padding_and_hash_from_oid(OID const& oid) +void encode_eac_bigint(DER_Encoder& der, const BigInt& x, ASN1_Tag tag) { - std::string padding_and_hash = OIDS::lookup(oid); // use the hash - assert(padding_and_hash.substr(0,6) == "ECDSA/"); // can only be ECDSA for now - assert(padding_and_hash.find("/",0) == 5); - padding_and_hash.erase(0, padding_and_hash.find("/",0) + 1); - return padding_and_hash; + der.encode(BigInt::encode_1363(x, x.bytes()), OCTET_STRING, tag); } -std::string fixed_len_seqnr(u32bit seqnr, u32bit len) +MemoryVector<byte> eac_1_1_encoding(const EC_PublicKey* key, + const OID& sig_algo) { - std::stringstream ss; - std::string result; - ss << seqnr; - ss >> result; - if (result.size() > len) - { - throw Invalid_Argument("fixed_len_seqnr(): number too high to be encoded in provided length"); - } - while (result.size() < len) + if(key->domain_format() == EC_DOMPAR_ENC_OID) + throw Encoding_Error("CVC encoder: cannot encode parameters by OID"); + + const EC_Domain_Params& domain = key->domain(); + + // This is why we can't have nice things + + DER_Encoder enc; + enc.start_cons(ASN1_Tag(73), APPLICATION) + .encode(sig_algo); + + if(key->domain_format() == EC_DOMPAR_ENC_EXPLICIT) { - result.insert(0,"0"); + encode_eac_bigint(enc, domain.get_curve().get_p(), ASN1_Tag(1)); + encode_eac_bigint(enc, domain.get_curve().get_a(), ASN1_Tag(2)); + encode_eac_bigint(enc, domain.get_curve().get_b(), ASN1_Tag(3)); + + enc.encode(EC2OSP(domain.get_base_point(), PointGFp::UNCOMPRESSED), + OCTET_STRING, ASN1_Tag(4)); + + encode_eac_bigint(enc, domain.get_order(), ASN1_Tag(4)); } - return result; + + enc.encode(EC2OSP(key->public_point(), PointGFp::UNCOMPRESSED), + OCTET_STRING, ASN1_Tag(6)); + + if(key->domain_format() == EC_DOMPAR_ENC_EXPLICIT) + encode_eac_bigint(enc, domain.get_cofactor(), ASN1_Tag(7)); + + enc.end_cons(); + + return enc.get_contents(); + } + +std::string padding_and_hash_from_oid(OID const& oid) + { + std::string padding_and_hash = OIDS::lookup(oid); // use the hash + + if(padding_and_hash.substr(0,6) != "ECDSA/") + throw Invalid_State("CVC: Can only use ECDSA, not " + padding_and_hash); + + padding_and_hash.erase(0, padding_and_hash.find("/") + 1); + return padding_and_hash; } } -namespace CVC_EAC -{ + +namespace CVC_EAC { EAC1_1_CVC create_self_signed_cert(Private_Key const& key, EAC1_1_CVC_Options const& opt, RandomNumberGenerator& rng) { - // NOTE: we ignore - // the value - // of opt.chr - ECDSA_PrivateKey const* priv_key = dynamic_cast<ECDSA_PrivateKey const*>(&key); + // NOTE: we ignore the value of opt.chr - if (priv_key == 0) - { + const ECDSA_PrivateKey* priv_key = dynamic_cast<const ECDSA_PrivateKey*>(&key); + + if(priv_key == 0) throw Invalid_Argument("CVC_EAC::create_self_signed_cert(): unsupported key type"); - } ASN1_Chr chr(opt.car.value()); @@ -86,19 +104,15 @@ EAC1_1_CVC create_self_signed_cert(Private_Key const& key, sig_algo.oid = OIDS::lookup(priv_key->algo_name() + "/" + padding_and_hash); sig_algo = AlgorithmIdentifier(sig_algo.oid, AlgorithmIdentifier::USE_NULL_PARAM); - std::unique_ptr<Botan::PK_Signer> signer(get_pk_signer(*priv_key, padding_and_hash)); - -#if 0 // FIXME - std::unique_ptr<EAC1_1_CVC_Encoder> enc(priv_key->cvc_eac1_1_encoder()); - MemoryVector<byte> enc_public_key = enc->public_key(sig_algo); -#else - MemoryVector<byte> enc_public_key; -#endif + PK_Signer signer(*priv_key, padding_and_hash); - return EAC1_1_CVC_CA::make_cert(*signer.get(), enc_public_key, - opt.car, chr, opt.holder_auth_templ, - opt.ced, opt.cex, rng); + MemoryVector<byte> enc_public_key = eac_1_1_encoding(priv_key, sig_algo.oid); + return make_cvc_cert(signer, + enc_public_key, + opt.car, chr, + opt.holder_auth_templ, + opt.ced, opt.cex, rng); } EAC1_1_Req create_cvc_req(Private_Key const& key, @@ -117,14 +131,9 @@ EAC1_1_Req create_cvc_req(Private_Key const& key, sig_algo.oid = OIDS::lookup(priv_key->algo_name() + "/" + padding_and_hash); sig_algo = AlgorithmIdentifier(sig_algo.oid, AlgorithmIdentifier::USE_NULL_PARAM); - std::unique_ptr<Botan::PK_Signer> signer(get_pk_signer(*priv_key, padding_and_hash)); + PK_Signer signer(*priv_key, padding_and_hash); -#if 0 // FIXME - std::unique_ptr<EAC1_1_CVC_Encoder> enc(priv_key->cvc_eac1_1_encoder()); - MemoryVector<byte> enc_public_key = enc->public_key(sig_algo); -#else - MemoryVector<byte> enc_public_key; -#endif + MemoryVector<byte> enc_public_key = eac_1_1_encoding(priv_key, sig_algo.oid); MemoryVector<byte> enc_cpi; enc_cpi.append(0x00); @@ -134,7 +143,10 @@ EAC1_1_Req create_cvc_req(Private_Key const& key, .encode(chr) .get_contents(); - MemoryVector<byte> signed_cert = EAC1_1_gen_CVC<EAC1_1_Req>::make_signed(*signer.get(), EAC1_1_gen_CVC<EAC1_1_Req>::build_cert_body(tbs), rng); + MemoryVector<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); DataSource_Memory source(signed_cert); return EAC1_1_Req(source); @@ -153,9 +165,7 @@ EAC1_1_ADO create_ado_req(Private_Key const& key, } std::string padding_and_hash = padding_and_hash_from_oid(req.signature_algorithm().oid); - - std::unique_ptr<Botan::PK_Signer> signer(get_pk_signer(*priv_key, padding_and_hash)); - + PK_Signer signer(*priv_key, padding_and_hash); SecureVector<byte> tbs_bits = req.BER_encode(); tbs_bits.append(DER_Encoder().encode(car).get_contents()); MemoryVector<byte> signed_cert = EAC1_1_ADO::make_signed(*signer.get(), tbs_bits, rng); @@ -187,7 +197,7 @@ EAC1_1_CVC create_cvca(Private_Key const& key, opts.cex.add_months(cvca_validity_months); opts.holder_auth_templ = (CVCA | (iris * IRIS) | (fingerpr * FINGERPRINT)); opts.hash_alg = hash; - return Botan::CVC_EAC::create_self_signed_cert(*priv_key, opts, rng); + return CVC_EAC::create_self_signed_cert(*priv_key, opts, rng); } @@ -218,25 +228,19 @@ 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); - std::unique_ptr<Botan::PK_Signer> pk_signer(get_pk_signer(*priv_key, padding_and_hash)); - std::unique_ptr<Public_Key> pk = signee.subject_public_key(); - ECDSA_PublicKey* subj_pk = dynamic_cast<ECDSA_PublicKey*>(pk.get()); + PK_Signer pk_signer(*priv_key, padding_and_hash); + std::auto_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); -#if 0 // FIXME - std::unique_ptr<EAC1_1_CVC_Encoder> enc(subj_pk->cvc_eac1_1_encoder()); - MemoryVector<byte> enc_public_key = enc->public_key(sig_algo); -#else - MemoryVector<byte> enc_public_key; -#endif - - return EAC1_1_CVC_CA::make_cert(*pk_signer.get(), enc_public_key, - signer.get_car(), - signee.get_chr(), - signer.get_chat_value(), - ced, - cex, - rng); + MemoryVector<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(), + signee.get_chr(), + signer.get_chat_value(), + ced, cex, + rng); } EAC1_1_CVC sign_request(EAC1_1_CVC const& signer_cert, @@ -255,11 +259,11 @@ 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.append(fixed_len_seqnr(seqnr, seqnr_len)); + chr_str += to_string(seqnr, seqnr_len); ASN1_Chr chr(chr_str); std::string padding_and_hash = padding_and_hash_from_oid(signee.signature_algorithm().oid); - std::unique_ptr<Botan::PK_Signer> pk_signer(get_pk_signer(*priv_key, padding_and_hash)); - std::unique_ptr<Public_Key> pk = signee.subject_public_key(); + PK_Signer pk_signer(*priv_key, padding_and_hash); + std::auto_ptr<Public_Key> pk = signee.subject_public_key(); ECDSA_PublicKey* subj_pk = dynamic_cast<ECDSA_PublicKey*>(pk.get()); std::unique_ptr<Public_Key> signer_pk = signer_cert.subject_public_key(); @@ -269,13 +273,6 @@ EAC1_1_CVC sign_request(EAC1_1_CVC const& signer_cert, subj_pk->set_parameter_encoding(EC_DOMPAR_ENC_IMPLICITCA); -#if 0 // FIXME - std::unique_ptr<EAC1_1_CVC_Encoder> enc(subj_pk->cvc_eac1_1_encoder()); - MemoryVector<byte> enc_public_key = enc->public_key(sig_algo); -#else - MemoryVector<byte> enc_public_key; -#endif - AlgorithmIdentifier sig_algo(signer_cert.signature_algorithm()); ASN1_Ced ced(std::chrono::system_clock::now()); @@ -288,13 +285,9 @@ EAC1_1_CVC sign_request(EAC1_1_CVC const& signer_cert, // we sign a dvca cex.add_months(dvca_validity_months); if (domestic) - { chat_val = DVCA_domestic | chat_low; - } else - { chat_val = DVCA_foreign | chat_low; - } } else if ((signer_cert.get_chat_value() & DVCA_domestic) == DVCA_domestic || (signer_cert.get_chat_value() & DVCA_foreign) == DVCA_foreign) @@ -307,13 +300,16 @@ EAC1_1_CVC sign_request(EAC1_1_CVC const& signer_cert, throw Invalid_Argument("sign_request(): encountered illegal value for CHAT"); // (IS cannot sign certificates) } - return EAC1_1_CVC_CA::make_cert(*pk_signer.get(), enc_public_key, - ASN1_Car(signer_cert.get_chr().iso_8859()), - chr, - chat_val, - ced, - cex, - rng); + + MemoryVector<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()), + chr, + chat_val, + ced, + cex, + rng); } EAC1_1_Req create_cvc_req(Private_Key const& prkey, @@ -328,7 +324,7 @@ EAC1_1_Req create_cvc_req(Private_Key const& prkey, } ECDSA_PrivateKey key(*priv_key); key.set_parameter_encoding(EC_DOMPAR_ENC_IMPLICITCA); - return Botan::CVC_EAC::create_cvc_req(key, chr, hash_alg, rng); + return CVC_EAC::create_cvc_req(key, chr, hash_alg, rng); } } // namespace DE_EAC diff --git a/src/cert/cvc/eac_asn_obj.h b/src/cert/cvc/eac_asn_obj.h index 79802951c..3ab57d7e4 100644 --- a/src/cert/cvc/eac_asn_obj.h +++ b/src/cert/cvc/eac_asn_obj.h @@ -1,7 +1,7 @@ /* * EAC ASN.1 Objects * (C) 2007-2008 FlexSecure GmbH -* 2008-2009 Jack Lloyd +* 2008-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -10,9 +10,6 @@ #define BOTAN_EAC_ASN1_OBJ_H__ #include <botan/asn1_obj.h> -#include <vector> -#include <map> -#include <chrono> namespace Botan { diff --git a/src/cert/cvc/eac_obj.h b/src/cert/cvc/eac_obj.h index 419929a19..66752b10c 100644 --- a/src/cert/cvc/eac_obj.h +++ b/src/cert/cvc/eac_obj.h @@ -8,17 +8,8 @@ #ifndef BOTAN_EAC_OBJ_H__ #define BOTAN_EAC_OBJ_H__ -#include <botan/pubkey.h> -#include <botan/x509_key.h> #include <botan/signed_obj.h> -#include <botan/pubkey_enums.h> -#include <botan/pubkey.h> -#include <botan/parsing.h> -#include <botan/pem.h> -#include <botan/oids.h> -#include <botan/look_pk.h> #include <botan/ecdsa_sig.h> -#include <string> namespace Botan { @@ -26,103 +17,38 @@ namespace Botan { * TR03110 v1.1 EAC CV Certificate */ template<typename Derived> // CRTP is used enable the call sequence: -class BOTAN_DLL EAC1_1_obj : public EAC_Signed_Object +class EAC1_1_obj : public EAC_Signed_Object { - // data members first: - protected: - - ECDSA_Signature m_sig; - - // member functions here: public: /** * Return the signature as a concatenation of the encoded parts. * @result the concatenated signature */ - SecureVector<byte> get_concat_sig() const; + SecureVector<byte> get_concat_sig() const + { return m_sig.get_concatenation(); } - /** - * Verify the signature of this objects. - * @param pub_key the public key to verify the signature with - * @result true if the verification succeeded - */ - virtual bool check_signature(Public_Key& pub_key) const; + bool check_signature(class Public_Key& key) const + { + return EAC_Signed_Object::check_signature(key, m_sig.DER_encode()); + } protected: - void init(DataSource& in); - - static SecureVector<byte> make_signature(PK_Signer& signer, - const MemoryRegion<byte>& tbs_bits, - RandomNumberGenerator& rng); - - virtual ~EAC1_1_obj<Derived>(){} - - }; - -template<typename Derived> SecureVector<byte> EAC1_1_obj<Derived>::get_concat_sig() const - { - return m_sig.get_concatenation(); - } - -template<typename Derived> SecureVector<byte> -EAC1_1_obj<Derived>::make_signature(PK_Signer& signer, - const MemoryRegion<byte>& tbs_bits, - RandomNumberGenerator& rng) - { - // this is the signature as a der sequence - SecureVector<byte> seq_sig = signer.sign_message(tbs_bits, rng); - - ECDSA_Signature sig(decode_seq(seq_sig)); - SecureVector<byte> concat_sig(sig.get_concatenation()); - return concat_sig; - } - -template<typename Derived> -void EAC1_1_obj<Derived>::init(DataSource& in) - { - try - { - Derived::decode_info(in, tbs_bits, m_sig); - } - catch(Decoding_Error) - { - throw Decoding_Error(PEM_label_pref + " decoding failed"); - } - } - -template<typename Derived> -bool EAC1_1_obj<Derived>::check_signature(Public_Key& pub_key) const - { - try - { - std::vector<std::string> sig_info = - split_on(OIDS::lookup(sig_algo.oid), '/'); + ECDSA_Signature m_sig; - if(sig_info.size() != 2 || sig_info[0] != pub_key.algo_name()) + void init(DataSource& in) { - return false; + try + { + Derived::decode_info(in, tbs_bits, m_sig); + } + catch(Decoding_Error) + { + throw Decoding_Error(PEM_label_pref + " decoding failed"); + } } - std::string padding = sig_info[1]; - Signature_Format format = - (pub_key.message_parts() >= 2) ? DER_SEQUENCE : IEEE_1363; - - if(!dynamic_cast<PK_Verifying_wo_MR_Key*>(&pub_key)) - return false; - - std::unique_ptr<ECDSA_Signature_Encoder> enc(new ECDSA_Signature_Encoder(&m_sig)); - SecureVector<byte> seq_sig = enc->signature_bits(); - SecureVector<byte> to_sign = tbs_data(); - - PK_Verifying_wo_MR_Key& sig_key = dynamic_cast<PK_Verifying_wo_MR_Key&>(pub_key); - std::unique_ptr<PK_Verifier> verifier(get_pk_verifier(sig_key, padding, format)); - return verifier->verify_message(to_sign, seq_sig); - } - catch(...) - { - return false; - } - } + virtual ~EAC1_1_obj<Derived>(){} + }; } diff --git a/src/cert/cvc/ecdsa_sig.cpp b/src/cert/cvc/ecdsa_sig.cpp index 1a60f7aa8..e003bb369 100644 --- a/src/cert/cvc/ecdsa_sig.cpp +++ b/src/cert/cvc/ecdsa_sig.cpp @@ -1,31 +1,36 @@ +/* +* ECDSA Signature +* (C) 2007 Falko Strenzke, FlexSecure GmbH +* (C) 2008-2010 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ #include <botan/ecdsa_sig.h> -#include <memory> namespace Botan { -ECDSA_Signature::ECDSA_Signature(const BigInt& r, const BigInt& s) - : m_r(r), - m_s(s) - {} - -ECDSA_Signature::ECDSA_Signature(const ECDSA_Signature& other) - : m_r(other.m_r), m_s(other.m_s) - {} - -ECDSA_Signature const& ECDSA_Signature::operator=(const ECDSA_Signature& other) +ECDSA_Signature::ECDSA_Signature(const MemoryRegion<byte>& ber) { - m_r = other.m_r; - m_s = other.m_s; - return *this; + BER_Decoder(ber) + .start_cons(SEQUENCE) + .decode(m_r) + .decode(m_s) + .end_cons() + .verify_end(); } -bool operator==(const ECDSA_Signature& lhs, const ECDSA_Signature& rhs) +MemoryVector<byte> ECDSA_Signature::DER_encode() const { - return (lhs.get_r() == rhs.get_r() && lhs.get_s() == rhs.get_s()); + return DER_Encoder() + .start_cons(SEQUENCE) + .encode(get_r()) + .encode(get_s()) + .end_cons() + .get_contents(); } -SecureVector<byte> const ECDSA_Signature::get_concatenation() const +MemoryVector<byte> ECDSA_Signature::get_concatenation() const { u32bit enc_len = m_r > m_s ? m_r.bytes() : m_s.bytes(); // use the larger @@ -37,16 +42,7 @@ SecureVector<byte> const ECDSA_Signature::get_concatenation() const return result; } -ECDSA_Signature const decode_seq(MemoryRegion<byte> const& seq) - { - ECDSA_Signature sig; - - std::unique_ptr<ECDSA_Signature_Decoder> dec(new ECDSA_Signature_Decoder(&sig)); - dec->signature_bits(seq); - return sig; - } - -ECDSA_Signature const decode_concatenation(MemoryRegion<byte> const& concat) +ECDSA_Signature decode_concatenation(const MemoryRegion<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 15015c76d..1397a92b1 100644 --- a/src/cert/cvc/ecdsa_sig.h +++ b/src/cert/cvc/ecdsa_sig.h @@ -1,7 +1,7 @@ /* -* ECDSA +* ECDSA Signature * (C) 2007 Falko Strenzke, FlexSecure GmbH -* (C) 2008 Jack Lloyd +* (C) 2008-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -21,9 +21,10 @@ class BOTAN_DLL ECDSA_Signature friend class ECDSA_Signature_Decoder; ECDSA_Signature() {} - ECDSA_Signature(const BigInt& r, const BigInt& s); - ECDSA_Signature(ECDSA_Signature const& other); - ECDSA_Signature const& operator=(ECDSA_Signature const& other); + ECDSA_Signature(const BigInt& r, const BigInt& s) : + m_r(r), m_s(s) {} + + ECDSA_Signature(const MemoryRegion<byte>& ber); const BigInt& get_r() const { return m_r; } const BigInt& get_s() const { return m_s; } @@ -31,57 +32,26 @@ class BOTAN_DLL ECDSA_Signature /** * return the r||s */ - SecureVector<byte> const get_concatenation() const; + MemoryVector<byte> get_concatenation() const; + + MemoryVector<byte> DER_encode() const; + + bool operator==(const ECDSA_Signature& other) const + { + return (get_r() == other.get_r() && get_s() == other.get_s()); + } + private: BigInt m_r; BigInt m_s; }; -/* Equality of ECDSA_Signature */ -bool operator==(const ECDSA_Signature& lhs, const ECDSA_Signature& rhs); inline bool operator!=(const ECDSA_Signature& lhs, const ECDSA_Signature& rhs) { return !(lhs == rhs); } -class BOTAN_DLL ECDSA_Signature_Decoder - { - public: - void signature_bits(const MemoryRegion<byte>& bits) - { - BER_Decoder(bits) - .start_cons(SEQUENCE) - .decode(m_signature->m_r) - .decode(m_signature->m_s) - .verify_end() - .end_cons(); - } - ECDSA_Signature_Decoder(ECDSA_Signature* signature) : m_signature(signature) - {} - private: - ECDSA_Signature* m_signature; - }; - -class BOTAN_DLL ECDSA_Signature_Encoder - { - public: - MemoryVector<byte> signature_bits() const - { - return DER_Encoder() - .start_cons(SEQUENCE) - .encode(m_signature->get_r()) - .encode(m_signature->get_s()) - .end_cons() - .get_contents(); - } - ECDSA_Signature_Encoder(const ECDSA_Signature* signature) : m_signature(signature) - {} - private: - const ECDSA_Signature* m_signature; - }; - -ECDSA_Signature const decode_seq(MemoryRegion<byte> const& seq); -ECDSA_Signature const decode_concatenation(MemoryRegion<byte> const& concatenation); +ECDSA_Signature decode_concatenation(const MemoryRegion<byte>& concatenation); } diff --git a/src/cert/cvc/info.txt b/src/cert/cvc/info.txt index 285838379..91de3bc19 100644 --- a/src/cert/cvc/info.txt +++ b/src/cert/cvc/info.txt @@ -3,10 +3,8 @@ load_on auto <header:public> cvc_ado.h -cvc_ca.h cvc_cert.h cvc_gen_cert.h -cvc_key.h cvc_req.h cvc_self.h eac_asn_obj.h @@ -20,7 +18,6 @@ asn1_eac_str.cpp asn1_eac_tm.cpp ecdsa_sig.cpp cvc_ado.cpp -cvc_ca.cpp cvc_cert.cpp cvc_req.cpp cvc_self.cpp @@ -35,7 +32,6 @@ filters libstate oid_lookup pem -pk_codecs pubkey x509 </requires> diff --git a/src/cert/cvc/signed_obj.cpp b/src/cert/cvc/signed_obj.cpp index 4a08ed0ac..d6aa2f02b 100644 --- a/src/cert/cvc/signed_obj.cpp +++ b/src/cert/cvc/signed_obj.cpp @@ -1,12 +1,15 @@ /* -* X.509 SIGNED Object -* (C) 1999-2007 Jack Lloyd +* EAC SIGNED Object +* (C) 1999-2010 Jack Lloyd * 2007 FlexSecure GmbH * * Distributed under the terms of the Botan license */ #include <botan/signed_obj.h> +#include <botan/pubkey.h> +#include <botan/oids.h> +#include <memory> namespace Botan { @@ -42,6 +45,34 @@ AlgorithmIdentifier EAC_Signed_Object::signature_algorithm() const return sig_algo; } +bool EAC_Signed_Object::check_signature(Public_Key& pub_key, + const MemoryRegion<byte>& sig) const + { + try + { + std::vector<std::string> sig_info = + split_on(OIDS::lookup(sig_algo.oid), '/'); + + if(sig_info.size() != 2 || sig_info[0] != pub_key.algo_name()) + { + return false; + } + + std::string padding = sig_info[1]; + Signature_Format format = + (pub_key.message_parts() >= 2) ? DER_SEQUENCE : IEEE_1363; + + SecureVector<byte> to_sign = tbs_data(); + + PK_Verifier verifier(pub_key, padding, format); + return verifier.verify_message(to_sign, sig); + } + catch(...) + { + return false; + } + } + /* * Try to decode the actual information */ @@ -53,14 +84,12 @@ void EAC_Signed_Object::do_decode() catch(Decoding_Error& e) { const std::string what = e.what(); - throw Decoding_Error(PEM_label_pref + " decoding failed (" + - what.substr(23, std::string::npos) + ")"); + throw Decoding_Error(PEM_label_pref + " decoding failed (" + what + ")"); } catch(Invalid_Argument& e) { const std::string what = e.what(); - throw Decoding_Error(PEM_label_pref + " decoding failed (" + - what.substr(7, std::string::npos) + ")"); + throw Decoding_Error(PEM_label_pref + " decoding failed (" + what + ")"); } } diff --git a/src/cert/cvc/signed_obj.h b/src/cert/cvc/signed_obj.h index 17b75a08a..0e7dd6bdb 100644 --- a/src/cert/cvc/signed_obj.h +++ b/src/cert/cvc/signed_obj.h @@ -53,7 +53,8 @@ class BOTAN_DLL EAC_Signed_Object * @return true if the signature was created by the private key * associated with this public key */ - virtual bool check_signature(class Public_Key&) const = 0; + bool check_signature(class Public_Key& key, + const MemoryRegion<byte>& sig) const; /** * Write this object DER encoded into a specified pipe. diff --git a/src/cert/x509/info.txt b/src/cert/x509/info.txt index a5cd973a4..510163e69 100644 --- a/src/cert/x509/info.txt +++ b/src/cert/x509/info.txt @@ -39,7 +39,6 @@ filters libstate oid_lookup pem -pk_codecs pubkey rng sha1 diff --git a/src/cert/x509/x509_ca.cpp b/src/cert/x509/x509_ca.cpp index 59a5bbaf8..3eb7ff77e 100644 --- a/src/cert/x509/x509_ca.cpp +++ b/src/cert/x509/x509_ca.cpp @@ -7,12 +7,12 @@ #include <botan/x509_ca.h> #include <botan/x509stor.h> +#include <botan/pubkey.h> #include <botan/der_enc.h> #include <botan/ber_dec.h> #include <botan/bigint.h> #include <botan/parsing.h> #include <botan/lookup.h> -#include <botan/look_pk.h> #include <botan/oids.h> #include <memory> #include <set> @@ -26,10 +26,6 @@ X509_CA::X509_CA(const X509_Certificate& c, const Private_Key& key, const std::string& hash_fn) : cert(c) { - // Use pointer dynamic_cast to avoid exception if cast fails - if(!dynamic_cast<const PK_Signing_Key*>(&key)) - throw Invalid_Argument("X509_CA: " + key.algo_name() + " cannot sign"); - if(!cert.is_CA_cert()) throw Invalid_Argument("X509_CA: This certificate is not for a CA"); @@ -270,17 +266,9 @@ PK_Signer* choose_sig_format(const Private_Key& key, padding = padding + '(' + proto_hash->name() + ')'; sig_algo.oid = OIDS::lookup(algo_name + "/" + padding); + sig_algo.parameters = key.algorithm_identifier().parameters; - std::unique_ptr<X509_Encoder> encoding(key.x509_encoder()); - if(!encoding.get()) - throw Encoding_Error("Key " + algo_name + " does not support " - "X.509 encoding"); - - sig_algo.parameters = encoding->alg_id().parameters; - - const PK_Signing_Key& sig_key = dynamic_cast<const PK_Signing_Key&>(key); - - return get_pk_signer(sig_key, padding, format); + return new PK_Signer(key, padding, format); } } diff --git a/src/cert/x509/x509_obj.cpp b/src/cert/x509/x509_obj.cpp index 95a1c1cca..820972614 100644 --- a/src/cert/x509/x509_obj.cpp +++ b/src/cert/x509/x509_obj.cpp @@ -7,7 +7,7 @@ #include <botan/x509_obj.h> #include <botan/x509_key.h> -#include <botan/look_pk.h> +#include <botan/pubkey.h> #include <botan/oids.h> #include <botan/der_enc.h> #include <botan/ber_dec.h> @@ -168,24 +168,9 @@ bool X509_Object::check_signature(Public_Key& pub_key) const Signature_Format format = (pub_key.message_parts() >= 2) ? DER_SEQUENCE : IEEE_1363; - std::unique_ptr<PK_Verifier> verifier; + PK_Verifier verifier(pub_key, padding, format); - if(dynamic_cast<PK_Verifying_with_MR_Key*>(&pub_key)) - { - PK_Verifying_with_MR_Key& sig_key = - dynamic_cast<PK_Verifying_with_MR_Key&>(pub_key); - verifier.reset(get_pk_verifier(sig_key, padding, format)); - } - else if(dynamic_cast<PK_Verifying_wo_MR_Key*>(&pub_key)) - { - PK_Verifying_wo_MR_Key& sig_key = - dynamic_cast<PK_Verifying_wo_MR_Key&>(pub_key); - verifier.reset(get_pk_verifier(sig_key, padding, format)); - } - else - return false; - - return verifier->verify_message(tbs_data(), signature()); + return verifier.verify_message(tbs_data(), signature()); } catch(...) { diff --git a/src/cert/x509/x509self.cpp b/src/cert/x509/x509self.cpp index df31897bb..1f647f8bb 100644 --- a/src/cert/x509/x509self.cpp +++ b/src/cert/x509/x509self.cpp @@ -9,7 +9,6 @@ #include <botan/x509_ext.h> #include <botan/x509_ca.h> #include <botan/der_enc.h> -#include <botan/look_pk.h> #include <botan/oids.h> #include <botan/pipe.h> #include <memory> @@ -24,10 +23,6 @@ namespace { MemoryVector<byte> shared_setup(const X509_Cert_Options& opts, const Private_Key& key) { - const Private_Key* key_pointer = &key; - if(!dynamic_cast<const PK_Signing_Key*>(key_pointer)) - throw Invalid_Argument("Key type " + key.algo_name() + " cannot sign"); - opts.sanity_check(); Pipe key_encoder; diff --git a/src/cert/x509/x509stor.cpp b/src/cert/x509/x509stor.cpp index 80507c1dd..6b2c0eee0 100644 --- a/src/cert/x509/x509stor.cpp +++ b/src/cert/x509/x509stor.cpp @@ -8,7 +8,6 @@ #include <botan/x509stor.h> #include <botan/parsing.h> #include <botan/pubkey.h> -#include <botan/look_pk.h> #include <botan/oids.h> #include <algorithm> #include <chrono> @@ -384,7 +383,6 @@ X509_Code X509_Store::check_sig(const Cert_Info& cert_info, X509_Code X509_Store::check_sig(const X509_Object& object, Public_Key* key) { std::unique_ptr<Public_Key> pub_key(key); - std::unique_ptr<PK_Verifier> verifier; try { std::vector<std::string> sig_info = @@ -398,29 +396,17 @@ X509_Code X509_Store::check_sig(const X509_Object& object, Public_Key* key) if(key->message_parts() >= 2) format = DER_SEQUENCE; else format = IEEE_1363; - if(dynamic_cast<PK_Verifying_with_MR_Key*>(pub_key.get())) - { - PK_Verifying_with_MR_Key* sig_key = - dynamic_cast<PK_Verifying_with_MR_Key*>(pub_key.get()); - verifier.reset(get_pk_verifier(*sig_key, padding, format)); - } - else if(dynamic_cast<PK_Verifying_wo_MR_Key*>(pub_key.get())) - { - PK_Verifying_wo_MR_Key* sig_key = - dynamic_cast<PK_Verifying_wo_MR_Key*>(pub_key.get()); - verifier.reset(get_pk_verifier(*sig_key, padding, format)); - } - else - return CA_CERT_CANNOT_SIGN; + PK_Verifier verifier(*pub_key.get(), padding, format); - bool valid = verifier->verify_message(object.tbs_data(), - object.signature()); + bool valid = verifier.verify_message(object.tbs_data(), + object.signature()); if(valid) return VERIFIED; else return SIGNATURE_ERROR; } + catch(Lookup_Error) { return CA_CERT_CANNOT_SIGN; } catch(Decoding_Error) { return CERT_FORMAT_ERROR; } catch(Exception) {} diff --git a/src/cms/cms_dalg.cpp b/src/cms/cms_dalg.cpp index 8d559f9a9..2a380b596 100644 --- a/src/cms/cms_dalg.cpp +++ b/src/cms/cms_dalg.cpp @@ -10,7 +10,6 @@ #include <botan/ber_dec.h> #include <botan/oids.h> #include <botan/hash.h> -#include <botan/look_pk.h> #include <botan/bigint.h> #include <botan/libstate.h> #include <memory> diff --git a/src/cms/cms_ealg.cpp b/src/cms/cms_ealg.cpp index 60479a820..3ddf8a39e 100644 --- a/src/cms/cms_ealg.cpp +++ b/src/cms/cms_ealg.cpp @@ -6,15 +6,15 @@ */ #include <botan/cms_enc.h> -#include <botan/der_enc.h> -#include <botan/x509find.h> #include <botan/bigint.h> -#include <botan/oids.h> #include <botan/cbc.h> +#include <botan/der_enc.h> #include <botan/hash.h> -#include <botan/look_pk.h> #include <botan/libstate.h> +#include <botan/oids.h> #include <botan/pipe.h> +#include <botan/pubkey.h> +#include <botan/x509find.h> #include <memory> namespace Botan { @@ -107,12 +107,7 @@ void CMS_Encoder::encrypt(RandomNumberGenerator& rng, if(constraints != NO_CONSTRAINTS && !(constraints & KEY_ENCIPHERMENT)) throw Invalid_Argument("CMS: Constraints not set for encryption"); - PK_Encrypting_Key* enc_key = dynamic_cast<PK_Encrypting_Key*>(key.get()); - if(enc_key == 0) - throw Internal_Error("CMS_Encoder::encrypt: " + algo + - " can't encrypt"); - - encrypt_ktri(rng, to, enc_key, cipher); + encrypt_ktri(rng, to, key.get(), cipher); } else if(algo == "DH") { @@ -130,12 +125,13 @@ void CMS_Encoder::encrypt(RandomNumberGenerator& rng, */ void CMS_Encoder::encrypt_ktri(RandomNumberGenerator& rng, const X509_Certificate& to, - PK_Encrypting_Key* pub_key, + Public_Key* pub_key, const std::string& cipher) { const std::string padding = "EME-PKCS1-v1_5"; const std::string pk_algo = pub_key->algo_name(); - std::auto_ptr<PK_Encryptor> enc(get_pk_encryptor(*pub_key, padding)); + + PK_Encryptor_EME encryptor(*pub_key, padding); SymmetricKey cek = setup_key(rng, cipher); @@ -151,7 +147,7 @@ void CMS_Encoder::encrypt_ktri(RandomNumberGenerator& rng, .encode((u32bit)0); encode_si(encoder, to) .encode(alg_id) - .encode(enc->encrypt(cek.bits_of(), rng), OCTET_STRING) + .encode(encryptor.encrypt(cek.bits_of(), rng), OCTET_STRING) .end_cons() .end_cons() .raw_bytes(do_encrypt(rng, cek, cipher)) @@ -295,18 +291,16 @@ void CMS_Encoder::sign(const X509_Certificate& cert, { std::string padding = pad_algo + "(" + hash + ")"; - // FIXME: Add new get_format() func to PK_Signing_Key, PK_Verifying_*_Key Signature_Format format = IEEE_1363; - const PK_Signing_Key& sig_key = dynamic_cast<const PK_Signing_Key&>(key); - std::auto_ptr<PK_Signer> signer(get_pk_signer(sig_key, padding, format)); + PK_Signer signer(key, padding, format); AlgorithmIdentifier sig_algo(OIDS::lookup(key.algo_name() + "/" + padding), AlgorithmIdentifier::USE_NULL_PARAM); SecureVector<byte> signed_attr = encode_attr(data, type, hash); - signer->update(signed_attr); - SecureVector<byte> signature = signer->signature(rng); + signer.update(signed_attr); + SecureVector<byte> signature = signer.signature(rng); signed_attr[0] = 0xA0; const u32bit SI_VERSION = cert.subject_key_id().size() ? 3 : 1; diff --git a/src/cms/cms_enc.h b/src/cms/cms_enc.h index b1e18ef7d..ec2fdf3b3 100644 --- a/src/cms/cms_enc.h +++ b/src/cms/cms_enc.h @@ -59,7 +59,7 @@ class BOTAN_DLL CMS_Encoder void add_layer(const std::string&, DER_Encoder&); void encrypt_ktri(RandomNumberGenerator&, - const X509_Certificate&, PK_Encrypting_Key*, + const X509_Certificate&, Public_Key*, const std::string&); void encrypt_kari(RandomNumberGenerator&, const X509_Certificate&, Public_Key*, diff --git a/src/cms/info.txt b/src/cms/info.txt index 44c5811f8..b863a9a26 100644 --- a/src/cms/info.txt +++ b/src/cms/info.txt @@ -9,7 +9,7 @@ hash libstate oid_lookup pem -pk_codecs +pubkey sha1 sym_algo x509 diff --git a/src/engine/def_engine/def_pk_ops.cpp b/src/engine/def_engine/def_pk_ops.cpp index e1040142e..d3264e67e 100644 --- a/src/engine/def_engine/def_pk_ops.cpp +++ b/src/engine/def_engine/def_pk_ops.cpp @@ -1,89 +1,170 @@ /* * PK Operations -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ #include <botan/internal/default_engine.h> -#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY) - #include <botan/if_op.h> +#if defined(BOTAN_HAS_RSA) + #include <botan/rsa.h> +#endif + +#if defined(BOTAN_HAS_RW) + #include <botan/rw.h> #endif #if defined(BOTAN_HAS_DSA) - #include <botan/dsa_op.h> + #include <botan/dsa.h> #endif -#if defined(BOTAN_HAS_NYBERG_RUEPPEL) - #include <botan/nr_op.h> +#if defined(BOTAN_HAS_ECDSA) + #include <botan/ecdsa.h> #endif #if defined(BOTAN_HAS_ELGAMAL) - #include <botan/elg_op.h> + #include <botan/elgamal.h> +#endif + +#if defined(BOTAN_HAS_GOST_3410_2001) + #include <botan/gost_3410.h> +#endif + +#if defined(BOTAN_HAS_NYBERG_RUEPPEL) + #include <botan/nr.h> #endif #if defined(BOTAN_HAS_DIFFIE_HELLMAN) - #include <botan/dh_op.h> + #include <botan/dh.h> +#endif + +#if defined(BOTAN_HAS_ECDH) + #include <botan/ecdh.h> #endif namespace Botan { -#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY) -/* -* Acquire an IF op -*/ -IF_Operation* Default_Engine::if_op(const BigInt& e, const BigInt& n, - const BigInt& d, const BigInt& p, - const BigInt& q, const BigInt& d1, - const BigInt& d2, const BigInt& c) const +PK_Ops::Encryption* +Default_Engine::get_encryption_op(const Public_Key& key) const { - return new Default_IF_Op(e, n, d, p, q, d1, d2, c); - } +#if defined(BOTAN_HAS_RSA) + if(const RSA_PublicKey* s = dynamic_cast<const RSA_PublicKey*>(&key)) + return new RSA_Public_Operation(*s); #endif -#if defined(BOTAN_HAS_DSA) -/* -* Acquire a DSA op -*/ -DSA_Operation* Default_Engine::dsa_op(const DL_Group& group, const BigInt& y, - const BigInt& x) const - { - return new Default_DSA_Op(group, y, x); - } +#if defined(BOTAN_HAS_ELGAMAL) + if(const ElGamal_PublicKey* s = dynamic_cast<const ElGamal_PublicKey*>(&key)) + return new ElGamal_Encryption_Operation(*s); #endif -#if defined(BOTAN_HAS_NYBERG_RUEPPEL) -/* -* Acquire a NR op -*/ -NR_Operation* Default_Engine::nr_op(const DL_Group& group, const BigInt& y, - const BigInt& x) const - { - return new Default_NR_Op(group, y, x); + return 0; } + +PK_Ops::Decryption* +Default_Engine::get_decryption_op(const Private_Key& key) const + { +#if defined(BOTAN_HAS_RSA) + if(const RSA_PrivateKey* s = dynamic_cast<const RSA_PrivateKey*>(&key)) + return new RSA_Private_Operation(*s); #endif #if defined(BOTAN_HAS_ELGAMAL) -/* -* Acquire an ElGamal op -*/ -ELG_Operation* Default_Engine::elg_op(const DL_Group& group, const BigInt& y, - const BigInt& x) const - { - return new Default_ELG_Op(group, y, x); - } + if(const ElGamal_PrivateKey* s = dynamic_cast<const ElGamal_PrivateKey*>(&key)) + return new ElGamal_Decryption_Operation(*s); #endif + return 0; + } + +PK_Ops::Key_Agreement* +Default_Engine::get_key_agreement_op(const Private_Key& key) const + { #if defined(BOTAN_HAS_DIFFIE_HELLMAN) -/* -* Acquire a DH op -*/ -DH_Operation* Default_Engine::dh_op(const DL_Group& group, - const BigInt& x) const + if(const DH_PrivateKey* dh = dynamic_cast<const DH_PrivateKey*>(&key)) + return new DH_KA_Operation(*dh); +#endif + +#if defined(BOTAN_HAS_ECDH) + if(const ECDH_PrivateKey* ecdh = dynamic_cast<const ECDH_PrivateKey*>(&key)) + return new ECDH_KA_Operation(*ecdh); +#endif + + return 0; + } + +PK_Ops::Signature* +Default_Engine::get_signature_op(const Private_Key& key) const { - return new Default_DH_Op(group, x); +#if defined(BOTAN_HAS_RSA) + if(const RSA_PrivateKey* s = dynamic_cast<const RSA_PrivateKey*>(&key)) + return new RSA_Private_Operation(*s); +#endif + +#if defined(BOTAN_HAS_RW) + if(const RW_PrivateKey* s = dynamic_cast<const RW_PrivateKey*>(&key)) + return new RW_Signature_Operation(*s); +#endif + +#if defined(BOTAN_HAS_DSA) + if(const DSA_PrivateKey* s = dynamic_cast<const DSA_PrivateKey*>(&key)) + return new DSA_Signature_Operation(*s); +#endif + +#if defined(BOTAN_HAS_ECDSA) + if(const ECDSA_PrivateKey* s = dynamic_cast<const ECDSA_PrivateKey*>(&key)) + return new ECDSA_Signature_Operation(*s); +#endif + +#if defined(BOTAN_HAS_GOST_3410_2001) + if(const GOST_3410_PrivateKey* s = + dynamic_cast<const GOST_3410_PrivateKey*>(&key)) + return new GOST_3410_Signature_Operation(*s); +#endif + +#if defined(BOTAN_HAS_NYBERG_RUEPPEL) + if(const NR_PrivateKey* s = dynamic_cast<const NR_PrivateKey*>(&key)) + return new NR_Signature_Operation(*s); +#endif + + return 0; } + +PK_Ops::Verification* +Default_Engine::get_verify_op(const Public_Key& key) const + { +#if defined(BOTAN_HAS_RSA) + if(const RSA_PublicKey* s = dynamic_cast<const RSA_PublicKey*>(&key)) + return new RSA_Public_Operation(*s); +#endif + +#if defined(BOTAN_HAS_RW) + if(const RW_PublicKey* s = dynamic_cast<const RW_PublicKey*>(&key)) + return new RW_Verification_Operation(*s); #endif +#if defined(BOTAN_HAS_DSA) + if(const DSA_PublicKey* s = dynamic_cast<const DSA_PublicKey*>(&key)) + return new DSA_Verification_Operation(*s); +#endif + +#if defined(BOTAN_HAS_ECDSA) + if(const ECDSA_PublicKey* s = dynamic_cast<const ECDSA_PublicKey*>(&key)) + return new ECDSA_Verification_Operation(*s); +#endif + +#if defined(BOTAN_HAS_GOST_3410_2001) + if(const GOST_3410_PublicKey* s = + dynamic_cast<const GOST_3410_PublicKey*>(&key)) + return new GOST_3410_Verification_Operation(*s); +#endif + +#if defined(BOTAN_HAS_NYBERG_RUEPPEL) + if(const NR_PublicKey* s = dynamic_cast<const NR_PublicKey*>(&key)) + return new NR_Verification_Operation(*s); +#endif + + return 0; + } + } diff --git a/src/engine/def_engine/default_engine.h b/src/engine/def_engine/default_engine.h index aa753fadb..1e40cfe46 100644 --- a/src/engine/def_engine/default_engine.h +++ b/src/engine/def_engine/default_engine.h @@ -20,31 +20,19 @@ class Default_Engine : public Engine public: std::string provider_name() const { return "core"; } -#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY) - IF_Operation* if_op(const BigInt&, const BigInt&, const BigInt&, - const BigInt&, const BigInt&, const BigInt&, - const BigInt&, const BigInt&) const; -#endif + PK_Ops::Key_Agreement* + get_key_agreement_op(const Private_Key& key) const; -#if defined(BOTAN_HAS_DSA) - DSA_Operation* dsa_op(const DL_Group&, const BigInt&, - const BigInt&) const; -#endif + PK_Ops::Signature* + get_signature_op(const Private_Key& key) const; -#if defined(BOTAN_HAS_NYBERG_RUEPPEL) - NR_Operation* nr_op(const DL_Group&, const BigInt&, const BigInt&) const; -#endif + PK_Ops::Verification* get_verify_op(const Public_Key& key) const; -#if defined(BOTAN_HAS_ELGAMAL) - ELG_Operation* elg_op(const DL_Group&, const BigInt&, - const BigInt&) const; -#endif + PK_Ops::Encryption* get_encryption_op(const Public_Key& key) const; -#if defined(BOTAN_HAS_DIFFIE_HELLMAN) - DH_Operation* dh_op(const DL_Group&, const BigInt&) const; -#endif + PK_Ops::Decryption* get_decryption_op(const Private_Key& key) const; - Modular_Exponentiator* mod_exp(const BigInt&, + Modular_Exponentiator* mod_exp(const BigInt& n, Power_Mod::Usage_Hints) const; virtual bool can_add_algorithms() { return true; } diff --git a/src/engine/engine.h b/src/engine/engine.h index ba5f95c27..69592886c 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -15,30 +15,12 @@ #include <botan/hash.h> #include <botan/mac.h> #include <botan/pow_mod.h> +#include <botan/pk_keys.h> +#include <botan/pk_ops.h> #include <utility> #include <map> -#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY) - #include <botan/if_op.h> -#endif - -#if defined(BOTAN_HAS_DSA) - #include <botan/dsa_op.h> -#endif - -#if defined(BOTAN_HAS_DIFFIE_HELLMAN) - #include <botan/dh_op.h> -#endif - -#if defined(BOTAN_HAS_NYBERG_RUEPPEL) - #include <botan/nr_op.h> -#endif - -#if defined(BOTAN_HAS_ELGAMAL) - #include <botan/elg_op.h> -#endif - namespace Botan { class Algorithm_Factory; @@ -80,35 +62,31 @@ class BOTAN_DLL Engine Algorithm_Factory&) { return 0; } -#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY) - virtual IF_Operation* if_op(const BigInt&, const BigInt&, const BigInt&, - const BigInt&, const BigInt&, const BigInt&, - const BigInt&, const BigInt&) const - { return 0; } -#endif - -#if defined(BOTAN_HAS_DSA) - virtual DSA_Operation* dsa_op(const DL_Group&, const BigInt&, - const BigInt&) const - { return 0; } -#endif - -#if defined(BOTAN_HAS_NYBERG_RUEPPEL) - virtual NR_Operation* nr_op(const DL_Group&, const BigInt&, - const BigInt&) const - { return 0; } -#endif - -#if defined(BOTAN_HAS_ELGAMAL) - virtual ELG_Operation* elg_op(const DL_Group&, const BigInt&, - const BigInt&) const - { return 0; } -#endif - -#if defined(BOTAN_HAS_DIFFIE_HELLMAN) - virtual DH_Operation* dh_op(const DL_Group&, const BigInt&) const - { return 0; } -#endif + virtual PK_Ops::Key_Agreement* + get_key_agreement_op(const Private_Key&) const + { + return 0; + } + + virtual PK_Ops::Signature* get_signature_op(const Private_Key&) const + { + return 0; + } + + virtual PK_Ops::Verification* get_verify_op(const Public_Key&) const + { + return 0; + } + + virtual PK_Ops::Encryption* get_encryption_op(const Public_Key&) const + { + return 0; + } + + virtual PK_Ops::Decryption* get_decryption_op(const Private_Key&) const + { + return 0; + } }; } diff --git a/src/engine/gnump/gmp_dh.cpp b/src/engine/gnump/gmp_dh.cpp deleted file mode 100644 index 430530dd3..000000000 --- a/src/engine/gnump/gmp_dh.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* -* GMP Engine -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/internal/gnump_engine.h> -#include <botan/internal/gmp_wrap.h> -#include <gmp.h> - -namespace Botan { - -#if defined(BOTAN_HAS_DIFFIE_HELLMAN) -namespace { - -/* -* GMP DH Operation -*/ -class GMP_DH_Op : public DH_Operation - { - public: - BigInt agree(const BigInt& i) const; - DH_Operation* clone() const { return new GMP_DH_Op(*this); } - - GMP_DH_Op(const DL_Group& group, const BigInt& x_bn) : - x(x_bn), p(group.get_p()) {} - private: - GMP_MPZ x, p; - }; - -/* -* GMP DH Key Agreement Operation -*/ -BigInt GMP_DH_Op::agree(const BigInt& i_bn) const - { - GMP_MPZ i(i_bn); - mpz_powm(i.value, i.value, x.value, p.value); - return i.to_bigint(); - } - -} - -/* -* Acquire a DH op -*/ -DH_Operation* GMP_Engine::dh_op(const DL_Group& group, const BigInt& x) const - { - return new GMP_DH_Op(group, x); - } -#endif - -} diff --git a/src/engine/gnump/gmp_dsa.cpp b/src/engine/gnump/gmp_dsa.cpp deleted file mode 100644 index b350a2075..000000000 --- a/src/engine/gnump/gmp_dsa.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/* -* GMP DSA Engine -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/internal/gnump_engine.h> -#include <botan/internal/gmp_wrap.h> -#include <gmp.h> - -namespace Botan { - -#if defined(BOTAN_HAS_DSA) - -namespace { - -/* -* GMP DSA Operation -*/ -class GMP_DSA_Op : public DSA_Operation - { - public: - bool verify(const byte[], u32bit, const byte[], u32bit) const; - SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const; - - DSA_Operation* clone() const { return new GMP_DSA_Op(*this); } - - GMP_DSA_Op(const DL_Group& group, const BigInt& y1, const BigInt& x1) : - x(x1), y(y1), p(group.get_p()), q(group.get_q()), g(group.get_g()) {} - private: - const GMP_MPZ x, y, p, q, g; - }; - -/* -* GMP DSA Verify Operation -*/ -bool GMP_DSA_Op::verify(const byte msg[], u32bit msg_len, - const byte sig[], u32bit sig_len) const - { - const u32bit q_bytes = q.bytes(); - - if(sig_len != 2*q_bytes || msg_len > q_bytes) - return false; - - GMP_MPZ r(sig, q_bytes); - GMP_MPZ s(sig + q_bytes, q_bytes); - GMP_MPZ i(msg, msg_len); - - if(mpz_cmp_ui(r.value, 0) <= 0 || mpz_cmp(r.value, q.value) >= 0) - return false; - if(mpz_cmp_ui(s.value, 0) <= 0 || mpz_cmp(s.value, q.value) >= 0) - return false; - - if(mpz_invert(s.value, s.value, q.value) == 0) - return false; - - GMP_MPZ si; - mpz_mul(si.value, s.value, i.value); - mpz_mod(si.value, si.value, q.value); - mpz_powm(si.value, g.value, si.value, p.value); - - GMP_MPZ sr; - mpz_mul(sr.value, s.value, r.value); - mpz_mod(sr.value, sr.value, q.value); - mpz_powm(sr.value, y.value, sr.value, p.value); - - mpz_mul(si.value, si.value, sr.value); - mpz_mod(si.value, si.value, p.value); - mpz_mod(si.value, si.value, q.value); - - if(mpz_cmp(si.value, r.value) == 0) - return true; - return false; - } - -/* -* GMP DSA Sign Operation -*/ -SecureVector<byte> GMP_DSA_Op::sign(const byte in[], u32bit length, - const BigInt& k_bn) const - { - if(mpz_cmp_ui(x.value, 0) == 0) - throw Internal_Error("GMP_DSA_Op::sign: No private key"); - - GMP_MPZ i(in, length); - GMP_MPZ k(k_bn); - - GMP_MPZ r; - mpz_powm(r.value, g.value, k.value, p.value); - mpz_mod(r.value, r.value, q.value); - - mpz_invert(k.value, k.value, q.value); - - GMP_MPZ s; - mpz_mul(s.value, x.value, r.value); - mpz_add(s.value, s.value, i.value); - mpz_mul(s.value, s.value, k.value); - mpz_mod(s.value, s.value, q.value); - - 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"); - - const u32bit q_bytes = q.bytes(); - - SecureVector<byte> output(2*q_bytes); - r.encode(output, q_bytes); - s.encode(output + q_bytes, q_bytes); - return output; - } - -} - -/* -* Acquire a DSA op -*/ -DSA_Operation* GMP_Engine::dsa_op(const DL_Group& group, const BigInt& y, - const BigInt& x) const - { - return new GMP_DSA_Op(group, y, x); - } -#endif - -} diff --git a/src/engine/gnump/gmp_elg.cpp b/src/engine/gnump/gmp_elg.cpp deleted file mode 100644 index 539804a23..000000000 --- a/src/engine/gnump/gmp_elg.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/* -* GMP ElGamal Engine -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/internal/gnump_engine.h> -#include <botan/internal/gmp_wrap.h> -#include <gmp.h> - -namespace Botan { - -#if defined(BOTAN_HAS_ELGAMAL) - -namespace { - -/* -* GMP ElGamal Operation -*/ -class GMP_ELG_Op : public ELG_Operation - { - public: - SecureVector<byte> encrypt(const byte[], u32bit, const BigInt&) const; - BigInt decrypt(const BigInt&, const BigInt&) const; - - ELG_Operation* clone() const { return new GMP_ELG_Op(*this); } - - GMP_ELG_Op(const DL_Group& group, const BigInt& y1, const BigInt& x1) : - x(x1), y(y1), g(group.get_g()), p(group.get_p()) {} - private: - GMP_MPZ x, y, g, p; - }; - -/* -* GMP ElGamal Encrypt Operation -*/ -SecureVector<byte> GMP_ELG_Op::encrypt(const byte in[], u32bit length, - const BigInt& k_bn) const - { - GMP_MPZ i(in, length); - - if(mpz_cmp(i.value, p.value) >= 0) - throw Invalid_Argument("GMP_ELG_Op: Input is too large"); - - GMP_MPZ a, b, k(k_bn); - - mpz_powm(a.value, g.value, k.value, p.value); - mpz_powm(b.value, y.value, k.value, p.value); - mpz_mul(b.value, b.value, i.value); - mpz_mod(b.value, b.value, p.value); - - const u32bit p_bytes = p.bytes(); - SecureVector<byte> output(2*p_bytes); - a.encode(output, p_bytes); - b.encode(output + p_bytes, p_bytes); - return output; - } - -/* -* GMP ElGamal Decrypt Operation -*/ -BigInt GMP_ELG_Op::decrypt(const BigInt& a_bn, const BigInt& b_bn) const - { - if(mpz_cmp_ui(x.value, 0) == 0) - throw Internal_Error("GMP_ELG_Op::decrypt: No private key"); - - GMP_MPZ a(a_bn), b(b_bn); - - if(mpz_cmp(a.value, p.value) >= 0 || mpz_cmp(b.value, p.value) >= 0) - throw Invalid_Argument("GMP_ELG_Op: Invalid message"); - - mpz_powm(a.value, a.value, x.value, p.value); - mpz_invert(a.value, a.value, p.value); - mpz_mul(a.value, a.value, b.value); - mpz_mod(a.value, a.value, p.value); - return a.to_bigint(); - } - -} - -/* -* Acquire an ElGamal op -*/ -ELG_Operation* GMP_Engine::elg_op(const DL_Group& group, const BigInt& y, - const BigInt& x) const - { - return new GMP_ELG_Op(group, y, x); - } -#endif - -} diff --git a/src/engine/gnump/gmp_if.cpp b/src/engine/gnump/gmp_if.cpp deleted file mode 100644 index 64fbe386a..000000000 --- a/src/engine/gnump/gmp_if.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* -* GMP IF Engine -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/internal/gnump_engine.h> -#include <botan/internal/gmp_wrap.h> -#include <gmp.h> - -namespace Botan { - -#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY) - -namespace { - -/* -* GMP IF Operation -*/ -class GMP_IF_Op : public IF_Operation - { - public: - BigInt public_op(const BigInt&) const; - BigInt private_op(const BigInt&) const; - - IF_Operation* clone() const { return new GMP_IF_Op(*this); } - - GMP_IF_Op(const BigInt& e_bn, const BigInt& n_bn, const BigInt&, - const BigInt& p_bn, const BigInt& q_bn, const BigInt& d1_bn, - const BigInt& d2_bn, const BigInt& c_bn) : - e(e_bn), n(n_bn), p(p_bn), q(q_bn), d1(d1_bn), d2(d2_bn), c(c_bn) {} - private: - const GMP_MPZ e, n, p, q, d1, d2, c; - }; - -/* -* GMP IF Public Operation -*/ -BigInt GMP_IF_Op::public_op(const BigInt& i_bn) const - { - GMP_MPZ i(i_bn); - mpz_powm(i.value, i.value, e.value, n.value); - return i.to_bigint(); - } - -/* -* GMP IF Private Operation -*/ -BigInt GMP_IF_Op::private_op(const BigInt& i_bn) const - { - if(mpz_cmp_ui(p.value, 0) == 0) - throw Internal_Error("GMP_IF_Op::private_op: No private key"); - - GMP_MPZ j1, j2, h(i_bn); - - mpz_powm(j1.value, h.value, d1.value, p.value); - mpz_powm(j2.value, h.value, d2.value, q.value); - mpz_sub(h.value, j1.value, j2.value); - mpz_mul(h.value, h.value, c.value); - mpz_mod(h.value, h.value, p.value); - mpz_mul(h.value, h.value, q.value); - mpz_add(h.value, h.value, j2.value); - return h.to_bigint(); - } - -} - -/* -* Acquire an IF op -*/ -IF_Operation* GMP_Engine::if_op(const BigInt& e, const BigInt& n, - const BigInt& d, const BigInt& p, - const BigInt& q, const BigInt& d1, - const BigInt& d2, const BigInt& c) const - { - return new GMP_IF_Op(e, n, d, p, q, d1, d2, c); - } -#endif - -} diff --git a/src/engine/gnump/gmp_nr.cpp b/src/engine/gnump/gmp_nr.cpp deleted file mode 100644 index 7d6fe536d..000000000 --- a/src/engine/gnump/gmp_nr.cpp +++ /dev/null @@ -1,107 +0,0 @@ -/* -* GMP NR Engine -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/internal/gnump_engine.h> -#include <botan/internal/gmp_wrap.h> -#include <gmp.h> - -namespace Botan { - -#if defined(BOTAN_HAS_NYBERG_RUEPPEL) - -namespace { - -/* -* GMP NR Operation -*/ -class GMP_NR_Op : public NR_Operation - { - public: - SecureVector<byte> verify(const byte[], u32bit) const; - SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const; - - NR_Operation* clone() const { return new GMP_NR_Op(*this); } - - GMP_NR_Op(const DL_Group& group, const BigInt& y1, const BigInt& x1) : - x(x1), y(y1), p(group.get_p()), q(group.get_q()), g(group.get_g()) {} - private: - const GMP_MPZ x, y, p, q, g; - }; - -/* -* GMP NR Verify Operation -*/ -SecureVector<byte> GMP_NR_Op::verify(const byte sig[], u32bit sig_len) const - { - const u32bit q_bytes = q.bytes(); - - if(sig_len != 2*q_bytes) - return false; - - GMP_MPZ c(sig, q_bytes); - GMP_MPZ d(sig + q_bytes, q_bytes); - - if(mpz_cmp_ui(c.value, 0) <= 0 || mpz_cmp(c.value, q.value) >= 0 || - mpz_cmp(d.value, q.value) >= 0) - throw Invalid_Argument("GMP_NR_Op::verify: Invalid signature"); - - GMP_MPZ i1, i2; - mpz_powm(i1.value, g.value, d.value, p.value); - mpz_powm(i2.value, y.value, c.value, p.value); - mpz_mul(i1.value, i1.value, i2.value); - mpz_mod(i1.value, i1.value, p.value); - mpz_sub(i1.value, c.value, i1.value); - mpz_mod(i1.value, i1.value, q.value); - return BigInt::encode(i1.to_bigint()); - } - -/* -* GMP NR Sign Operation -*/ -SecureVector<byte> GMP_NR_Op::sign(const byte in[], u32bit length, - const BigInt& k_bn) const - { - if(mpz_cmp_ui(x.value, 0) == 0) - throw Internal_Error("GMP_NR_Op::sign: No private key"); - - GMP_MPZ f(in, length); - GMP_MPZ k(k_bn); - - if(mpz_cmp(f.value, q.value) >= 0) - throw Invalid_Argument("GMP_NR_Op::sign: Input is out of range"); - - GMP_MPZ c, d; - mpz_powm(c.value, g.value, k.value, p.value); - mpz_add(c.value, c.value, f.value); - mpz_mod(c.value, c.value, q.value); - mpz_mul(d.value, x.value, c.value); - mpz_sub(d.value, k.value, d.value); - mpz_mod(d.value, d.value, q.value); - - if(mpz_cmp_ui(c.value, 0) == 0) - throw Internal_Error("Default_NR_Op::sign: c was zero"); - - const u32bit q_bytes = q.bytes(); - SecureVector<byte> output(2*q_bytes); - c.encode(output, q_bytes); - d.encode(output + q_bytes, q_bytes); - return output; - } - -} - -/* -* Acquire a NR op -*/ -NR_Operation* GMP_Engine::nr_op(const DL_Group& group, const BigInt& y, - const BigInt& x) const - { - return new GMP_NR_Op(group, y, x); - } -#endif - -} diff --git a/src/engine/gnump/gmp_wrap.h b/src/engine/gnump/gmp_wrap.h index f8d9cf365..82437ceba 100644 --- a/src/engine/gnump/gmp_wrap.h +++ b/src/engine/gnump/gmp_wrap.h @@ -25,6 +25,9 @@ class GMP_MPZ void encode(byte[], u32bit) const; u32bit bytes() const; + SecureVector<byte> to_bytes() const + { return BigInt::encode(to_bigint()); } + GMP_MPZ& operator=(const GMP_MPZ&); GMP_MPZ(const GMP_MPZ&); diff --git a/src/engine/gnump/gnump_engine.h b/src/engine/gnump/gnump_engine.h index d0b070441..1ca5a3548 100644 --- a/src/engine/gnump/gnump_engine.h +++ b/src/engine/gnump/gnump_engine.h @@ -23,29 +23,17 @@ class GMP_Engine : public Engine std::string provider_name() const { return "gmp"; } -#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY) - IF_Operation* if_op(const BigInt&, const BigInt&, const BigInt&, - const BigInt&, const BigInt&, const BigInt&, - const BigInt&, const BigInt&) const; -#endif + PK_Ops::Key_Agreement* + get_key_agreement_op(const Private_Key& key) const; -#if defined(BOTAN_HAS_DSA) - DSA_Operation* dsa_op(const DL_Group&, const BigInt&, - const BigInt&) const; -#endif + PK_Ops::Signature* + get_signature_op(const Private_Key& key) const; -#if defined(BOTAN_HAS_NYBERG_RUEPPEL) - NR_Operation* nr_op(const DL_Group&, const BigInt&, const BigInt&) const; -#endif + PK_Ops::Verification* get_verify_op(const Public_Key& key) const; -#if defined(BOTAN_HAS_ELGAMAL) - ELG_Operation* elg_op(const DL_Group&, const BigInt&, - const BigInt&) const; -#endif + PK_Ops::Encryption* get_encryption_op(const Public_Key& key) const; -#if defined(BOTAN_HAS_DIFFIE_HELLMAN) - DH_Operation* dh_op(const DL_Group&, const BigInt&) const; -#endif + PK_Ops::Decryption* get_decryption_op(const Private_Key& key) const; Modular_Exponentiator* mod_exp(const BigInt&, Power_Mod::Usage_Hints) const; diff --git a/src/engine/gnump/gnump_pk.cpp b/src/engine/gnump/gnump_pk.cpp new file mode 100644 index 000000000..8d003a5d4 --- /dev/null +++ b/src/engine/gnump/gnump_pk.cpp @@ -0,0 +1,350 @@ +/* +* GnuMP PK operations +* (C) 1999-2010 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/internal/gnump_engine.h> +#include <botan/internal/gmp_wrap.h> +#include <gmp.h> + +/* GnuMP 5.0 and later have a side-channel resistent powm */ +#if defined(HAVE_MPZ_POWM_SEC) + #undef mpz_powm + #define mpz_powm mpz_powm_sec +#endif + +#if defined(BOTAN_HAS_RSA) + #include <botan/rsa.h> +#endif + +#if defined(BOTAN_HAS_RW) + #include <botan/rw.h> +#endif + +#if defined(BOTAN_HAS_DSA) + #include <botan/dsa.h> +#endif + +#if defined(BOTAN_HAS_ELGAMAL) + #include <botan/elgamal.h> +#endif + +#if defined(BOTAN_HAS_NYBERG_RUEPPEL) + #include <botan/nr.h> +#endif + +#if defined(BOTAN_HAS_DIFFIE_HELLMAN) + #include <botan/dh.h> +#endif + +namespace Botan { + +namespace { + +#if defined(BOTAN_HAS_DIFFIE_HELLMAN) +class GMP_DH_KA_Operation : public PK_Ops::Key_Agreement + { + public: + GMP_DH_KA_Operation(const DH_PrivateKey& dh) : + x(dh.get_x()), p(dh.group_p()) {} + + SecureVector<byte> agree(const byte w[], u32bit w_len) + { + GMP_MPZ z(w, w_len); + mpz_powm(z.value, z.value, x.value, p.value); + return z.to_bytes(); + } + + private: + GMP_MPZ x, p; + }; +#endif + +#if defined(BOTAN_HAS_DSA) + +class GMP_DSA_Signature_Operation : public PK_Ops::Signature + { + public: + GMP_DSA_Signature_Operation(const DSA_PrivateKey& dsa) : + x(dsa.get_x()), + p(dsa.group_p()), + q(dsa.group_q()), + g(dsa.group_g()), + q_bits(dsa.group_q().bits()) {} + + u32bit message_parts() const { return 2; } + u32bit message_part_size() const { return (q_bits + 7) / 8; } + u32bit max_input_bits() const { return q_bits; } + + SecureVector<byte> sign(const byte msg[], u32bit msg_len, + RandomNumberGenerator& rng); + private: + const GMP_MPZ x, p, q, g; + u32bit q_bits; + }; + +SecureVector<byte> +GMP_DSA_Signature_Operation::sign(const byte msg[], u32bit msg_len, + RandomNumberGenerator& rng) + { + const u32bit q_bytes = (q_bits + 7) / 8; + + rng.add_entropy(msg, msg_len); + + BigInt k_bn; + do + k_bn.randomize(rng, q_bits); + while(k_bn >= q.to_bigint()); + + GMP_MPZ i(msg, msg_len); + GMP_MPZ k(k_bn); + + GMP_MPZ r; + mpz_powm(r.value, g.value, k.value, p.value); + mpz_mod(r.value, r.value, q.value); + + mpz_invert(k.value, k.value, q.value); + + GMP_MPZ s; + mpz_mul(s.value, x.value, r.value); + mpz_add(s.value, s.value, i.value); + mpz_mul(s.value, s.value, k.value); + mpz_mod(s.value, s.value, q.value); + + 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); + r.encode(output, q_bytes); + s.encode(output + q_bytes, q_bytes); + return output; + } + +class GMP_DSA_Verification_Operation : public PK_Ops::Verification + { + public: + GMP_DSA_Verification_Operation(const DSA_PublicKey& dsa) : + y(dsa.get_y()), + p(dsa.group_p()), + q(dsa.group_q()), + g(dsa.group_g()), + q_bits(dsa.group_q().bits()) {} + + u32bit message_parts() const { return 2; } + u32bit message_part_size() const { return (q_bits + 7) / 8; } + u32bit max_input_bits() const { return q_bits; } + + bool with_recovery() const { return false; } + + bool verify(const byte msg[], u32bit msg_len, + const byte sig[], u32bit sig_len); + private: + const GMP_MPZ y, p, q, g; + u32bit q_bits; + }; + +bool GMP_DSA_Verification_Operation::verify(const byte msg[], u32bit msg_len, + const byte sig[], u32bit sig_len) + { + const u32bit q_bytes = q.bytes(); + + if(sig_len != 2*q_bytes || msg_len > q_bytes) + return false; + + GMP_MPZ r(sig, q_bytes); + GMP_MPZ s(sig + q_bytes, q_bytes); + GMP_MPZ i(msg, msg_len); + + if(mpz_cmp_ui(r.value, 0) <= 0 || mpz_cmp(r.value, q.value) >= 0) + return false; + if(mpz_cmp_ui(s.value, 0) <= 0 || mpz_cmp(s.value, q.value) >= 0) + return false; + + if(mpz_invert(s.value, s.value, q.value) == 0) + return false; + + GMP_MPZ si; + mpz_mul(si.value, s.value, i.value); + mpz_mod(si.value, si.value, q.value); + mpz_powm(si.value, g.value, si.value, p.value); + + GMP_MPZ sr; + mpz_mul(sr.value, s.value, r.value); + mpz_mod(sr.value, sr.value, q.value); + mpz_powm(sr.value, y.value, sr.value, p.value); + + mpz_mul(si.value, si.value, sr.value); + mpz_mod(si.value, si.value, p.value); + mpz_mod(si.value, si.value, q.value); + + if(mpz_cmp(si.value, r.value) == 0) + return true; + return false; + } + +#endif + +#if defined(BOTAN_HAS_RSA) + +class GMP_RSA_Private_Operation : public PK_Ops::Signature, + public PK_Ops::Decryption + { + public: + GMP_RSA_Private_Operation(const RSA_PrivateKey& rsa) : + mod(rsa.get_n()), + p(rsa.get_p()), + q(rsa.get_q()), + d1(rsa.get_d1()), + d2(rsa.get_d2()), + c(rsa.get_c()), + n_bits(rsa.get_n().bits()) + {} + + u32bit max_input_bits() const { return (n_bits - 1); } + + SecureVector<byte> sign(const byte msg[], u32bit msg_len, + RandomNumberGenerator&) + { + BigInt m(msg, msg_len); + BigInt x = private_op(m); + return BigInt::encode_1363(x, (n_bits + 7) / 8); + } + + SecureVector<byte> decrypt(const byte msg[], u32bit msg_len) + { + BigInt m(msg, msg_len); + return BigInt::encode(private_op(m)); + } + + private: + BigInt private_op(const BigInt& m) const; + + GMP_MPZ mod, p, q, d1, d2, c; + u32bit n_bits; + }; + +BigInt GMP_RSA_Private_Operation::private_op(const BigInt& m) const + { + GMP_MPZ j1, j2, h(m); + + mpz_powm(j1.value, h.value, d1.value, p.value); + mpz_powm(j2.value, h.value, d2.value, q.value); + mpz_sub(h.value, j1.value, j2.value); + mpz_mul(h.value, h.value, c.value); + mpz_mod(h.value, h.value, p.value); + mpz_mul(h.value, h.value, q.value); + mpz_add(h.value, h.value, j2.value); + return h.to_bigint(); + } + +class GMP_RSA_Public_Operation : public PK_Ops::Verification, + public PK_Ops::Encryption + { + public: + GMP_RSA_Public_Operation(const RSA_PublicKey& rsa) : + n(rsa.get_n()), e(rsa.get_e()), mod(rsa.get_n()) + {} + + u32bit max_input_bits() const { return (n.bits() - 1); } + bool with_recovery() const { return true; } + + SecureVector<byte> encrypt(const byte msg[], u32bit msg_len, + RandomNumberGenerator&) + { + BigInt m(msg, msg_len); + return BigInt::encode_1363(public_op(m), n.bytes()); + } + + SecureVector<byte> verify_mr(const byte msg[], u32bit msg_len) + { + BigInt m(msg, msg_len); + return BigInt::encode(public_op(m)); + } + + private: + BigInt public_op(const BigInt& m) const + { + if(m >= n) + throw Invalid_Argument("RSA public op - input is too large"); + + GMP_MPZ m_gmp(m); + mpz_powm(m_gmp.value, m_gmp.value, e.value, mod.value); + return m_gmp.to_bigint(); + } + + const BigInt& n; + const GMP_MPZ e, mod; + }; + +#endif + +} + +PK_Ops::Key_Agreement* +GMP_Engine::get_key_agreement_op(const Private_Key& key) const + { +#if defined(BOTAN_HAS_DIFFIE_HELLMAN) + if(const DH_PrivateKey* dh = dynamic_cast<const DH_PrivateKey*>(&key)) + return new GMP_DH_KA_Operation(*dh); +#endif + + return 0; + } + +PK_Ops::Signature* +GMP_Engine::get_signature_op(const Private_Key& key) const + { +#if defined(BOTAN_HAS_RSA) + if(const RSA_PrivateKey* s = dynamic_cast<const RSA_PrivateKey*>(&key)) + return new GMP_RSA_Private_Operation(*s); +#endif + +#if defined(BOTAN_HAS_DSA) + if(const DSA_PrivateKey* s = dynamic_cast<const DSA_PrivateKey*>(&key)) + return new GMP_DSA_Signature_Operation(*s); +#endif + + return 0; + } + +PK_Ops::Verification* +GMP_Engine::get_verify_op(const Public_Key& key) const + { +#if defined(BOTAN_HAS_RSA) + if(const RSA_PublicKey* s = dynamic_cast<const RSA_PublicKey*>(&key)) + return new GMP_RSA_Public_Operation(*s); +#endif + +#if defined(BOTAN_HAS_DSA) + if(const DSA_PublicKey* s = dynamic_cast<const DSA_PublicKey*>(&key)) + return new GMP_DSA_Verification_Operation(*s); +#endif + + return 0; + } + +PK_Ops::Encryption* +GMP_Engine::get_encryption_op(const Public_Key& key) const + { +#if defined(BOTAN_HAS_RSA) + if(const RSA_PublicKey* s = dynamic_cast<const RSA_PublicKey*>(&key)) + return new GMP_RSA_Public_Operation(*s); +#endif + + return 0; + } + +PK_Ops::Decryption* +GMP_Engine::get_decryption_op(const Private_Key& key) const + { +#if defined(BOTAN_HAS_RSA) + if(const RSA_PrivateKey* s = dynamic_cast<const RSA_PrivateKey*>(&key)) + return new GMP_RSA_Private_Operation(*s); +#endif + + return 0; + } + +} diff --git a/src/engine/gnump/info.txt b/src/engine/gnump/info.txt index bd5c15f7f..7a789681e 100644 --- a/src/engine/gnump/info.txt +++ b/src/engine/gnump/info.txt @@ -12,14 +12,10 @@ gmp_wrap.h </header:internal> <source> -gmp_dh.cpp -gmp_dsa.cpp -gmp_elg.cpp -gmp_if.cpp gmp_mem.cpp -gmp_nr.cpp gmp_powm.cpp gmp_wrap.cpp +gnump_pk.cpp </source> <requires> diff --git a/src/engine/info.txt b/src/engine/info.txt index b270edaa5..32fcf21c2 100644 --- a/src/engine/info.txt +++ b/src/engine/info.txt @@ -10,5 +10,6 @@ hash libstate mac numbertheory +pubkey stream </requires> diff --git a/src/engine/openssl/bn_wrap.h b/src/engine/openssl/bn_wrap.h index 0307189a9..02a229fdd 100644 --- a/src/engine/openssl/bn_wrap.h +++ b/src/engine/openssl/bn_wrap.h @@ -25,6 +25,9 @@ class OSSL_BN void encode(byte[], u32bit) const; u32bit bytes() const; + SecureVector<byte> to_bytes() const + { return BigInt::encode(to_bigint()); } + OSSL_BN& operator=(const OSSL_BN&); OSSL_BN(const OSSL_BN&); diff --git a/src/engine/openssl/info.txt b/src/engine/openssl/info.txt index c65f80a29..38322bfff 100644 --- a/src/engine/openssl/info.txt +++ b/src/engine/openssl/info.txt @@ -16,12 +16,8 @@ arc4_openssl.cpp bn_powm.cpp bn_wrap.cpp ossl_bc.cpp -ossl_dh.cpp -ossl_dsa.cpp -ossl_elg.cpp -ossl_if.cpp ossl_md.cpp -ossl_nr.cpp +openssl_pk.cpp </source> <requires> diff --git a/src/engine/openssl/openssl_engine.h b/src/engine/openssl/openssl_engine.h index 4ee2be2c0..1ee7e4c11 100644 --- a/src/engine/openssl/openssl_engine.h +++ b/src/engine/openssl/openssl_engine.h @@ -23,29 +23,17 @@ class OpenSSL_Engine : public Engine */ std::string provider_name() const { return "openssl"; } -#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY) - IF_Operation* if_op(const BigInt&, const BigInt&, const BigInt&, - const BigInt&, const BigInt&, const BigInt&, - const BigInt&, const BigInt&) const; -#endif + PK_Ops::Key_Agreement* + get_key_agreement_op(const Private_Key& key) const; -#if defined(BOTAN_HAS_DSA) - DSA_Operation* dsa_op(const DL_Group&, const BigInt&, - const BigInt&) const; -#endif + PK_Ops::Signature* + get_signature_op(const Private_Key& key) const; -#if defined(BOTAN_HAS_NYBERG_RUEPPEL) - NR_Operation* nr_op(const DL_Group&, const BigInt&, const BigInt&) const; -#endif + PK_Ops::Verification* get_verify_op(const Public_Key& key) const; -#if defined(BOTAN_HAS_ELGAMAL) - ELG_Operation* elg_op(const DL_Group&, const BigInt&, - const BigInt&) const; -#endif + PK_Ops::Encryption* get_encryption_op(const Public_Key& key) const; -#if defined(BOTAN_HAS_DIFFIE_HELLMAN) - DH_Operation* dh_op(const DL_Group&, const BigInt&) const; -#endif + PK_Ops::Decryption* get_decryption_op(const Private_Key& key) const; Modular_Exponentiator* mod_exp(const BigInt&, Power_Mod::Usage_Hints) const; diff --git a/src/engine/openssl/openssl_pk.cpp b/src/engine/openssl/openssl_pk.cpp new file mode 100644 index 000000000..8b8e83ebe --- /dev/null +++ b/src/engine/openssl/openssl_pk.cpp @@ -0,0 +1,345 @@ +/* +* OpenSSL PK operations +* (C) 1999-2010 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/internal/openssl_engine.h> +#include <botan/internal/bn_wrap.h> + +#if defined(BOTAN_HAS_RSA) + #include <botan/rsa.h> +#endif + +#if defined(BOTAN_HAS_RW) + #include <botan/rw.h> +#endif + +#if defined(BOTAN_HAS_DSA) + #include <botan/dsa.h> +#endif + +#if defined(BOTAN_HAS_ELGAMAL) + #include <botan/elgamal.h> +#endif + +#if defined(BOTAN_HAS_NYBERG_RUEPPEL) + #include <botan/nr.h> +#endif + +#if defined(BOTAN_HAS_DIFFIE_HELLMAN) + #include <botan/dh.h> +#endif + +namespace Botan { + +namespace { + +#if defined(BOTAN_HAS_DIFFIE_HELLMAN) +class OSSL_DH_KA_Operation : public PK_Ops::Key_Agreement + { + public: + OSSL_DH_KA_Operation(const DH_PrivateKey& dh) : + x(dh.get_x()), p(dh.group_p()) {} + + SecureVector<byte> agree(const byte w[], u32bit w_len) + { + OSSL_BN i(w, w_len), r; + BN_mod_exp(r.value, i.value, x.value, p.value, ctx.value); + return r.to_bytes(); + } + + private: + const OSSL_BN x, p; + OSSL_BN_CTX ctx; + }; +#endif + +#if defined(BOTAN_HAS_DSA) + +class OSSL_DSA_Signature_Operation : public PK_Ops::Signature + { + public: + OSSL_DSA_Signature_Operation(const DSA_PrivateKey& dsa) : + x(dsa.get_x()), + p(dsa.group_p()), + q(dsa.group_q()), + g(dsa.group_g()), + q_bits(dsa.group_q().bits()) {} + + u32bit message_parts() const { return 2; } + u32bit message_part_size() const { return (q_bits + 7) / 8; } + u32bit max_input_bits() const { return q_bits; } + + SecureVector<byte> sign(const byte msg[], u32bit msg_len, + RandomNumberGenerator& rng); + private: + const OSSL_BN x, p, q, g; + const OSSL_BN_CTX ctx; + u32bit q_bits; + }; + +SecureVector<byte> +OSSL_DSA_Signature_Operation::sign(const byte msg[], u32bit msg_len, + RandomNumberGenerator& rng) + { + const u32bit q_bytes = (q_bits + 7) / 8; + + rng.add_entropy(msg, msg_len); + + BigInt k_bn; + do + k_bn.randomize(rng, q_bits); + while(k_bn >= q.to_bigint()); + + OSSL_BN i(msg, msg_len); + OSSL_BN k(k_bn); + + OSSL_BN r; + BN_mod_exp(r.value, g.value, k.value, p.value, ctx.value); + BN_nnmod(r.value, r.value, q.value, ctx.value); + + BN_mod_inverse(k.value, k.value, q.value, ctx.value); + + OSSL_BN s; + BN_mul(s.value, x.value, r.value, ctx.value); + BN_add(s.value, s.value, i.value); + BN_mod_mul(s.value, s.value, k.value, q.value, ctx.value); + + 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); + r.encode(output, q_bytes); + s.encode(output + q_bytes, q_bytes); + return output; + } + +class OSSL_DSA_Verification_Operation : public PK_Ops::Verification + { + public: + OSSL_DSA_Verification_Operation(const DSA_PublicKey& dsa) : + y(dsa.get_y()), + p(dsa.group_p()), + q(dsa.group_q()), + g(dsa.group_g()), + q_bits(dsa.group_q().bits()) {} + + u32bit message_parts() const { return 2; } + u32bit message_part_size() const { return (q_bits + 7) / 8; } + u32bit max_input_bits() const { return q_bits; } + + bool with_recovery() const { return false; } + + bool verify(const byte msg[], u32bit msg_len, + const byte sig[], u32bit sig_len); + private: + const OSSL_BN y, p, q, g; + const OSSL_BN_CTX ctx; + u32bit q_bits; + }; + +bool OSSL_DSA_Verification_Operation::verify(const byte msg[], u32bit msg_len, + const byte sig[], u32bit sig_len) + { + const u32bit q_bytes = q.bytes(); + + if(sig_len != 2*q_bytes || msg_len > q_bytes) + return false; + + OSSL_BN r(sig, q_bytes); + OSSL_BN s(sig + q_bytes, q_bytes); + OSSL_BN i(msg, msg_len); + + if(BN_is_zero(r.value) || BN_cmp(r.value, q.value) >= 0) + return false; + if(BN_is_zero(s.value) || BN_cmp(s.value, q.value) >= 0) + return false; + + if(BN_mod_inverse(s.value, s.value, q.value, ctx.value) == 0) + return false; + + OSSL_BN si; + BN_mod_mul(si.value, s.value, i.value, q.value, ctx.value); + BN_mod_exp(si.value, g.value, si.value, p.value, ctx.value); + + OSSL_BN sr; + BN_mod_mul(sr.value, s.value, r.value, q.value, ctx.value); + BN_mod_exp(sr.value, y.value, sr.value, p.value, ctx.value); + + BN_mod_mul(si.value, si.value, sr.value, p.value, ctx.value); + BN_nnmod(si.value, si.value, q.value, ctx.value); + + if(BN_cmp(si.value, r.value) == 0) + return true; + return false; + + return false; + } + +#endif + +#if defined(BOTAN_HAS_RSA) + +class OSSL_RSA_Private_Operation : public PK_Ops::Signature, + public PK_Ops::Decryption + { + public: + OSSL_RSA_Private_Operation(const RSA_PrivateKey& rsa) : + mod(rsa.get_n()), + p(rsa.get_p()), + q(rsa.get_q()), + d1(rsa.get_d1()), + d2(rsa.get_d2()), + c(rsa.get_c()), + n_bits(rsa.get_n().bits()) + {} + + u32bit max_input_bits() const { return (n_bits - 1); } + + SecureVector<byte> sign(const byte msg[], u32bit msg_len, + RandomNumberGenerator& rng) + { + BigInt m(msg, msg_len); + BigInt x = private_op(m); + return BigInt::encode_1363(x, (n_bits + 7) / 8); + } + + SecureVector<byte> decrypt(const byte msg[], u32bit msg_len) + { + BigInt m(msg, msg_len); + return BigInt::encode(private_op(m)); + } + + private: + BigInt private_op(const BigInt& m) const; + + const OSSL_BN mod, p, q, d1, d2, c; + const OSSL_BN_CTX ctx; + u32bit n_bits; + }; + +BigInt OSSL_RSA_Private_Operation::private_op(const BigInt& m) const + { + OSSL_BN j1, j2, h(m); + + BN_mod_exp(j1.value, h.value, d1.value, p.value, ctx.value); + BN_mod_exp(j2.value, h.value, d2.value, q.value, ctx.value); + BN_sub(h.value, j1.value, j2.value); + BN_mod_mul(h.value, h.value, c.value, p.value, ctx.value); + BN_mul(h.value, h.value, q.value, ctx.value); + BN_add(h.value, h.value, j2.value); + return h.to_bigint(); + } + +class OSSL_RSA_Public_Operation : public PK_Ops::Verification, + public PK_Ops::Encryption + { + public: + OSSL_RSA_Public_Operation(const RSA_PublicKey& rsa) : + n(rsa.get_n()), e(rsa.get_e()), mod(rsa.get_n()) + {} + + u32bit max_input_bits() const { return (n.bits() - 1); } + bool with_recovery() const { return true; } + + SecureVector<byte> encrypt(const byte msg[], u32bit msg_len, + RandomNumberGenerator&) + { + BigInt m(msg, msg_len); + return BigInt::encode_1363(public_op(m), n.bytes()); + } + + SecureVector<byte> verify_mr(const byte msg[], u32bit msg_len) + { + BigInt m(msg, msg_len); + return BigInt::encode(public_op(m)); + } + + private: + BigInt public_op(const BigInt& m) const + { + if(m >= n) + throw Invalid_Argument("RSA public op - input is too large"); + + OSSL_BN m_bn(m), r; + BN_mod_exp(r.value, m_bn.value, e.value, mod.value, ctx.value); + return r.to_bigint(); + } + + const BigInt& n; + const OSSL_BN e, mod; + const OSSL_BN_CTX ctx; + }; + +#endif + +} + +PK_Ops::Key_Agreement* +OpenSSL_Engine::get_key_agreement_op(const Private_Key& key) const + { +#if defined(BOTAN_HAS_DIFFIE_HELLMAN) + if(const DH_PrivateKey* dh = dynamic_cast<const DH_PrivateKey*>(&key)) + return new OSSL_DH_KA_Operation(*dh); +#endif + + return 0; + } + +PK_Ops::Signature* +OpenSSL_Engine::get_signature_op(const Private_Key& key) const + { +#if defined(BOTAN_HAS_RSA) + if(const RSA_PrivateKey* s = dynamic_cast<const RSA_PrivateKey*>(&key)) + return new OSSL_RSA_Private_Operation(*s); +#endif + +#if defined(BOTAN_HAS_DSA) + if(const DSA_PrivateKey* s = dynamic_cast<const DSA_PrivateKey*>(&key)) + return new OSSL_DSA_Signature_Operation(*s); +#endif + + return 0; + } + +PK_Ops::Verification* +OpenSSL_Engine::get_verify_op(const Public_Key& key) const + { +#if defined(BOTAN_HAS_RSA) + if(const RSA_PublicKey* s = dynamic_cast<const RSA_PublicKey*>(&key)) + return new OSSL_RSA_Public_Operation(*s); +#endif + +#if defined(BOTAN_HAS_DSA) + if(const DSA_PublicKey* s = dynamic_cast<const DSA_PublicKey*>(&key)) + return new OSSL_DSA_Verification_Operation(*s); +#endif + + return 0; + } + +PK_Ops::Encryption* +OpenSSL_Engine::get_encryption_op(const Public_Key& key) const + { +#if defined(BOTAN_HAS_RSA) + if(const RSA_PublicKey* s = dynamic_cast<const RSA_PublicKey*>(&key)) + return new OSSL_RSA_Public_Operation(*s); +#endif + + return 0; + } + +PK_Ops::Decryption* +OpenSSL_Engine::get_decryption_op(const Private_Key& key) const + { +#if defined(BOTAN_HAS_RSA) + if(const RSA_PrivateKey* s = dynamic_cast<const RSA_PrivateKey*>(&key)) + return new OSSL_RSA_Private_Operation(*s); +#endif + + return 0; + } + +} diff --git a/src/engine/openssl/ossl_dh.cpp b/src/engine/openssl/ossl_dh.cpp deleted file mode 100644 index 7cbe6477d..000000000 --- a/src/engine/openssl/ossl_dh.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* -* OpenSSL Engine -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/internal/openssl_engine.h> -#include <botan/internal/bn_wrap.h> -#include <openssl/opensslv.h> - -#if OPENSSL_VERSION_NUMBER < 0x0090700F - #error Your OpenSSL install is too old, upgrade to 0.9.7 or later -#endif - -namespace Botan { - -#if defined(BOTAN_HAS_DIFFIE_HELLMAN) - -namespace { - -/* -* OpenSSL DH Operation -*/ -class OpenSSL_DH_Op : public DH_Operation - { - public: - BigInt agree(const BigInt& i) const; - DH_Operation* clone() const { return new OpenSSL_DH_Op(*this); } - - OpenSSL_DH_Op(const DL_Group& group, const BigInt& x_bn) : - x(x_bn), p(group.get_p()) {} - private: - OSSL_BN x, p; - OSSL_BN_CTX ctx; - }; - -/* -* OpenSSL DH Key Agreement Operation -*/ -BigInt OpenSSL_DH_Op::agree(const BigInt& i_bn) const - { - OSSL_BN i(i_bn), r; - BN_mod_exp(r.value, i.value, x.value, p.value, ctx.value); - return r.to_bigint(); - } - -} - -/* -* Acquire a DH op -*/ -DH_Operation* OpenSSL_Engine::dh_op(const DL_Group& group, - const BigInt& x) const - { - return new OpenSSL_DH_Op(group, x); - } -#endif - -} diff --git a/src/engine/openssl/ossl_dsa.cpp b/src/engine/openssl/ossl_dsa.cpp deleted file mode 100644 index 66529bcec..000000000 --- a/src/engine/openssl/ossl_dsa.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/* -* OpenSSL DSA Engine -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/internal/openssl_engine.h> -#include <botan/internal/bn_wrap.h> -#include <openssl/opensslv.h> - -#if OPENSSL_VERSION_NUMBER < 0x0090700F - #error Your OpenSSL install is too old, upgrade to 0.9.7 or later -#endif - -namespace Botan { - -#if defined(BOTAN_HAS_DSA) - -namespace { - -/* -* OpenSSL DSA Operation -*/ -class OpenSSL_DSA_Op : public DSA_Operation - { - public: - bool verify(const byte[], u32bit, const byte[], u32bit) const; - SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const; - - DSA_Operation* clone() const { return new OpenSSL_DSA_Op(*this); } - - OpenSSL_DSA_Op(const DL_Group& group, const BigInt& y1, - const BigInt& x1) : - x(x1), y(y1), p(group.get_p()), q(group.get_q()), g(group.get_g()) {} - private: - const OSSL_BN x, y, p, q, g; - OSSL_BN_CTX ctx; - }; - -/* -* OpenSSL DSA Verify Operation -*/ -bool OpenSSL_DSA_Op::verify(const byte msg[], u32bit msg_len, - const byte sig[], u32bit sig_len) const - { - const u32bit q_bytes = q.bytes(); - - if(sig_len != 2*q_bytes || msg_len > q_bytes) - return false; - - OSSL_BN r(sig, q_bytes); - OSSL_BN s(sig + q_bytes, q_bytes); - OSSL_BN i(msg, msg_len); - - if(BN_is_zero(r.value) || BN_cmp(r.value, q.value) >= 0) - return false; - if(BN_is_zero(s.value) || BN_cmp(s.value, q.value) >= 0) - return false; - - if(BN_mod_inverse(s.value, s.value, q.value, ctx.value) == 0) - return false; - - OSSL_BN si; - BN_mod_mul(si.value, s.value, i.value, q.value, ctx.value); - BN_mod_exp(si.value, g.value, si.value, p.value, ctx.value); - - OSSL_BN sr; - BN_mod_mul(sr.value, s.value, r.value, q.value, ctx.value); - BN_mod_exp(sr.value, y.value, sr.value, p.value, ctx.value); - - BN_mod_mul(si.value, si.value, sr.value, p.value, ctx.value); - BN_nnmod(si.value, si.value, q.value, ctx.value); - - if(BN_cmp(si.value, r.value) == 0) - return true; - return false; - } - -/* -* OpenSSL DSA Sign Operation -*/ -SecureVector<byte> OpenSSL_DSA_Op::sign(const byte in[], u32bit length, - const BigInt& k_bn) const - { - if(BN_is_zero(x.value)) - throw Internal_Error("OpenSSL_DSA_Op::sign: No private key"); - - OSSL_BN i(in, length); - OSSL_BN k(k_bn); - - OSSL_BN r; - BN_mod_exp(r.value, g.value, k.value, p.value, ctx.value); - BN_nnmod(r.value, r.value, q.value, ctx.value); - - BN_mod_inverse(k.value, k.value, q.value, ctx.value); - - OSSL_BN s; - BN_mul(s.value, x.value, r.value, ctx.value); - BN_add(s.value, s.value, i.value); - BN_mod_mul(s.value, s.value, k.value, q.value, ctx.value); - - if(BN_is_zero(r.value) || BN_is_zero(s.value)) - throw Internal_Error("OpenSSL_DSA_Op::sign: r or s was zero"); - - const u32bit q_bytes = q.bytes(); - - SecureVector<byte> output(2*q_bytes); - r.encode(output, q_bytes); - s.encode(output + q_bytes, q_bytes); - return output; - } - -} - -/* -* Acquire a DSA op -*/ -DSA_Operation* OpenSSL_Engine::dsa_op(const DL_Group& group, const BigInt& y, - const BigInt& x) const - { - return new OpenSSL_DSA_Op(group, y, x); - } -#endif - -} diff --git a/src/engine/openssl/ossl_elg.cpp b/src/engine/openssl/ossl_elg.cpp deleted file mode 100644 index 35c59a7ff..000000000 --- a/src/engine/openssl/ossl_elg.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/* -* OpenSSL Engine -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/internal/openssl_engine.h> -#include <botan/internal/bn_wrap.h> -#include <openssl/opensslv.h> - -#if OPENSSL_VERSION_NUMBER < 0x0090700F - #error Your OpenSSL install is too old, upgrade to 0.9.7 or later -#endif - -namespace Botan { - -#if defined(BOTAN_HAS_ELGAMAL) - -namespace { - -/* -* OpenSSL ElGamal Operation -*/ -class OpenSSL_ELG_Op : public ELG_Operation - { - public: - SecureVector<byte> encrypt(const byte[], u32bit, const BigInt&) const; - BigInt decrypt(const BigInt&, const BigInt&) const; - - ELG_Operation* clone() const { return new OpenSSL_ELG_Op(*this); } - OpenSSL_ELG_Op(const DL_Group& group, const BigInt& y1, - const BigInt& x1) : - x(x1), y(y1), g(group.get_g()), p(group.get_p()) {} - private: - OSSL_BN x, y, g, p; - OSSL_BN_CTX ctx; - }; - -/* -* OpenSSL ElGamal Encrypt Operation -*/ -SecureVector<byte> OpenSSL_ELG_Op::encrypt(const byte in[], u32bit length, - const BigInt& k_bn) const - { - OSSL_BN i(in, length); - - if(BN_cmp(i.value, p.value) >= 0) - throw Invalid_Argument("OpenSSL_ELG_Op: Input is too large"); - - OSSL_BN a, b, k(k_bn); - - BN_mod_exp(a.value, g.value, k.value, p.value, ctx.value); - BN_mod_exp(b.value, y.value, k.value, p.value, ctx.value); - BN_mod_mul(b.value, b.value, i.value, p.value, ctx.value); - - const u32bit p_bytes = p.bytes(); - SecureVector<byte> output(2*p_bytes); - a.encode(output, p_bytes); - b.encode(output + p_bytes, p_bytes); - return output; - } - -/* -* OpenSSL ElGamal Decrypt Operation -*/ -BigInt OpenSSL_ELG_Op::decrypt(const BigInt& a_bn, const BigInt& b_bn) const - { - if(BN_is_zero(x.value)) - throw Internal_Error("OpenSSL_ELG_Op::decrypt: No private key"); - - OSSL_BN a(a_bn), b(b_bn), t; - - if(BN_cmp(a.value, p.value) >= 0 || BN_cmp(b.value, p.value) >= 0) - throw Invalid_Argument("OpenSSL_ELG_Op: Invalid message"); - - BN_mod_exp(t.value, a.value, x.value, p.value, ctx.value); - BN_mod_inverse(a.value, t.value, p.value, ctx.value); - BN_mod_mul(a.value, a.value, b.value, p.value, ctx.value); - return a.to_bigint(); - } - -} - -/* -* Acquire an ElGamal op -*/ -ELG_Operation* OpenSSL_Engine::elg_op(const DL_Group& group, const BigInt& y, - const BigInt& x) const - { - return new OpenSSL_ELG_Op(group, y, x); - } -#endif - -} diff --git a/src/engine/openssl/ossl_if.cpp b/src/engine/openssl/ossl_if.cpp deleted file mode 100644 index a30a4d8b4..000000000 --- a/src/engine/openssl/ossl_if.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* -* OpenSSL IF Engine -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/internal/openssl_engine.h> -#include <botan/internal/bn_wrap.h> -#include <openssl/opensslv.h> - -#if OPENSSL_VERSION_NUMBER < 0x0090700F - #error Your OpenSSL install is too old, upgrade to 0.9.7 or later -#endif - -namespace Botan { - -#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY) - -namespace { - -/* -* OpenSSL IF Operation -*/ -class OpenSSL_IF_Op : public IF_Operation - { - public: - BigInt public_op(const BigInt&) const; - BigInt private_op(const BigInt&) const; - - IF_Operation* clone() const { return new OpenSSL_IF_Op(*this); } - - OpenSSL_IF_Op(const BigInt& e_bn, const BigInt& n_bn, const BigInt&, - const BigInt& p_bn, const BigInt& q_bn, const BigInt& d1_bn, - const BigInt& d2_bn, const BigInt& c_bn) : - e(e_bn), n(n_bn), p(p_bn), q(q_bn), d1(d1_bn), d2(d2_bn), c(c_bn) {} - private: - const OSSL_BN e, n, p, q, d1, d2, c; - OSSL_BN_CTX ctx; - }; - -/* -* OpenSSL IF Public Operation -*/ -BigInt OpenSSL_IF_Op::public_op(const BigInt& i_bn) const - { - OSSL_BN i(i_bn), r; - BN_mod_exp(r.value, i.value, e.value, n.value, ctx.value); - return r.to_bigint(); - } - -/* -* OpenSSL IF Private Operation -*/ -BigInt OpenSSL_IF_Op::private_op(const BigInt& i_bn) const - { - if(BN_is_zero(p.value)) - throw Internal_Error("OpenSSL_IF_Op::private_op: No private key"); - - OSSL_BN j1, j2, h(i_bn); - - BN_mod_exp(j1.value, h.value, d1.value, p.value, ctx.value); - BN_mod_exp(j2.value, h.value, d2.value, q.value, ctx.value); - BN_sub(h.value, j1.value, j2.value); - BN_mod_mul(h.value, h.value, c.value, p.value, ctx.value); - BN_mul(h.value, h.value, q.value, ctx.value); - BN_add(h.value, h.value, j2.value); - return h.to_bigint(); - } - -} - -/* -* Acquire an IF op -*/ -IF_Operation* OpenSSL_Engine::if_op(const BigInt& e, const BigInt& n, - const BigInt& d, const BigInt& p, - const BigInt& q, const BigInt& d1, - const BigInt& d2, const BigInt& c) const - { - return new OpenSSL_IF_Op(e, n, d, p, q, d1, d2, c); - } -#endif - -} diff --git a/src/engine/openssl/ossl_nr.cpp b/src/engine/openssl/ossl_nr.cpp deleted file mode 100644 index b14ec7f8c..000000000 --- a/src/engine/openssl/ossl_nr.cpp +++ /dev/null @@ -1,113 +0,0 @@ -/* -* OpenSSL NR Engine -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/internal/openssl_engine.h> -#include <botan/internal/bn_wrap.h> -#include <openssl/opensslv.h> - -#if OPENSSL_VERSION_NUMBER < 0x0090700F - #error Your OpenSSL install is too old, upgrade to 0.9.7 or later -#endif - -namespace Botan { - -#if defined(BOTAN_HAS_NYBERG_RUEPPEL) - -namespace { - -/* -* OpenSSL NR Operation -*/ -class OpenSSL_NR_Op : public NR_Operation - { - public: - SecureVector<byte> verify(const byte[], u32bit) const; - SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const; - - NR_Operation* clone() const { return new OpenSSL_NR_Op(*this); } - - OpenSSL_NR_Op(const DL_Group& group, const BigInt& y1, - const BigInt& x1) : - x(x1), y(y1), p(group.get_p()), q(group.get_q()), g(group.get_g()) {} - private: - const OSSL_BN x, y, p, q, g; - OSSL_BN_CTX ctx; - }; - -/* -* OpenSSL NR Verify Operation -*/ -SecureVector<byte> OpenSSL_NR_Op::verify(const byte sig[], - u32bit sig_len) const - { - const u32bit q_bytes = q.bytes(); - - if(sig_len != 2*q_bytes) - return false; - - OSSL_BN c(sig, q_bytes); - OSSL_BN d(sig + q_bytes, q_bytes); - - if(BN_is_zero(c.value) || BN_cmp(c.value, q.value) >= 0 || - BN_cmp(d.value, q.value) >= 0) - throw Invalid_Argument("OpenSSL_NR_Op::verify: Invalid signature"); - - OSSL_BN i1, i2; - BN_mod_exp(i1.value, g.value, d.value, p.value, ctx.value); - BN_mod_exp(i2.value, y.value, c.value, p.value, ctx.value); - BN_mod_mul(i1.value, i1.value, i2.value, p.value, ctx.value); - BN_sub(i1.value, c.value, i1.value); - BN_nnmod(i1.value, i1.value, q.value, ctx.value); - return BigInt::encode(i1.to_bigint()); - } - -/* -* OpenSSL NR Sign Operation -*/ -SecureVector<byte> OpenSSL_NR_Op::sign(const byte in[], u32bit length, - const BigInt& k_bn) const - { - if(BN_is_zero(x.value)) - throw Internal_Error("OpenSSL_NR_Op::sign: No private key"); - - OSSL_BN f(in, length); - OSSL_BN k(k_bn); - - if(BN_cmp(f.value, q.value) >= 0) - throw Invalid_Argument("OpenSSL_NR_Op::sign: Input is out of range"); - - OSSL_BN c, d; - BN_mod_exp(c.value, g.value, k.value, p.value, ctx.value); - BN_add(c.value, c.value, f.value); - BN_nnmod(c.value, c.value, q.value, ctx.value); - BN_mul(d.value, x.value, c.value, ctx.value); - BN_sub(d.value, k.value, d.value); - BN_nnmod(d.value, d.value, q.value, ctx.value); - - if(BN_is_zero(c.value)) - throw Internal_Error("Default_NR_Op::sign: c was zero"); - - const u32bit q_bytes = q.bytes(); - SecureVector<byte> output(2*q_bytes); - c.encode(output, q_bytes); - d.encode(output + q_bytes, q_bytes); - return output; - } - -} - -/* -* Acquire a NR op -*/ -NR_Operation* OpenSSL_Engine::nr_op(const DL_Group& group, const BigInt& y, - const BigInt& x) const - { - return new OpenSSL_NR_Op(group, y, x); - } -#endif - -} diff --git a/src/hash/gost_3411/gost_3411.cpp b/src/hash/gost_3411/gost_3411.cpp index 01d8a0d46..244a3fddf 100644 --- a/src/hash/gost_3411/gost_3411.cpp +++ b/src/hash/gost_3411/gost_3411.cpp @@ -191,12 +191,18 @@ void GOST_34_11::compress_n(const byte input[], u32bit blocks) S2[19] = S[ 5] ^ S[ 7] ^ S[11] ^ S[13] ^ S[15] ^ S[17] ^ S[23] ^ S[25] ^ S[29]; S2[20] = S[ 6] ^ S[ 8] ^ S[12] ^ S[14] ^ S[16] ^ S[18] ^ S[24] ^ S[26] ^ S[30]; S2[21] = S[ 7] ^ S[ 9] ^ S[13] ^ S[15] ^ S[17] ^ S[19] ^ S[25] ^ S[27] ^ S[31]; - S2[22] = S[ 0] ^ S[ 2] ^ S[ 4] ^ S[ 6] ^ S[ 8] ^ S[10] ^ S[14] ^ S[16] ^ S[18] ^ S[20] ^ S[24] ^ S[26] ^ S[28] ^ S[30]; - S2[23] = S[ 1] ^ S[ 3] ^ S[ 5] ^ S[ 7] ^ S[ 9] ^ S[11] ^ S[15] ^ S[17] ^ S[19] ^ S[21] ^ S[25] ^ S[27] ^ S[29] ^ S[31]; - S2[24] = S[ 0] ^ S[ 8] ^ S[10] ^ S[12] ^ S[16] ^ S[18] ^ S[20] ^ S[22] ^ S[24] ^ S[26] ^ S[28]; - S2[25] = S[ 1] ^ S[ 9] ^ S[11] ^ S[13] ^ S[17] ^ S[19] ^ S[21] ^ S[23] ^ S[25] ^ S[27] ^ S[29]; - S2[26] = S[ 2] ^ S[10] ^ S[12] ^ S[14] ^ S[18] ^ S[20] ^ S[22] ^ S[24] ^ S[26] ^ S[28] ^ S[30]; - S2[27] = S[ 3] ^ S[11] ^ S[13] ^ S[15] ^ S[19] ^ S[21] ^ S[23] ^ S[25] ^ S[27] ^ S[29] ^ S[31]; + S2[22] = S[ 0] ^ S[ 2] ^ S[ 4] ^ S[ 6] ^ S[ 8] ^ S[10] ^ S[14] ^ S[16] ^ + S[18] ^ S[20] ^ S[24] ^ S[26] ^ S[28] ^ S[30]; + S2[23] = S[ 1] ^ S[ 3] ^ S[ 5] ^ S[ 7] ^ S[ 9] ^ S[11] ^ S[15] ^ S[17] ^ + S[19] ^ S[21] ^ S[25] ^ S[27] ^ S[29] ^ S[31]; + S2[24] = S[ 0] ^ S[ 8] ^ S[10] ^ S[12] ^ S[16] ^ S[18] ^ S[20] ^ S[22] ^ + S[24] ^ S[26] ^ S[28]; + S2[25] = S[ 1] ^ S[ 9] ^ S[11] ^ S[13] ^ S[17] ^ S[19] ^ S[21] ^ S[23] ^ + S[25] ^ S[27] ^ S[29]; + S2[26] = S[ 2] ^ S[10] ^ S[12] ^ S[14] ^ S[18] ^ S[20] ^ S[22] ^ S[24] ^ + S[26] ^ S[28] ^ S[30]; + S2[27] = S[ 3] ^ S[11] ^ S[13] ^ S[15] ^ S[19] ^ S[21] ^ S[23] ^ S[25] ^ + S[27] ^ S[29] ^ S[31]; S2[28] = S[ 0] ^ S[ 2] ^ S[ 6] ^ S[12] ^ S[14] ^ S[16] ^ S[20] ^ S[22] ^ S[26] ^ S[28]; S2[29] = S[ 1] ^ S[ 3] ^ S[ 7] ^ S[13] ^ S[15] ^ S[17] ^ S[21] ^ S[23] ^ S[27] ^ S[29]; S2[30] = S[ 2] ^ S[ 4] ^ S[ 8] ^ S[14] ^ S[16] ^ S[18] ^ S[22] ^ S[24] ^ S[28] ^ S[30]; diff --git a/src/libstate/info.txt b/src/libstate/info.txt index cb584f4d8..f50b7f3dc 100644 --- a/src/libstate/info.txt +++ b/src/libstate/info.txt @@ -11,17 +11,11 @@ lookup.h scan_name.h </header:public> -<header:internal> -pk_engine.h -</header:internal> - <source> get_enc.cpp init.cpp libstate.cpp -look_pk.cpp lookup.cpp -pk_engine.cpp policy.cpp scan_name.cpp </source> diff --git a/src/libstate/look_pk.cpp b/src/libstate/look_pk.cpp deleted file mode 100644 index 8eb473858..000000000 --- a/src/libstate/look_pk.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* -* PK Algorithm Lookup -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/look_pk.h> -#include <botan/lookup.h> - -namespace Botan { - -/* -* Get a PK_Encryptor object -*/ -PK_Encryptor* get_pk_encryptor(const PK_Encrypting_Key& key, - const std::string& eme) - { - return new PK_Encryptor_MR_with_EME(key, get_eme(eme)); - } - -/* -* Get a PK_Decryptor object -*/ -PK_Decryptor* get_pk_decryptor(const PK_Decrypting_Key& key, - const std::string& eme) - { - return new PK_Decryptor_MR_with_EME(key, get_eme(eme)); - } - -/* -* Get a PK_Signer object -*/ -PK_Signer* get_pk_signer(const PK_Signing_Key& key, - const std::string& emsa, - Signature_Format sig_format) - { - PK_Signer* signer = new PK_Signer(key, get_emsa(emsa)); - signer->set_output_format(sig_format); - return signer; - } - -/* -* Get a PK_Verifier object -*/ -PK_Verifier* get_pk_verifier(const PK_Verifying_with_MR_Key& key, - const std::string& emsa, - Signature_Format sig_format) - { - PK_Verifier* verifier = new PK_Verifier_with_MR(key, get_emsa(emsa)); - verifier->set_input_format(sig_format); - return verifier; - } - -/* -* Get a PK_Verifier object -*/ -PK_Verifier* get_pk_verifier(const PK_Verifying_wo_MR_Key& key, - const std::string& emsa, - Signature_Format sig_format) - { - PK_Verifier* verifier = new PK_Verifier_wo_MR(key, get_emsa(emsa)); - verifier->set_input_format(sig_format); - return verifier; - } - -/* -* Get a PK_Key_Agreement object -*/ -PK_Key_Agreement* get_pk_kas(const PK_Key_Agreement_Key& key, - const std::string& kdf) - { - return new PK_Key_Agreement(key, get_kdf(kdf)); - } - -} diff --git a/src/libstate/look_pk.h b/src/libstate/look_pk.h index 27b67dc5b..833b28f67 100644 --- a/src/libstate/look_pk.h +++ b/src/libstate/look_pk.h @@ -1,6 +1,6 @@ /* * PK Algorithm Lookup -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -8,7 +8,7 @@ #ifndef BOTAN_PK_LOOKUP_H__ #define BOTAN_PK_LOOKUP_H__ -#include <botan/build.h> +#include <botan/lookup.h> #include <botan/pubkey.h> namespace Botan { @@ -16,62 +16,66 @@ namespace Botan { /** * Public key encryptor factory method. * @param key the key that will work inside the encryptor -* @param pad determines the algorithm and encoding +* @param eme determines the algorithm and encoding * @return the public key encryptor object */ -BOTAN_DLL PK_Encryptor* get_pk_encryptor(const PK_Encrypting_Key& key, - const std::string& pad); +inline PK_Encryptor* get_pk_encryptor(const Public_Key& key, + const std::string& eme) + { + return new PK_Encryptor_EME(key, eme); + } /** * Public key decryptor factory method. * @param key the key that will work inside the decryptor -* @param pad determines the algorithm and encoding +* @param eme determines the algorithm and encoding * @return the public key decryptor object */ -BOTAN_DLL PK_Decryptor* get_pk_decryptor(const PK_Decrypting_Key& key, - const std::string& pad); +inline PK_Decryptor* get_pk_decryptor(const Private_Key& key, + const std::string& eme) + { + return new PK_Decryptor_EME(key, eme); + } /** * Public key signer factory method. * @param key the key that will work inside the signer -* @param pad determines the algorithm, encoding and hash algorithm +* @param emsa determines the algorithm, encoding and hash algorithm * @param sig_format the signature format to be used * @return the public key signer object */ -BOTAN_DLL PK_Signer* get_pk_signer(const PK_Signing_Key& key, - const std::string& pad, - Signature_Format = IEEE_1363); +inline PK_Signer* get_pk_signer(const Private_Key& key, + const std::string& emsa, + Signature_Format sig_format = IEEE_1363) + { + return new PK_Signer(key, emsa, sig_format); + } /** * Public key verifier factory method. * @param key the key that will work inside the verifier -* @param pad determines the algorithm, encoding and hash algorithm +* @param emsa determines the algorithm, encoding and hash algorithm * @param sig_format the signature format to be used * @return the public key verifier object */ -BOTAN_DLL PK_Verifier* get_pk_verifier(const PK_Verifying_with_MR_Key& key, - const std::string& pad, - Signature_Format = IEEE_1363); - -/** -* Public key verifier factory method. -* @param key the key that will work inside the verifier -* @param pad determines the algorithm, encoding and hash algorithm -* @param sig_form the signature format to be used -* @return the public key verifier object -*/ -BOTAN_DLL PK_Verifier* get_pk_verifier(const PK_Verifying_wo_MR_Key& key, - const std::string& pad, - Signature_Format sig_form = IEEE_1363); +inline PK_Verifier* get_pk_verifier(const Public_Key& key, + const std::string& emsa, + Signature_Format sig_format = IEEE_1363) + { + return new PK_Verifier(key, emsa, sig_format); + } /** * Public key key agreement factory method. * @param key the key that will work inside the key agreement -* @param pad determines the algorithm, encoding and hash algorithm -* @return the public key verifier object +* @param kdf the kdf algorithm to use +* @return the key agreement algorithm */ -BOTAN_DLL PK_Key_Agreement* get_pk_kas(const PK_Key_Agreement_Key& key, - const std::string& pad); +inline PK_Key_Agreement* get_pk_kas(const PK_Key_Agreement_Key& key, + const std::string& kdf) + { + return new PK_Key_Agreement(key, kdf); + } } diff --git a/src/libstate/oid_lookup/oids.cpp b/src/libstate/oid_lookup/oids.cpp index 232c63360..c54762c58 100644 --- a/src/libstate/oid_lookup/oids.cpp +++ b/src/libstate/oid_lookup/oids.cpp @@ -49,7 +49,7 @@ OID lookup(const std::string& name) { return OID(name); } - catch(Exception) + catch(...) { throw Lookup_Error("No object identifier found for " + name); } diff --git a/src/libstate/pk_engine.cpp b/src/libstate/pk_engine.cpp deleted file mode 100644 index ac2fa68b0..000000000 --- a/src/libstate/pk_engine.cpp +++ /dev/null @@ -1,133 +0,0 @@ -/* -* PK Engine Lookup -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/internal/pk_engine.h> -#include <botan/libstate.h> -#include <botan/engine.h> - -namespace Botan { - -namespace Engine_Core { - -#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY) -/* -* Acquire an IF op -*/ -IF_Operation* if_op(const BigInt& e, const BigInt& n, const BigInt& d, - const BigInt& p, const BigInt& q, const BigInt& d1, - const BigInt& d2, const BigInt& c) - { - Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory()); - - while(const Engine* engine = i.next()) - { - IF_Operation* op = engine->if_op(e, n, d, p, q, d1, d2, c); - if(op) - return op; - } - - throw Lookup_Error("Engine_Core::if_op: Unable to find a working engine"); - } -#endif - -#if defined(BOTAN_HAS_DSA) -/* -* Acquire a DSA op -*/ -DSA_Operation* dsa_op(const DL_Group& group, const BigInt& y, const BigInt& x) - { - Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory()); - - while(const Engine* engine = i.next()) - { - DSA_Operation* op = engine->dsa_op(group, y, x); - if(op) - return op; - } - - throw Lookup_Error("Engine_Core::dsa_op: Unable to find a working engine"); - } -#endif - -#if defined(BOTAN_HAS_NYBERG_RUEPPEL) -/* -* Acquire a NR op -*/ -NR_Operation* nr_op(const DL_Group& group, const BigInt& y, const BigInt& x) - { - Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory()); - - while(const Engine* engine = i.next()) - { - NR_Operation* op = engine->nr_op(group, y, x); - if(op) - return op; - } - - throw Lookup_Error("Engine_Core::nr_op: Unable to find a working engine"); - } -#endif - -#if defined(BOTAN_HAS_ELGAMAL) -/* -* Acquire an ElGamal op -*/ -ELG_Operation* elg_op(const DL_Group& group, const BigInt& y, const BigInt& x) - { - Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory()); - - while(const Engine* engine = i.next()) - { - ELG_Operation* op = engine->elg_op(group, y, x); - if(op) - return op; - } - - throw Lookup_Error("Engine_Core::elg_op: Unable to find a working engine"); - } -#endif - -#if defined(BOTAN_HAS_DIFFIE_HELLMAN) -/* -* Acquire a DH op -*/ -DH_Operation* dh_op(const DL_Group& group, const BigInt& x) - { - Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory()); - - while(const Engine* engine = i.next()) - { - DH_Operation* op = engine->dh_op(group, x); - if(op) - return op; - } - - throw Lookup_Error("Engine_Core::dh_op: Unable to find a working engine"); - } -#endif - -/* -* Acquire a modular exponentiator -*/ -Modular_Exponentiator* mod_exp(const BigInt& n, Power_Mod::Usage_Hints hints) - { - Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory()); - - while(const Engine* engine = i.next()) - { - Modular_Exponentiator* op = engine->mod_exp(n, hints); - - if(op) - return op; - } - - throw Lookup_Error("Engine_Core::mod_exp: Unable to find a working engine"); - } - -} - -} diff --git a/src/libstate/pk_engine.h b/src/libstate/pk_engine.h deleted file mode 100644 index 25f326ef0..000000000 --- a/src/libstate/pk_engine.h +++ /dev/null @@ -1,73 +0,0 @@ -/** -* Engine for PK -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_ENGINE_PK_LOOKUP_H__ -#define BOTAN_ENGINE_PK_LOOKUP_H__ - -#include <botan/bigint.h> -#include <botan/pow_mod.h> - -#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY) - #include <botan/if_op.h> -#endif - -#if defined(BOTAN_HAS_DSA) - #include <botan/dsa_op.h> -#endif - -#if defined(BOTAN_HAS_DIFFIE_HELLMAN) - #include <botan/dh_op.h> -#endif - -#if defined(BOTAN_HAS_NYBERG_RUEPPEL) - #include <botan/nr_op.h> -#endif - -#if defined(BOTAN_HAS_ELGAMAL) - #include <botan/elg_op.h> -#endif - -namespace Botan { - -class Algorithm_Factory; -class Keyed_Filter; -class Modular_Exponentiator; - -namespace Engine_Core { - -/* -* Get an operation from an Engine -*/ -Modular_Exponentiator* mod_exp(const BigInt&, Power_Mod::Usage_Hints); - -#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY) -IF_Operation* if_op(const BigInt&, const BigInt&, const BigInt&, - const BigInt&, const BigInt&, const BigInt&, - const BigInt&, const BigInt&); -#endif - -#if defined(BOTAN_HAS_DSA) -DSA_Operation* dsa_op(const DL_Group&, const BigInt&, const BigInt&); -#endif - -#if defined(BOTAN_HAS_NYBERG_RUEPPEL) -NR_Operation* nr_op(const DL_Group&, const BigInt&, const BigInt&); -#endif - -#if defined(BOTAN_HAS_ELGAMAL) -ELG_Operation* elg_op(const DL_Group&, const BigInt&, const BigInt&); -#endif - -#if defined(BOTAN_HAS_DIFFIE_HELLMAN) -DH_Operation* dh_op(const DL_Group&, const BigInt&); -#endif - -} - -} - -#endif diff --git a/src/libstate/policy.cpp b/src/libstate/policy.cpp index bb775b049..d792443a0 100644 --- a/src/libstate/policy.cpp +++ b/src/libstate/policy.cpp @@ -34,7 +34,7 @@ void set_default_oids(Library_State& config) add_oid(config, "2.5.8.1.1", "RSA"); // RSA alternate add_oid(config, "1.2.840.10040.4.1", "DSA"); add_oid(config, "1.2.840.10046.2.1", "DH"); - add_oid(config, "1.3.6.1.4.1.3029.1.2.1", "ELG"); + add_oid(config, "1.3.6.1.4.1.3029.1.2.1", "ElGamal"); add_oid(config, "1.3.6.1.4.1.25258.1.1", "RW"); add_oid(config, "1.3.6.1.4.1.25258.1.2", "NR"); add_oid(config, "1.2.840.10045.2.1", "ECDSA"); // X9.62 @@ -93,12 +93,14 @@ void set_default_oids(Library_State& config) add_oid(config, "2.16.840.1.101.3.4.3.1", "DSA/EMSA1(SHA-224)"); add_oid(config, "2.16.840.1.101.3.4.3.2", "DSA/EMSA1(SHA-256)"); - add_oid(config, "1.2.840.10045.4.1", "ECDSA/EMSA1_BSI(SHA-160)"); - add_oid(config, "1.2.840.10045.4.3.1", "ECDSA/EMSA1_BSI(SHA-224)"); - add_oid(config, "1.2.840.10045.4.3.2", "ECDSA/EMSA1_BSI(SHA-256)"); - add_oid(config, "1.2.840.10045.4.3.3", "ECDSA/EMSA1_BSI(SHA-384)"); - add_oid(config, "1.2.840.10045.4.3.4", "ECDSA/EMSA1_BSI(SHA-512)"); + add_oid(config, "0.4.0.127.0.7.1.1.4.1.1", "ECDSA/EMSA1_BSI(SHA-160)"); + add_oid(config, "0.4.0.127.0.7.1.1.4.1.2", "ECDSA/EMSA1_BSI(SHA-224)"); + add_oid(config, "0.4.0.127.0.7.1.1.4.1.3", "ECDSA/EMSA1_BSI(SHA-256)"); + add_oid(config, "0.4.0.127.0.7.1.1.4.1.4", "ECDSA/EMSA1_BSI(SHA-384)"); + add_oid(config, "0.4.0.127.0.7.1.1.4.1.5", "ECDSA/EMSA1_BSI(SHA-512)"); + add_oid(config, "0.4.0.127.0.7.1.1.4.1.6", "ECDSA/EMSA1_BSI(RIPEMD-160)"); + add_oid(config, "1.2.840.10045.4.1", "ECDSA/EMSA1(SHA-160)"); add_oid(config, "1.2.840.10045.4.3.1", "ECDSA/EMSA1(SHA-224)"); add_oid(config, "1.2.840.10045.4.3.2", "ECDSA/EMSA1(SHA-256)"); add_oid(config, "1.2.840.10045.4.3.3", "ECDSA/EMSA1(SHA-384)"); @@ -543,111 +545,111 @@ void set_default_dl_groups(Library_State& config) "-----END DSA PARAMETERS-----"); config.set("ec", "secp112r1", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MHQCAQEwGgYHKoZIzj0BAQIPANt8Kr9i415mgHa+rSCLMCAEDtt8Kr9i415mgHa+" "rSCIBA5lnvi6BDkW7t6JEXArIgQdBAlIcjmZWl7na1X5wvCYqJzlr4ckwKI+Dg/3" "dQACDwDbfCq/YuNedijfrGVhxQIBAQ==" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "secp112r2", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MHMCAQEwGgYHKoZIzj0BAQIPANt8Kr9i415mgHa+rSCLMCAEDmEnwkwF84oKqvZc" "DvAsBA5R3vGBXbXtdPzDTIXXCQQdBEujCrXokrThZJ3QkoZDrc1G9YguN0fe826V" "bpcCDjbfCq/YuNdZfKEFINBLAgEB" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "secp128r1", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIGAAgEBMBwGByqGSM49AQECEQD////9////////////////MCQEEP////3/////" "//////////wEEOh1ecEQefQ92CSZPCzuXtMEIQQWH/dSi4mbLQwoYHylLFuGz1rI" "OVuv6xPALaKS3e16gwIRAP////4AAAAAdaMNG5A4oRUCAQE=" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "secp128r2", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MH8CAQEwHAYHKoZIzj0BAQIRAP////3///////////////8wJAQQ1gMZmNGzu/6/" "Wcybv/mu4QQQXu78o4DQKRncLGVYu22KXQQhBHtqpdheVymD5vsyp83rwUAntpFq" "iU067nEG/oBfw0tEAhA/////f////74AJHIGE7WjAgEE" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "secp160k1", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIGYAgEBMCAGByqGSM49AQECFQD////////////////////+//+sczAsBBQAAAAA" "AAAAAAAAAAAAAAAAAAAAAAQUAAAAAAAAAAAAAAAAAAAAAAAAAAcEKQQ7TDgs43qh" "kqQBnnYwNvT13U1+u5OM+TUxj9zta8KChlMXM8PwPE/uAhUBAAAAAAAAAAAAAbj6" "Ft+rmsoWtrMCAQE=" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "secp160r1", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIGYAgEBMCAGByqGSM49AQECFQD/////////////////////f////zAsBBT/////" "////////////////f////AQUHJe+/FS9eotlrPifgdTUrcVl+kUEKQRKlrVojvVz" "KEZkaYlow4u5E8v8giOmKFUxaJR9WdzJEgQjUTd6xfsyAhUBAAAAAAAAAAAAAfTI" "+Seu08p1IlcCAQE=" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "secp160r2", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIGYAgEBMCAGByqGSM49AQECFQD////////////////////+//+sczAsBBT/////" "///////////////+//+scAQUtOE00/tZ64urVydJBGZNWvUDiLoEKQRS3LA0KToR" "fh9P8Rsw9xmdMUTObf6v/vLjMfKW4HH6DfmYLP6n1D8uAhUBAAAAAAAAAAAAADUe" "54aoGPOhoWsCAQE=" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "secp192k1", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIGwAgEBMCQGByqGSM49AQECGQD//////////////////////////v//7jcwNAQY" "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" "AAMEMQTbT/EOwFfpriawfQKAt/Q0HaXRsergbH2bLy9tnFYop4RBY9AVvoY0QIKq" "iNleL50CGQD///////////////4m8vwXD2lGanTe/Y0CAQE=" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "secp192r1", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIGwAgEBMCQGByqGSM49AQECGQD////////////////////+//////////8wNAQY" "/////////////////////v/////////8BBhkIQUZ5ZyA5w+n6atyJDBJ/rje7MFG" "ubEEMQQYjagOsDCQ9ny/IOtDoYgA9P8K/YL/EBIHGSuV/8jaeGMQEe1rJM3Vc/l3" "oR55SBECGQD///////////////+Z3vg2FGvJsbTSKDECAQE=" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "secp224k1", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIHIAgEBMCgGByqGSM49AQECHQD///////////////////////////////7//+Vt" "MDwEHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEHAAAAAAAAAAAAAAAAAAA" "AAAAAAAAAAAAAAAAAAUEOQShRVszTfCZ3zD8KKFppGfp5HB1qQ9+ZQ62t6Rcfgif" "7X+6NEKCyvvW9+MZ98CwvVniykvbVW1hpQIdAQAAAAAAAAAAAAAAAAAB3OjS7GGE" "yvCpcXafsfcCAQE=" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "secp224r1", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIHIAgEBMCgGByqGSM49AQECHQD/////////////////////AAAAAAAAAAAAAAAB" "MDwEHP////////////////////7///////////////4EHLQFCoUMBLOr9UEyVlBE" "sLfXv9i6Jws5QyNV/7QEOQS3Dgy9a7S/fzITkLlKA8HTVsIRIjQygNYRXB0hvTdj" "iLX3I/tMIt/mzUN1oFoHR2RE1YGZhQB+NAIdAP//////////////////FqLguPA+" "E90pRVxcKj0CAQE=" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "secp256k1", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIHgAgEBMCwGByqGSM49AQECIQD////////////////////////////////////+" "///8LzBEBCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQgAAAAAAAA" "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcEQQR5vmZ++dy7rFWgYpXOhwsHApv8" "2y3OKNlZ8oFbFvgXmEg62ncmo8RlXaT7/A4RCKj9F7RIpoVUGZxH0I/7ENS4AiEA" "/////////////////////rqu3OavSKA7v9JejNA2QUECAQE=" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "secp256r1", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIHgAgEBMCwGByqGSM49AQECIQD/////AAAAAQAAAAAAAAAAAAAAAP//////////" "/////zBEBCD/////AAAAAQAAAAAAAAAAAAAAAP///////////////AQgWsY12Ko6" "k+ez671VdpiGvGUdBrDMU7D2O848PifSYEsEQQRrF9Hy4SxCR/i85uVjpEDydwN9" "gS3rM6D0oTlF2JjClk/jQuL+Gn+bjufrSnwPnhYrzjNXazFezsu2QGg3v1H1AiEA" "/////wAAAAD//////////7zm+q2nF56E87nKwvxjJVECAQE=" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "secp384r1", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIIBQAIBATA8BgcqhkjOPQEBAjEA////////////////////////////////////" "//////7/////AAAAAAAAAAD/////MGQEMP//////////////////////////////" "///////////+/////wAAAAAAAAAA/////AQwszEvp+I+5+SYjgVr4/gtGRgdnG7+" @@ -655,10 +657,10 @@ void set_default_dl_groups(Library_State& config) "O2KLp5uYWfdB4IJUKjhVAvJdv1UpbDpUXjhydgq3NhfeSpYmLG9dnpi/kpLcKfj0" "Hb0omhR86doxE7XwuMAKYLHOHX6BnXpDHXyQ6g5fAjEA////////////////////" "////////////x2NNgfQ3Ld9YGg2ySLCneuzsGWrMxSlzAgEB" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "secp521r1", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIIBrAIBATBNBgcqhkjOPQEBAkIB////////////////////////////////////" "//////////////////////////////////////////////////8wgYgEQgH/////" "////////////////////////////////////////////////////////////////" @@ -668,10 +670,10 @@ void set_default_dl_groups(Library_State& config) "fn4xwuW9ZgEYOSlqeJo7wARcil+0LH0b2Zj1RElXm0RoF6+9Fyc+ZiyX7nKZXvQm" "QMVQuQE/rQdhNTxwhqJywkCIvpR2n9FmUAJCAf//////////////////////////" "////////////////+lGGh4O/L5Zrf8wBSPcJpdA7tcm4iZxHrrtvtx6ROGQJAgEB" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "1.3.6.1.4.1.8301.3.1.2.9.0.38", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIIBrAIBATBNBgcqhkjOPQEBAkIB////////////////////////////////////" "//////////////////////////////////////////////////8wgYgEQgH/////" "////////////////////////////////////////////////////////////////" @@ -681,54 +683,54 @@ void set_default_dl_groups(Library_State& config) "fn4xwuW9ZgEYOSlqeJo7wARcil+0LH0b2Zj1RElXm0RoF6+9Fyc+ZiyX7nKZXvQm" "QMVQuQE/rQdhNTxwhqJywkCIvpR2n9FmUAJCAf//////////////////////////" "////////////////+lGGh4O/L5Zrf8wBSPcJpdA7tcm4iZxHrrtvtx6ROGQJAgEB" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "brainpool160r1", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIGYAgEBMCAGByqGSM49AQECFQDpXkpfc3BZ3GDfx62Vs9gTlRViDzAsBBQ0Dnvi" "ooDrdOK+YbradF2X6PfDAAQUHliahZVCNBITT6otveyVyNhnXlgEKQS+1a8W6j9q" "T2KTjEYx61r3vbzbwxZny0d6Go7DOPlHQWacl2MW2mMhAhUA6V5KX3NwWdxg31mR" "1FApQJ5g/AkCAQE=" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "brainpool192r1", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIGwAgEBMCQGByqGSM49AQECGQDDAvQdkyo2zaejRjCT0Y23j85HbeGoYpcwNAQY" "apEXQHax4OGcOcAx/oaFwcrgQOXGmijvBBhGmijvfCjMo9xyHQRPRJa8yn70FG+/" "JckEMQTAoGR+qrakh1OwM8VssPCQCi9cSFM3X9YUtpCGar1buItfSCjBSQAC5nc/" "ovopm48CGQDDAvQdkyo2zaejRi+enpFrW+jxAprErMECAQE=" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "brainpool224r1", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIHIAgEBMCgGByqGSM49AQECHQDXwTSqJkNmhioYMCV10deHsJ8HV5faifV+yMD/" "MDwEHGil5iypzmwcKZgDpsFTC1FOGCrYsAQqWcrSn0MEHCWA9jzP5EE4hwcTsakj" "aeM+ITXSZtuzcjhsQAsEOQQNkCmtLH5c9DQII7KofcaMnkzjF0webv3uEsB9WKpW" "93LAcm8kxrieTs2sJDVLnpnKo/bTdhQCzQIdANfBNKomQ2aGKhgwJXXQ+5jRFrxL" "bd68o6Wnk58CAQE=" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "brainpool256r1", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIHgAgEBMCwGByqGSM49AQECIQCp+1fboe6pvD5mCpCdg41ybjv2I9UmICggE0gd" "H25TdzBEBCB9Wgl1/CwwV+72dTBBev/n+4BVwSbcXGzpSktE8zC12QQgJtxcbOlK" "S0TzMLXZu9d8v5WEFilc9+HOa8zcGP+MB7YEQQSL0q65y35XyyxLSC/8gbevud4n" "4eO9I8I6RFO9ms4yYlR++DXD2sT9l/hGGhRhHcnCd0UTLe2OVFwdVMcvBGmXAiEA" "qftX26Huqbw+ZgqQnYONcYw5eqO1Yab3kB4OgpdIVqcCAQE=" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "brainpool320r1", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIIBEAIBATA0BgcqhkjOPQEBAikA015HIDa8T7fhPHhe0gHgZfmPz6b29A3vT5K5" "7HiT7Cj81BKx8bMuJzBUBCg+4wtWj7qw+IPM69RtPzu4oqc1E/XredpmGQ6whf+p" "9JLzdal9hg60BChSCIOUnf28QtOtGYZAaIpv4T9BNJVUtJrMMdzNiEU5gW9etKyP" "sfGmBFEEQ71+mvtT2LhSibzEjuW/5vIBN9EKCH6254ceKhClmccQr40NOeIGERT9" "0FVF7BzIq0CTJH93J14HQ//tEXGC6qnHeHeqrGrH01JF0WkujuECKQDTXkcgNrxP" "t+E8eF7SAeBl+Y/PpbaPEqMtSC7H7oZY6YaRVVtExZMRAgEB" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "brainpool384r1", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIIBQAIBATA8BgcqhkjOPQEBAjEAjLkegqM4bSgPXW9+UOZB3xUvcQntVFa0ErHa" "GX+3ESOs06cpkB0acYdHABMxB+xTMGQEMHvDgsY9jBUMPHIICs4Fr6DCvqKOT7In" "hxORZe+6kfkPiqWBSlA61OsEqMfdIs4oJgQwBKjH3SLOKCaLObVUFvBEfC+3feEH" @@ -736,10 +738,10 @@ void set_default_dl_groups(Library_State& config) "o+d+8U/j23/K/gy9EOjoJuA0NtZGqu+HsuJH1K8eir4ddSD5wqRcseuOlc/VUmK3" "Cyn+7Fhk4ZwFT/mRKSgORkYhd5GBEUKCA0EmPFMVAjEAjLkegqM4bSgPXW9+UOZB" "3xUvcQntVFazHxZubKwEJafPOrava3/DEDuIMgLpBGVlAgEB" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "brainpool512r1", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIIBogIBATBMBgcqhkjOPQEBAkEAqt2duNvpxIs/1OauM8n8B8swjbOzydIO1mOc" "ynAzCHF9TZsAm8ZoQq7NoSrmo4DmKIH/Ly2CxoUoqmBWWDpI8zCBhARAeDCjMYtg" "O4niMnFFrCNMxZTL3Y09+RYQqDRByuqYY7wt7V1aqCU6oQou8cmLmsi1fxEXpyvy" @@ -749,59 +751,59 @@ void set_default_dl_groups(Library_State& config) "fd44XVZjMuzA6r+pz3gi/fIJ9wAkpXsaoADFW4gfgRGy3N5JSl9IXlvKS9iKJ2Ou" "0corL6jwVAZ4zR4POtgIkgJBAKrdnbjb6cSLP9TmrjPJ/AfLMI2zs8nSDtZjnMpw" "MwhwVT5cQUypJhlBhmEZf6wQRx2x04EIXdrdtYeWgpypAGkCAQE=" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "x962_p192v2", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIGwAgEBMCQGByqGSM49AQECGQD////////////////////+//////////8wNAQY" "/////////////////////v/////////8BBjMItbfuVxrJeScDWNkpOWYDDk6ohZo" "2VMEMQTuorrn4Ul4QvLed2nP6cmJwHKtaW9IA0pldNEdabbsemcruCoIPfLysIR9" "6XCy3hUCGQD///////////////5fsack3IBBhkjY3TECAQE=" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "x962_p192v3", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIGwAgEBMCQGByqGSM49AQECGQD////////////////////+//////////8wNAQY" "/////////////////////v/////////8BBgiEj3COVoFyqdCPa7MyUdgp9RiJWvV" "aRYEMQR9KXeBAMZaHaF4NxZYjc4ri0rujiKPGJY4qQ8iY3M3M0tJ3LZqbcj5l4rK" "dkipQ7ACGQD///////////////96YtAxyD9ClPZA7BMCAQE=" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "x962_p239v1", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIHSAgEBMCkGByqGSM49AQECHn///////////////3///////4AAAAAAAH//////" "/zBABB5///////////////9///////+AAAAAAAB///////wEHmsBbDvc8YlB0NZU" "khR1ynGp2y+yfR03eWGFwpQsCgQ9BA/6ljzcqIFszDO4ZCvt+QXD01hXPT8n+707" "PLmqr33r6OTpCl2ubkBUylMLoEZUs2gYziJrOfzLewLxrgIef///////////////" "f///nl6an12QcfvRUiaIkJ0LAgEB" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "x962_p239v2", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIHSAgEBMCkGByqGSM49AQECHn///////////////3///////4AAAAAAAH//////" "/zBABB5///////////////9///////+AAAAAAAB///////wEHmF/q2gyV2y7/tUN" "mfAknD/uWLlLoAOMeuhMjIMvLAQ9BDivCdmHJ3BRIMkhu16eJilqPNzy81dXoOr9" "h7gw51sBJeTb6g7HIG2g/AHZsIEyn7VV3m70YCN9/4vkugIef///////////////" "gAAAz6foWUN31BTAOCG8WCBjAgEB" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "x962_p239v3", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIHSAgEBMCkGByqGSM49AQECHn///////////////3///////4AAAAAAAH//////" "/zBABB5///////////////9///////+AAAAAAAB///////wEHiVXBfoqMGZUsfTL" "A9anUKMMJQEC1JiHF9m6FattPgQ9BGdoro4Yu5LPzwBclJqixtlIU9DmYLv4VLHJ" "UF/pWhYH5omPOQwGvB1VK60ibztvz+SLboGEma8Y4+1s8wIef///////////////" "f///l13rQbOmBXw8QyFGUmVRAgEB" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "gost_256A", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIHgAgEBMCwGByqGSM49AQECIQD/////////////////////////////////////" "///9lzBEBCD////////////////////////////////////////9lAQgAAAAAAAA" "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKYEQQQAAAAAAAAAAAAAAAAAAAAAAAAA" "AAAAAAAAAAAAAAAAAY2R5HHgmJzaJ99QWkU/K3Y1KU8t3yPjsSKsyZyenx4UAiEA" "/////////////////////2xhEHCZWtEARYQbCbdhuJMCAQE=" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); } } diff --git a/src/math/numbertheory/blinding.cpp b/src/math/numbertheory/blinding.cpp deleted file mode 100644 index c6a3fd1bd..000000000 --- a/src/math/numbertheory/blinding.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/* -* Blinder -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/blinding.h> -#include <botan/numthry.h> - -namespace Botan { - -/* -* Blinder Constructor -*/ -Blinder::Blinder(const BigInt& e, const BigInt& d, const BigInt& n) - { - if(e < 1 || d < 1 || n < 1) - throw Invalid_Argument("Blinder: Arguments too small"); - - reducer = Modular_Reducer(n); - this->e = e; - this->d = d; - } - -/* -* Blind a number -*/ -BigInt Blinder::blind(const BigInt& i) const - { - if(!reducer.initialized()) - return i; - - e = reducer.square(e); - d = reducer.square(d); - return reducer.multiply(i, e); - } - -/* -* Unblind a number -*/ -BigInt Blinder::unblind(const BigInt& i) const - { - if(!reducer.initialized()) - return i; - return reducer.multiply(i, d); - } - -} diff --git a/src/math/numbertheory/blinding.h b/src/math/numbertheory/blinding.h deleted file mode 100644 index 5f7f9e6b7..000000000 --- a/src/math/numbertheory/blinding.h +++ /dev/null @@ -1,34 +0,0 @@ -/* -* Blinder -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_BLINDER_H__ -#define BOTAN_BLINDER_H__ - -#include <botan/bigint.h> -#include <botan/reducer.h> - -namespace Botan { - -/* -* Blinding Function Object -*/ -class BOTAN_DLL Blinder - { - public: - BigInt blind(const BigInt&) const; - BigInt unblind(const BigInt&) const; - - Blinder() {} - Blinder(const BigInt&, const BigInt&, const BigInt&); - private: - Modular_Reducer reducer; - mutable BigInt e, d; - }; - -} - -#endif diff --git a/src/math/numbertheory/info.txt b/src/math/numbertheory/info.txt index 58851e055..18349ef78 100644 --- a/src/math/numbertheory/info.txt +++ b/src/math/numbertheory/info.txt @@ -3,7 +3,6 @@ load_on auto define BIGINT_MATH <header:public> -blinding.h curve_gfp.h numthry.h point_gfp.h @@ -16,7 +15,6 @@ def_powm.h </header:internal> <source> -blinding.cpp dsa_gen.cpp jacobi.cpp make_prm.cpp diff --git a/src/math/numbertheory/make_prm.cpp b/src/math/numbertheory/make_prm.cpp index 3eb01cd42..23b8cf549 100644 --- a/src/math/numbertheory/make_prm.cpp +++ b/src/math/numbertheory/make_prm.cpp @@ -38,6 +38,9 @@ BigInt random_prime(RandomNumberGenerator& rng, while(true) { BigInt p(rng, bits); + + // Force lowest and two top bits on + p.set_bit(bits - 1); p.set_bit(bits - 2); p.set_bit(0); diff --git a/src/math/numbertheory/point_gfp.cpp b/src/math/numbertheory/point_gfp.cpp index bed08eb39..db422c8aa 100644 --- a/src/math/numbertheory/point_gfp.cpp +++ b/src/math/numbertheory/point_gfp.cpp @@ -202,7 +202,7 @@ void PointGFp::mult2() BigInt PointGFp::get_affine_x() const { if(is_zero()) - throw Illegal_Transformation("cannot convert to affine"); + throw Illegal_Transformation("Cannot convert zero point to affine"); const Modular_Reducer& mod_p = curve.mod_p(); @@ -213,7 +213,7 @@ BigInt PointGFp::get_affine_x() const BigInt PointGFp::get_affine_y() const { if(is_zero()) - throw Illegal_Transformation("cannot convert to affine"); + throw Illegal_Transformation("Cannot convert zero point to affine"); const Modular_Reducer& mod_p = curve.mod_p(); @@ -326,38 +326,39 @@ SecureVector<byte> EC2OSP(const PointGFp& point, byte format) throw Invalid_Argument("illegal point encoding format specification"); } -PointGFp OS2ECP(const MemoryRegion<byte>& os, const CurveGFp& curve) +PointGFp OS2ECP(const byte data[], u32bit data_len, + const CurveGFp& curve) { - if(os.size() == 1 && os[0] == 0) + if(data_len <= 1) return PointGFp(curve); // return zero - const byte pc = os[0]; + const byte pc = data[0]; BigInt x, y; if(pc == 2 || pc == 3) { //compressed form - x = BigInt::decode(&os[1], os.size() - 1); + x = BigInt::decode(&data[1], data_len - 1); bool yMod2 = ((pc & 0x01) == 1); y = decompress_point(yMod2, x, curve); } else if(pc == 4) { - // uncompressed form - u32bit l = (os.size() - 1) / 2; + const u32bit l = (data_len - 1) / 2; - x = BigInt::decode(&os[1], l); - y = BigInt::decode(&os[l+1], l); + // uncompressed form + x = BigInt::decode(&data[1], l); + y = BigInt::decode(&data[l+1], l); } else if(pc == 6 || pc == 7) { - // hybrid form - u32bit l = (os.size() - 1) / 2; + const u32bit l = (data_len - 1) / 2; - x = BigInt::decode(&os[1], l); - y = BigInt::decode(&os[l+1], l); + // hybrid form + x = BigInt::decode(&data[1], l); + y = BigInt::decode(&data[l+1], l); bool yMod2 = ((pc & 0x01) == 1); diff --git a/src/math/numbertheory/point_gfp.h b/src/math/numbertheory/point_gfp.h index 3bb763d44..2f31421fc 100644 --- a/src/math/numbertheory/point_gfp.h +++ b/src/math/numbertheory/point_gfp.h @@ -219,7 +219,12 @@ inline PointGFp operator*(const PointGFp& point, const BigInt& scalar) // encoding and decoding SecureVector<byte> BOTAN_DLL EC2OSP(const PointGFp& point, byte format); -PointGFp BOTAN_DLL OS2ECP(const MemoryRegion<byte>& os, const CurveGFp& curve); + +PointGFp BOTAN_DLL OS2ECP(const byte data[], u32bit data_len, + const CurveGFp& curve); + +inline PointGFp OS2ECP(const MemoryRegion<byte>& data, const CurveGFp& curve) + { return OS2ECP(&data[0], data.size(), curve); } } diff --git a/src/math/numbertheory/pow_mod.cpp b/src/math/numbertheory/pow_mod.cpp index 8d6bac699..5ab5638ea 100644 --- a/src/math/numbertheory/pow_mod.cpp +++ b/src/math/numbertheory/pow_mod.cpp @@ -6,7 +6,8 @@ */ #include <botan/pow_mod.h> -#include <botan/internal/pk_engine.h> +#include <botan/libstate.h> +#include <botan/engine.h> namespace Botan { @@ -55,7 +56,23 @@ Power_Mod::~Power_Mod() void Power_Mod::set_modulus(const BigInt& n, Usage_Hints hints) const { delete core; - core = ((n == 0) ? 0 : Engine_Core::mod_exp(n, hints)); + core = 0; + + if(n != 0) + { + Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory()); + + while(const Engine* engine = i.next()) + { + core = engine->mod_exp(n, hints); + + if(core) + break; + } + + if(!core) + throw Lookup_Error("Power_Mod: Unable to find a working engine"); + } } /* @@ -94,6 +111,38 @@ BigInt Power_Mod::execute() const return core->execute(); } +/* +* Try to choose a good window size +*/ +u32bit Power_Mod::window_bits(u32bit exp_bits, u32bit, + Power_Mod::Usage_Hints hints) + { + static const u32bit wsize[][2] = { + { 2048, 7 }, { 1024, 6 }, { 256, 5 }, { 128, 4 }, { 64, 3 }, { 0, 0 } + }; + + u32bit window_bits = 1; + + if(exp_bits) + { + for(u32bit j = 0; wsize[j][0]; ++j) + { + if(exp_bits >= wsize[j][0]) + { + window_bits += wsize[j][1]; + break; + } + } + } + + if(hints & Power_Mod::BASE_IS_FIXED) + window_bits += 2; + if(hints & Power_Mod::EXP_IS_LARGE) + ++window_bits; + + return window_bits; + } + namespace { /* diff --git a/src/math/numbertheory/pow_mod.h b/src/math/numbertheory/pow_mod.h index 6952dcd1b..7b92f0ec4 100644 --- a/src/math/numbertheory/pow_mod.h +++ b/src/math/numbertheory/pow_mod.h @@ -31,6 +31,7 @@ class BOTAN_DLL Modular_Exponentiator class BOTAN_DLL Power_Mod { public: + enum Usage_Hints { NO_HINTS = 0x0000, @@ -44,6 +45,12 @@ class BOTAN_DLL Power_Mod EXP_IS_LARGE = 0x0400 }; + /* + * Try to choose a good window size + */ + static u32bit window_bits(u32bit exp_bits, u32bit base_bits, + Power_Mod::Usage_Hints hints); + void set_modulus(const BigInt&, Usage_Hints = NO_HINTS) const; void set_base(const BigInt&) const; void set_exponent(const BigInt&) const; diff --git a/src/math/numbertheory/powm_fw.cpp b/src/math/numbertheory/powm_fw.cpp index 1cfcdcd66..68dabc332 100644 --- a/src/math/numbertheory/powm_fw.cpp +++ b/src/math/numbertheory/powm_fw.cpp @@ -11,44 +11,6 @@ namespace Botan { -namespace { - -/* -* Try to choose a good window size -*/ -u32bit fw_powm_window_bits(u32bit exp_bits, u32bit, - Power_Mod::Usage_Hints hints) - { - static const u32bit wsize[][2] = { - { 2048, 7 }, { 1024, 6 }, { 256, 5 }, { 128, 4 }, { 64, 3 }, { 0, 0 } - }; - - u32bit window_bits = 3; - - if(exp_bits) - { - for(u32bit j = 0; wsize[j][0]; ++j) - { - if(exp_bits >= wsize[j][0]) - { - window_bits += wsize[j][1]; - break; - } - } - } - - if(hints & Power_Mod::EXP_IS_FIXED) - window_bits += 2; - if(hints & Power_Mod::EXP_IS_LARGE) - window_bits += 2; - if(hints & Power_Mod::BASE_IS_FIXED) - ++window_bits; - - return window_bits; - } - -} - /* * Set the exponent */ @@ -62,7 +24,7 @@ void Fixed_Window_Exponentiator::set_exponent(const BigInt& e) */ void Fixed_Window_Exponentiator::set_base(const BigInt& base) { - window_bits = fw_powm_window_bits(exp.bits(), base.bits(), hints); + window_bits = Power_Mod::window_bits(exp.bits(), base.bits(), hints); g.resize((1 << window_bits) - 1); g[0] = base; diff --git a/src/math/numbertheory/powm_mnt.cpp b/src/math/numbertheory/powm_mnt.cpp index 2d18ccdef..cce142020 100644 --- a/src/math/numbertheory/powm_mnt.cpp +++ b/src/math/numbertheory/powm_mnt.cpp @@ -14,38 +14,6 @@ namespace Botan { namespace { /* -* Try to choose a good window size -*/ -u32bit montgomery_powm_window_bits(u32bit exp_bits, u32bit, - Power_Mod::Usage_Hints hints) - { - static const u32bit wsize[][2] = { - { 2048, 4 }, { 1024, 3 }, { 256, 2 }, { 128, 1 }, { 0, 0 } - }; - - u32bit window_bits = 1; - - if(exp_bits) - { - for(u32bit j = 0; wsize[j][0]; ++j) - { - if(exp_bits >= wsize[j][0]) - { - window_bits += wsize[j][1]; - break; - } - } - } - - if(hints & Power_Mod::BASE_IS_FIXED) - window_bits += 2; - if(hints & Power_Mod::EXP_IS_LARGE) - ++window_bits; - - return window_bits; - } - -/* * Montgomery Reduction */ inline void montgomery_reduce(BigInt& out, MemoryRegion<word>& z_buf, @@ -76,7 +44,7 @@ void Montgomery_Exponentiator::set_exponent(const BigInt& exp) */ void Montgomery_Exponentiator::set_base(const BigInt& base) { - window_bits = montgomery_powm_window_bits(exp.bits(), base.bits(), hints); + window_bits = Power_Mod::window_bits(exp.bits(), base.bits(), hints); g.resize((1 << window_bits) - 1); diff --git a/src/math/numbertheory/reducer.h b/src/math/numbertheory/reducer.h index 80c0f27e1..c121f1499 100644 --- a/src/math/numbertheory/reducer.h +++ b/src/math/numbertheory/reducer.h @@ -18,6 +18,8 @@ namespace Botan { class BOTAN_DLL Modular_Reducer { public: + const BigInt& get_modulus() const { return modulus; } + BigInt reduce(const BigInt& x) const; /** diff --git a/src/pubkey/blinding.cpp b/src/pubkey/blinding.cpp new file mode 100644 index 000000000..819d0dd20 --- /dev/null +++ b/src/pubkey/blinding.cpp @@ -0,0 +1,76 @@ +/* +* Blinding for public key operations +* (C) 1999-2010 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/blinding.h> +#include <botan/numthry.h> +#include <botan/libstate.h> +#include <botan/hash.h> +#include <botan/time.h> +#include <botan/loadstor.h> +#include <memory> + +namespace Botan { + +/* +* Blinder Constructor +*/ +Blinder::Blinder(const BigInt& e, const BigInt& d, const BigInt& n) + { + if(e < 1 || d < 1 || n < 1) + throw Invalid_Argument("Blinder: Arguments too small"); + + reducer = Modular_Reducer(n); + this->e = e; + this->d = d; + } + +BigInt Blinder::choose_nonce(const BigInt& x, const BigInt& mod) + { + Algorithm_Factory& af = global_state().algorithm_factory(); + + std::auto_ptr<HashFunction> hash(af.make_hash_function("SHA-512")); + + u64bit ns_clock = get_nanoseconds_clock(); + for(size_t i = 0; i != sizeof(ns_clock); ++i) + hash->update(get_byte(i, ns_clock)); + + hash->update(BigInt::encode(x)); + hash->update(BigInt::encode(mod)); + + u64bit timestamp = system_time(); + for(size_t i = 0; i != sizeof(timestamp); ++i) + hash->update(get_byte(i, timestamp)); + + SecureVector<byte> r = hash->final(); + + return BigInt::decode(r) % mod; + } + +/* +* Blind a number +*/ +BigInt Blinder::blind(const BigInt& i) const + { + if(!reducer.initialized()) + return i; + + e = reducer.square(e); + d = reducer.square(d); + return reducer.multiply(i, e); + } + +/* +* Unblind a number +*/ +BigInt Blinder::unblind(const BigInt& i) const + { + if(!reducer.initialized()) + return i; + return reducer.multiply(i, d); + } + +} diff --git a/src/pubkey/blinding.h b/src/pubkey/blinding.h new file mode 100644 index 000000000..3398f8c6f --- /dev/null +++ b/src/pubkey/blinding.h @@ -0,0 +1,53 @@ +/* +* Blinding for public key operations +* (C) 1999-2010 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_BLINDER_H__ +#define BOTAN_BLINDER_H__ + +#include <botan/bigint.h> +#include <botan/reducer.h> + +namespace Botan { + +/* +* Blinding Function Object +*/ +class BOTAN_DLL Blinder + { + public: + BigInt blind(const BigInt& x) const; + BigInt unblind(const BigInt& x) const; + + bool initialized() const { return reducer.initialized(); } + + /** + * Choose a nonce to use for blinding + * @param x a secret seed value + * @param mod the modulus + */ + static BigInt choose_nonce(const BigInt& x, const BigInt& mod); + + Blinder() {} + + /** + * Construct a blinder + * @param mask the forward (blinding) mask + * @param inverse_mask the inverse of mask (depends on algo) + * @param modulus of the group operations are performed in + */ + Blinder(const BigInt& mask, + const BigInt& inverse_mask, + const BigInt& modulus); + + private: + Modular_Reducer reducer; + mutable BigInt e, d; + }; + +} + +#endif diff --git a/src/pubkey/dh/dh.cpp b/src/pubkey/dh/dh.cpp index baaa31126..b491be7bc 100644 --- a/src/pubkey/dh/dh.cpp +++ b/src/pubkey/dh/dh.cpp @@ -18,22 +18,6 @@ DH_PublicKey::DH_PublicKey(const DL_Group& grp, const BigInt& y1) { group = grp; y = y1; - X509_load_hook(); - } - -/* -* Algorithm Specific X.509 Initialization Code -*/ -void DH_PublicKey::X509_load_hook() - { - } - -/* -* Return the maximum input size in bits -*/ -u32bit DH_PublicKey::max_input_bits() const - { - return group_p().bits(); } /* @@ -58,26 +42,29 @@ DH_PrivateKey::DH_PrivateKey(RandomNumberGenerator& rng, { const BigInt& p = group_p(); x.randomize(rng, 2 * dl_work_factor(p.bits())); - PKCS8_load_hook(rng, true); } + + if(y == 0) + y = power_mod(group_g(), x, group_p()); + + if(x == 0) + gen_check(rng); else - PKCS8_load_hook(rng, false); + load_check(rng); } /* -* Algorithm Specific PKCS #8 Initialization Code +* Load a DH private key */ -void DH_PrivateKey::PKCS8_load_hook(RandomNumberGenerator& rng, - bool generated) +DH_PrivateKey::DH_PrivateKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits, + RandomNumberGenerator& rng) : + DL_Scheme_PrivateKey(alg_id, key_bits, DL_Group::ANSI_X9_42) { if(y == 0) y = power_mod(group_g(), x, group_p()); - core = DH_Core(rng, group, x); - if(generated) - gen_check(rng); - else - load_check(rng); + load_check(rng); } /* @@ -88,32 +75,20 @@ MemoryVector<byte> DH_PrivateKey::public_value() const return DH_PublicKey::public_value(); } -/* -* Derive a key -*/ -SecureVector<byte> DH_PrivateKey::derive_key(const byte w[], - u32bit w_len) const +DH_KA_Operation::DH_KA_Operation(const DH_PrivateKey& dh) : + p(dh.group_p()), powermod_x_p(dh.get_x(), p) { - return derive_key(BigInt::decode(w, w_len)); + BigInt k = Blinder::choose_nonce(powermod_x_p(2), p); + blinder = Blinder(k, powermod_x_p(inverse_mod(k, p)), p); } -/* -* Derive a key -*/ -SecureVector<byte> DH_PrivateKey::derive_key(const DH_PublicKey& key) const +SecureVector<byte> DH_KA_Operation::agree(const byte w[], u32bit w_len) { - return derive_key(key.get_y()); - } + BigInt input = BigInt::decode(w, w_len); -/* -* Derive a key -*/ -SecureVector<byte> DH_PrivateKey::derive_key(const BigInt& w) const - { - const BigInt& p = group_p(); - if(w <= 1 || w >= p-1) - throw Invalid_Argument(algo_name() + "::derive_key: Invalid key input"); - return BigInt::encode_1363(core.agree(w), p.bytes()); + BigInt r = blinder.unblind(powermod_x_p(blinder.blind(input))); + + return BigInt::encode_1363(r, p.bytes()); } } diff --git a/src/pubkey/dh/dh.h b/src/pubkey/dh/dh.h index fa558bce2..738b3f9c4 100644 --- a/src/pubkey/dh/dh.h +++ b/src/pubkey/dh/dh.h @@ -9,7 +9,9 @@ #define BOTAN_DIFFIE_HELLMAN_H__ #include <botan/dl_algo.h> -#include <botan/dh_core.h> +#include <botan/pow_mod.h> +#include <botan/blinding.h> +#include <botan/pk_ops.h> namespace Botan { @@ -22,15 +24,13 @@ class BOTAN_DLL DH_PublicKey : public virtual DL_Scheme_PublicKey std::string algo_name() const { return "DH"; } MemoryVector<byte> public_value() const; - u32bit max_input_bits() const; + u32bit max_input_bits() const { return group_p().bits(); } DL_Group::Format group_format() const { return DL_Group::ANSI_X9_42; } - /** - * Construct an uninitialized key. Use this constructor if you wish - * to decode an encoded key into the new instance. - */ - DH_PublicKey() {} + DH_PublicKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits) : + DL_Scheme_PublicKey(alg_id, key_bits, DL_Group::ANSI_X9_42) {} /** * Construct a public key with the specified parameters. @@ -38,8 +38,8 @@ class BOTAN_DLL DH_PublicKey : public virtual DL_Scheme_PublicKey * @param y the public value y */ DH_PublicKey(const DL_Group& grp, const BigInt& y); - private: - void X509_load_hook(); + protected: + DH_PublicKey() {} }; /** @@ -50,17 +50,17 @@ class BOTAN_DLL DH_PrivateKey : public DH_PublicKey, public virtual DL_Scheme_PrivateKey { public: - SecureVector<byte> derive_key(const byte other[], u32bit length) const; - SecureVector<byte> derive_key(const DH_PublicKey& other) const; - SecureVector<byte> derive_key(const BigInt& other) const; - MemoryVector<byte> public_value() const; /** - * Construct an uninitialized key. Use this constructor if you wish - * to decode an encoded key into the new instance. + * Load a DH private key + * @param alg_id the algorithm id + * @param key_bits the subject public key + * @rng a random number generator */ - DH_PrivateKey() {} + DH_PrivateKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits, + RandomNumberGenerator& rng); /** * Construct a private key with predetermined value. @@ -70,9 +70,22 @@ class BOTAN_DLL DH_PrivateKey : public DH_PublicKey, */ DH_PrivateKey(RandomNumberGenerator& rng, const DL_Group& grp, const BigInt& x = 0); + }; + +/** +* DH operation +*/ +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[], u32bit w_len); private: - void PKCS8_load_hook(RandomNumberGenerator& rng, bool = false); - DH_Core core; + const BigInt& p; + + Fixed_Exponent_Power_Mod powermod_x_p; + Blinder blinder; }; } diff --git a/src/pubkey/dh/dh_core.cpp b/src/pubkey/dh/dh_core.cpp deleted file mode 100644 index cbe2dc9f1..000000000 --- a/src/pubkey/dh/dh_core.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* -* PK Algorithm Core -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/dh_core.h> -#include <botan/numthry.h> -#include <botan/internal/pk_engine.h> -#include <botan/parsing.h> -#include <algorithm> - -namespace Botan { - -/* -* DH_Core Constructor -*/ -DH_Core::DH_Core(RandomNumberGenerator& rng, - const DL_Group& group, const BigInt& x) - { - const u32bit BLINDING_BITS = BOTAN_PRIVATE_KEY_OP_BLINDING_BITS; - - op = Engine_Core::dh_op(group, x); - - const BigInt& p = group.get_p(); - - BigInt k(rng, std::min(p.bits()-1, BLINDING_BITS)); - - if(k != 0) - blinder = Blinder(k, power_mod(inverse_mod(k, p), x, p), p); - } - -/* -* DH_Core Copy Constructor -*/ -DH_Core::DH_Core(const DH_Core& core) - { - op = 0; - if(core.op) - op = core.op->clone(); - blinder = core.blinder; - } - -/* -* DH_Core Assignment Operator -*/ -DH_Core& DH_Core::operator=(const DH_Core& core) - { - delete op; - if(core.op) - op = core.op->clone(); - blinder = core.blinder; - return (*this); - } - -/* -* DH Operation -*/ -BigInt DH_Core::agree(const BigInt& i) const - { - return blinder.unblind(op->agree(blinder.blind(i))); - } - -} diff --git a/src/pubkey/dh/dh_core.h b/src/pubkey/dh/dh_core.h deleted file mode 100644 index 91b50a27a..000000000 --- a/src/pubkey/dh/dh_core.h +++ /dev/null @@ -1,38 +0,0 @@ -/* -* DH Core -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_DH_CORE_H__ -#define BOTAN_DH_CORE_H__ - -#include <botan/dh_op.h> -#include <botan/blinding.h> - -namespace Botan { - -/* -* DH Core -*/ -class BOTAN_DLL DH_Core - { - public: - BigInt agree(const BigInt&) const; - - DH_Core& operator=(const DH_Core&); - - DH_Core() { op = 0; } - DH_Core(const DH_Core&); - DH_Core(RandomNumberGenerator& rng, - const DL_Group&, const BigInt&); - ~DH_Core() { delete op; } - private: - DH_Operation* op; - Blinder blinder; - }; - -} - -#endif diff --git a/src/pubkey/dh/dh_op.h b/src/pubkey/dh/dh_op.h deleted file mode 100644 index 50f3d7825..000000000 --- a/src/pubkey/dh/dh_op.h +++ /dev/null @@ -1,45 +0,0 @@ -/* -* DH Operations -* (C) 1999-2008 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_DH_OPS_H__ -#define BOTAN_DH_OPS_H__ - -#include <botan/dl_group.h> -#include <botan/reducer.h> -#include <botan/pow_mod.h> - -namespace Botan { - -/* -* DH Operation Interface -*/ -class BOTAN_DLL DH_Operation - { - public: - virtual BigInt agree(const BigInt&) const = 0; - virtual DH_Operation* clone() const = 0; - virtual ~DH_Operation() {} - }; - -/* -* Botan's Default DH Operation -*/ -class BOTAN_DLL Default_DH_Op : public DH_Operation - { - public: - BigInt agree(const BigInt& i) const { return powermod_x_p(i); } - DH_Operation* clone() const { return new Default_DH_Op(*this); } - - Default_DH_Op(const DL_Group& group, const BigInt& x) : - powermod_x_p(x, group.get_p()) {} - private: - Fixed_Exponent_Power_Mod powermod_x_p; - }; - -} - -#endif diff --git a/src/pubkey/dh/info.txt b/src/pubkey/dh/info.txt index ca8f74fa1..e1e460cd0 100644 --- a/src/pubkey/dh/info.txt +++ b/src/pubkey/dh/info.txt @@ -1,14 +1,11 @@ define DIFFIE_HELLMAN <header:public> -dh_core.h -dh_op.h dh.h </header:public> <source> dh.cpp -dh_core.cpp </source> <requires> diff --git a/src/pubkey/dl_algo/dl_algo.cpp b/src/pubkey/dl_algo/dl_algo.cpp index 8ce34465a..8e326ef6a 100644 --- a/src/pubkey/dl_algo/dl_algo.cpp +++ b/src/pubkey/dl_algo/dl_algo.cpp @@ -12,120 +12,40 @@ namespace Botan { -/* -* Return the X.509 public key encoder -*/ -X509_Encoder* DL_Scheme_PublicKey::x509_encoder() const +AlgorithmIdentifier DL_Scheme_PublicKey::algorithm_identifier() const { - class DL_Scheme_Encoder : public X509_Encoder - { - public: - AlgorithmIdentifier alg_id() const - { - MemoryVector<byte> group = - key->group.DER_encode(key->group_format()); - - return AlgorithmIdentifier(key->get_oid(), group); - } - - MemoryVector<byte> key_bits() const - { - return DER_Encoder().encode(key->y).get_contents(); - } - - DL_Scheme_Encoder(const DL_Scheme_PublicKey* k) : key(k) {} - private: - const DL_Scheme_PublicKey* key; - }; - - return new DL_Scheme_Encoder(this); + return AlgorithmIdentifier(get_oid(), + group.DER_encode(group_format())); } -/* -* Return the X.509 public key decoder -*/ -X509_Decoder* DL_Scheme_PublicKey::x509_decoder() +MemoryVector<byte> DL_Scheme_PublicKey::x509_subject_public_key() const { - class DL_Scheme_Decoder : public X509_Decoder - { - public: - void alg_id(const AlgorithmIdentifier& alg_id) - { - DataSource_Memory source(alg_id.parameters); - key->group.BER_decode(source, key->group_format()); - } - - void key_bits(const MemoryRegion<byte>& bits) - { - BER_Decoder(bits).decode(key->y); - key->X509_load_hook(); - } - - DL_Scheme_Decoder(DL_Scheme_PublicKey* k) : key(k) {} - private: - DL_Scheme_PublicKey* key; - }; - - return new DL_Scheme_Decoder(this); + return DER_Encoder().encode(y).get_contents(); } -/* -* Return the PKCS #8 private key encoder -*/ -PKCS8_Encoder* DL_Scheme_PrivateKey::pkcs8_encoder() const +DL_Scheme_PublicKey::DL_Scheme_PublicKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits, + DL_Group::Format format) { - class DL_Scheme_Encoder : public PKCS8_Encoder - { - public: - AlgorithmIdentifier alg_id() const - { - MemoryVector<byte> group = - key->group.DER_encode(key->group_format()); - - return AlgorithmIdentifier(key->get_oid(), group); - } - - MemoryVector<byte> key_bits() const - { - return DER_Encoder().encode(key->x).get_contents(); - } - - DL_Scheme_Encoder(const DL_Scheme_PrivateKey* k) : key(k) {} - private: - const DL_Scheme_PrivateKey* key; - }; - - return new DL_Scheme_Encoder(this); + DataSource_Memory source(alg_id.parameters); + group.BER_decode(source, format); + + BER_Decoder(key_bits).decode(y); } -/* -* Return the PKCS #8 private key decoder -*/ -PKCS8_Decoder* DL_Scheme_PrivateKey::pkcs8_decoder(RandomNumberGenerator& rng) +MemoryVector<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, + DL_Group::Format format) { - class DL_Scheme_Decoder : public PKCS8_Decoder - { - public: - void alg_id(const AlgorithmIdentifier& alg_id) - { - DataSource_Memory source(alg_id.parameters); - key->group.BER_decode(source, key->group_format()); - } - - void key_bits(const MemoryRegion<byte>& bits) - { - BER_Decoder(bits).decode(key->x); - key->PKCS8_load_hook(rng); - } - - DL_Scheme_Decoder(DL_Scheme_PrivateKey* k, RandomNumberGenerator& r) : - key(k), rng(r) {} - private: - DL_Scheme_PrivateKey* key; - RandomNumberGenerator& rng; - }; - - return new DL_Scheme_Decoder(this, rng); + DataSource_Memory source(alg_id.parameters); + group.BER_decode(source, format); + + BER_Decoder(key_bits).decode(x); } /* diff --git a/src/pubkey/dl_algo/dl_algo.h b/src/pubkey/dl_algo/dl_algo.h index 256ce96ee..bb594a393 100644 --- a/src/pubkey/dl_algo/dl_algo.h +++ b/src/pubkey/dl_algo/dl_algo.h @@ -23,6 +23,10 @@ class BOTAN_DLL DL_Scheme_PublicKey : public virtual Public_Key public: bool check_key(RandomNumberGenerator& rng, bool) const; + AlgorithmIdentifier algorithm_identifier() const; + + MemoryVector<byte> x509_subject_public_key() const; + /** * Get the DL domain parameters of this key. * @return the DL domain parameters of this key @@ -58,23 +62,14 @@ class BOTAN_DLL DL_Scheme_PublicKey : public virtual Public_Key */ virtual DL_Group::Format group_format() const = 0; - /** - * Get an X509 encoder for this key. - * @return an encoder usable to encode this key. - */ - X509_Encoder* x509_encoder() const; + DL_Scheme_PublicKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits, + DL_Group::Format group_format); - /** - * Get an X509 decoder for this key. - * @return an decoder usable to decode a DL key and store the - * values in this instance. - */ - X509_Decoder* x509_decoder(); protected: + DL_Scheme_PublicKey() {} BigInt y; DL_Group group; - private: - virtual void X509_load_hook() {} }; /** @@ -92,23 +87,15 @@ class BOTAN_DLL DL_Scheme_PrivateKey : public virtual DL_Scheme_PublicKey, */ const BigInt& get_x() const { return x; } - /** - * Get an PKCS#8 encoder for this key. - * @return an encoder usable to encode this key. - */ - PKCS8_Encoder* pkcs8_encoder() const; + MemoryVector<byte> pkcs8_private_key() const; + + DL_Scheme_PrivateKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits, + DL_Group::Format group_format); - /** - * Get an PKCS#8 decoder for this key. - * @param rng the rng to use - * @return an decoder usable to decode a DL key and store the - * values in this instance. - */ - PKCS8_Decoder* pkcs8_decoder(RandomNumberGenerator& rng); protected: + DL_Scheme_PrivateKey() {} BigInt x; - private: - virtual void PKCS8_load_hook(RandomNumberGenerator&, bool = false) {} }; } diff --git a/src/pubkey/dl_algo/info.txt b/src/pubkey/dl_algo/info.txt index 21829fa42..f6e609062 100644 --- a/src/pubkey/dl_algo/info.txt +++ b/src/pubkey/dl_algo/info.txt @@ -4,6 +4,5 @@ define DL_PUBLIC_KEY_FAMILY asn1 dl_group numbertheory -pk_codecs rng </requires> diff --git a/src/pubkey/dlies/dlies.cpp b/src/pubkey/dlies/dlies.cpp index 6ef3292e1..07477fd5d 100644 --- a/src/pubkey/dlies/dlies.cpp +++ b/src/pubkey/dlies/dlies.cpp @@ -6,7 +6,6 @@ */ #include <botan/dlies.h> -#include <botan/look_pk.h> #include <botan/internal/xor_buf.h> namespace Botan { @@ -14,12 +13,16 @@ namespace Botan { /* * DLIES_Encryptor Constructor */ -DLIES_Encryptor::DLIES_Encryptor(const PK_Key_Agreement_Key& k, +DLIES_Encryptor::DLIES_Encryptor(const PK_Key_Agreement_Key& key, KDF* kdf_obj, MessageAuthenticationCode* mac_obj, u32bit mac_kl) : - key(k), kdf(kdf_obj), mac(mac_obj), mac_keylen(mac_kl) + ka(key, "Raw"), + kdf(kdf_obj), + mac(mac_obj), + mac_keylen(mac_kl) { + my_key = key.public_value(); } DLIES_Encryptor::~DLIES_Encryptor() @@ -39,19 +42,18 @@ SecureVector<byte> DLIES_Encryptor::enc(const byte in[], u32bit length, if(other_key.empty()) throw Invalid_State("DLIES: The other key was never set"); - MemoryVector<byte> v = key.public_value(); + SecureVector<byte> out(my_key.size() + length + mac->OUTPUT_LENGTH); + out.copy(my_key, my_key.size()); + out.copy(my_key.size(), in, length); - SecureVector<byte> out(v.size() + length + mac->OUTPUT_LENGTH); - out.copy(v, v.size()); - out.copy(v.size(), in, length); - - SecureVector<byte> vz(v, key.derive_key(other_key, other_key.size())); + SecureVector<byte> vz(my_key, ka.derive_key(0, other_key).bits_of()); const u32bit K_LENGTH = length + mac_keylen; OctetString K = kdf->derive_key(K_LENGTH, vz, vz.size()); + if(K.length() != K_LENGTH) throw Encoding_Error("DLIES: KDF did not provide sufficient output"); - byte* C = out + v.size(); + byte* C = out + my_key.size(); xor_buf(C, K.begin() + mac_keylen, length); mac->set_key(K.begin(), mac_keylen); @@ -84,12 +86,16 @@ u32bit DLIES_Encryptor::maximum_input_size() const /* * DLIES_Decryptor Constructor */ -DLIES_Decryptor::DLIES_Decryptor(const PK_Key_Agreement_Key& k, +DLIES_Decryptor::DLIES_Decryptor(const PK_Key_Agreement_Key& key, KDF* kdf_obj, MessageAuthenticationCode* mac_obj, u32bit mac_kl) : - key(k), kdf(kdf_obj), mac(mac_obj), mac_keylen(mac_kl) + ka(key, "Raw"), + kdf(kdf_obj), + mac(mac_obj), + mac_keylen(mac_kl) { + my_key = key.public_value(); } DLIES_Decryptor::~DLIES_Decryptor() @@ -103,18 +109,16 @@ DLIES_Decryptor::~DLIES_Decryptor() */ SecureVector<byte> DLIES_Decryptor::dec(const byte msg[], u32bit length) const { - const u32bit public_len = key.public_value().size(); - - if(length < public_len + mac->OUTPUT_LENGTH) + if(length < my_key.size() + mac->OUTPUT_LENGTH) throw Decoding_Error("DLIES decryption: ciphertext is too short"); - const u32bit CIPHER_LEN = length - public_len - mac->OUTPUT_LENGTH; + const u32bit CIPHER_LEN = length - my_key.size() - mac->OUTPUT_LENGTH; - SecureVector<byte> v(msg, public_len); - SecureVector<byte> C(msg + public_len, CIPHER_LEN); - SecureVector<byte> T(msg + public_len + CIPHER_LEN, 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); - SecureVector<byte> vz(v, key.derive_key(v, v.size())); + SecureVector<byte> vz(v, ka.derive_key(0, v).bits_of()); const u32bit K_LENGTH = C.size() + mac_keylen; OctetString K = kdf->derive_key(K_LENGTH, vz, vz.size()); diff --git a/src/pubkey/dlies/dlies.h b/src/pubkey/dlies/dlies.h index 88a22b9de..fd2cefe4a 100644 --- a/src/pubkey/dlies/dlies.h +++ b/src/pubkey/dlies/dlies.h @@ -33,9 +33,9 @@ class BOTAN_DLL DLIES_Encryptor : public PK_Encryptor RandomNumberGenerator&) const; u32bit maximum_input_size() const; - const PK_Key_Agreement_Key& key; - SecureVector<byte> other_key; + SecureVector<byte> other_key, my_key; + PK_Key_Agreement ka; KDF* kdf; MessageAuthenticationCode* mac; u32bit mac_keylen; @@ -57,8 +57,9 @@ class BOTAN_DLL DLIES_Decryptor : public PK_Decryptor private: SecureVector<byte> dec(const byte[], u32bit) const; - const PK_Key_Agreement_Key& key; + SecureVector<byte> my_key; + PK_Key_Agreement ka; KDF* kdf; MessageAuthenticationCode* mac; u32bit mac_keylen; diff --git a/src/pubkey/dsa/dsa.cpp b/src/pubkey/dsa/dsa.cpp index 5be3e1d48..feac712b8 100644 --- a/src/pubkey/dsa/dsa.cpp +++ b/src/pubkey/dsa/dsa.cpp @@ -1,6 +1,6 @@ /* * DSA -* (C) 1999-2008 Jack Lloyd +* (C) 1999-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -8,7 +8,6 @@ #include <botan/dsa.h> #include <botan/numthry.h> #include <botan/keypair.h> -#include <botan/look_pk.h> namespace Botan { @@ -19,40 +18,6 @@ DSA_PublicKey::DSA_PublicKey(const DL_Group& grp, const BigInt& y1) { group = grp; y = y1; - X509_load_hook(); - } - -/* -* Algorithm Specific X.509 Initialization Code -*/ -void DSA_PublicKey::X509_load_hook() - { - core = DSA_Core(group, y); - } - -/* -* DSA Verification Function -*/ -bool DSA_PublicKey::verify(const byte msg[], u32bit msg_len, - const byte sig[], u32bit sig_len) const - { - return core.verify(msg, msg_len, sig, sig_len); - } - -/* -* Return the maximum input size in bits -*/ -u32bit DSA_PublicKey::max_input_bits() const - { - return group_q().bits(); - } - -/* -* Return the size of each portion of the sig -*/ -u32bit DSA_PublicKey::message_part_size() const - { - return group_q().bytes(); } /* @@ -66,45 +31,24 @@ DSA_PrivateKey::DSA_PrivateKey(RandomNumberGenerator& rng, x = x_arg; if(x == 0) - { x = BigInt::random_integer(rng, 2, group_q() - 1); - PKCS8_load_hook(rng, true); - } - else - PKCS8_load_hook(rng, false); - } -/* -* Algorithm Specific PKCS #8 Initialization Code -*/ -void DSA_PrivateKey::PKCS8_load_hook(RandomNumberGenerator& rng, - bool generated) - { y = power_mod(group_g(), x, group_p()); - core = DSA_Core(group, y, x); - if(generated) + if(x_arg == 0) gen_check(rng); else load_check(rng); } -/* -* DSA Signature Operation -*/ -SecureVector<byte> DSA_PrivateKey::sign(const byte in[], u32bit length, - RandomNumberGenerator& rng) const +DSA_PrivateKey::DSA_PrivateKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits, + RandomNumberGenerator& rng) : + DL_Scheme_PrivateKey(alg_id, key_bits, DL_Group::ANSI_X9_57) { - const BigInt& q = group_q(); - - rng.add_entropy(in, length); - - BigInt k; - do - k.randomize(rng, q.bits()); - while(k >= q); + y = power_mod(group_g(), x, group_p()); - return core.sign(in, length, k); + load_check(rng); } /* @@ -120,10 +64,9 @@ bool DSA_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const try { - KeyPair::check_key(rng, - get_pk_signer(*this, "EMSA1(SHA-1)"), - get_pk_verifier(*this, "EMSA1(SHA-1)") - ); + PK_Signer this_signer(*this, "EMSA1(SHA-1)"); + PK_Verifier this_verifier(*this, "EMSA1(SHA-1)"); + KeyPair::check_key(rng, this_signer, this_verifier); } catch(Self_Test_Failure) { @@ -133,4 +76,68 @@ bool DSA_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const return true; } +DSA_Signature_Operation::DSA_Signature_Operation(const DSA_PrivateKey& dsa) : + q(dsa.group_q()), + x(dsa.get_x()), + powermod_g_p(dsa.group_g(), dsa.group_p()), + mod_q(dsa.group_q()) + { + } + +SecureVector<byte> +DSA_Signature_Operation::sign(const byte msg[], u32bit msg_len, + RandomNumberGenerator& rng) + { + rng.add_entropy(msg, msg_len); + + BigInt k; + do + k.randomize(rng, q.bits()); + while(k >= q); + + BigInt i(msg, msg_len); + + BigInt r = mod_q.reduce(powermod_g_p(k)); + BigInt s = mod_q.multiply(inverse_mod(k, q), mul_add(x, r, i)); + + if(r.is_zero() || s.is_zero()) + throw Internal_Error("DSA signature gen failure: r or s was zero"); + + SecureVector<byte> output(2*q.bytes()); + r.binary_encode(output + (output.size() / 2 - r.bytes())); + s.binary_encode(output + (output.size() - s.bytes())); + return output; + } + +DSA_Verification_Operation::DSA_Verification_Operation(const DSA_PublicKey& dsa) : + q(dsa.group_q()), y(dsa.get_y()) + { + powermod_g_p = Fixed_Base_Power_Mod(dsa.group_g(), dsa.group_p()); + powermod_y_p = Fixed_Base_Power_Mod(y, dsa.group_p()); + mod_p = Modular_Reducer(dsa.group_p()); + mod_q = Modular_Reducer(dsa.group_q()); + } + +bool DSA_Verification_Operation::verify(const byte msg[], u32bit msg_len, + const byte sig[], u32bit sig_len) + { + const BigInt& q = mod_q.get_modulus(); + + if(sig_len != 2*q.bytes() || msg_len > q.bytes()) + return false; + + BigInt r(sig, q.bytes()); + BigInt s(sig + q.bytes(), q.bytes()); + BigInt i(msg, msg_len); + + if(r <= 0 || r >= q || s <= 0 || s >= q) + 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))); + + return (mod_q.reduce(s) == r); + } + } diff --git a/src/pubkey/dsa/dsa.h b/src/pubkey/dsa/dsa.h index 4c9b708f4..8121cfbbc 100644 --- a/src/pubkey/dsa/dsa.h +++ b/src/pubkey/dsa/dsa.h @@ -1,6 +1,6 @@ /* * DSA -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -9,52 +9,91 @@ #define BOTAN_DSA_H__ #include <botan/dl_algo.h> -#include <botan/dsa_core.h> +#include <botan/pk_ops.h> +#include <botan/reducer.h> +#include <botan/pow_mod.h> namespace Botan { /* * DSA Public Key */ -class BOTAN_DLL DSA_PublicKey : public PK_Verifying_wo_MR_Key, - public virtual DL_Scheme_PublicKey +class BOTAN_DLL DSA_PublicKey : public virtual DL_Scheme_PublicKey { public: std::string algo_name() const { return "DSA"; } DL_Group::Format group_format() const { return DL_Group::ANSI_X9_57; } u32bit message_parts() const { return 2; } - u32bit message_part_size() const; + u32bit message_part_size() const { return group_q().bytes(); } + u32bit max_input_bits() const { return group_q().bits(); } - bool verify(const byte[], u32bit, const byte[], u32bit) const; - u32bit max_input_bits() const; + DSA_PublicKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits) : + DL_Scheme_PublicKey(alg_id, key_bits, DL_Group::ANSI_X9_57) + { + } - DSA_PublicKey() {} - DSA_PublicKey(const DL_Group&, const BigInt&); + DSA_PublicKey(const DL_Group& group, const BigInt& y); protected: - DSA_Core core; - private: - void X509_load_hook(); + DSA_PublicKey() {} }; /* * DSA Private Key */ class BOTAN_DLL DSA_PrivateKey : public DSA_PublicKey, - public PK_Signing_Key, public virtual DL_Scheme_PrivateKey { public: - SecureVector<byte> sign(const byte[], u32bit, - RandomNumberGenerator& rng) const; + DSA_PrivateKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits, + RandomNumberGenerator& rng); + + DSA_PrivateKey(RandomNumberGenerator& rng, + const DL_Group& group, + const BigInt& private_key = 0); + + bool check_key(RandomNumberGenerator& rng, bool strong) const; + }; + +class BOTAN_DLL DSA_Signature_Operation : public PK_Ops::Signature + { + public: + DSA_Signature_Operation(const DSA_PrivateKey& dsa); + + u32bit message_parts() const { return 2; } + u32bit message_part_size() const { return q.bytes(); } + u32bit max_input_bits() const { return q.bits(); } + + SecureVector<byte> sign(const byte msg[], u32bit msg_len, + RandomNumberGenerator& rng); + private: + const BigInt& q; + const BigInt& x; + Fixed_Base_Power_Mod powermod_g_p; + Modular_Reducer mod_q; + }; + +class BOTAN_DLL DSA_Verification_Operation : public PK_Ops::Verification + { + public: + DSA_Verification_Operation(const DSA_PublicKey& dsa); - bool check_key(RandomNumberGenerator& rng, bool) const; + u32bit message_parts() const { return 2; } + u32bit message_part_size() const { return q.bytes(); } + u32bit max_input_bits() const { return q.bits(); } - DSA_PrivateKey() {} - DSA_PrivateKey(RandomNumberGenerator&, const DL_Group&, - const BigInt& = 0); + bool with_recovery() const { return false; } + + bool verify(const byte msg[], u32bit msg_len, + const byte sig[], u32bit sig_len); private: - void PKCS8_load_hook(RandomNumberGenerator& rng, bool = false); + const BigInt& q; + const BigInt& y; + + Fixed_Base_Power_Mod powermod_g_p, powermod_y_p; + Modular_Reducer mod_p, mod_q; }; } diff --git a/src/pubkey/dsa/dsa_core.cpp b/src/pubkey/dsa/dsa_core.cpp deleted file mode 100644 index d952e10eb..000000000 --- a/src/pubkey/dsa/dsa_core.cpp +++ /dev/null @@ -1,63 +0,0 @@ -/* -* DSA Core -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/dsa_core.h> -#include <botan/numthry.h> -#include <botan/internal/pk_engine.h> -#include <botan/parsing.h> -#include <algorithm> - -namespace Botan { - -/* -* DSA_Core Constructor -*/ -DSA_Core::DSA_Core(const DL_Group& group, const BigInt& y, const BigInt& x) - { - op = Engine_Core::dsa_op(group, y, x); - } - -/* -* DSA_Core Copy Constructor -*/ -DSA_Core::DSA_Core(const DSA_Core& core) - { - op = 0; - if(core.op) - op = core.op->clone(); - } - -/* -* DSA_Core Assignment Operator -*/ -DSA_Core& DSA_Core::operator=(const DSA_Core& core) - { - delete op; - if(core.op) - op = core.op->clone(); - return (*this); - } - -/* -* DSA Verification Operation -*/ -bool DSA_Core::verify(const byte msg[], u32bit msg_length, - const byte sig[], u32bit sig_length) const - { - return op->verify(msg, msg_length, sig, sig_length); - } - -/* -* DSA Signature Operation -*/ -SecureVector<byte> DSA_Core::sign(const byte in[], u32bit length, - const BigInt& k) const - { - return op->sign(in, length, k); - } - -} diff --git a/src/pubkey/dsa/dsa_core.h b/src/pubkey/dsa/dsa_core.h deleted file mode 100644 index 8bb16211f..000000000 --- a/src/pubkey/dsa/dsa_core.h +++ /dev/null @@ -1,37 +0,0 @@ -/* -* DSA Core -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_DSA_CORE_H__ -#define BOTAN_DSA_CORE_H__ - -#include <botan/dsa_op.h> -#include <botan/dl_group.h> - -namespace Botan { - -/* -* DSA Core -*/ -class BOTAN_DLL DSA_Core - { - public: - SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const; - bool verify(const byte[], u32bit, const byte[], u32bit) const; - - DSA_Core& operator=(const DSA_Core&); - - DSA_Core() { op = 0; } - DSA_Core(const DSA_Core&); - DSA_Core(const DL_Group&, const BigInt&, const BigInt& = 0); - ~DSA_Core() { delete op; } - private: - DSA_Operation* op; - }; - -} - -#endif diff --git a/src/pubkey/dsa/dsa_op.cpp b/src/pubkey/dsa/dsa_op.cpp deleted file mode 100644 index e83fd83b7..000000000 --- a/src/pubkey/dsa/dsa_op.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* -* DSA Operations -* (C) 1999-2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/dsa_op.h> -#include <future> - -namespace Botan { - -/* -* Default_DSA_Op Constructor -*/ -Default_DSA_Op::Default_DSA_Op(const DL_Group& grp, const BigInt& y1, - const BigInt& x1) : x(x1), y(y1), group(grp) - { - powermod_g_p = Fixed_Base_Power_Mod(group.get_g(), group.get_p()); - powermod_y_p = Fixed_Base_Power_Mod(y, group.get_p()); - mod_p = Modular_Reducer(group.get_p()); - mod_q = Modular_Reducer(group.get_q()); - } - -/* -* Default DSA Verify Operation -*/ -bool Default_DSA_Op::verify(const byte msg[], u32bit msg_len, - const byte sig[], u32bit sig_len) const - { - const BigInt& q = group.get_q(); - - if(sig_len != 2*q.bytes() || msg_len > q.bytes()) - return false; - - BigInt r(sig, q.bytes()); - BigInt s(sig + q.bytes(), q.bytes()); - BigInt i(msg, msg_len); - - if(r <= 0 || r >= q || s <= 0 || s >= q) - return false; - - s = inverse_mod(s, q); - - 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); - } - -/* -* Default DSA Sign Operation -*/ -SecureVector<byte> Default_DSA_Op::sign(const byte in[], u32bit length, - const BigInt& k) const - { - if(x == 0) - throw Internal_Error("Default_DSA_Op::sign: No private key"); - - auto future_r = std::async(std::launch::async, - [&]() { return mod_q.reduce(powermod_g_p(k)); }); - - const BigInt& q = group.get_q(); - BigInt i(in, length); - - BigInt s = inverse_mod(k, q); - BigInt r = future_r.get(); - - s = mod_q.multiply(s, mul_add(x, r, i)); - - if(r.is_zero() || s.is_zero()) - throw Internal_Error("Default_DSA_Op::sign: r or s was zero"); - - SecureVector<byte> output(2*q.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/dsa/dsa_op.h b/src/pubkey/dsa/dsa_op.h deleted file mode 100644 index 47a9d09e1..000000000 --- a/src/pubkey/dsa/dsa_op.h +++ /dev/null @@ -1,59 +0,0 @@ -/* -* DSA Operations -* (C) 1999-2008 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_DSA_OPS_H__ -#define BOTAN_DSA_OPS_H__ - -#include <botan/numthry.h> -#include <botan/pow_mod.h> -#include <botan/reducer.h> -#include <botan/dl_group.h> - -namespace Botan { - -/* -* DSA Operation -*/ -class BOTAN_DLL DSA_Operation - { - public: - virtual bool verify(const byte msg[], u32bit msg_len, - const byte sig[], u32bit sig_len) const = 0; - - virtual SecureVector<byte> sign(const byte msg[], u32bit msg_len, - const BigInt& k) const = 0; - - virtual DSA_Operation* clone() const = 0; - - virtual ~DSA_Operation() {} - }; - -/* -* Botan's Default DSA Operation -*/ -class BOTAN_DLL Default_DSA_Op : public DSA_Operation - { - public: - bool verify(const byte msg[], u32bit msg_len, - const byte sig[], u32bit sig_len) const; - - SecureVector<byte> sign(const byte msg[], u32bit msg_len, - const BigInt& k) const; - - DSA_Operation* clone() const { return new Default_DSA_Op(*this); } - - Default_DSA_Op(const DL_Group&, const BigInt&, const BigInt&); - private: - const BigInt x, y; - const DL_Group group; - Fixed_Base_Power_Mod powermod_g_p, powermod_y_p; - Modular_Reducer mod_p, mod_q; - }; - -} - -#endif diff --git a/src/pubkey/dsa/info.txt b/src/pubkey/dsa/info.txt index 1248cf68d..d59fe7aa7 100644 --- a/src/pubkey/dsa/info.txt +++ b/src/pubkey/dsa/info.txt @@ -1,17 +1,5 @@ define DSA -<header:public> -dsa.h -dsa_core.h -dsa_op.h -</header:public> - -<source> -dsa.cpp -dsa_core.cpp -dsa_op.cpp -</source> - <requires> dl_algo dl_group diff --git a/src/pubkey/ec_dompar/ec_dompar.cpp b/src/pubkey/ec_dompar/ec_dompar.cpp index 7910e898f..42ae9211e 100644 --- a/src/pubkey/ec_dompar/ec_dompar.cpp +++ b/src/pubkey/ec_dompar/ec_dompar.cpp @@ -35,7 +35,7 @@ EC_Domain_Params::EC_Domain_Params(const std::string& pem) DataSource_Memory input(pem); *this = EC_Domain_Params( - PEM_Code::decode_check_label(input, "ECC DOMAIN PARAMETERS")); + PEM_Code::decode_check_label(input, "EC PARAMETERS")); } } @@ -136,7 +136,7 @@ EC_Domain_Params::DER_encode(EC_Domain_Params_Encoding form) const std::string EC_Domain_Params::PEM_encode() const { SecureVector<byte> der = DER_encode(EC_DOMPAR_ENC_EXPLICIT); - return PEM_Code::encode(der, "ECC DOMAIN PARAMETERS"); + return PEM_Code::encode(der, "EC PARAMETERS"); } } diff --git a/src/pubkey/ecc_key/ecc_key.cpp b/src/pubkey/ecc_key/ecc_key.cpp index 10968fa7e..a4bd9b635 100644 --- a/src/pubkey/ecc_key/ecc_key.cpp +++ b/src/pubkey/ecc_key/ecc_key.cpp @@ -35,8 +35,14 @@ EC_PublicKey::EC_PublicKey(const EC_Domain_Params& dom_par, } } -void EC_PublicKey::X509_load_hook() +EC_PublicKey::EC_PublicKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits) { + domain_params = EC_Domain_Params(alg_id.parameters); + domain_encoding = EC_DOMPAR_ENC_EXPLICIT; + + public_key = PointGFp(OS2ECP(key_bits, domain().get_curve())); + try { public_point().check_invariants(); @@ -47,54 +53,14 @@ void EC_PublicKey::X509_load_hook() } } -X509_Encoder* EC_PublicKey::x509_encoder() const +AlgorithmIdentifier EC_PublicKey::algorithm_identifier() const { - class EC_Key_Encoder : public X509_Encoder - { - public: - AlgorithmIdentifier alg_id() const - { - return AlgorithmIdentifier(key->get_oid(), - key->domain().DER_encode(key->domain_format())); - } - - MemoryVector<byte> key_bits() const - { - return EC2OSP(key->public_point(), PointGFp::COMPRESSED); - } - - EC_Key_Encoder(const EC_PublicKey* k): key(k) {} - private: - const EC_PublicKey* key; - }; - - return new EC_Key_Encoder(this); + return AlgorithmIdentifier(get_oid(), DER_domain()); } -X509_Decoder* EC_PublicKey::x509_decoder() +MemoryVector<byte> EC_PublicKey::x509_subject_public_key() const { - class EC_Key_Decoder : public X509_Decoder - { - public: - void alg_id(const AlgorithmIdentifier& alg_id) - { - key->domain_params = EC_Domain_Params(alg_id.parameters); - } - - void key_bits(const MemoryRegion<byte>& bits) - { - key->public_key = PointGFp( - OS2ECP(bits, key->domain().get_curve())); - - key->X509_load_hook(); - } - - EC_Key_Decoder(EC_PublicKey* k): key(k) {} - private: - EC_PublicKey* key; - }; - - return new EC_Key_Decoder(this); + return EC2OSP(public_point(), PointGFp::COMPRESSED); } void EC_PublicKey::set_parameter_encoding(EC_Domain_Params_Encoding form) @@ -122,21 +88,25 @@ const BigInt& EC_PrivateKey::private_value() const /** * EC_PrivateKey generator -**/ +*/ EC_PrivateKey::EC_PrivateKey(const EC_Domain_Params& dom_par, - const BigInt& priv_key) : - EC_PublicKey(dom_par, dom_par.get_base_point() * private_key), - private_key(priv_key) + const BigInt& priv_key) { + domain_params = dom_par; + domain_encoding = EC_DOMPAR_ENC_EXPLICIT; + + public_key = domain().get_base_point() * priv_key; + private_key = priv_key; } /** * EC_PrivateKey generator -**/ +*/ EC_PrivateKey::EC_PrivateKey(RandomNumberGenerator& rng, const EC_Domain_Params& dom_par) { domain_params = dom_par; + domain_encoding = EC_DOMPAR_ENC_EXPLICIT; private_key = BigInt::random_integer(rng, 1, domain().get_order()); public_key = domain().get_base_point() * private_key; @@ -145,89 +115,54 @@ EC_PrivateKey::EC_PrivateKey(RandomNumberGenerator& rng, { public_key.check_invariants(); } - catch(Illegal_Point& e) + catch(Illegal_Point) { throw Internal_Error("ECC private key generation failed"); } } -/** -* Return the PKCS #8 public key encoder -**/ -PKCS8_Encoder* EC_PrivateKey::pkcs8_encoder() const +MemoryVector<byte> EC_PrivateKey::pkcs8_private_key() const { - class EC_Key_Encoder : public PKCS8_Encoder - { - public: - AlgorithmIdentifier alg_id() const - { - return AlgorithmIdentifier(key->get_oid(), - key->domain().DER_encode(EC_DOMPAR_ENC_EXPLICIT)); - } - - MemoryVector<byte> key_bits() const - { - return DER_Encoder() - .start_cons(SEQUENCE) - .encode(BigInt(1)) - .encode(BigInt::encode_1363(key->private_key, key->private_key.bytes()), - OCTET_STRING) - .end_cons() - .get_contents(); - } - - EC_Key_Encoder(const EC_PrivateKey* k): key(k) {} - private: - const EC_PrivateKey* key; - }; - - return new EC_Key_Encoder(this); + return DER_Encoder() + .start_cons(SEQUENCE) + .encode(BigInt(1)) + .encode(BigInt::encode_1363(private_key, private_key.bytes()), + OCTET_STRING) + .end_cons() + .get_contents(); } -/** -* Return the PKCS #8 public key decoder -*/ -PKCS8_Decoder* EC_PrivateKey::pkcs8_decoder(RandomNumberGenerator&) +EC_PrivateKey::EC_PrivateKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits) { - class EC_Key_Decoder : public PKCS8_Decoder - { - public: - void alg_id(const AlgorithmIdentifier& alg_id) - { - key->domain_params = EC_Domain_Params(alg_id.parameters); - } - - void key_bits(const MemoryRegion<byte>& bits) - { - u32bit version; - SecureVector<byte> octstr_secret; - - BER_Decoder(bits) - .start_cons(SEQUENCE) - .decode(version) - .decode(octstr_secret, OCTET_STRING) - .verify_end() - .end_cons(); - - key->private_key = BigInt::decode(octstr_secret, octstr_secret.size()); - - if(version != 1) - throw Decoding_Error("Wrong PKCS #1 key format version for EC key"); - - key->PKCS8_load_hook(); - } - - EC_Key_Decoder(EC_PrivateKey* k): key(k) {} - private: - EC_PrivateKey* key; - }; - - return new EC_Key_Decoder(this); - } + domain_params = EC_Domain_Params(alg_id.parameters); + domain_encoding = EC_DOMPAR_ENC_EXPLICIT; + + u32bit version; + SecureVector<byte> octstr_secret; + + BER_Decoder(key_bits) + .start_cons(SEQUENCE) + .decode(version) + .decode(octstr_secret, OCTET_STRING) + .verify_end() + .end_cons(); + + if(version != 1) + throw Decoding_Error("Wrong key format version for EC key"); + + private_key = BigInt::decode(octstr_secret, octstr_secret.size()); -void EC_PrivateKey::PKCS8_load_hook(bool) - { public_key = domain().get_base_point() * private_key; + + try + { + public_key.check_invariants(); + } + catch(Illegal_Point) + { + throw Internal_Error("Loaded ECC private key failed self test"); + } } } diff --git a/src/pubkey/ecc_key/ecc_key.h b/src/pubkey/ecc_key/ecc_key.h index 653f97cab..92f02613c 100644 --- a/src/pubkey/ecc_key/ecc_key.h +++ b/src/pubkey/ecc_key/ecc_key.h @@ -31,6 +31,11 @@ namespace Botan { class BOTAN_DLL EC_PublicKey : public virtual Public_Key { public: + EC_PublicKey(const EC_Domain_Params& dom_par, + const PointGFp& pub_point); + + EC_PublicKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits); /** * Get the public point of this key. @@ -40,6 +45,10 @@ class BOTAN_DLL EC_PublicKey : public virtual Public_Key */ const PointGFp& public_point() const { return public_key; } + AlgorithmIdentifier algorithm_identifier() const; + + MemoryVector<byte> x509_subject_public_key() const; + /** * Get the domain parameters of this key. * @throw Invalid_State is thrown if the @@ -55,33 +64,20 @@ class BOTAN_DLL EC_PublicKey : public virtual Public_Key void set_parameter_encoding(EC_Domain_Params_Encoding enc); /** + * Return the DER encoding of this keys domain in whatever format + * is preset for this particular key + */ + MemoryVector<byte> DER_domain() const + { return domain().DER_encode(domain_format()); } + + /** * Get the domain parameter encoding to be used when encoding this key. * @result the encoding to use */ EC_Domain_Params_Encoding domain_format() const { return domain_encoding; } - - /** - * Get an x509_encoder that can be used to encode this key. - * @result an x509_encoder for this key - */ - X509_Encoder* x509_encoder() const; - - /** - * Get an x509_decoder that can be used to decode a stored key into - * this key. - * @result an x509_decoder for this key - */ - X509_Decoder* x509_decoder(); - - EC_PublicKey() : domain_encoding(EC_DOMPAR_ENC_EXPLICIT) {} - - EC_PublicKey(const EC_Domain_Params& dom_par, - const PointGFp& pub_point); - - virtual ~EC_PublicKey() {} protected: - virtual void X509_load_hook(); + EC_PublicKey() : domain_encoding(EC_DOMPAR_ENC_EXPLICIT) {} EC_Domain_Params domain_params; PointGFp public_key; @@ -95,28 +91,16 @@ class BOTAN_DLL EC_PrivateKey : public virtual EC_PublicKey, public virtual Private_Key { public: - EC_PrivateKey() {} - EC_PrivateKey(const EC_Domain_Params& domain, const BigInt& private_key); EC_PrivateKey(RandomNumberGenerator& rng, const EC_Domain_Params& domain); - virtual ~EC_PrivateKey() {} + EC_PrivateKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits); - /** - * Get an PKCS#8 encoder that can be used to encoded this key. - * @result an PKCS#8 encoder for this key - */ - PKCS8_Encoder* pkcs8_encoder() const; - - /** - * Get an PKCS#8 decoder that can be used to decoded a stored key into - * this key. - * @result an PKCS#8 decoder for this key - */ - PKCS8_Decoder* pkcs8_decoder(RandomNumberGenerator&); + MemoryVector<byte> pkcs8_private_key() const; /** * Get the private key value of this key object. @@ -124,7 +108,7 @@ class BOTAN_DLL EC_PrivateKey : public virtual EC_PublicKey, */ const BigInt& private_value() const; protected: - virtual void PKCS8_load_hook(bool = false); + EC_PrivateKey() {} BigInt private_key; }; diff --git a/src/pubkey/ecc_key/info.txt b/src/pubkey/ecc_key/info.txt index 4650fb612..e08a4231d 100644 --- a/src/pubkey/ecc_key/info.txt +++ b/src/pubkey/ecc_key/info.txt @@ -6,5 +6,4 @@ asn1 bigint ec_dompar numbertheory -pk_codecs </requires> diff --git a/src/pubkey/ecdh/ecdh.cpp b/src/pubkey/ecdh/ecdh.cpp index 7577a8569..bf8a57b3b 100644 --- a/src/pubkey/ecdh/ecdh.cpp +++ b/src/pubkey/ecdh/ecdh.cpp @@ -11,41 +11,23 @@ namespace Botan { -/** -* Derive a key -*/ -SecureVector<byte> ECDH_PrivateKey::derive_key(const byte key[], - u32bit key_len) const - { - MemoryVector<byte> key_x(key, key_len); // FIXME: nasty/slow - PointGFp point = OS2ECP(key_x, public_point().get_curve()); - - return derive_key(point); - } - -/** -* Derive a key -*/ -SecureVector<byte> ECDH_PrivateKey::derive_key(const ECDH_PublicKey& key) const +ECDH_KA_Operation::ECDH_KA_Operation(const ECDH_PrivateKey& key) : + curve(key.domain().get_curve()), + cofactor(key.domain().get_cofactor()) { - return derive_key(key.public_point()); + l_times_priv = inverse_mod(cofactor, key.domain().get_order()) * + key.private_value(); } -/** -* Derive a key -*/ -SecureVector<byte> ECDH_PrivateKey::derive_key(const PointGFp& point) const +SecureVector<byte> ECDH_KA_Operation::agree(const byte w[], u32bit w_len) { - const BigInt& cofactor = domain().get_cofactor(); - const BigInt& n = domain().get_order(); - - BigInt l = inverse_mod(cofactor, n); // can precompute this + PointGFp point = OS2ECP(w, w_len, curve); - PointGFp S = (cofactor * point) * (private_value() * l); + PointGFp S = (cofactor * point) * l_times_priv; S.check_invariants(); return BigInt::encode_1363(S.get_affine_x(), - point.get_curve().get_p().bytes()); + curve.get_p().bytes()); } } diff --git a/src/pubkey/ecdh/ecdh.h b/src/pubkey/ecdh/ecdh.h index 630237edf..d670361f6 100644 --- a/src/pubkey/ecdh/ecdh.h +++ b/src/pubkey/ecdh/ecdh.h @@ -11,6 +11,7 @@ #define BOTAN_ECDH_KEY_H__ #include <botan/ecc_key.h> +#include <botan/pk_ops.h> namespace Botan { @@ -21,11 +22,10 @@ class BOTAN_DLL ECDH_PublicKey : public virtual EC_PublicKey { public: - /** - * Default constructor. Use this one if you want to later fill - * this object with data from an encoded key. - */ - ECDH_PublicKey() {} + + ECDH_PublicKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits) : + EC_PublicKey(alg_id, key_bits) {} /** * Construct a public key from a given public point. @@ -49,6 +49,8 @@ class BOTAN_DLL ECDH_PublicKey : public virtual EC_PublicKey * @result the maximum number of input bits */ u32bit max_input_bits() const { return domain().get_order().bits(); } + protected: + ECDH_PublicKey() {} }; /** @@ -60,11 +62,9 @@ class BOTAN_DLL ECDH_PrivateKey : public ECDH_PublicKey, { public: - /** - * Default constructor. Use this one if you want to later fill - * this object with data from an encoded key. - */ - ECDH_PrivateKey() {} + ECDH_PrivateKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits) : + EC_PrivateKey(alg_id, key_bits) {} /** * Generate a new private key @@ -76,25 +76,21 @@ class BOTAN_DLL ECDH_PrivateKey : public ECDH_PublicKey, MemoryVector<byte> public_value() const { return EC2OSP(public_point(), PointGFp::UNCOMPRESSED); } + }; - /** - * Derive a shared key with the other parties public key. - * @param key the other partys public key - * @param key_len the other partys public key - */ - SecureVector<byte> derive_key(const byte key[], u32bit key_len) const; - - /** - * Derive a shared key with the other parties public key. - * @param other the other partys public key - */ - SecureVector<byte> derive_key(const ECDH_PublicKey& other) const; +/** +* ECDH operation +*/ +class BOTAN_DLL ECDH_KA_Operation : public PK_Ops::Key_Agreement + { + public: + ECDH_KA_Operation(const ECDH_PrivateKey& key); - /** - * Derive a shared key with the other parties public key. - * @param point the public point of the other parties key - */ - SecureVector<byte> derive_key(const PointGFp& point) const; + SecureVector<byte> agree(const byte w[], u32bit w_len); + private: + const CurveGFp& curve; + const BigInt& cofactor; + BigInt l_times_priv; }; } diff --git a/src/pubkey/ecdsa/ecdsa.cpp b/src/pubkey/ecdsa/ecdsa.cpp index d245543f7..afca6cc73 100644 --- a/src/pubkey/ecdsa/ecdsa.cpp +++ b/src/pubkey/ecdsa/ecdsa.cpp @@ -11,64 +11,71 @@ namespace Botan { -bool ECDSA_PublicKey::verify(const byte msg[], u32bit msg_len, - const byte sig[], u32bit sig_len) const +ECDSA_Signature_Operation::ECDSA_Signature_Operation(const ECDSA_PrivateKey& ecdsa) : + base_point(ecdsa.domain().get_base_point()), + order(ecdsa.domain().get_order()), + x(ecdsa.private_value()) { - const BigInt& n = domain().get_order(); + } - if(n == 0) - throw Invalid_State("ECDSA_PublicKey::verify: Not initialized"); +SecureVector<byte> +ECDSA_Signature_Operation::sign(const byte msg[], u32bit msg_len, + RandomNumberGenerator& rng) + { + rng.add_entropy(msg, msg_len); - if(sig_len != n.bytes()*2) - return false; + BigInt k; + k.randomize(rng, order.bits()); + + while(k >= order) + k.randomize(rng, order.bits() - 1); BigInt e(msg, msg_len); - BigInt r(sig, sig_len / 2); - BigInt s(sig + sig_len / 2, sig_len / 2); + PointGFp k_times_P = base_point * k; + BigInt r = k_times_P.get_affine_x() % order; - if(r < 0 || r >= n || s < 0 || s >= n) - return false; + if(r == 0) + throw Internal_Error("ECDSA_Signature_Operation: r was zero"); - BigInt w = inverse_mod(s, n); + BigInt k_inv = inverse_mod(k, order); - PointGFp R = w * (e * domain().get_base_point() + r*public_point()); - if(R.is_zero()) - return false; + BigInt s = (((r * x) + e) * k_inv) % order; - return (R.get_affine_x() % n == r); + SecureVector<byte> output(2*order.bytes()); + r.binary_encode(output + (output.size() / 2 - r.bytes())); + s.binary_encode(output + (output.size() - s.bytes())); + return output; } -SecureVector<byte> ECDSA_PrivateKey::sign(const byte msg[], - u32bit msg_len, - RandomNumberGenerator& rng) const +ECDSA_Verification_Operation::ECDSA_Verification_Operation(const ECDSA_PublicKey& ecdsa) : + base_point(ecdsa.domain().get_base_point()), + public_point(ecdsa.public_point()), + order(ecdsa.domain().get_order()) { - const BigInt& n = domain().get_order(); - - if(n == 0 || private_value() == 0) - throw Invalid_State("ECDSA_PrivateKey::sign: Not initialized"); + } - BigInt k; - do - k.randomize(rng, n.bits()-1); - while(k >= n); +bool ECDSA_Verification_Operation::verify(const byte msg[], u32bit msg_len, + const byte sig[], u32bit sig_len) + { + if(sig_len != order.bytes()*2) + return false; BigInt e(msg, msg_len); - PointGFp k_times_P = domain().get_base_point() * k; - BigInt r = k_times_P.get_affine_x() % n; + BigInt r(sig, sig_len / 2); + BigInt s(sig + sig_len / 2, sig_len / 2); - if(r == 0) - throw Internal_Error("Default_ECDSA_Op::sign: r was zero"); + if(r < 0 || r >= order || s < 0 || s >= order) + return false; - BigInt k_inv = inverse_mod(k, n); + BigInt w = inverse_mod(s, order); - BigInt s = (((r * private_value()) + e) * k_inv) % n; + PointGFp R = w * (e * base_point + r * public_point); + if(R.is_zero()) + return false; - SecureVector<byte> output(2*n.bytes()); - r.binary_encode(output + (output.size() / 2 - r.bytes())); - s.binary_encode(output + (output.size() - s.bytes())); - return output; + return (R.get_affine_x() % order == r); } } diff --git a/src/pubkey/ecdsa/ecdsa.h b/src/pubkey/ecdsa/ecdsa.h index e7f29b600..e20a234fc 100644 --- a/src/pubkey/ecdsa/ecdsa.h +++ b/src/pubkey/ecdsa/ecdsa.h @@ -11,18 +11,31 @@ #define BOTAN_ECDSA_KEY_H__ #include <botan/ecc_key.h> +#include <botan/pk_ops.h> namespace Botan { /** * This class represents ECDSA Public Keys. */ -class BOTAN_DLL ECDSA_PublicKey : public virtual EC_PublicKey, - public PK_Verifying_wo_MR_Key +class BOTAN_DLL ECDSA_PublicKey : public virtual EC_PublicKey { public: /** + * Construct a public key from a given public point. + * @param dom_par the domain parameters associated with this key + * @param public_point the public point defining this key + */ + ECDSA_PublicKey(const EC_Domain_Params& dom_par, + const PointGFp& public_point) : + EC_PublicKey(dom_par, public_point) {} + + ECDSA_PublicKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits) : + EC_PublicKey(alg_id, key_bits) {} + + /** * Get this keys algorithm name. * @result this keys algorithm name ("ECDSA") */ @@ -40,46 +53,21 @@ class BOTAN_DLL ECDSA_PublicKey : public virtual EC_PublicKey, u32bit message_part_size() const { return domain().get_order().bytes(); } - /** - * Verify a message with this key. - * @param message the byte array containing the message - * @param mess_len the number of bytes in the message byte array - * @param signature the byte array containing the signature - * @param sig_len the number of bytes in the signature byte array - */ - bool verify(const byte message[], u32bit mess_len, - const byte signature[], u32bit sig_len) const; - - /** - * Default constructor. Use this one if you want to later fill - * this object with data from an encoded key. - */ + protected: ECDSA_PublicKey() {} - - /** - * Construct a public key from a given public point. - * @param dom_par the domain parameters associated with this key - * @param public_point the public point defining this key - */ - ECDSA_PublicKey(const EC_Domain_Params& dom_par, - const PointGFp& public_point) : - EC_PublicKey(dom_par, public_point) {} - }; /** * This class represents ECDSA Private Keys */ class BOTAN_DLL ECDSA_PrivateKey : public ECDSA_PublicKey, - public EC_PrivateKey, - public PK_Signing_Key + public EC_PrivateKey { public: - /** - * Default constructor. Use this one if you want to later fill - * this object with data from an encoded key. - */ - ECDSA_PrivateKey() {} + + ECDSA_PrivateKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits) : + EC_PrivateKey(alg_id, key_bits) {} /** * Generate a new private key @@ -96,16 +84,43 @@ class BOTAN_DLL ECDSA_PrivateKey : public ECDSA_PublicKey, */ ECDSA_PrivateKey(const EC_Domain_Params& domain, const BigInt& x) : EC_PrivateKey(domain, x) {} + }; - /** - * Sign a message with this key. - * @param message the byte array representing the message to be signed - * @param mess_len the length of the message byte array - * @result the signature - */ +class BOTAN_DLL ECDSA_Signature_Operation : public PK_Ops::Signature + { + public: + ECDSA_Signature_Operation(const ECDSA_PrivateKey& ecdsa); + + SecureVector<byte> sign(const byte msg[], u32bit msg_len, + RandomNumberGenerator& rng); + + u32bit message_parts() const { return 2; } + u32bit message_part_size() const { return order.bytes(); } + u32bit max_input_bits() const { return order.bits(); } + + private: + const PointGFp& base_point; + const BigInt& order; + const BigInt& x; + }; + +class BOTAN_DLL ECDSA_Verification_Operation : public PK_Ops::Verification + { + public: + ECDSA_Verification_Operation(const ECDSA_PublicKey& ecdsa); + + u32bit message_parts() const { return 2; } + u32bit message_part_size() const { return order.bytes(); } + u32bit max_input_bits() const { return order.bits(); } + + bool with_recovery() const { return false; } - SecureVector<byte> sign(const byte message[], u32bit mess_len, - RandomNumberGenerator& rng) const; + bool verify(const byte msg[], u32bit msg_len, + const byte sig[], u32bit sig_len); + private: + const PointGFp& base_point; + const PointGFp& public_point; + const BigInt& order; }; } diff --git a/src/pubkey/elgamal/elg_core.cpp b/src/pubkey/elgamal/elg_core.cpp deleted file mode 100644 index 0005c4ffc..000000000 --- a/src/pubkey/elgamal/elg_core.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* -* ElGamal Core -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/elg_core.h> -#include <botan/numthry.h> -#include <botan/internal/pk_engine.h> -#include <botan/parsing.h> -#include <algorithm> - -namespace Botan { - -/* -* ELG_Core Constructor -*/ -ELG_Core::ELG_Core(const DL_Group& group, const BigInt& y) - { - op = Engine_Core::elg_op(group, y, 0); - p_bytes = 0; - } - -/* -* ELG_Core Constructor -*/ -ELG_Core::ELG_Core(RandomNumberGenerator& rng, - const DL_Group& group, const BigInt& y, const BigInt& x) - { - const u32bit BLINDING_BITS = BOTAN_PRIVATE_KEY_OP_BLINDING_BITS; - - op = Engine_Core::elg_op(group, y, x); - - const BigInt& p = group.get_p(); - p_bytes = p.bytes(); - - if(BLINDING_BITS) - { - BigInt k(rng, std::min(p.bits()-1, BLINDING_BITS)); - blinder = Blinder(k, power_mod(k, x, p), p); - } - } - -/* -* ELG_Core Copy Constructor -*/ -ELG_Core::ELG_Core(const ELG_Core& core) - { - op = 0; - if(core.op) - op = core.op->clone(); - blinder = core.blinder; - p_bytes = core.p_bytes; - } - -/* -* ELG_Core Assignment Operator -*/ -ELG_Core& ELG_Core::operator=(const ELG_Core& core) - { - delete op; - if(core.op) - op = core.op->clone(); - blinder = core.blinder; - p_bytes = core.p_bytes; - return (*this); - } - -/* -* ElGamal Encrypt Operation -*/ -SecureVector<byte> ELG_Core::encrypt(const byte in[], u32bit length, - const BigInt& k) const - { - return op->encrypt(in, length, k); - } - -/* -* ElGamal Decrypt Operation -*/ -SecureVector<byte> ELG_Core::decrypt(const byte in[], u32bit length) const - { - if(length != 2*p_bytes) - throw Invalid_Argument("ELG_Core::decrypt: Invalid message"); - - BigInt a(in, p_bytes); - BigInt b(in + p_bytes, p_bytes); - - return BigInt::encode(blinder.unblind(op->decrypt(blinder.blind(a), b))); - } - -} diff --git a/src/pubkey/elgamal/elg_core.h b/src/pubkey/elgamal/elg_core.h deleted file mode 100644 index a7768a6ae..000000000 --- a/src/pubkey/elgamal/elg_core.h +++ /dev/null @@ -1,44 +0,0 @@ -/* -* ElGamal Core -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_ELGAMAL_CORE_H__ -#define BOTAN_ELGAMAL_CORE_H__ - -#include <botan/elg_op.h> -#include <botan/blinding.h> -#include <botan/dl_group.h> - -namespace Botan { - -/* -* ElGamal Core -*/ -class BOTAN_DLL ELG_Core - { - public: - SecureVector<byte> encrypt(const byte[], u32bit, const BigInt&) const; - SecureVector<byte> decrypt(const byte[], u32bit) const; - - ELG_Core& operator=(const ELG_Core&); - - ELG_Core() { op = 0; } - ELG_Core(const ELG_Core&); - - ELG_Core(const DL_Group&, const BigInt&); - ELG_Core(RandomNumberGenerator&, const DL_Group&, - const BigInt&, const BigInt&); - - ~ELG_Core() { delete op; } - private: - ELG_Operation* op; - Blinder blinder; - u32bit p_bytes; - }; - -} - -#endif diff --git a/src/pubkey/elgamal/elg_op.cpp b/src/pubkey/elgamal/elg_op.cpp deleted file mode 100644 index 4bde60bee..000000000 --- a/src/pubkey/elgamal/elg_op.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* -* ElGamal Operations -* (C) 1999-2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/elg_op.h> -#include <future> - -namespace Botan { - -/* -* Default_ELG_Op Constructor -*/ -Default_ELG_Op::Default_ELG_Op(const DL_Group& group, const BigInt& y, - const BigInt& x) : p(group.get_p()) - { - powermod_g_p = Fixed_Base_Power_Mod(group.get_g(), p); - powermod_y_p = Fixed_Base_Power_Mod(y, p); - mod_p = Modular_Reducer(p); - - if(x != 0) - powermod_x_p = Fixed_Exponent_Power_Mod(x, p); - } - -/* -* Default ElGamal Encrypt Operation -*/ -SecureVector<byte> Default_ELG_Op::encrypt(const byte in[], u32bit length, - const BigInt& k) const - { - BigInt m(in, length); - if(m >= p) - throw Invalid_Argument("Default_ELG_Op::encrypt: Input is too large"); - - auto future_a = std::async(std::launch::async, powermod_g_p, k); - BigInt b = mod_p.multiply(m, powermod_y_p(k)); - BigInt a = future_a.get(); - - SecureVector<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; - } - -/* -* Default ElGamal Decrypt Operation -*/ -BigInt Default_ELG_Op::decrypt(const BigInt& a, const BigInt& b) const - { - if(a >= p || b >= p) - throw Invalid_Argument("Default_ELG_Op: Invalid message"); - - return mod_p.multiply(b, inverse_mod(powermod_x_p(a), p)); - } - -} diff --git a/src/pubkey/elgamal/elg_op.h b/src/pubkey/elgamal/elg_op.h deleted file mode 100644 index 39ed897f4..000000000 --- a/src/pubkey/elgamal/elg_op.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -* ElGamal Operations -* (C) 1999-2008 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_ELGAMAL_OPS_H__ -#define BOTAN_ELGAMAL_OPS_H__ - -#include <botan/pow_mod.h> -#include <botan/numthry.h> -#include <botan/reducer.h> -#include <botan/dl_group.h> - -namespace Botan { - -/* -* ElGamal Operation -*/ -class BOTAN_DLL ELG_Operation - { - public: - virtual SecureVector<byte> encrypt(const byte[], u32bit, - const BigInt&) const = 0; - virtual BigInt decrypt(const BigInt&, const BigInt&) const = 0; - virtual ELG_Operation* clone() const = 0; - virtual ~ELG_Operation() {} - }; - -/* -* Botan's Default ElGamal Operation -*/ -class BOTAN_DLL Default_ELG_Op : public ELG_Operation - { - public: - SecureVector<byte> encrypt(const byte[], u32bit, const BigInt&) const; - BigInt decrypt(const BigInt&, const BigInt&) const; - - ELG_Operation* clone() const { return new Default_ELG_Op(*this); } - - Default_ELG_Op(const DL_Group&, const BigInt&, const BigInt&); - private: - const BigInt p; - Fixed_Base_Power_Mod powermod_g_p, powermod_y_p; - Fixed_Exponent_Power_Mod powermod_x_p; - Modular_Reducer mod_p; - }; - -} - -#endif diff --git a/src/pubkey/elgamal/elgamal.cpp b/src/pubkey/elgamal/elgamal.cpp index e3215f757..b9c4803f3 100644 --- a/src/pubkey/elgamal/elgamal.cpp +++ b/src/pubkey/elgamal/elgamal.cpp @@ -8,7 +8,6 @@ #include <botan/elgamal.h> #include <botan/numthry.h> #include <botan/keypair.h> -#include <botan/look_pk.h> #include <botan/internal/workfactor.h> namespace Botan { @@ -20,34 +19,6 @@ ElGamal_PublicKey::ElGamal_PublicKey(const DL_Group& grp, const BigInt& y1) { group = grp; y = y1; - X509_load_hook(); - } - -/* -* Algorithm Specific X.509 Initialization Code -*/ -void ElGamal_PublicKey::X509_load_hook() - { - core = ELG_Core(group, y); - } - -/* -* ElGamal Encryption Function -*/ -SecureVector<byte> -ElGamal_PublicKey::encrypt(const byte in[], u32bit length, - RandomNumberGenerator& rng) const - { - BigInt k(rng, 2 * dl_work_factor(group_p().bits())); - return core.encrypt(in, length, k); - } - -/* -* Return the maximum input size in bits -*/ -u32bit ElGamal_PublicKey::max_input_bits() const - { - return (group_p().bits() - 1); } /* @@ -61,37 +32,23 @@ ElGamal_PrivateKey::ElGamal_PrivateKey(RandomNumberGenerator& rng, x = x_arg; if(x == 0) - { x.randomize(rng, 2 * dl_work_factor(group_p().bits())); - PKCS8_load_hook(rng, true); - } - else - PKCS8_load_hook(rng, false); - } -/* -* Algorithm Specific PKCS #8 Initialization Code -*/ -void ElGamal_PrivateKey::PKCS8_load_hook(RandomNumberGenerator& rng, - bool generated) - { - if(y == 0) - y = power_mod(group_g(), x, group_p()); - core = ELG_Core(rng, group, y, x); + y = power_mod(group_g(), x, group_p()); - if(generated) + if(x_arg == 0) gen_check(rng); else load_check(rng); } -/* -* ElGamal Decryption Function -*/ -SecureVector<byte> ElGamal_PrivateKey::decrypt(const byte in[], - u32bit length) const +ElGamal_PrivateKey::ElGamal_PrivateKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits, + RandomNumberGenerator& rng) : + DL_Scheme_PrivateKey(alg_id, key_bits, DL_Group::ANSI_X9_42) { - return core.decrypt(in, length); + y = power_mod(group_g(), x, group_p()); + load_check(rng); } /* @@ -108,10 +65,12 @@ bool ElGamal_PrivateKey::check_key(RandomNumberGenerator& rng, try { + PK_Encryptor_EME this_encryptor(*this, "EME1(SHA-1)"); + PK_Decryptor_EME this_decryptor(*this, "EME1(SHA-1)"); + KeyPair::check_key(rng, - get_pk_encryptor(*this, "EME1(SHA-1)"), - get_pk_decryptor(*this, "EME1(SHA-1)") - ); + this_encryptor, + this_decryptor); } catch(Self_Test_Failure) { @@ -121,4 +80,69 @@ bool ElGamal_PrivateKey::check_key(RandomNumberGenerator& rng, return true; } +ElGamal_Encryption_Operation::ElGamal_Encryption_Operation(const ElGamal_PublicKey& key) + { + const BigInt& p = key.group_p(); + + powermod_g_p = Fixed_Base_Power_Mod(key.group_g(), p); + powermod_y_p = Fixed_Base_Power_Mod(key.get_y(), p); + mod_p = Modular_Reducer(p); + } + +SecureVector<byte> +ElGamal_Encryption_Operation::encrypt(const byte msg[], u32bit msg_len, + RandomNumberGenerator& rng) + { + const BigInt& p = mod_p.get_modulus(); + + BigInt m(msg, msg_len); + + if(m >= p) + throw Invalid_Argument("ElGamal encryption: Input is too large"); + + BigInt k(rng, 2 * dl_work_factor(p.bits())); + + BigInt a = powermod_g_p(k); + BigInt b = mod_p.multiply(m, powermod_y_p(k)); + + SecureVector<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; + } + +ElGamal_Decryption_Operation::ElGamal_Decryption_Operation(const ElGamal_PrivateKey& key) + { + const BigInt& p = key.group_p(); + + powermod_x_p = Fixed_Exponent_Power_Mod(key.get_x(), p); + mod_p = Modular_Reducer(p); + + BigInt k = Blinder::choose_nonce(powermod_x_p(2), p); + blinder = Blinder(k, powermod_x_p(k), p); + } + +SecureVector<byte> +ElGamal_Decryption_Operation::decrypt(const byte msg[], u32bit msg_len) + { + const BigInt& p = mod_p.get_modulus(); + + const u32bit p_bytes = p.bytes(); + + if(msg_len != 2 * p_bytes) + throw Invalid_Argument("ElGamal decryption: Invalid message"); + + BigInt a(msg, p_bytes); + BigInt b(msg + p_bytes, p_bytes); + + if(a >= p || b >= p) + throw Invalid_Argument("ElGamal decryption: Invalid message"); + + a = blinder.blind(a); + + BigInt r = mod_p.multiply(b, inverse_mod(powermod_x_p(a), p)); + + return BigInt::encode(blinder.unblind(r)); + } + } diff --git a/src/pubkey/elgamal/elgamal.h b/src/pubkey/elgamal/elgamal.h index 93e640f09..143b417ec 100644 --- a/src/pubkey/elgamal/elgamal.h +++ b/src/pubkey/elgamal/elgamal.h @@ -9,49 +9,79 @@ #define BOTAN_ELGAMAL_H__ #include <botan/dl_algo.h> -#include <botan/elg_core.h> +#include <botan/numthry.h> +#include <botan/reducer.h> +#include <botan/blinding.h> +#include <botan/pk_ops.h> namespace Botan { /* * ElGamal Public Key */ -class BOTAN_DLL ElGamal_PublicKey : public PK_Encrypting_Key, - public virtual DL_Scheme_PublicKey +class BOTAN_DLL ElGamal_PublicKey : public virtual DL_Scheme_PublicKey { public: std::string algo_name() const { return "ElGamal"; } DL_Group::Format group_format() const { return DL_Group::ANSI_X9_42; } - SecureVector<byte> encrypt(const byte[], u32bit, - RandomNumberGenerator& rng) const; - u32bit max_input_bits() const; + u32bit max_input_bits() const { return (group_p().bits() - 1); } - ElGamal_PublicKey() {} - ElGamal_PublicKey(const DL_Group&, const BigInt&); + ElGamal_PublicKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits) : + DL_Scheme_PublicKey(alg_id, key_bits, DL_Group::ANSI_X9_42) + {} + + ElGamal_PublicKey(const DL_Group& group, const BigInt& y); protected: - ELG_Core core; - private: - void X509_load_hook(); + ElGamal_PublicKey() {} }; /* * ElGamal Private Key */ class BOTAN_DLL ElGamal_PrivateKey : public ElGamal_PublicKey, - public PK_Decrypting_Key, public virtual DL_Scheme_PrivateKey { public: - SecureVector<byte> decrypt(const byte[], u32bit) const; - bool check_key(RandomNumberGenerator& rng, bool) const; - ElGamal_PrivateKey() {} - ElGamal_PrivateKey(RandomNumberGenerator&, const DL_Group&, - const BigInt& = 0); + ElGamal_PrivateKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits, + RandomNumberGenerator& rng); + + ElGamal_PrivateKey(RandomNumberGenerator& rng, + const DL_Group& group, + const BigInt& priv_key = 0); + }; + +class BOTAN_DLL ElGamal_Encryption_Operation : public PK_Ops::Encryption + { + public: + u32bit max_input_bits() const { return mod_p.get_modulus().bits() - 1; } + + ElGamal_Encryption_Operation(const ElGamal_PublicKey& key); + + SecureVector<byte> encrypt(const byte msg[], u32bit msg_len, + RandomNumberGenerator& rng); + + private: + Fixed_Base_Power_Mod powermod_g_p, powermod_y_p; + Modular_Reducer mod_p; + }; + +class BOTAN_DLL ElGamal_Decryption_Operation : public PK_Ops::Decryption + { + public: + u32bit max_input_bits() const { return mod_p.get_modulus().bits() - 1; } + + ElGamal_Decryption_Operation(const ElGamal_PrivateKey& key); + + SecureVector<byte> decrypt(const byte msg[], u32bit msg_len); private: - void PKCS8_load_hook(RandomNumberGenerator&, bool = false); + Fixed_Exponent_Power_Mod powermod_x_p; + Modular_Reducer mod_p; + Blinder blinder; }; } diff --git a/src/pubkey/gost_3410/gost_3410.cpp b/src/pubkey/gost_3410/gost_3410.cpp index 8dd72dfc1..c5cc1ddbd 100644 --- a/src/pubkey/gost_3410/gost_3410.cpp +++ b/src/pubkey/gost_3410/gost_3410.cpp @@ -8,170 +8,140 @@ */ #include <botan/gost_3410.h> -#include <botan/numthry.h> #include <botan/der_enc.h> #include <botan/ber_dec.h> -#include <botan/secmem.h> -#include <botan/point_gfp.h> namespace Botan { -X509_Encoder* GOST_3410_PublicKey::x509_encoder() const +MemoryVector<byte> GOST_3410_PublicKey::x509_subject_public_key() const { - class GOST_3410_Key_Encoder : public X509_Encoder - { - public: - AlgorithmIdentifier alg_id() const - { - return AlgorithmIdentifier(key->get_oid(), - key->domain().DER_encode(key->domain_format())); - } - - MemoryVector<byte> key_bits() const - { - // Trust CryptoPro to come up with something obnoxious - const BigInt x = key->public_point().get_affine_x(); - const BigInt y = key->public_point().get_affine_y(); - - SecureVector<byte> bits(2*std::max(x.bytes(), y.bytes())); + // Trust CryptoPro to come up with something obnoxious + const BigInt& x = public_point().get_affine_x(); + const BigInt& y = public_point().get_affine_y(); - y.binary_encode(bits + (bits.size() / 2 - y.bytes())); - x.binary_encode(bits + (bits.size() - y.bytes())); + MemoryVector<byte> bits(2*std::max(x.bytes(), y.bytes())); - return DER_Encoder().encode(bits, OCTET_STRING).get_contents(); - } + y.binary_encode(bits + (bits.size() / 2 - y.bytes())); + x.binary_encode(bits + (bits.size() - x.bytes())); - GOST_3410_Key_Encoder(const GOST_3410_PublicKey* k): key(k) {} - private: - const GOST_3410_PublicKey* key; - }; - - return new GOST_3410_Key_Encoder(this); + return DER_Encoder().encode(bits, OCTET_STRING).get_contents(); } -X509_Decoder* GOST_3410_PublicKey::x509_decoder() +AlgorithmIdentifier GOST_3410_PublicKey::algorithm_identifier() const { - class GOST_3410_Key_Decoder : public X509_Decoder - { - public: - void alg_id(const AlgorithmIdentifier& alg_id) - { - // Also includes hash and cipher OIDs... brilliant design guys - OID ecc_param_id; + MemoryVector<byte> params = + DER_Encoder().start_cons(SEQUENCE) + .encode(OID(domain().get_oid())) + .end_cons() + .get_contents(); - BER_Decoder ber(alg_id.parameters); - ber.start_cons(SEQUENCE).decode(ecc_param_id); + return AlgorithmIdentifier(get_oid(), params); + } - key->domain_params = EC_Domain_Params(ecc_param_id); - } +GOST_3410_PublicKey::GOST_3410_PublicKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits) + { + OID ecc_param_id; - void key_bits(const MemoryRegion<byte>& bits) - { + // Also includes hash and cipher OIDs... brilliant design guys + BER_Decoder(alg_id.parameters).start_cons(SEQUENCE).decode(ecc_param_id); - SecureVector<byte> key_bits; - BER_Decoder ber(bits); - ber.decode(key_bits, OCTET_STRING); + domain_params = EC_Domain_Params(ecc_param_id); - const u32bit part_size = key_bits.size() / 2; + SecureVector<byte> bits; + BER_Decoder(key_bits).decode(bits, OCTET_STRING); - BigInt y(key_bits, part_size); - BigInt x(key_bits + part_size, part_size); + const u32bit part_size = bits.size() / 2; - const BigInt p = key->domain().get_curve().get_p(); + BigInt y(bits, part_size); + BigInt x(bits + part_size, part_size); - key->public_key = PointGFp(key->domain().get_curve(), x, y); + public_key = PointGFp(domain().get_curve(), x, y); - key->X509_load_hook(); - } + try + { + public_key.check_invariants(); + } + catch(Illegal_Point) + { + throw Internal_Error("Loaded ECC public key failed self test"); + } + } - GOST_3410_Key_Decoder(GOST_3410_PublicKey* k): key(k) {} - private: - GOST_3410_PublicKey* key; - }; +GOST_3410_Signature_Operation::GOST_3410_Signature_Operation( + const GOST_3410_PrivateKey& gost_3410) : - return new GOST_3410_Key_Decoder(this); + base_point(gost_3410.domain().get_base_point()), + order(gost_3410.domain().get_order()), + x(gost_3410.private_value()) + { } -bool GOST_3410_PublicKey::verify(const byte msg[], u32bit msg_len, - const byte sig[], u32bit sig_len) const +SecureVector<byte> +GOST_3410_Signature_Operation::sign(const byte msg[], u32bit msg_len, + RandomNumberGenerator& rng) const { - const BigInt& n = domain().get_order(); - - if(sig_len != n.bytes()*2) - return false; - - // NOTE: it is not checked whether the public point is set - if(domain().get_curve().get_p() == 0) - throw Internal_Error("domain parameters not set"); + BigInt k; + do + k.randomize(rng, order.bits()-1); + while(k >= order); BigInt e(msg, msg_len); - BigInt r(sig, sig_len / 2); - BigInt s(sig + sig_len / 2, sig_len / 2); - - if(r < 0 || r >= n || s < 0 || s >= n) - return false; - - e %= n; + e %= order; if(e == 0) e = 1; - BigInt v = inverse_mod(e, n); + PointGFp k_times_P = base_point * k; + k_times_P.check_invariants(); - BigInt z1 = (s*v) % n; - BigInt z2 = (-r*v) % n; + BigInt r = k_times_P.get_affine_x() % order; - PointGFp R = (z1 * domain().get_base_point() + z2 * public_point()); + BigInt s = (r*x + k*e) % order; - return (R.get_affine_x() == r); + if(r == 0 || s == 0) + throw Invalid_State("GOST 34.10: r == 0 || s == 0"); + + SecureVector<byte> output(2*order.bytes()); + r.binary_encode(output + (output.size() / 2 - r.bytes())); + s.binary_encode(output + (output.size() - s.bytes())); + return output; } -GOST_3410_PublicKey::GOST_3410_PublicKey(const EC_Domain_Params& dom_par, - const PointGFp& pub_point) + +GOST_3410_Verification_Operation::GOST_3410_Verification_Operation(const GOST_3410_PublicKey& gost) : + base_point(gost.domain().get_base_point()), + public_point(gost.public_point()), + order(gost.domain().get_order()) { - domain_params = dom_par; - public_key = pub_point; - domain_encoding = EC_DOMPAR_ENC_EXPLICIT; } -SecureVector<byte> -GOST_3410_PrivateKey::sign(const byte msg[], - u32bit msg_len, - RandomNumberGenerator& rng) const +bool GOST_3410_Verification_Operation::verify(const byte msg[], u32bit msg_len, + const byte sig[], u32bit sig_len) const { - const BigInt& n = domain().get_order(); - - BigInt k; - do - k.randomize(rng, n.bits()-1); - while(k >= n); + if(sig_len != order.bytes()*2) + return false; - if(private_value() == 0) - throw Internal_Error("GOST_3410::sign(): no private key"); + BigInt e(msg, msg_len); - if(n == 0) - throw Internal_Error("GOST_3410::sign(): domain parameters not set"); + BigInt r(sig, sig_len / 2); + BigInt s(sig + sig_len / 2, sig_len / 2); - BigInt e(msg, msg_len); + if(r < 0 || r >= order || s < 0 || s >= order) + return false; - e %= n; + e %= order; if(e == 0) e = 1; - PointGFp k_times_P = domain().get_base_point() * k; - k_times_P.check_invariants(); + BigInt v = inverse_mod(e, order); - BigInt r = k_times_P.get_affine_x() % n; + BigInt z1 = (s*v) % order; + BigInt z2 = (-r*v) % order; - if(r == 0) - throw Internal_Error("GOST_3410::sign: r was zero"); + PointGFp R = (z1 * base_point + z2 * public_point); - BigInt s = (r*private_value() + k*e) % n; - - SecureVector<byte> output(2*n.bytes()); - r.binary_encode(output + (output.size() / 2 - r.bytes())); - s.binary_encode(output + (output.size() - s.bytes())); - return output; + return (R.get_affine_x() == r); } } diff --git a/src/pubkey/gost_3410/gost_3410.h b/src/pubkey/gost_3410/gost_3410.h index 8104cbb75..ffdbc6e19 100644 --- a/src/pubkey/gost_3410/gost_3410.h +++ b/src/pubkey/gost_3410/gost_3410.h @@ -2,7 +2,7 @@ * GOST 34.10-2001 * (C) 2007 Falko Strenzke, FlexSecure GmbH * Manuel Hartl, FlexSecure GmbH -* (C) 2008-2009 Jack Lloyd +* (C) 2008-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -11,23 +11,42 @@ #define BOTAN_GOST_3410_KEY_H__ #include <botan/ecc_key.h> +#include <botan/pk_ops.h> namespace Botan { /** * This class represents GOST_3410 Public Keys. */ -class BOTAN_DLL GOST_3410_PublicKey : public virtual EC_PublicKey, - public PK_Verifying_wo_MR_Key +class BOTAN_DLL GOST_3410_PublicKey : public virtual EC_PublicKey { public: /** + * Construct a public key from a given public point. + * @param dom_par the domain parameters associated with this key + * @param public_point the public point defining this key + */ + GOST_3410_PublicKey(const EC_Domain_Params& dom_par, + const PointGFp& public_point) : + EC_PublicKey(dom_par, public_point) {} + + /** + * Construct from X.509 algorithm id and subject public key bits + */ + GOST_3410_PublicKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits); + + /** * Get this keys algorithm name. * @result this keys algorithm name */ std::string algo_name() const { return "GOST-34.10"; } + AlgorithmIdentifier algorithm_identifier() const; + + MemoryVector<byte> x509_subject_public_key() const; + /** * Get the maximum number of bits allowed to be fed to this key. * This is the bitlength of the order of the base point. @@ -41,57 +60,21 @@ class BOTAN_DLL GOST_3410_PublicKey : public virtual EC_PublicKey, u32bit message_part_size() const { return domain().get_order().bytes(); } - /** - * Verify a message with this key. - * @param message the byte array containing the message - * @param mess_len the number of bytes in the message byte array - * @param signature the byte array containing the signature - * @param sig_len the number of bytes in the signature byte array - */ - bool verify(const byte message[], u32bit mess_len, - const byte signature[], u32bit sig_len) const; - - /** - * Default constructor. Use this one if you want to later fill - * this object with data from an encoded key. - */ + protected: GOST_3410_PublicKey() {} - - /** - * Construct a public key from a given public point. - * @param dom_par the domain parameters associated with this key - * @param public_point the public point defining this key - */ - GOST_3410_PublicKey(const EC_Domain_Params& dom_par, - const PointGFp& public_point); - - /** - * Get an x509_encoder that can be used to encode this key. - * @result an x509_encoder for this key - */ - X509_Encoder* x509_encoder() const; - - /** - * Get an x509_decoder that can be used to decode a stored key into - * this key. - * @result an x509_decoder for this key - */ - X509_Decoder* x509_decoder(); }; /** * This class represents GOST_3410 Private Keys */ class BOTAN_DLL GOST_3410_PrivateKey : public GOST_3410_PublicKey, - public EC_PrivateKey, - public PK_Signing_Key + public EC_PrivateKey { public: - /** - * Default constructor. Use this one if you want to later fill - * this object with data from an encoded key. - */ - GOST_3410_PrivateKey() {} + + GOST_3410_PrivateKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits) : + EC_PrivateKey(alg_id, key_bits) {} /** * Generate a new private key @@ -109,14 +92,45 @@ class BOTAN_DLL GOST_3410_PrivateKey : public GOST_3410_PublicKey, GOST_3410_PrivateKey(const EC_Domain_Params& domain, const BigInt& x) : EC_PrivateKey(domain, x) {} - /** - * Sign a message with this key. - * @param message the byte array representing the message to be signed - * @param mess_len the length of the message byte array - * @result the signature - */ - SecureVector<byte> sign(const byte message[], u32bit mess_len, + AlgorithmIdentifier pkcs8_algorithm_identifier() const + { return EC_PublicKey::algorithm_identifier(); } + }; + +class BOTAN_DLL GOST_3410_Signature_Operation : public PK_Ops::Signature + { + public: + GOST_3410_Signature_Operation(const GOST_3410_PrivateKey& gost_3410); + + u32bit message_parts() const { return 2; } + u32bit message_part_size() const { return order.bytes(); } + u32bit max_input_bits() const { return order.bits(); } + + SecureVector<byte> sign(const byte msg[], u32bit msg_len, RandomNumberGenerator& rng) const; + + private: + const PointGFp& base_point; + const BigInt& order; + const BigInt& x; + }; + +class BOTAN_DLL GOST_3410_Verification_Operation : public PK_Ops::Verification + { + public: + GOST_3410_Verification_Operation(const GOST_3410_PublicKey& gost); + + u32bit message_parts() const { return 2; } + u32bit message_part_size() const { return order.bytes(); } + u32bit max_input_bits() const { return order.bits(); } + + bool with_recovery() const { return false; } + + bool verify(const byte msg[], u32bit msg_len, + const byte sig[], u32bit sig_len) const; + private: + const PointGFp& base_point; + const PointGFp& public_point; + const BigInt& order; }; } diff --git a/src/pubkey/if_algo/if_algo.cpp b/src/pubkey/if_algo/if_algo.cpp index 556c86f6f..759c30c61 100644 --- a/src/pubkey/if_algo/if_algo.cpp +++ b/src/pubkey/if_algo/if_algo.cpp @@ -12,175 +12,102 @@ namespace Botan { -/* -* Return the X.509 public key encoder -*/ -X509_Encoder* IF_Scheme_PublicKey::x509_encoder() const +AlgorithmIdentifier IF_Scheme_PublicKey::algorithm_identifier() const { - class IF_Scheme_Encoder : public X509_Encoder - { - public: - AlgorithmIdentifier alg_id() const - { - return AlgorithmIdentifier(key->get_oid(), - AlgorithmIdentifier::USE_NULL_PARAM); - } - - MemoryVector<byte> key_bits() const - { - return DER_Encoder() - .start_cons(SEQUENCE) - .encode(key->n) - .encode(key->e) - .end_cons() - .get_contents(); - } - - IF_Scheme_Encoder(const IF_Scheme_PublicKey* k) : key(k) {} - private: - const IF_Scheme_PublicKey* key; - }; - - return new IF_Scheme_Encoder(this); + return AlgorithmIdentifier(get_oid(), + AlgorithmIdentifier::USE_NULL_PARAM); } -/* -* Return the X.509 public key decoder -*/ -X509_Decoder* IF_Scheme_PublicKey::x509_decoder() +MemoryVector<byte> IF_Scheme_PublicKey::x509_subject_public_key() const { - class IF_Scheme_Decoder : public X509_Decoder - { - public: - void alg_id(const AlgorithmIdentifier&) {} - - void key_bits(const MemoryRegion<byte>& bits) - { - BER_Decoder(bits) - .start_cons(SEQUENCE) - .decode(key->n) - .decode(key->e) - .verify_end() - .end_cons(); - - key->X509_load_hook(); - } - - IF_Scheme_Decoder(IF_Scheme_PublicKey* k) : key(k) {} - private: - IF_Scheme_PublicKey* key; - }; - - return new IF_Scheme_Decoder(this); + return DER_Encoder() + .start_cons(SEQUENCE) + .encode(n) + .encode(e) + .end_cons() + .get_contents(); } -/* -* Return the PKCS #8 public key encoder -*/ -PKCS8_Encoder* IF_Scheme_PrivateKey::pkcs8_encoder() const +IF_Scheme_PublicKey::IF_Scheme_PublicKey(const AlgorithmIdentifier&, + const MemoryRegion<byte>& key_bits) { - class IF_Scheme_Encoder : public PKCS8_Encoder - { - public: - AlgorithmIdentifier alg_id() const - { - return AlgorithmIdentifier(key->get_oid(), - AlgorithmIdentifier::USE_NULL_PARAM); - } - - MemoryVector<byte> key_bits() const - { - return DER_Encoder() - .start_cons(SEQUENCE) - .encode(static_cast<u32bit>(0)) - .encode(key->n) - .encode(key->e) - .encode(key->d) - .encode(key->p) - .encode(key->q) - .encode(key->d1) - .encode(key->d2) - .encode(key->c) - .end_cons() - .get_contents(); - } - - IF_Scheme_Encoder(const IF_Scheme_PrivateKey* k) : key(k) {} - private: - const IF_Scheme_PrivateKey* key; - }; - - return new IF_Scheme_Encoder(this); + BER_Decoder(key_bits) + .start_cons(SEQUENCE) + .decode(n) + .decode(e) + .verify_end() + .end_cons(); } -/* -* Return the PKCS #8 public key decoder -*/ -PKCS8_Decoder* IF_Scheme_PrivateKey::pkcs8_decoder(RandomNumberGenerator& rng) +MemoryVector<byte> IF_Scheme_PrivateKey::pkcs8_private_key() const { - class IF_Scheme_Decoder : public PKCS8_Decoder - { - public: - void alg_id(const AlgorithmIdentifier&) {} - - void key_bits(const MemoryRegion<byte>& bits) - { - u32bit version; - - BER_Decoder(bits) - .start_cons(SEQUENCE) - .decode(version) - .decode(key->n) - .decode(key->e) - .decode(key->d) - .decode(key->p) - .decode(key->q) - .decode(key->d1) - .decode(key->d2) - .decode(key->c) - .end_cons(); - - if(version != 0) - throw Decoding_Error("Unknown PKCS #1 key format version"); - - key->PKCS8_load_hook(rng); - } - - IF_Scheme_Decoder(IF_Scheme_PrivateKey* k, RandomNumberGenerator& r) : - key(k), rng(r) {} - private: - IF_Scheme_PrivateKey* key; - RandomNumberGenerator& rng; - }; - - return new IF_Scheme_Decoder(this, rng); + return DER_Encoder() + .start_cons(SEQUENCE) + .encode(static_cast<u32bit>(0)) + .encode(n) + .encode(e) + .encode(d) + .encode(p) + .encode(q) + .encode(d1) + .encode(d2) + .encode(c) + .end_cons() + .get_contents(); } -/* -* Algorithm Specific X.509 Initialization Code -*/ -void IF_Scheme_PublicKey::X509_load_hook() +IF_Scheme_PrivateKey::IF_Scheme_PrivateKey(RandomNumberGenerator& rng, + const AlgorithmIdentifier&, + const MemoryRegion<byte>& key_bits) { - core = IF_Core(e, n); + u32bit version; + + BER_Decoder(key_bits) + .start_cons(SEQUENCE) + .decode(version) + .decode(n) + .decode(e) + .decode(d) + .decode(p) + .decode(q) + .decode(d1) + .decode(d2) + .decode(c) + .end_cons(); + + if(version != 0) + throw Decoding_Error("Unknown PKCS #1 key format version"); + + load_check(rng); } -/* -* Algorithm Specific PKCS #8 Initialization Code -*/ -void IF_Scheme_PrivateKey::PKCS8_load_hook(RandomNumberGenerator& rng, - bool generated) +IF_Scheme_PrivateKey::IF_Scheme_PrivateKey(RandomNumberGenerator& rng, + const BigInt& prime1, + const BigInt& prime2, + const BigInt& exp, + const BigInt& d_exp, + const BigInt& mod) { - if(n == 0) n = p * q; - if(d1 == 0) d1 = d % (p - 1); - if(d2 == 0) d2 = d % (q - 1); - if(c == 0) c = inverse_mod(q, p); + p = prime1; + q = prime2; + e = exp; + d = d_exp; + n = mod.is_nonzero() ? mod : p * q; + + if(d == 0) + { + BigInt inv_for_d = lcm(p - 1, q - 1); + if(e.is_even()) + inv_for_d >>= 1; + + d = inverse_mod(e, inv_for_d); + } - core = IF_Core(rng, e, n, d, p, q, d1, d2, c); + d1 = d % (p - 1); + d2 = d % (q - 1); + c = inverse_mod(q, p); - if(generated) - gen_check(rng); - else - load_check(rng); + load_check(rng); } /* diff --git a/src/pubkey/if_algo/if_algo.h b/src/pubkey/if_algo/if_algo.h index 32a29be49..65bb8aed4 100644 --- a/src/pubkey/if_algo/if_algo.h +++ b/src/pubkey/if_algo/if_algo.h @@ -8,9 +8,10 @@ #ifndef BOTAN_IF_ALGO_H__ #define BOTAN_IF_ALGO_H__ -#include <botan/if_core.h> +#include <botan/bigint.h> #include <botan/x509_key.h> #include <botan/pkcs8.h> +#include <botan/pk_ops.h> namespace Botan { @@ -21,8 +22,18 @@ namespace Botan { class BOTAN_DLL IF_Scheme_PublicKey : public virtual Public_Key { public: + IF_Scheme_PublicKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits); + + IF_Scheme_PublicKey(const BigInt& n, const BigInt& e) : + n(n), e(e) {} + bool check_key(RandomNumberGenerator& rng, bool) const; + AlgorithmIdentifier algorithm_identifier() const; + + MemoryVector<byte> x509_subject_public_key() const; + /** * Get n = p * q. * @return n @@ -37,12 +48,10 @@ class BOTAN_DLL IF_Scheme_PublicKey : public virtual Public_Key u32bit max_input_bits() const { return (n.bits() - 1); } - X509_Encoder* x509_encoder() const; - X509_Decoder* x509_decoder(); protected: - virtual void X509_load_hook(); + IF_Scheme_PublicKey() {} + BigInt n, e; - IF_Core core; }; /** @@ -53,6 +62,16 @@ class BOTAN_DLL IF_Scheme_PrivateKey : public virtual IF_Scheme_PublicKey, public virtual Private_Key { public: + + IF_Scheme_PrivateKey(RandomNumberGenerator& rng, + const BigInt& prime1, const BigInt& prime2, + const BigInt& exp, const BigInt& d_exp, + const BigInt& mod); + + IF_Scheme_PrivateKey(RandomNumberGenerator& rng, + const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits); + bool check_key(RandomNumberGenerator& rng, bool) const; /** @@ -73,10 +92,15 @@ class BOTAN_DLL IF_Scheme_PrivateKey : public virtual IF_Scheme_PublicKey, */ const BigInt& get_d() const { return d; } - PKCS8_Encoder* pkcs8_encoder() const; - PKCS8_Decoder* pkcs8_decoder(RandomNumberGenerator&); + const BigInt& get_c() const { return c; } + const BigInt& get_d1() const { return d1; } + const BigInt& get_d2() const { return d2; } + + MemoryVector<byte> pkcs8_private_key() const; + protected: - virtual void PKCS8_load_hook(RandomNumberGenerator&, bool = false); + IF_Scheme_PrivateKey() {} + BigInt d, p, q, d1, d2, c; }; diff --git a/src/pubkey/if_algo/if_core.cpp b/src/pubkey/if_algo/if_core.cpp deleted file mode 100644 index 41ebfe8dd..000000000 --- a/src/pubkey/if_algo/if_core.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* -* IF Algorithm Core -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/if_core.h> -#include <botan/numthry.h> -#include <botan/internal/pk_engine.h> -#include <botan/parsing.h> -#include <algorithm> - -namespace Botan { - -/* -* IF_Core Constructor -*/ -IF_Core::IF_Core(const BigInt& e, const BigInt& n) - { - op = Engine_Core::if_op(e, n, 0, 0, 0, 0, 0, 0); - } - - -/* -* IF_Core Constructor -*/ -IF_Core::IF_Core(RandomNumberGenerator& rng, - const BigInt& e, const BigInt& n, const BigInt& d, - const BigInt& p, const BigInt& q, - const BigInt& d1, const BigInt& d2, const BigInt& c) - { - const u32bit BLINDING_BITS = BOTAN_PRIVATE_KEY_OP_BLINDING_BITS; - - op = Engine_Core::if_op(e, n, d, p, q, d1, d2, c); - - if(BLINDING_BITS) - { - BigInt k(rng, std::min(n.bits()-1, BLINDING_BITS)); - blinder = Blinder(power_mod(k, e, n), inverse_mod(k, n), n); - } - } - -/* -* IF_Core Copy Constructor -*/ -IF_Core::IF_Core(const IF_Core& core) - { - op = 0; - if(core.op) - op = core.op->clone(); - blinder = core.blinder; - } - -/* -* IF_Core Assignment Operator -*/ -IF_Core& IF_Core::operator=(const IF_Core& core) - { - delete op; - if(core.op) - op = core.op->clone(); - blinder = core.blinder; - return (*this); - } - -/* -* IF Public Operation -*/ -BigInt IF_Core::public_op(const BigInt& i) const - { - return op->public_op(i); - } - -/* -* IF Private Operation -*/ -BigInt IF_Core::private_op(const BigInt& i) const - { - return blinder.unblind(op->private_op(blinder.blind(i))); - } - -} diff --git a/src/pubkey/if_algo/if_core.h b/src/pubkey/if_algo/if_core.h deleted file mode 100644 index b7f487706..000000000 --- a/src/pubkey/if_algo/if_core.h +++ /dev/null @@ -1,45 +0,0 @@ -/* -* IF Algorithm Core -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_IF_CORE_H__ -#define BOTAN_IF_CORE_H__ - -#include <botan/if_op.h> -#include <botan/blinding.h> - -namespace Botan { - -/* -* IF Core -*/ -class BOTAN_DLL IF_Core - { - public: - BigInt public_op(const BigInt&) const; - BigInt private_op(const BigInt&) const; - - IF_Core& operator=(const IF_Core&); - - IF_Core() { op = 0; } - IF_Core(const IF_Core&); - - IF_Core(const BigInt&, const BigInt&); - - IF_Core(RandomNumberGenerator& rng, - const BigInt&, const BigInt&, - const BigInt&, const BigInt&, const BigInt&, - const BigInt&, const BigInt&, const BigInt&); - - ~IF_Core() { delete op; } - private: - IF_Operation* op; - Blinder blinder; - }; - -} - -#endif diff --git a/src/pubkey/if_algo/if_op.cpp b/src/pubkey/if_algo/if_op.cpp deleted file mode 100644 index 99f68400d..000000000 --- a/src/pubkey/if_algo/if_op.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* -* Integer Factorization Scheme (RSA/RW) Operation -* (C) 1999-2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/if_op.h> -#include <botan/numthry.h> -#include <future> - -namespace Botan { - -/* -* Default_IF_Op Constructor -*/ -Default_IF_Op::Default_IF_Op(const BigInt& e, const BigInt& n, const BigInt&, - const BigInt& p, const BigInt& q, - const BigInt& d1, const BigInt& d2, - const BigInt& c) - { - powermod_e_n = Fixed_Exponent_Power_Mod(e, n); - - if(d1 != 0 && d2 != 0 && p != 0 && q != 0) - { - powermod_d1_p = Fixed_Exponent_Power_Mod(d1, p); - powermod_d2_q = Fixed_Exponent_Power_Mod(d2, q); - reducer = Modular_Reducer(p); - this->c = c; - this->q = q; - } - } - -/* -* Default IF Private Operation -*/ -BigInt Default_IF_Op::private_op(const BigInt& i) const - { - if(q == 0) - throw Internal_Error("Default_IF_Op::private_op: No private key"); - - auto future_j1 = std::async(std::launch::async, powermod_d1_p, i); - BigInt j2 = powermod_d2_q(i); - BigInt j1 = future_j1.get(); - - j1 = reducer.reduce(sub_mul(j1, j2, c)); - return mul_add(j1, q, j2); - } - -} diff --git a/src/pubkey/if_algo/if_op.h b/src/pubkey/if_algo/if_op.h deleted file mode 100644 index 516902fd9..000000000 --- a/src/pubkey/if_algo/if_op.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -* IF Operations -* (C) 1999-2008 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_IF_OP_H__ -#define BOTAN_IF_OP_H__ - -#include <botan/bigint.h> -#include <botan/pow_mod.h> -#include <botan/reducer.h> - -namespace Botan { - -/* -* IF Operation -*/ -class BOTAN_DLL IF_Operation - { - public: - virtual BigInt public_op(const BigInt&) const = 0; - virtual BigInt private_op(const BigInt&) const = 0; - virtual IF_Operation* clone() const = 0; - virtual ~IF_Operation() {} - }; - -/* -* Default IF Operation -*/ -class BOTAN_DLL Default_IF_Op : public IF_Operation - { - public: - BigInt public_op(const BigInt& i) const - { return powermod_e_n(i); } - BigInt private_op(const BigInt&) const; - - IF_Operation* clone() const { return new Default_IF_Op(*this); } - - Default_IF_Op(const BigInt&, const BigInt&, const BigInt&, - const BigInt&, const BigInt&, const BigInt&, - const BigInt&, const BigInt&); - private: - Fixed_Exponent_Power_Mod powermod_e_n, powermod_d1_p, powermod_d2_q; - Modular_Reducer reducer; - BigInt c, q; - }; - -} - -#endif diff --git a/src/pubkey/if_algo/info.txt b/src/pubkey/if_algo/info.txt index 833117819..32e50e684 100644 --- a/src/pubkey/if_algo/info.txt +++ b/src/pubkey/if_algo/info.txt @@ -2,22 +2,9 @@ define IF_PUBLIC_KEY_FAMILY load_on dep -<header:public> -if_algo.h -if_core.h -if_op.h -</header:public> - -<source> -if_algo.cpp -if_core.cpp -if_op.cpp -</source> - <requires> asn1 bigint libstate numbertheory -pk_codecs </requires> diff --git a/src/pubkey/info.txt b/src/pubkey/info.txt index b28bd1868..956a5e369 100644 --- a/src/pubkey/info.txt +++ b/src/pubkey/info.txt @@ -1,17 +1,24 @@ define PUBLIC_KEY_CRYPTO <source> +blinding.cpp pk_algs.cpp pk_keys.cpp +pkcs8.cpp pubkey.cpp pubkey_enums.cpp workfactor.cpp +x509_key.cpp </source> <header:public> +blinding.h pk_keys.h +pk_ops.h +pkcs8.h pubkey.h pubkey_enums.h +x509_key.h </header:public> <header:internal> @@ -23,9 +30,13 @@ workfactor.h alloc asn1 bigint +engine filters kdf +libstate oid_lookup +pbe +pem pk_pad rng sym_algo diff --git a/src/pubkey/keypair/keypair.cpp b/src/pubkey/keypair/keypair.cpp index 7eaa33395..d54d8e442 100644 --- a/src/pubkey/keypair/keypair.cpp +++ b/src/pubkey/keypair/keypair.cpp @@ -1,13 +1,11 @@ /* * Keypair Checks -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ #include <botan/keypair.h> -#include <botan/look_pk.h> -#include <memory> namespace Botan { @@ -17,22 +15,20 @@ namespace KeyPair { * Check an encryption key pair for consistency */ void check_key(RandomNumberGenerator& rng, - PK_Encryptor* encryptor, PK_Decryptor* decryptor) + PK_Encryptor& encryptor, + PK_Decryptor& decryptor) { - if(encryptor->maximum_input_size() == 0) + if(encryptor.maximum_input_size() == 0) return; - std::unique_ptr<PK_Encryptor> enc(encryptor); - std::unique_ptr<PK_Decryptor> dec(decryptor); - - SecureVector<byte> message(enc->maximum_input_size() - 1); + SecureVector<byte> message(encryptor.maximum_input_size() - 1); rng.randomize(message, message.size()); - SecureVector<byte> ciphertext = enc->encrypt(message, rng); + SecureVector<byte> ciphertext = encryptor.encrypt(message, rng); if(ciphertext == message) throw Self_Test_Failure("Encryption key pair consistency failure"); - SecureVector<byte> message2 = dec->decrypt(ciphertext); + SecureVector<byte> message2 = decryptor.decrypt(ciphertext); if(message != message2) throw Self_Test_Failure("Encryption key pair consistency failure"); } @@ -41,11 +37,9 @@ void check_key(RandomNumberGenerator& rng, * Check a signature key pair for consistency */ void check_key(RandomNumberGenerator& rng, - PK_Signer* signer, PK_Verifier* verifier) + PK_Signer& signer, + PK_Verifier& verifier) { - std::unique_ptr<PK_Signer> sig(signer); - std::unique_ptr<PK_Verifier> ver(verifier); - SecureVector<byte> message(16); rng.randomize(message, message.size()); @@ -53,18 +47,18 @@ void check_key(RandomNumberGenerator& rng, try { - signature = sig->sign_message(message, rng); + signature = signer.sign_message(message, rng); } catch(Encoding_Error) { return; } - if(!ver->verify_message(message, signature)) + if(!verifier.verify_message(message, signature)) throw Self_Test_Failure("Signature key pair consistency failure"); ++message[0]; - if(ver->verify_message(message, signature)) + if(verifier.verify_message(message, signature)) throw Self_Test_Failure("Signature key pair consistency failure"); } diff --git a/src/pubkey/keypair/keypair.h b/src/pubkey/keypair/keypair.h index b1d5c2da0..22dcca0ea 100644 --- a/src/pubkey/keypair/keypair.h +++ b/src/pubkey/keypair/keypair.h @@ -24,8 +24,8 @@ namespace KeyPair { * @throw Self_Test_Failure if the arguments are not related to each other */ BOTAN_DLL void check_key(RandomNumberGenerator& rng, - PK_Encryptor* enc, - PK_Decryptor* dec); + PK_Encryptor& enc, + PK_Decryptor& dec); /** * Tests whether the specified signer and verifier are related to each other, @@ -37,8 +37,8 @@ BOTAN_DLL void check_key(RandomNumberGenerator& rng, * @throw Self_Test_Failure if the arguments are not related to each other */ BOTAN_DLL void check_key(RandomNumberGenerator& rng, - PK_Signer* sig, - PK_Verifier* ver); + PK_Signer& sig, + PK_Verifier& ver); } diff --git a/src/pubkey/nr/nr.cpp b/src/pubkey/nr/nr.cpp index ad4ae78d3..cf59615da 100644 --- a/src/pubkey/nr/nr.cpp +++ b/src/pubkey/nr/nr.cpp @@ -1,6 +1,6 @@ /* * Nyberg-Rueppel -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -8,10 +8,15 @@ #include <botan/nr.h> #include <botan/numthry.h> #include <botan/keypair.h> -#include <botan/look_pk.h> namespace Botan { +NR_PublicKey::NR_PublicKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits) : + DL_Scheme_PublicKey(alg_id, key_bits, DL_Group::ANSI_X9_57) + { + } + /* * NR_PublicKey Constructor */ @@ -19,39 +24,6 @@ NR_PublicKey::NR_PublicKey(const DL_Group& grp, const BigInt& y1) { group = grp; y = y1; - X509_load_hook(); - } - -/* -* Algorithm Specific X.509 Initialization Code -*/ -void NR_PublicKey::X509_load_hook() - { - core = NR_Core(group, y); - } - -/* -* Nyberg-Rueppel Verification Function -*/ -SecureVector<byte> NR_PublicKey::verify(const byte sig[], u32bit sig_len) const - { - return core.verify(sig, sig_len); - } - -/* -* Return the maximum input size in bits -*/ -u32bit NR_PublicKey::max_input_bits() const - { - return (group_q().bits() - 1); - } - -/* -* Return the size of each portion of the sig -*/ -u32bit NR_PublicKey::message_part_size() const - { - return group_q().bytes(); } /* @@ -65,44 +37,24 @@ NR_PrivateKey::NR_PrivateKey(RandomNumberGenerator& rng, x = x_arg; if(x == 0) - { x = BigInt::random_integer(rng, 2, group_q() - 1); - PKCS8_load_hook(rng, true); - } - else - PKCS8_load_hook(rng, false); - } -/* -* Algorithm Specific PKCS #8 Initialization Code -*/ -void NR_PrivateKey::PKCS8_load_hook(RandomNumberGenerator& rng, - bool generated) - { - if(y == 0) - y = power_mod(group_g(), x, group_p()); - core = NR_Core(group, y, x); + y = power_mod(group_g(), x, group_p()); - if(generated) + if(x_arg == 0) gen_check(rng); else load_check(rng); } -/* -* Nyberg-Rueppel Signature Operation -*/ -SecureVector<byte> NR_PrivateKey::sign(const byte in[], u32bit length, - RandomNumberGenerator& rng) const +NR_PrivateKey::NR_PrivateKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits, + RandomNumberGenerator& rng) : + DL_Scheme_PrivateKey(alg_id, key_bits, DL_Group::ANSI_X9_57) { - const BigInt& q = group_q(); + y = power_mod(group_g(), x, group_p()); - BigInt k; - do - k.randomize(rng, q.bits()); - while(k >= q); - - return core.sign(in, length, k); + load_check(rng); } /* @@ -118,10 +70,12 @@ bool NR_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const try { + PK_Signer this_signer(*this, "EMSA1(SHA-1)"); + PK_Verifier this_verifier(*this, "EMSA1(SHA-1)"); + KeyPair::check_key(rng, - get_pk_signer(*this, "EMSA1(SHA-1)"), - get_pk_verifier(*this, "EMSA1(SHA-1)") - ); + this_signer, + this_verifier); } catch(Self_Test_Failure) { @@ -131,4 +85,66 @@ bool NR_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const return true; } +NR_Signature_Operation::NR_Signature_Operation(const NR_PrivateKey& nr) : + q(nr.group_q()), + x(nr.get_x()), + powermod_g_p(nr.group_g(), nr.group_p()), + mod_q(nr.group_q()) + { + } + +SecureVector<byte> +NR_Signature_Operation::sign(const byte msg[], u32bit msg_len, + RandomNumberGenerator& rng) + { + rng.add_entropy(msg, msg_len); + + BigInt k; + do + k.randomize(rng, q.bits()); + while(k >= q); + + BigInt f(msg, msg_len); + + if(f >= q) + throw Invalid_Argument("NR_Signature_Operation: Input is out of range"); + + BigInt c = mod_q.reduce(powermod_g_p(k) + f); + if(c.is_zero()) + throw Internal_Error("NR_Signature_Operation: c was zero"); + BigInt d = mod_q.reduce(k - x * c); + + SecureVector<byte> output(2*q.bytes()); + c.binary_encode(output + (output.size() / 2 - c.bytes())); + d.binary_encode(output + (output.size() - d.bytes())); + return output; + } + +NR_Verification_Operation::NR_Verification_Operation(const NR_PublicKey& nr) : + q(nr.group_q()), y(nr.get_y()) + { + powermod_g_p = Fixed_Base_Power_Mod(nr.group_g(), nr.group_p()); + powermod_y_p = Fixed_Base_Power_Mod(y, nr.group_p()); + mod_p = Modular_Reducer(nr.group_p()); + mod_q = Modular_Reducer(nr.group_q()); + } + +SecureVector<byte> +NR_Verification_Operation::verify_mr(const byte msg[], u32bit msg_len) + { + const BigInt& q = mod_q.get_modulus(); + + if(msg_len != 2*q.bytes()) + return false; + + BigInt c(msg, q.bytes()); + BigInt d(msg + q.bytes(), q.bytes()); + + 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)); + } + } diff --git a/src/pubkey/nr/nr.h b/src/pubkey/nr/nr.h index 144c5ec2a..bd125ab92 100644 --- a/src/pubkey/nr/nr.h +++ b/src/pubkey/nr/nr.h @@ -1,6 +1,6 @@ /* * Nyberg-Rueppel -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -9,53 +9,88 @@ #define BOTAN_NYBERG_RUEPPEL_H__ #include <botan/dl_algo.h> -#include <botan/nr_core.h> +#include <botan/pk_ops.h> +#include <botan/numthry.h> +#include <botan/reducer.h> namespace Botan { /* * Nyberg-Rueppel Public Key */ -class BOTAN_DLL NR_PublicKey : public PK_Verifying_with_MR_Key, - public virtual DL_Scheme_PublicKey +class BOTAN_DLL NR_PublicKey : public virtual DL_Scheme_PublicKey { public: std::string algo_name() const { return "NR"; } - SecureVector<byte> verify(const byte[], u32bit) const; - u32bit max_input_bits() const; - DL_Group::Format group_format() const { return DL_Group::ANSI_X9_57; } + u32bit message_parts() const { return 2; } - u32bit message_part_size() const; + u32bit message_part_size() const { return group_q().bytes(); } + u32bit max_input_bits() const { return (group_q().bits() - 1); } - NR_PublicKey() {} - NR_PublicKey(const DL_Group&, const BigInt&); + NR_PublicKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits); + + NR_PublicKey(const DL_Group& group, const BigInt& pub_key); protected: - NR_Core core; - private: - void X509_load_hook(); + NR_PublicKey() {} }; /* * Nyberg-Rueppel Private Key */ class BOTAN_DLL NR_PrivateKey : public NR_PublicKey, - public PK_Signing_Key, public virtual DL_Scheme_PrivateKey { public: - SecureVector<byte> sign(const byte[], u32bit, - RandomNumberGenerator& rng) const; + bool check_key(RandomNumberGenerator& rng, bool strong) const; + + NR_PrivateKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits, + RandomNumberGenerator& rng); + + NR_PrivateKey(RandomNumberGenerator& rng, + const DL_Group& group, + const BigInt& x = 0); + }; + +class BOTAN_DLL NR_Signature_Operation : public PK_Ops::Signature + { + public: + NR_Signature_Operation(const NR_PrivateKey& nr); - bool check_key(RandomNumberGenerator& rng, bool) const; + u32bit message_parts() const { return 2; } + u32bit message_part_size() const { return q.bytes(); } + u32bit max_input_bits() const { return (q.bits() - 1); } - NR_PrivateKey() {} + SecureVector<byte> sign(const byte msg[], u32bit msg_len, + RandomNumberGenerator& rng); + private: + const BigInt& q; + const BigInt& x; + Fixed_Base_Power_Mod powermod_g_p; + Modular_Reducer mod_q; + }; - NR_PrivateKey(RandomNumberGenerator&, const DL_Group&, - const BigInt& = 0); +class BOTAN_DLL NR_Verification_Operation : public PK_Ops::Verification + { + public: + NR_Verification_Operation(const NR_PublicKey& nr); + + u32bit message_parts() const { return 2; } + u32bit message_part_size() const { return q.bytes(); } + u32bit max_input_bits() const { return (q.bits() - 1); } + + bool with_recovery() const { return true; } + + SecureVector<byte> verify_mr(const byte msg[], u32bit msg_len); private: - void PKCS8_load_hook(RandomNumberGenerator&, bool = false); + const BigInt& q; + const BigInt& y; + + Fixed_Base_Power_Mod powermod_g_p, powermod_y_p; + Modular_Reducer mod_p, mod_q; }; } diff --git a/src/pubkey/nr/nr_core.cpp b/src/pubkey/nr/nr_core.cpp deleted file mode 100644 index a87c32d60..000000000 --- a/src/pubkey/nr/nr_core.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* -* NR Core -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/nr_core.h> -#include <botan/numthry.h> -#include <botan/internal/pk_engine.h> -#include <botan/parsing.h> -#include <algorithm> - -namespace Botan { - -/* -* NR_Core Constructor -*/ -NR_Core::NR_Core(const DL_Group& group, const BigInt& y, const BigInt& x) - { - op = Engine_Core::nr_op(group, y, x); - } - -/* -* NR_Core Copy Constructor -*/ -NR_Core::NR_Core(const NR_Core& core) - { - op = 0; - if(core.op) - op = core.op->clone(); - } - -/* -* NR_Core Assignment Operator -*/ -NR_Core& NR_Core::operator=(const NR_Core& core) - { - delete op; - if(core.op) - op = core.op->clone(); - return (*this); - } - -/* -* NR Verification Operation -*/ -SecureVector<byte> NR_Core::verify(const byte in[], u32bit length) const - { - return op->verify(in, length); - } - -/* -* NR Signature Operation -*/ -SecureVector<byte> NR_Core::sign(const byte in[], u32bit length, - const BigInt& k) const - { - return op->sign(in, length, k); - } - -} diff --git a/src/pubkey/nr/nr_core.h b/src/pubkey/nr/nr_core.h deleted file mode 100644 index 483773622..000000000 --- a/src/pubkey/nr/nr_core.h +++ /dev/null @@ -1,37 +0,0 @@ -/* -* NR Core -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_NR_CORE_H__ -#define BOTAN_NR_CORE_H__ - -#include <botan/nr_op.h> -#include <botan/dl_group.h> - -namespace Botan { - -/* -* NR Core -*/ -class BOTAN_DLL NR_Core - { - public: - SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const; - SecureVector<byte> verify(const byte[], u32bit) const; - - NR_Core& operator=(const NR_Core&); - - NR_Core() { op = 0; } - NR_Core(const NR_Core&); - NR_Core(const DL_Group&, const BigInt&, const BigInt& = 0); - ~NR_Core() { delete op; } - private: - NR_Operation* op; - }; - -} - -#endif diff --git a/src/pubkey/nr/nr_op.cpp b/src/pubkey/nr/nr_op.cpp deleted file mode 100644 index 10890a127..000000000 --- a/src/pubkey/nr/nr_op.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/* -* NR Operations -* (C) 1999-2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/nr_op.h> -#include <future> - -namespace Botan { - -/* -* Default_NR_Op Constructor -*/ -Default_NR_Op::Default_NR_Op(const DL_Group& grp, const BigInt& y1, - const BigInt& x1) : x(x1), y(y1), group(grp) - { - powermod_g_p = Fixed_Base_Power_Mod(group.get_g(), group.get_p()); - powermod_y_p = Fixed_Base_Power_Mod(y, group.get_p()); - mod_p = Modular_Reducer(group.get_p()); - mod_q = Modular_Reducer(group.get_q()); - } - -/* -* Default NR Verify Operation -*/ -SecureVector<byte> Default_NR_Op::verify(const byte in[], u32bit length) const - { - const BigInt& q = group.get_q(); - - if(length != 2*q.bytes()) - return false; - - BigInt c(in, q.bytes()); - BigInt d(in + q.bytes(), q.bytes()); - - if(c.is_zero() || c >= q || d >= q) - throw Invalid_Argument("Default_NR_Op::verify: Invalid signature"); - - 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(mod_q.reduce(c - i)); - } - -/* -* Default NR Sign Operation -*/ -SecureVector<byte> Default_NR_Op::sign(const byte in[], u32bit length, - const BigInt& k) const - { - if(x == 0) - throw Internal_Error("Default_NR_Op::sign: No private key"); - - const BigInt& q = group.get_q(); - - BigInt f(in, length); - - if(f >= q) - throw Invalid_Argument("Default_NR_Op::sign: Input is out of range"); - - BigInt c = mod_q.reduce(powermod_g_p(k) + f); - if(c.is_zero()) - throw Internal_Error("Default_NR_Op::sign: c was zero"); - BigInt d = mod_q.reduce(k - x * c); - - SecureVector<byte> output(2*q.bytes()); - c.binary_encode(output + (output.size() / 2 - c.bytes())); - d.binary_encode(output + (output.size() - d.bytes())); - return output; - } - -} diff --git a/src/pubkey/nr/nr_op.h b/src/pubkey/nr/nr_op.h deleted file mode 100644 index cba1465f2..000000000 --- a/src/pubkey/nr/nr_op.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -* NR Operations -* (C) 1999-2008 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_NR_OPS_H__ -#define BOTAN_NR_OPS_H__ - -#include <botan/pow_mod.h> -#include <botan/numthry.h> -#include <botan/reducer.h> -#include <botan/dl_group.h> - -namespace Botan { - -/* -* NR Operation -*/ -class BOTAN_DLL NR_Operation - { - public: - virtual SecureVector<byte> verify(const byte[], u32bit) const = 0; - virtual SecureVector<byte> sign(const byte[], u32bit, - const BigInt&) const = 0; - virtual NR_Operation* clone() const = 0; - virtual ~NR_Operation() {} - }; - -/* -* Botan's Default NR Operation -*/ -class BOTAN_DLL Default_NR_Op : public NR_Operation - { - public: - SecureVector<byte> verify(const byte[], u32bit) const; - SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const; - - NR_Operation* clone() const { return new Default_NR_Op(*this); } - - Default_NR_Op(const DL_Group&, const BigInt&, const BigInt&); - private: - const BigInt x, y; - const DL_Group group; - Fixed_Base_Power_Mod powermod_g_p, powermod_y_p; - Modular_Reducer mod_p, mod_q; - }; - - -} - -#endif diff --git a/src/pubkey/pk_algs.cpp b/src/pubkey/pk_algs.cpp index dd62eb5ac..18e08f82e 100644 --- a/src/pubkey/pk_algs.cpp +++ b/src/pubkey/pk_algs.cpp @@ -1,11 +1,12 @@ /* * PK Key -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ #include <botan/internal/pk_algs.h> +#include <botan/oids.h> #if defined(BOTAN_HAS_RSA) #include <botan/rsa.h> @@ -41,81 +42,102 @@ namespace Botan { -/* -* Get an PK public key object -*/ -Public_Key* get_public_key(const std::string& alg_name) +BOTAN_DLL Public_Key* make_public_key(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits) { + const std::string alg_name = OIDS::lookup(alg_id.oid); + if(alg_name == "") + throw Decoding_Error("Unknown algorithm OID: " + alg_id.oid.as_string()); + #if defined(BOTAN_HAS_RSA) - if(alg_name == "RSA") return new RSA_PublicKey; + if(alg_name == "RSA") + return new RSA_PublicKey(alg_id, key_bits); +#endif + +#if defined(BOTAN_HAS_RW) + if(alg_name == "RW") + return new RW_PublicKey(alg_id, key_bits); #endif #if defined(BOTAN_HAS_DSA) - if(alg_name == "DSA") return new DSA_PublicKey; + if(alg_name == "DSA") + return new DSA_PublicKey(alg_id, key_bits); #endif #if defined(BOTAN_HAS_DIFFIE_HELLMAN) - if(alg_name == "DH") return new DH_PublicKey; + if(alg_name == "DH") + return new DH_PublicKey(alg_id, key_bits); #endif #if defined(BOTAN_HAS_NYBERG_RUEPPEL) - if(alg_name == "NR") return new NR_PublicKey; + if(alg_name == "NR") + return new NR_PublicKey(alg_id, key_bits); #endif -#if defined(BOTAN_HAS_RW) - if(alg_name == "RW") return new RW_PublicKey; -#endif - -#if defined(BOTAN_HAS_ELG) - if(alg_name == "ELG") return new ElGamal_PublicKey; +#if defined(BOTAN_HAS_ELGAMAL) + if(alg_name == "ElGamal") + return new ElGamal_PublicKey(alg_id, key_bits); #endif #if defined(BOTAN_HAS_ECDSA) - if(alg_name == "ECDSA") return new ECDSA_PublicKey; + if(alg_name == "ECDSA") + return new ECDSA_PublicKey(alg_id, key_bits); #endif #if defined(BOTAN_HAS_GOST_34_10_2001) - if(alg_name == "GOST-34.10") return new GOST_3410_PublicKey; + if(alg_name == "GOST-34.10") + return new GOST_3410_PublicKey(alg_id, key_bits); #endif return 0; } -/* -* Get an PK private key object -*/ -Private_Key* get_private_key(const std::string& alg_name) +BOTAN_DLL Private_Key* make_private_key(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits, + RandomNumberGenerator& rng) { + const std::string alg_name = OIDS::lookup(alg_id.oid); + if(alg_name == "") + throw Decoding_Error("Unknown algorithm OID: " + alg_id.oid.as_string()); + #if defined(BOTAN_HAS_RSA) - if(alg_name == "RSA") return new RSA_PrivateKey; + if(alg_name == "RSA") + return new RSA_PrivateKey(alg_id, key_bits, rng); +#endif + +#if defined(BOTAN_HAS_RW) + if(alg_name == "RW") + return new RW_PrivateKey(alg_id, key_bits, rng); #endif #if defined(BOTAN_HAS_DSA) - if(alg_name == "DSA") return new DSA_PrivateKey; + if(alg_name == "DSA") + return new DSA_PrivateKey(alg_id, key_bits, rng); #endif #if defined(BOTAN_HAS_DIFFIE_HELLMAN) - if(alg_name == "DH") return new DH_PrivateKey; + if(alg_name == "DH") + return new DH_PrivateKey(alg_id, key_bits, rng); #endif #if defined(BOTAN_HAS_NYBERG_RUEPPEL) - if(alg_name == "NR") return new NR_PrivateKey; + if(alg_name == "NR") + return new NR_PrivateKey(alg_id, key_bits, rng); #endif -#if defined(BOTAN_HAS_RW) - if(alg_name == "RW") return new RW_PrivateKey; -#endif - -#if defined(BOTAN_HAS_ELG) - if(alg_name == "ELG") return new ElGamal_PrivateKey; +#if defined(BOTAN_HAS_ELGAMAL) + if(alg_name == "ElGamal") + return new ElGamal_PrivateKey(alg_id, key_bits, rng); #endif #if defined(BOTAN_HAS_ECDSA) - if(alg_name == "ECDSA") return new ECDSA_PrivateKey; + if(alg_name == "ECDSA") + return new ECDSA_PrivateKey(alg_id, key_bits); #endif #if defined(BOTAN_HAS_GOST_34_10_2001) - if(alg_name == "GOST-34.10") return new GOST_3410_PrivateKey; + if(alg_name == "GOST-34.10") + return new GOST_3410_PrivateKey(alg_id, key_bits); #endif return 0; diff --git a/src/pubkey/pk_algs.h b/src/pubkey/pk_algs.h index c41bf1a63..3fbaed234 100644 --- a/src/pubkey/pk_algs.h +++ b/src/pubkey/pk_algs.h @@ -1,6 +1,6 @@ /* * PK Key Factory -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -12,19 +12,12 @@ namespace Botan { -/** -* Get an empty public key object. -* @param name the name of the desired public key algorithm -* @return the public key object -*/ -BOTAN_DLL Public_Key* get_public_key(const std::string&); +BOTAN_DLL Public_Key* make_public_key(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits); -/** -* Get an empty private key object. -* @param name the name of the desired public key algorithm -* @return the private key object -*/ -BOTAN_DLL Private_Key* get_private_key(const std::string&); +BOTAN_DLL Private_Key* make_private_key(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits, + RandomNumberGenerator& rng); } diff --git a/src/pubkey/pk_codecs/info.txt b/src/pubkey/pk_codecs/info.txt deleted file mode 100644 index 64fb10b8a..000000000 --- a/src/pubkey/pk_codecs/info.txt +++ /dev/null @@ -1,7 +0,0 @@ -<requires> -asn1 -filters -oid_lookup -pbe -pem -</requires> diff --git a/src/pubkey/pk_keys.h b/src/pubkey/pk_keys.h index 5b612577d..da73db0ee 100644 --- a/src/pubkey/pk_keys.h +++ b/src/pubkey/pk_keys.h @@ -10,6 +10,7 @@ #include <botan/secmem.h> #include <botan/asn1_oid.h> +#include <botan/alg_id.h> #include <botan/rng.h> namespace Botan { @@ -61,17 +62,14 @@ class BOTAN_DLL Public_Key virtual u32bit max_input_bits() const = 0; /** - * Get an X509 encoder that can be used to encode this key in X509 format. - * @return an X509 encoder for this key + * @return X.509 AlgorithmIdentifier for this key */ - virtual class X509_Encoder* x509_encoder() const = 0; + virtual AlgorithmIdentifier algorithm_identifier() const = 0; /** - * Get an X509 decoder that can be used to set the values of this - * key based on an X509 encoded key object. - * @return an X509 decoder for this key + * @return X.509 subject key encoding for this key object */ - virtual class X509_Decoder* x509_decoder() = 0; + virtual MemoryVector<byte> x509_subject_public_key() const = 0; virtual ~Public_Key() {} protected: @@ -85,86 +83,30 @@ class BOTAN_DLL Private_Key : public virtual Public_Key { public: /** - * Get a PKCS#8 encoder that can be used to encode this key in - * PKCS#8 format. - * @return an PKCS#8 encoder for this key + * @return PKCS #8 private key encoding for this key object */ - virtual class PKCS8_Encoder* pkcs8_encoder() const - { return 0; } + virtual MemoryVector<byte> pkcs8_private_key() const = 0; /** - * Get an PKCS#8 decoder that can be used to set the values of this key - * based on an PKCS#8 encoded key object. - * @return an PKCS#8 decoder for this key + * @return PKCS #8 AlgorithmIdentifier for this key + * Might be different from the X.509 identifier, but normally is not */ - virtual class PKCS8_Decoder* pkcs8_decoder(RandomNumberGenerator&) - { return 0; } + virtual AlgorithmIdentifier pkcs8_algorithm_identifier() const + { return algorithm_identifier(); } + protected: void load_check(RandomNumberGenerator&) const; void gen_check(RandomNumberGenerator&) const; }; /** -* PK Encrypting Key. -*/ -class BOTAN_DLL PK_Encrypting_Key : public virtual Public_Key - { - public: - virtual SecureVector<byte> encrypt(const byte[], u32bit, - RandomNumberGenerator&) const = 0; - virtual ~PK_Encrypting_Key() {} - }; - -/** -* PK Decrypting Key -*/ -class BOTAN_DLL PK_Decrypting_Key : public virtual Private_Key - { - public: - virtual SecureVector<byte> decrypt(const byte[], u32bit) const = 0; - virtual ~PK_Decrypting_Key() {} - }; - -/** -* PK Signing Key -*/ -class BOTAN_DLL PK_Signing_Key : public virtual Private_Key - { - public: - virtual SecureVector<byte> sign(const byte[], u32bit, - RandomNumberGenerator& rng) const = 0; - virtual ~PK_Signing_Key() {} - }; - -/** -* PK Verifying Key, Message Recovery Version -*/ -class BOTAN_DLL PK_Verifying_with_MR_Key : public virtual Public_Key - { - public: - virtual SecureVector<byte> verify(const byte[], u32bit) const = 0; - virtual ~PK_Verifying_with_MR_Key() {} - }; - -/** -* PK Verifying Key, No Message Recovery Version -*/ -class BOTAN_DLL PK_Verifying_wo_MR_Key : public virtual Public_Key - { - public: - virtual bool verify(const byte[], u32bit, - const byte[], u32bit) const = 0; - virtual ~PK_Verifying_wo_MR_Key() {} - }; - -/** * PK Secret Value Derivation Key */ class BOTAN_DLL PK_Key_Agreement_Key : public virtual Private_Key { public: - virtual SecureVector<byte> derive_key(const byte[], u32bit) const = 0; virtual MemoryVector<byte> public_value() const = 0; + virtual ~PK_Key_Agreement_Key() {} }; diff --git a/src/pubkey/pk_ops.h b/src/pubkey/pk_ops.h new file mode 100644 index 000000000..97ba372c2 --- /dev/null +++ b/src/pubkey/pk_ops.h @@ -0,0 +1,151 @@ +/* +* PK Operation Types +* (C) 2010 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_PK_OPERATIONS_H__ +#define BOTAN_PK_OPERATIONS_H__ + +#include <botan/secmem.h> +#include <botan/rng.h> + +namespace Botan { + +namespace PK_Ops { + +class BOTAN_DLL Encryption + { + public: + virtual u32bit max_input_bits() const = 0; + + virtual SecureVector<byte> encrypt(const byte msg[], u32bit msg_len, + RandomNumberGenerator& rng) = 0; + + virtual ~Encryption() {} + }; + +class BOTAN_DLL Decryption + { + public: + virtual u32bit max_input_bits() const = 0; + + virtual SecureVector<byte> decrypt(const byte msg[], + u32bit msg_len) = 0; + + virtual ~Decryption() {} + }; + +class BOTAN_DLL Signature + { + public: + /** + * Find out the number of message parts supported by this scheme. + * @return the number of message parts + */ + virtual u32bit message_parts() const { return 1; } + + /** + * Find out the message part size supported by this scheme/key. + * @return the size of the message parts + */ + virtual u32bit message_part_size() const { return 0; } + + /** + * Get the maximum message size in bits supported by this public key. + * @return the maximum message in bits + */ + virtual u32bit max_input_bits() const = 0; + + /* + * Perform a signature operation + * @param msg the message + * @param msg_len the length of msg in bytes + * @param rng a random number generator + */ + virtual SecureVector<byte> sign(const byte msg[], u32bit msg_len, + RandomNumberGenerator& rng) = 0; + + virtual ~Signature() {} + }; + +class BOTAN_DLL Verification + { + public: + /** + * Get the maximum message size in bits supported by this public key. + * @return the maximum message in bits + */ + virtual u32bit max_input_bits() const = 0; + + /** + * Find out the number of message parts supported by this scheme. + * @return the number of message parts + */ + virtual u32bit message_parts() const { return 1; } + + /** + * Find out the message part size supported by this scheme/key. + * @return the size of the message parts + */ + virtual u32bit message_part_size() const { return 0; } + + /** + * @return boolean specifying if this key type supports message + * recovery and thus if you need to call verify() or verify_mr() + */ + virtual bool with_recovery() const = 0; + + /* + * Perform a signature check operation + * @param msg the message + * @param msg_len the length of msg in bytes + * @param sig the signature + * @param sig_len the length of sig in bytes + * @returns if signature is a valid one for message + */ + virtual bool verify(const byte[], u32bit, + const byte[], u32bit) + { + throw Invalid_State("Message recovery required"); + } + + /* + * Perform a signature operation (with message recovery) + * Only call this if with_recovery() returns true + * @param msg the message + * @param msg_len the length of msg in bytes + * @returns recovered message + */ + virtual SecureVector<byte> verify_mr(const byte[], + u32bit) + { + throw Invalid_State("Message recovery not supported"); + } + + virtual ~Verification() {} + }; + +/* +* A generic Key Agreement Operation (eg DH or ECDH) +*/ +class BOTAN_DLL Key_Agreement + { + public: + /* + * Perform a key agreement operation + * @param w the other key value + * @param w_len the length of w in bytes + * @returns the agreed key + */ + virtual SecureVector<byte> agree(const byte w[], u32bit w_len) = 0; + + virtual ~Key_Agreement() {} + }; + +} + +} + +#endif diff --git a/src/pubkey/pk_codecs/pkcs8.cpp b/src/pubkey/pkcs8.cpp index 830f3a10d..d3a62aa01 100644 --- a/src/pubkey/pk_codecs/pkcs8.cpp +++ b/src/pubkey/pkcs8.cpp @@ -1,6 +1,6 @@ /* * PKCS #8 -* (C) 1999-2008 Jack Lloyd +* (C) 1999-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -138,18 +138,14 @@ SecureVector<byte> PKCS8_decode(DataSource& source, const User_Interface& ui, */ void encode(const Private_Key& key, Pipe& pipe, X509_Encoding encoding) { - std::unique_ptr<PKCS8_Encoder> encoder(key.pkcs8_encoder()); - if(!encoder.get()) - throw Encoding_Error("PKCS8::encode: Key does not support encoding"); - const u32bit PKCS8_VERSION = 0; SecureVector<byte> contents = DER_Encoder() .start_cons(SEQUENCE) .encode(PKCS8_VERSION) - .encode(encoder->alg_id()) - .encode(encoder->key_bits(), OCTET_STRING) + .encode(key.pkcs8_algorithm_identifier()) + .encode(key.pkcs8_private_key(), OCTET_STRING) .end_cons() .get_contents(); @@ -244,21 +240,7 @@ Private_Key* load_key(DataSource& source, throw PKCS8_Exception("Unknown algorithm OID: " + alg_id.oid.as_string()); - std::unique_ptr<Private_Key> key(get_private_key(alg_name)); - - if(!key.get()) - throw PKCS8_Exception("Unknown PK algorithm/OID: " + alg_name + ", " + - alg_id.oid.as_string()); - - std::unique_ptr<PKCS8_Decoder> decoder(key->pkcs8_decoder(rng)); - - if(!decoder.get()) - throw Decoding_Error("Key does not support PKCS #8 decoding"); - - decoder->alg_id(alg_id); - decoder->key_bits(pkcs8_key); - - return key.release(); + return make_private_key(alg_id, pkcs8_key, rng); } /* diff --git a/src/pubkey/pk_codecs/pkcs8.h b/src/pubkey/pkcs8.h index adfad0e63..920f8c24a 100644 --- a/src/pubkey/pk_codecs/pkcs8.h +++ b/src/pubkey/pkcs8.h @@ -14,49 +14,6 @@ namespace Botan { /** -* PKCS #8 Private Key Encoder. -*/ -class BOTAN_DLL PKCS8_Encoder - { - public: - /** - * Get the algorithm identifier associated with the scheme - * this encoders key is part of. - * @return the algorithm identifier - */ - virtual AlgorithmIdentifier alg_id() const = 0; - - /** - * Get the DER encoded key. - * @return the DER encoded key - */ - // FIXME: Why not SecureVector? - virtual MemoryVector<byte> key_bits() const = 0; - virtual ~PKCS8_Encoder() {} - }; - -/* -* PKCS #8 Private Key Decoder -*/ -class BOTAN_DLL PKCS8_Decoder - { - public: - /** - * Set the algorithm identifier associated with the scheme - * this decoders key is part of. - * @param alg_id the algorithm identifier - */ - virtual void alg_id(const AlgorithmIdentifier&) = 0; - - /** - * Set the DER encoded key. - * @param key the DER encoded key - */ - virtual void key_bits(const MemoryRegion<byte>&) = 0; - virtual ~PKCS8_Decoder() {} - }; - -/** * PKCS #8 General Exception */ struct BOTAN_DLL PKCS8_Exception : public Decoding_Error diff --git a/src/pubkey/pubkey.cpp b/src/pubkey/pubkey.cpp index 69002207f..751f20583 100644 --- a/src/pubkey/pubkey.cpp +++ b/src/pubkey/pubkey.cpp @@ -1,6 +1,6 @@ /* * Public Key Base -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -10,130 +10,137 @@ #include <botan/ber_dec.h> #include <botan/bigint.h> #include <botan/parsing.h> +#include <botan/libstate.h> +#include <botan/engine.h> +#include <botan/lookup.h> #include <botan/internal/bit_ops.h> #include <memory> namespace Botan { /* -* Encrypt a message -*/ -SecureVector<byte> PK_Encryptor::encrypt(const byte in[], u32bit len, - RandomNumberGenerator& rng) const - { - return enc(in, len, rng); - } - -/* -* Encrypt a message +* PK_Encryptor_EME Constructor */ -SecureVector<byte> PK_Encryptor::encrypt(const MemoryRegion<byte>& in, - RandomNumberGenerator& rng) const +PK_Encryptor_EME::PK_Encryptor_EME(const Public_Key& key, + const std::string& eme_name) { - return enc(in.begin(), in.size(), rng); - } + Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory()); -/* -* Decrypt a message -*/ -SecureVector<byte> PK_Decryptor::decrypt(const byte in[], u32bit len) const - { - return dec(in, len); - } + while(const Engine* engine = i.next()) + { + op = engine->get_encryption_op(key); + if(op) + break; + } -/* -* Decrypt a message -*/ -SecureVector<byte> PK_Decryptor::decrypt(const MemoryRegion<byte>& in) const - { - return dec(in.begin(), in.size()); - } + if(!op) + throw Lookup_Error("PK_Encryptor_EME: No working engine for " + + key.algo_name()); -/* -* PK_Encryptor_MR_with_EME Constructor -*/ -PK_Encryptor_MR_with_EME::PK_Encryptor_MR_with_EME(const PK_Encrypting_Key& k, - EME* eme_obj) : - key(k), encoder(eme_obj) - { + eme = get_eme(eme_name); } /* * Encrypt a message */ SecureVector<byte> -PK_Encryptor_MR_with_EME::enc(const byte msg[], - u32bit length, - RandomNumberGenerator& rng) const +PK_Encryptor_EME::enc(const byte msg[], + u32bit length, + RandomNumberGenerator& rng) const { SecureVector<byte> message; - if(encoder) - message = encoder->encode(msg, length, key.max_input_bits(), rng); + if(eme) + message = eme->encode(msg, length, op->max_input_bits(), rng); else message.set(msg, length); - if(8*(message.size() - 1) + high_bit(message[0]) > key.max_input_bits()) - throw Invalid_Argument("PK_Encryptor_MR_with_EME: Input is too large"); + if(8*(message.size() - 1) + high_bit(message[0]) > op->max_input_bits()) + throw Invalid_Argument("PK_Encryptor_EME: Input is too large"); - return key.encrypt(message, message.size(), rng); + return op->encrypt(message, message.size(), rng); } /* * Return the max size, in bytes, of a message */ -u32bit PK_Encryptor_MR_with_EME::maximum_input_size() const +u32bit PK_Encryptor_EME::maximum_input_size() const { - if(!encoder) - return (key.max_input_bits() / 8); + if(!eme) + return (op->max_input_bits() / 8); else - return encoder->maximum_input_size(key.max_input_bits()); + return eme->maximum_input_size(op->max_input_bits()); } /* -* PK_Decryptor_MR_with_EME Constructor +* PK_Decryptor_EME Constructor */ -PK_Decryptor_MR_with_EME::PK_Decryptor_MR_with_EME(const PK_Decrypting_Key& k, - EME* eme_obj) : - key(k), encoder(eme_obj) +PK_Decryptor_EME::PK_Decryptor_EME(const Private_Key& key, + const std::string& eme_name) { + Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory()); + + while(const Engine* engine = i.next()) + { + op = engine->get_decryption_op(key); + if(op) + break; + } + + if(!op) + throw Lookup_Error("PK_Decryptor_EME: No working engine for " + + key.algo_name()); + + eme = get_eme(eme_name); } /* * Decrypt a message */ -SecureVector<byte> PK_Decryptor_MR_with_EME::dec(const byte msg[], - u32bit length) const +SecureVector<byte> PK_Decryptor_EME::dec(const byte msg[], + u32bit length) const { try { - SecureVector<byte> decrypted = key.decrypt(msg, length); - if(encoder) - return encoder->decode(decrypted, key.max_input_bits()); + SecureVector<byte> decrypted = op->decrypt(msg, length); + if(eme) + return eme->decode(decrypted, op->max_input_bits()); else return decrypted; } catch(Invalid_Argument) { - throw Decoding_Error("PK_Decryptor_MR_with_EME: Input is invalid"); + throw Decoding_Error("PK_Decryptor_EME: Input is invalid"); } } /* * PK_Signer Constructor */ -PK_Signer::PK_Signer(const PK_Signing_Key& k, EMSA* emsa_obj) : - key(k), emsa(emsa_obj) +PK_Signer::PK_Signer(const Private_Key& key, + const std::string& emsa_name, + Signature_Format format) { - sig_format = IEEE_1363; - } + Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory()); -/* -* Set the signature format -*/ -void PK_Signer::set_output_format(Signature_Format format) - { - if(key.message_parts() == 1 && format != IEEE_1363) - throw Invalid_State("PK_Signer: Cannot set the output format for " + - key.algo_name() + " keys"); + op = 0; + verify_op = 0; + + while(const Engine* engine = i.next()) + { + if(!op) + op = engine->get_signature_op(key); + + if(!verify_op) + verify_op = engine->get_verify_op(key); + + if(op && verify_op) + break; + } + + if(!op || !verify_op) + throw Lookup_Error("PK_Signer: No working engine for " + + key.algo_name()); + + emsa = get_emsa(emsa_name); sig_format = format; } @@ -148,15 +155,6 @@ SecureVector<byte> PK_Signer::sign_message(const byte msg[], u32bit length, } /* -* Sign a message -*/ -SecureVector<byte> PK_Signer::sign_message(const MemoryRegion<byte>& msg, - RandomNumberGenerator& rng) - { - return sign_message(msg, msg.size(), rng); - } - -/* * Add more to the message to be signed */ void PK_Signer::update(const byte in[], u32bit length) @@ -165,19 +163,32 @@ void PK_Signer::update(const byte in[], u32bit length) } /* -* Add more to the message to be signed +* Check the signature we just created, to help prevent fault attacks */ -void PK_Signer::update(byte in) +bool PK_Signer::self_test_signature(const MemoryRegion<byte>& msg, + const MemoryRegion<byte>& sig) const { - update(&in, 1); - } + if(verify_op->with_recovery()) + { + SecureVector<byte> recovered = + verify_op->verify_mr(&sig[0], sig.size()); -/* -* Add more to the message to be signed -*/ -void PK_Signer::update(const MemoryRegion<byte>& in) - { - update(in, in.size()); + if(msg.size() > recovered.size()) + { + u32bit extra_0s = msg.size() - recovered.size(); + + for(size_t i = 0; i != extra_0s; ++i) + if(msg[i] != 0) + return false; + + return same_mem(&msg[extra_0s], &recovered[0], recovered.size()); + } + + return (recovered == msg); + } + else + return verify_op->verify(&msg[0], msg.size(), + &sig[0], sig.size()); } /* @@ -186,21 +197,24 @@ void PK_Signer::update(const MemoryRegion<byte>& in) SecureVector<byte> PK_Signer::signature(RandomNumberGenerator& rng) { SecureVector<byte> encoded = emsa->encoding_of(emsa->raw_data(), - key.max_input_bits(), + op->max_input_bits(), rng); - SecureVector<byte> plain_sig = key.sign(encoded, encoded.size(), rng); + SecureVector<byte> plain_sig = op->sign(encoded, encoded.size(), rng); - if(key.message_parts() == 1 || sig_format == IEEE_1363) + if(!self_test_signature(encoded, plain_sig)) + throw Internal_Error("PK_Signer consistency check failed"); + + if(op->message_parts() == 1 || sig_format == IEEE_1363) return plain_sig; if(sig_format == DER_SEQUENCE) { - if(plain_sig.size() % key.message_parts()) + if(plain_sig.size() % op->message_parts()) throw Encoding_Error("PK_Signer: strange signature size found"); - const u32bit SIZE_OF_PART = plain_sig.size() / key.message_parts(); + const u32bit SIZE_OF_PART = plain_sig.size() / op->message_parts(); - std::vector<BigInt> sig_parts(key.message_parts()); + std::vector<BigInt> sig_parts(op->message_parts()); for(u32bit j = 0; j != sig_parts.size(); ++j) sig_parts[j].binary_decode(plain_sig + SIZE_OF_PART*j, SIZE_OF_PART); @@ -218,18 +232,25 @@ SecureVector<byte> PK_Signer::signature(RandomNumberGenerator& rng) /* * PK_Verifier Constructor */ -PK_Verifier::PK_Verifier(EMSA* emsa_obj) +PK_Verifier::PK_Verifier(const Public_Key& key, + const std::string& emsa_name, + Signature_Format format) { - emsa = emsa_obj; - sig_format = IEEE_1363; - } + Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory()); -/* -* PK_Verifier Destructor -*/ -PK_Verifier::~PK_Verifier() - { - delete emsa; + while(const Engine* engine = i.next()) + { + op = engine->get_verify_op(key); + if(op) + break; + } + + if(!op) + throw Lookup_Error("PK_Verifier: No working engine for " + + key.algo_name()); + + emsa = get_emsa(emsa_name); + sig_format = format; } /* @@ -237,7 +258,7 @@ PK_Verifier::~PK_Verifier() */ void PK_Verifier::set_input_format(Signature_Format format) { - if(key_message_parts() == 1 && format != IEEE_1363) + if(op->message_parts() == 1 && format != IEEE_1363) throw Invalid_State("PK_Verifier: This algorithm always uses IEEE 1363"); sig_format = format; } @@ -245,15 +266,6 @@ void PK_Verifier::set_input_format(Signature_Format format) /* * Verify a message */ -bool PK_Verifier::verify_message(const MemoryRegion<byte>& msg, - const MemoryRegion<byte>& sig) - { - return verify_message(msg, msg.size(), sig, sig.size()); - } - -/* -* Verify a message -*/ bool PK_Verifier::verify_message(const byte msg[], u32bit msg_length, const byte sig[], u32bit sig_length) { @@ -270,30 +282,6 @@ void PK_Verifier::update(const byte in[], u32bit length) } /* -* Append to the message -*/ -void PK_Verifier::update(byte in) - { - update(&in, 1); - } - -/* -* Append to the message -*/ -void PK_Verifier::update(const MemoryRegion<byte>& in) - { - update(in, in.size()); - } - -/* -* Check a signature -*/ -bool PK_Verifier::check_signature(const MemoryRegion<byte>& sig) - { - return check_signature(sig, sig.size()); - } - -/* * Check a signature */ bool PK_Verifier::check_signature(const byte sig[], u32bit length) @@ -313,10 +301,11 @@ bool PK_Verifier::check_signature(const byte sig[], u32bit length) BigInt sig_part; ber_sig.decode(sig_part); real_sig.append(BigInt::encode_1363(sig_part, - key_message_part_size())); + op->message_part_size())); ++count; } - if(count != key_message_parts()) + + if(count != op->message_parts()) throw Decoding_Error("PK_Verifier: signature size invalid"); return validate_signature(emsa->raw_data(), @@ -332,60 +321,57 @@ bool PK_Verifier::check_signature(const byte sig[], u32bit length) /* * Verify a signature */ -bool PK_Verifier_with_MR::validate_signature(const MemoryRegion<byte>& msg, - const byte sig[], u32bit sig_len) +bool PK_Verifier::validate_signature(const MemoryRegion<byte>& msg, + const byte sig[], u32bit sig_len) { - SecureVector<byte> output_of_key = key.verify(sig, sig_len); - return emsa->verify(output_of_key, msg, key.max_input_bits()); - } - -/* -* Verify a signature -*/ -bool PK_Verifier_wo_MR::validate_signature(const MemoryRegion<byte>& msg, - const byte sig[], u32bit sig_len) - { - Null_RNG rng; + if(op->with_recovery()) + { + SecureVector<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 = - emsa->encoding_of(msg, key.max_input_bits(), rng); + SecureVector<byte> encoded = + emsa->encoding_of(msg, op->max_input_bits(), rng); - return key.verify(encoded, encoded.size(), sig, sig_len); + return op->verify(encoded, encoded.size(), sig, sig_len); + } } /* * PK_Key_Agreement Constructor */ -PK_Key_Agreement::PK_Key_Agreement(const PK_Key_Agreement_Key& k, - KDF* kdf_obj) : - key(k), kdf(kdf_obj) +PK_Key_Agreement::PK_Key_Agreement(const PK_Key_Agreement_Key& key, + const std::string& kdf_name) { - } + Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory()); -/* -* Perform Key Agreement Operation -*/ -SymmetricKey PK_Key_Agreement::derive_key(u32bit key_len, - const byte in[], u32bit in_len, - const std::string& params) const - { - return derive_key(key_len, in, in_len, - reinterpret_cast<const byte*>(params.data()), - params.length()); + while(const Engine* engine = i.next()) + { + op = engine->get_key_agreement_op(key); + if(op) + break; + } + + if(!op) + throw Lookup_Error("PK_Key_Agreement: No working engine for " + + key.algo_name()); + + kdf = get_kdf(kdf_name); } -/* -* Perform Key Agreement Operation -*/ SymmetricKey PK_Key_Agreement::derive_key(u32bit key_len, const byte in[], u32bit in_len, const byte params[], u32bit params_len) const { - OctetString z = key.derive_key(in, in_len); + SecureVector<byte> z = op->agree(in, in_len); + if(!kdf) return z; - return kdf->derive_key(key_len, z.bits_of(), params, params_len); + return kdf->derive_key(key_len, z, params, params_len); } } diff --git a/src/pubkey/pubkey.h b/src/pubkey/pubkey.h index c73a54d35..c31aed67b 100644 --- a/src/pubkey/pubkey.h +++ b/src/pubkey/pubkey.h @@ -1,6 +1,6 @@ /* * Public Key Interface -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -9,6 +9,7 @@ #define BOTAN_PUBKEY_H__ #include <botan/pk_keys.h> +#include <botan/pk_ops.h> #include <botan/symkey.h> #include <botan/rng.h> #include <botan/eme.h> @@ -37,7 +38,10 @@ class BOTAN_DLL PK_Encryptor * @return the encrypted message */ SecureVector<byte> encrypt(const byte in[], u32bit length, - RandomNumberGenerator& rng) const; + RandomNumberGenerator& rng) const + { + return enc(in, length, rng); + } /** * Encrypt a message. @@ -46,7 +50,10 @@ class BOTAN_DLL PK_Encryptor * @return the encrypted message */ SecureVector<byte> encrypt(const MemoryRegion<byte>& in, - RandomNumberGenerator& rng) const; + RandomNumberGenerator& rng) const + { + return enc(&in[0], in.size(), rng); + } /** * Return the maximum allowed message size in bytes. @@ -54,8 +61,12 @@ class BOTAN_DLL PK_Encryptor */ virtual u32bit maximum_input_size() const = 0; + PK_Encryptor() {} virtual ~PK_Encryptor() {} private: + PK_Encryptor(const PK_Encryptor&) {} + PK_Encryptor& operator=(const PK_Encryptor&) { return *this; } + virtual SecureVector<byte> enc(const byte[], u32bit, RandomNumberGenerator&) const = 0; }; @@ -72,17 +83,27 @@ class BOTAN_DLL PK_Decryptor * @param length the length of the above byte array * @return the decrypted message */ - SecureVector<byte> decrypt(const byte in[], u32bit length) const; + SecureVector<byte> decrypt(const byte in[], u32bit length) const + { + return dec(in, length); + } /** * Decrypt a ciphertext. * @param in the ciphertext * @return the decrypted message */ - SecureVector<byte> decrypt(const MemoryRegion<byte>& in) const; + SecureVector<byte> decrypt(const MemoryRegion<byte>& in) const + { + return dec(&in[0], in.size()); + } + PK_Decryptor() {} virtual ~PK_Decryptor() {} private: + PK_Decryptor(const PK_Decryptor&) {} + PK_Decryptor& operator=(const PK_Decryptor&) { return *this; } + virtual SecureVector<byte> dec(const byte[], u32bit) const = 0; }; @@ -111,13 +132,14 @@ class BOTAN_DLL PK_Signer * @return the signature */ SecureVector<byte> sign_message(const MemoryRegion<byte>& in, - RandomNumberGenerator& rng); + RandomNumberGenerator& rng) + { return sign_message(&in[0], in.size(), rng); } /** * Add a message part (single byte). * @param the byte to add */ - void update(byte in); + void update(byte in) { update(&in, 1); } /** * Add a message part. @@ -130,7 +152,7 @@ class BOTAN_DLL PK_Signer * Add a message part. * @param in the message part to add */ - void update(const MemoryRegion<byte>& in); + void update(const MemoryRegion<byte>& in) { update(&in[0], in.size()); } /** * Get the signature of the so far processed message (provided by the @@ -144,24 +166,31 @@ class BOTAN_DLL PK_Signer * Set the output format of the signature. * @param format the signature format to use */ - void set_output_format(Signature_Format format); + void set_output_format(Signature_Format format) { sig_format = format; } /** * Construct a PK Signer. * @param key the key to use inside this signer * @param emsa the EMSA to use * An example would be "EMSA1(SHA-224)". + * @param format the signature format to use */ - PK_Signer(const PK_Signing_Key& key, EMSA* emsa); + PK_Signer(const Private_Key& key, + const std::string& emsa, + Signature_Format format = IEEE_1363); - ~PK_Signer() { delete emsa; } + ~PK_Signer() { delete op; delete verify_op; delete emsa; } private: - PK_Signer(const PK_Signer&); - PK_Signer& operator=(const PK_Signer&); + bool self_test_signature(const MemoryRegion<byte>& msg, + const MemoryRegion<byte>& sig) const; - const PK_Signing_Key& key; - Signature_Format sig_format; + PK_Signer(const PK_Signer&) {} + PK_Signer& operator=(const PK_Signer&) { return *this; } + + PK_Ops::Signature* op; + PK_Ops::Verification* verify_op; EMSA* emsa; + Signature_Format sig_format; }; /** @@ -189,14 +218,17 @@ class BOTAN_DLL PK_Verifier * @return true if the signature is valid */ bool verify_message(const MemoryRegion<byte>& msg, - const MemoryRegion<byte>& sig); + const MemoryRegion<byte>& sig) + { + return verify_message(msg, msg.size(), sig, sig.size()); + } /** * Add a message part (single byte) of the message corresponding to the * signature to be verified. - * @param msg_part the byte to add + * @param in the byte to add */ - void update(byte msg_part); + void update(byte in) { update(&in, 1); } /** * Add a message part of the message corresponding to the @@ -209,9 +241,10 @@ class BOTAN_DLL PK_Verifier /** * Add a message part of the message corresponding to the * signature to be verified. - * @param msg_part the new message part + * @param in the new message part */ - void update(const MemoryRegion<byte>& msg_part); + void update(const MemoryRegion<byte>& in) + { update(&in[0], in.size()); } /** * Check the signature of the buffered message, i.e. the one build @@ -228,7 +261,10 @@ 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); + bool check_signature(const MemoryRegion<byte>& sig) + { + return check_signature(&sig[0], sig.size()); + } /** * Set the format of the signatures fed to this verifier. @@ -238,23 +274,25 @@ class BOTAN_DLL PK_Verifier /** * Construct a PK Verifier. - * @param emsa the EMSA to use - * An example would be new EMSA1(new SHA_224) + * @param pub_key the public key to verify against + * @param emsa the EMSA to use (eg "EMSA3(SHA-1)") + * @param format the signature format to use */ - PK_Verifier(EMSA* emsa); + PK_Verifier(const Public_Key& pub_key, + const std::string& emsa, + Signature_Format format = IEEE_1363); - virtual ~PK_Verifier(); - protected: - virtual bool validate_signature(const MemoryRegion<byte>&, - const byte[], u32bit) = 0; - virtual u32bit key_message_parts() const = 0; - virtual u32bit key_message_part_size() const = 0; + ~PK_Verifier() { delete op; delete emsa; } + private: + PK_Verifier(const PK_Verifier&) {} + PK_Verifier& operator=(const PK_Verifier&) { return *this; } - Signature_Format sig_format; + bool validate_signature(const MemoryRegion<byte>& msg, + const byte sig[], u32bit sig_len); + + PK_Ops::Verification* op; EMSA* emsa; - private: - PK_Verifier(const PK_Verifier&); - PK_Verifier& operator=(const PK_Verifier&); + Signature_Format sig_format; }; /* @@ -263,31 +301,90 @@ class BOTAN_DLL PK_Verifier class BOTAN_DLL PK_Key_Agreement { public: - SymmetricKey derive_key(u32bit, const byte[], u32bit, - const std::string& = "") const; - SymmetricKey derive_key(u32bit, const byte[], u32bit, - const byte[], u32bit) const; + + /* + * Perform Key Agreement Operation + * @param key_len the desired key output size + * @param in the other parties key + * @param in_len the length of in in bytes + * @param params extra derivation params + * @param params_len the length of params in bytes + */ + SymmetricKey derive_key(u32bit key_len, + const byte in[], + u32bit in_len, + const byte params[], + u32bit params_len) const; + + /* + * Perform Key Agreement Operation + * @param key_len the desired key output size + * @param in the other parties key + * @param in_len the length of in in bytes + * @param params extra derivation params + * @param params_len the length of params in bytes + */ + SymmetricKey derive_key(u32bit key_len, + const MemoryRegion<byte>& in, + const byte params[], + u32bit params_len) const + { + return derive_key(key_len, &in[0], in.size(), + params, params_len); + } + + /* + * Perform Key Agreement Operation + * @param key_len the desired key output size + * @param in the other parties key + * @param in_len the length of in in bytes + * @param params extra derivation params + */ + SymmetricKey derive_key(u32bit key_len, + const byte in[], u32bit in_len, + const std::string& params = "") const + { + return derive_key(key_len, in, in_len, + reinterpret_cast<const byte*>(params.data()), + params.length()); + } + + /* + * Perform Key Agreement Operation + * @param key_len the desired key output size + * @param in the other parties key + * @param params extra derivation params + */ + SymmetricKey derive_key(u32bit key_len, + const MemoryRegion<byte>& in, + const std::string& params = "") const + { + return derive_key(key_len, &in[0], in.size(), + reinterpret_cast<const byte*>(params.data()), + params.length()); + } /** * Construct a PK Key Agreement. * @param key the key to use - * @param kdf the KDF to use + * @param kdf name of the KDF to use (or 'Raw' for no KDF) */ - PK_Key_Agreement(const PK_Key_Agreement_Key& key, KDF* kdf); + PK_Key_Agreement(const PK_Key_Agreement_Key& key, + const std::string& kdf); - ~PK_Key_Agreement() { delete kdf; } + ~PK_Key_Agreement() { delete op; delete kdf; } private: - PK_Key_Agreement(const PK_Key_Agreement_Key&); - PK_Key_Agreement& operator=(const PK_Key_Agreement&); + PK_Key_Agreement(const PK_Key_Agreement_Key&) {} + PK_Key_Agreement& operator=(const PK_Key_Agreement&) { return *this; } - const PK_Key_Agreement_Key& key; + PK_Ops::Key_Agreement* op; KDF* kdf; }; /** * Encryption with an MR algorithm and an EME. */ -class BOTAN_DLL PK_Encryptor_MR_with_EME : public PK_Encryptor +class BOTAN_DLL PK_Encryptor_EME : public PK_Encryptor { public: u32bit maximum_input_size() const; @@ -297,25 +394,22 @@ class BOTAN_DLL PK_Encryptor_MR_with_EME : public PK_Encryptor * @param key the key to use inside the decryptor * @param eme the EME to use */ - PK_Encryptor_MR_with_EME(const PK_Encrypting_Key& key, - EME* eme); + PK_Encryptor_EME(const Public_Key& key, + const std::string& eme); - ~PK_Encryptor_MR_with_EME() { delete encoder; } + ~PK_Encryptor_EME() { delete op; delete eme; } private: - PK_Encryptor_MR_with_EME(const PK_Encryptor_MR_with_EME&); - PK_Encryptor_MR_with_EME& operator=(const PK_Encryptor_MR_with_EME&); - SecureVector<byte> enc(const byte[], u32bit, RandomNumberGenerator& rng) const; - const PK_Encrypting_Key& key; - const EME* encoder; + PK_Ops::Encryption* op; + const EME* eme; }; /** * Decryption with an MR algorithm and an EME. */ -class BOTAN_DLL PK_Decryptor_MR_with_EME : public PK_Decryptor +class BOTAN_DLL PK_Decryptor_EME : public PK_Decryptor { public: /** @@ -323,68 +417,15 @@ class BOTAN_DLL PK_Decryptor_MR_with_EME : public PK_Decryptor * @param key the key to use inside the encryptor * @param eme the EME to use */ - PK_Decryptor_MR_with_EME(const PK_Decrypting_Key& key, - EME* eme); + PK_Decryptor_EME(const Private_Key& key, + const std::string& eme); - ~PK_Decryptor_MR_with_EME() { delete encoder; } + ~PK_Decryptor_EME() { delete op; delete eme; } private: - PK_Decryptor_MR_with_EME(const PK_Decryptor_MR_with_EME&); - PK_Decryptor_MR_with_EME& operator=(const PK_Decryptor_MR_with_EME&); - SecureVector<byte> dec(const byte[], u32bit) const; - const PK_Decrypting_Key& key; - const EME* encoder; - }; - -/** -* Public Key Verifier with Message Recovery. -*/ -class BOTAN_DLL PK_Verifier_with_MR : public PK_Verifier - { - public: - /** - * Construct an instance. - * @param key the key to use inside the verifier - * @param emsa_name the name of the EMSA to use - */ - PK_Verifier_with_MR(const PK_Verifying_with_MR_Key& k, - EMSA* emsa_obj) : PK_Verifier(emsa_obj), key(k) {} - - private: - PK_Verifier_with_MR(const PK_Verifying_with_MR_Key&); - PK_Verifier_with_MR& operator=(const PK_Verifier_with_MR&); - - bool validate_signature(const MemoryRegion<byte>&, const byte[], u32bit); - u32bit key_message_parts() const { return key.message_parts(); } - u32bit key_message_part_size() const { return key.message_part_size(); } - - const PK_Verifying_with_MR_Key& key; - }; - -/** -* Public Key Verifier without Message Recovery -*/ -class BOTAN_DLL PK_Verifier_wo_MR : public PK_Verifier - { - public: - /** - * Construct an instance. - * @param key the key to use inside the verifier - * @param emsa_name the name of the EMSA to use - */ - PK_Verifier_wo_MR(const PK_Verifying_wo_MR_Key& k, - EMSA* emsa_obj) : PK_Verifier(emsa_obj), key(k) {} - - private: - PK_Verifier_wo_MR(const PK_Verifying_wo_MR_Key&); - PK_Verifier_wo_MR& operator=(const PK_Verifier_wo_MR&); - - bool validate_signature(const MemoryRegion<byte>&, const byte[], u32bit); - u32bit key_message_parts() const { return key.message_parts(); } - u32bit key_message_part_size() const { return key.message_part_size(); } - - const PK_Verifying_wo_MR_Key& key; + PK_Ops::Decryption* op; + const EME* eme; }; } diff --git a/src/pubkey/rsa/rsa.cpp b/src/pubkey/rsa/rsa.cpp index 38ea1eeca..200e92821 100644 --- a/src/pubkey/rsa/rsa.cpp +++ b/src/pubkey/rsa/rsa.cpp @@ -1,6 +1,6 @@ /* * RSA -* (C) 1999-2008 Jack Lloyd +* (C) 1999-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -9,50 +9,10 @@ #include <botan/parsing.h> #include <botan/numthry.h> #include <botan/keypair.h> -#include <botan/look_pk.h> namespace Botan { /* -* RSA_PublicKey Constructor -*/ -RSA_PublicKey::RSA_PublicKey(const BigInt& mod, const BigInt& exp) - { - n = mod; - e = exp; - X509_load_hook(); - } - -/* -* RSA Public Operation -*/ -BigInt RSA_PublicKey::public_op(const BigInt& i) const - { - if(i >= n) - throw Invalid_Argument(algo_name() + "::public_op: input is too large"); - return core.public_op(i); - } - -/* -* RSA Encryption Function -*/ -SecureVector<byte> RSA_PublicKey::encrypt(const byte in[], u32bit len, - RandomNumberGenerator&) const - { - BigInt i(in, len); - return BigInt::encode_1363(public_op(i), n.bytes()); - } - -/* -* RSA Verification Function -*/ -SecureVector<byte> RSA_PublicKey::verify(const byte in[], u32bit len) const - { - BigInt i(in, len); - return BigInt::encode(public_op(i)); - } - -/* * Create a RSA private key */ RSA_PrivateKey::RSA_PrivateKey(RandomNumberGenerator& rng, @@ -67,64 +27,17 @@ RSA_PrivateKey::RSA_PrivateKey(RandomNumberGenerator& rng, e = exp; p = random_prime(rng, (bits + 1) / 2, e); q = random_prime(rng, bits - p.bits(), e); - d = inverse_mod(e, lcm(p - 1, q - 1)); - - PKCS8_load_hook(rng, true); + n = p * q; if(n.bits() != bits) throw Self_Test_Failure(algo_name() + " private key generation failed"); - } - -/* -* RSA_PrivateKey Constructor -*/ -RSA_PrivateKey::RSA_PrivateKey(RandomNumberGenerator& rng, - const BigInt& prime1, const BigInt& prime2, - const BigInt& exp, const BigInt& d_exp, - const BigInt& mod) - { - p = prime1; - q = prime2; - e = exp; - d = d_exp; - n = mod; - - if(d == 0) - d = inverse_mod(e, lcm(p - 1, q - 1)); - - PKCS8_load_hook(rng); - } - -/* -* RSA Private Operation -*/ -BigInt RSA_PrivateKey::private_op(const byte in[], u32bit length) const - { - BigInt i(in, length); - if(i >= n) - throw Invalid_Argument(algo_name() + "::private_op: input is too large"); - - BigInt r = core.private_op(i); - if(i != public_op(r)) - throw Self_Test_Failure(algo_name() + " private operation check failed"); - return r; - } -/* -* RSA Decryption Operation -*/ -SecureVector<byte> RSA_PrivateKey::decrypt(const byte in[], u32bit len) const - { - return BigInt::encode(private_op(in, len)); - } + d = inverse_mod(e, lcm(p - 1, q - 1)); + d1 = d % (p - 1); + d2 = d % (q - 1); + c = inverse_mod(q, p); -/* -* RSA Signature Operation -*/ -SecureVector<byte> RSA_PrivateKey::sign(const byte in[], u32bit len, - RandomNumberGenerator&) const - { - return BigInt::encode_1363(private_op(in, len), n.bytes()); + gen_check(rng); } /* @@ -143,15 +56,12 @@ bool RSA_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const try { - KeyPair::check_key(rng, - get_pk_encryptor(*this, "EME1(SHA-1)"), - get_pk_decryptor(*this, "EME1(SHA-1)") - ); + PK_Signer this_signer(*this, "EMSA4(SHA-1)"); + PK_Verifier this_verifier(*this, "EMSA4(SHA-1)"); KeyPair::check_key(rng, - get_pk_signer(*this, "EMSA4(SHA-1)"), - get_pk_verifier(*this, "EMSA4(SHA-1)") - ); + this_signer, + this_verifier); } catch(Self_Test_Failure) { @@ -161,4 +71,59 @@ bool RSA_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const return true; } +RSA_Private_Operation::RSA_Private_Operation(const RSA_PrivateKey& rsa) : + n(rsa.get_n()), + q(rsa.get_q()), + c(rsa.get_c()), + powermod_e_n(rsa.get_e(), rsa.get_n()), + powermod_d1_p(rsa.get_d1(), rsa.get_p()), + powermod_d2_q(rsa.get_d2(), rsa.get_q()), + mod_p(rsa.get_p()) + { + BigInt k = Blinder::choose_nonce(powermod_e_n(q), n); + blinder = Blinder(powermod_e_n(k), inverse_mod(k, n), n); + } + +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); + BigInt j2 = powermod_d2_q(m); + + j1 = mod_p.reduce(sub_mul(j1, j2, c)); + + return mul_add(j1, q, j2); + } + +SecureVector<byte> +RSA_Private_Operation::sign(const byte msg[], u32bit msg_len, + RandomNumberGenerator& rng) + { + /* We don't check signatures against powermod_e_n here because + PK_Signer checks verification consistency for all signature + algorithms. + */ + + BigInt m(msg, msg_len); + BigInt x = blinder.unblind(private_op(blinder.blind(m))); + return BigInt::encode_1363(x, n.bytes()); + } + +/* +* RSA Decryption Operation +*/ +SecureVector<byte> +RSA_Private_Operation::decrypt(const byte msg[], u32bit msg_len) + { + BigInt m(msg, msg_len); + BigInt x = blinder.unblind(private_op(blinder.blind(m))); + + if(m != powermod_e_n(x)) + throw Internal_Error("RSA private op failed consistency check"); + + return BigInt::encode(x); + } + } diff --git a/src/pubkey/rsa/rsa.h b/src/pubkey/rsa/rsa.h index 0580fe8eb..72cd80fef 100644 --- a/src/pubkey/rsa/rsa.h +++ b/src/pubkey/rsa/rsa.h @@ -9,15 +9,15 @@ #define BOTAN_RSA_H__ #include <botan/if_algo.h> +#include <botan/reducer.h> +#include <botan/blinding.h> namespace Botan { /** * RSA Public Key */ -class BOTAN_DLL RSA_PublicKey : public PK_Encrypting_Key, - public PK_Verifying_with_MR_Key, - public virtual IF_Scheme_PublicKey +class BOTAN_DLL RSA_PublicKey : public virtual IF_Scheme_PublicKey { public: std::string algo_name() const { return "RSA"; } @@ -25,57 +25,57 @@ class BOTAN_DLL RSA_PublicKey : public PK_Encrypting_Key, SecureVector<byte> encrypt(const byte[], u32bit, RandomNumberGenerator& rng) const; - SecureVector<byte> verify(const byte[], u32bit) const; - - RSA_PublicKey() {} + RSA_PublicKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits) : + IF_Scheme_PublicKey(alg_id, key_bits) + {} /** * Create a RSA_PublicKey * @arg n the modulus * @arg e the exponent */ - RSA_PublicKey(const BigInt& n, const BigInt& e); + RSA_PublicKey(const BigInt& n, const BigInt& e) : + IF_Scheme_PublicKey(n, e) + {} + protected: - BigInt public_op(const BigInt&) const; + RSA_PublicKey() {} }; /** * RSA Private Key class. */ class BOTAN_DLL RSA_PrivateKey : public RSA_PublicKey, - public PK_Decrypting_Key, - public PK_Signing_Key, public IF_Scheme_PrivateKey { public: - SecureVector<byte> sign(const byte[], u32bit, - RandomNumberGenerator&) const; - SecureVector<byte> decrypt(const byte[], u32bit) const; bool check_key(RandomNumberGenerator& rng, bool) const; - /** - * Default constructor, does not set any internal values. Use this - * constructor if you wish to decode a DER or PEM encoded key. - */ - RSA_PrivateKey() {} + RSA_PrivateKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits, + RandomNumberGenerator& rng) : + IF_Scheme_PrivateKey(rng, alg_id, key_bits) {} /** * Construct a private key from the specified parameters. - * @param rng the random number generator to use - * @param prime1 the first prime - * @param prime2 the second prime - * @param exp the exponent - * @param d_exp if specified, this has to be d with + * @param rng a random number generator + * @param p the first prime + * @param q the second prime + * @param e the exponent + * @param d if specified, this has to be d with * exp * d = 1 mod (p - 1, q - 1). Leave it as 0 if you wish to * the constructor to calculate it. * @param n if specified, this must be n = p * q. Leave it as 0 * if you wish to the constructor to calculate it. */ RSA_PrivateKey(RandomNumberGenerator& rng, - const BigInt& p, const BigInt& q, const BigInt& e, - const BigInt& d = 0, const BigInt& n = 0); + const BigInt& p, const BigInt& q, + const BigInt& e, const BigInt& d = 0, + const BigInt& n = 0) : + IF_Scheme_PrivateKey(rng, p, q, e, d, n) {} /** * Create a new private key with the specified bit length @@ -85,8 +85,66 @@ class BOTAN_DLL RSA_PrivateKey : public RSA_PublicKey, */ RSA_PrivateKey(RandomNumberGenerator& rng, u32bit bits, u32bit exp = 65537); + }; + +class BOTAN_DLL RSA_Private_Operation : public PK_Ops::Signature, + public PK_Ops::Decryption + { + public: + RSA_Private_Operation(const RSA_PrivateKey& rsa); + + u32bit max_input_bits() const { return (n.bits() - 1); } + + SecureVector<byte> sign(const byte msg[], u32bit msg_len, + RandomNumberGenerator& rng); + + SecureVector<byte> decrypt(const byte msg[], u32bit msg_len); + + private: + BigInt private_op(const BigInt& m) const; + + const BigInt& n; + const BigInt& q; + const BigInt& c; + Fixed_Exponent_Power_Mod powermod_e_n, powermod_d1_p, powermod_d2_q; + Modular_Reducer mod_p; + Blinder blinder; + }; + +class BOTAN_DLL RSA_Public_Operation : public PK_Ops::Verification, + public PK_Ops::Encryption + { + public: + RSA_Public_Operation(const RSA_PublicKey& rsa) : + n(rsa.get_n()), powermod_e_n(rsa.get_e(), rsa.get_n()) + {} + + u32bit max_input_bits() const { return (n.bits() - 1); } + bool with_recovery() const { return true; } + + SecureVector<byte> encrypt(const byte msg[], u32bit msg_len, + RandomNumberGenerator&) + { + BigInt m(msg, msg_len); + return BigInt::encode_1363(public_op(m), n.bytes()); + } + + SecureVector<byte> verify_mr(const byte msg[], u32bit msg_len) + { + BigInt m(msg, msg_len); + return BigInt::encode(public_op(m)); + } + private: - BigInt private_op(const byte[], u32bit) const; + BigInt public_op(const BigInt& m) const + { + if(m >= n) + throw Invalid_Argument("RSA public op - input is too large"); + return powermod_e_n(m); + } + + const BigInt& n; + Fixed_Exponent_Power_Mod powermod_e_n; }; } diff --git a/src/pubkey/rw/rw.cpp b/src/pubkey/rw/rw.cpp index 460c740ab..9600ae709 100644 --- a/src/pubkey/rw/rw.cpp +++ b/src/pubkey/rw/rw.cpp @@ -8,51 +8,12 @@ #include <botan/rw.h> #include <botan/numthry.h> #include <botan/keypair.h> -#include <botan/look_pk.h> #include <botan/parsing.h> #include <algorithm> namespace Botan { /* -* RW_PublicKey Constructor -*/ -RW_PublicKey::RW_PublicKey(const BigInt& mod, const BigInt& exp) - { - n = mod; - e = exp; - X509_load_hook(); - } - -/* -* Rabin-Williams Public Operation -*/ -BigInt RW_PublicKey::public_op(const BigInt& i) const - { - if((i > (n >> 1)) || i.is_negative()) - throw Invalid_Argument(algo_name() + "::public_op: i > n / 2 || i < 0"); - - BigInt r = core.public_op(i); - if(r % 16 == 12) return r; - if(r % 8 == 6) return 2*r; - - r = n - r; - if(r % 16 == 12) return r; - if(r % 8 == 6) return 2*r; - - throw Invalid_Argument(algo_name() + "::public_op: Invalid input"); - } - -/* -* Rabin-Williams Verification Function -*/ -SecureVector<byte> RW_PublicKey::verify(const byte in[], u32bit len) const - { - BigInt i(in, len); - return BigInt::encode(public_op(i)); - } - -/* * Create a Rabin-Williams private key */ RW_PrivateKey::RW_PrivateKey(RandomNumberGenerator& rng, @@ -67,53 +28,18 @@ RW_PrivateKey::RW_PrivateKey(RandomNumberGenerator& rng, e = exp; p = random_prime(rng, (bits + 1) / 2, e / 2, 3, 4); q = random_prime(rng, bits - p.bits(), e / 2, ((p % 8 == 3) ? 7 : 3), 8); - d = inverse_mod(e, lcm(p - 1, q - 1) >> 1); - PKCS8_load_hook(rng, true); + n = p * q; if(n.bits() != bits) throw Self_Test_Failure(algo_name() + " private key generation failed"); - } - -/* -* RW_PrivateKey Constructor -*/ -RW_PrivateKey::RW_PrivateKey(RandomNumberGenerator& rng, - const BigInt& prime1, const BigInt& prime2, - const BigInt& exp, const BigInt& d_exp, - const BigInt& mod) - { - p = prime1; - q = prime2; - e = exp; - d = d_exp; - n = mod; - - if(d == 0) - d = inverse_mod(e, lcm(p - 1, q - 1) >> 1); - - PKCS8_load_hook(rng); - } - -/* -* Rabin-Williams Signature Operation -*/ -SecureVector<byte> RW_PrivateKey::sign(const byte in[], u32bit len, - RandomNumberGenerator&) const - { - BigInt i(in, len); - if(i >= n || i % 16 != 12) - throw Invalid_Argument(algo_name() + "::sign: Invalid input"); - - BigInt r; - if(jacobi(i, n) == 1) r = core.private_op(i); - else r = core.private_op(i >> 1); - r = std::min(r, n - r); - if(i != public_op(r)) - throw Self_Test_Failure(algo_name() + " private operation check failed"); + d = inverse_mod(e, lcm(p - 1, q - 1) >> 1); + d1 = d % (p - 1); + d2 = d % (q - 1); + c = inverse_mod(q, p); - return BigInt::encode_1363(r, n.bytes()); + gen_check(rng); } /* @@ -132,10 +58,12 @@ bool RW_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const try { + PK_Signer this_signer(*this, "EMSA2(SHA-1)"); + PK_Verifier this_verifier(*this, "EMSA2(SHA-1)"); + KeyPair::check_key(rng, - get_pk_signer(*this, "EMSA2(SHA-1)"), - get_pk_verifier(*this, "EMSA2(SHA-1)") - ); + this_signer, + this_verifier); } catch(Self_Test_Failure) { @@ -145,4 +73,69 @@ bool RW_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const return true; } +RW_Signature_Operation::RW_Signature_Operation(const RW_PrivateKey& rw) : + n(rw.get_n()), + e(rw.get_e()), + q(rw.get_q()), + c(rw.get_c()), + powermod_d1_p(rw.get_d1(), rw.get_p()), + powermod_d2_q(rw.get_d2(), rw.get_q()), + mod_p(rw.get_p()) + { + } + +SecureVector<byte> +RW_Signature_Operation::sign(const byte msg[], u32bit msg_len, + RandomNumberGenerator& rng) + { + if(!blinder.initialized()) + { + BigInt k(rng, n.bits() / 2); + blinder = Blinder(power_mod(k, e, n), inverse_mod(k, n), n); + } + + BigInt i(msg, msg_len); + + if(i >= n || i % 16 != 12) + throw Invalid_Argument("Rabin-Williams: invalid input"); + + if(jacobi(i, n) != 1) + i >>= 1; + + 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)); + + BigInt r = blinder.unblind(mul_add(j1, q, j2)); + + r = std::min(r, n - r); + + return BigInt::encode_1363(r, n.bytes()); + } + +SecureVector<byte> +RW_Verification_Operation::verify_mr(const byte msg[], u32bit msg_len) + { + BigInt m(msg, msg_len); + + if((m > (n >> 1)) || m.is_negative()) + throw Invalid_Argument("RW signature verification: m > n / 2 || m < 0"); + + BigInt r = powermod_e_n(m); + if(r % 16 == 12) + return BigInt::encode(r); + if(r % 8 == 6) + return BigInt::encode(2*r); + + r = n - r; + if(r % 16 == 12) + return BigInt::encode(r); + if(r % 8 == 6) + return BigInt::encode(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 900e5ebda..3ca9bb722 100644 --- a/src/pubkey/rw/rw.h +++ b/src/pubkey/rw/rw.h @@ -9,46 +9,90 @@ #define BOTAN_RW_H__ #include <botan/if_algo.h> +#include <botan/reducer.h> +#include <botan/blinding.h> namespace Botan { /* * Rabin-Williams Public Key */ -class BOTAN_DLL RW_PublicKey : public PK_Verifying_with_MR_Key, - public virtual IF_Scheme_PublicKey +class BOTAN_DLL RW_PublicKey : public virtual IF_Scheme_PublicKey { public: std::string algo_name() const { return "RW"; } - SecureVector<byte> verify(const byte[], u32bit) const; + RW_PublicKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits) : + IF_Scheme_PublicKey(alg_id, key_bits) + {} + + RW_PublicKey(const BigInt& mod, const BigInt& exponent) : + IF_Scheme_PublicKey(mod, exponent) + {} - RW_PublicKey() {} - RW_PublicKey(const BigInt&, const BigInt&); protected: - BigInt public_op(const BigInt&) const; + RW_PublicKey() {} }; /* * Rabin-Williams Private Key */ class BOTAN_DLL RW_PrivateKey : public RW_PublicKey, - public PK_Signing_Key, public IF_Scheme_PrivateKey { public: - SecureVector<byte> sign(const byte[], u32bit, - RandomNumberGenerator& rng) const; + RW_PrivateKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits, + RandomNumberGenerator& rng) : + IF_Scheme_PrivateKey(rng, alg_id, key_bits) {} + + RW_PrivateKey(RandomNumberGenerator& rng, + const BigInt& p, const BigInt& q, + const BigInt& e, const BigInt& d = 0, + const BigInt& n = 0) : + IF_Scheme_PrivateKey(rng, p, q, e, d, n) {} + + RW_PrivateKey(RandomNumberGenerator& rng, u32bit bits, u32bit = 2); bool check_key(RandomNumberGenerator& rng, bool) const; + }; + +class BOTAN_DLL RW_Signature_Operation : public PK_Ops::Signature + { + public: + RW_Signature_Operation(const RW_PrivateKey& rw); - RW_PrivateKey() {} + u32bit max_input_bits() const { return (n.bits() - 1); } - RW_PrivateKey(RandomNumberGenerator&, - const BigInt&, const BigInt&, const BigInt&, - const BigInt& = 0, const BigInt& = 0); + SecureVector<byte> sign(const byte msg[], u32bit msg_len, + RandomNumberGenerator& rng); + private: + const BigInt& n; + const BigInt& e; + const BigInt& q; + const BigInt& c; - RW_PrivateKey(RandomNumberGenerator& rng, u32bit bits, u32bit = 2); + Fixed_Exponent_Power_Mod powermod_d1_p, powermod_d2_q; + Modular_Reducer mod_p; + Blinder blinder; + }; + +class BOTAN_DLL RW_Verification_Operation : public PK_Ops::Verification + { + public: + RW_Verification_Operation(const RW_PublicKey& rw) : + n(rw.get_n()), powermod_e_n(rw.get_e(), rw.get_n()) + {} + + u32bit max_input_bits() const { return (n.bits() - 1); } + bool with_recovery() const { return true; } + + SecureVector<byte> verify_mr(const byte msg[], u32bit msg_len); + + private: + const BigInt& n; + Fixed_Exponent_Power_Mod powermod_e_n; }; } diff --git a/src/pubkey/pk_codecs/x509_key.cpp b/src/pubkey/x509_key.cpp index 4cd6371d8..babeb517f 100644 --- a/src/pubkey/pk_codecs/x509_key.cpp +++ b/src/pubkey/x509_key.cpp @@ -10,7 +10,6 @@ #include <botan/asn1_obj.h> #include <botan/der_enc.h> #include <botan/ber_dec.h> -#include <botan/oids.h> #include <botan/pem.h> #include <botan/internal/pk_algs.h> #include <memory> @@ -24,15 +23,11 @@ namespace X509 { */ void encode(const Public_Key& key, Pipe& pipe, X509_Encoding encoding) { - std::unique_ptr<X509_Encoder> encoder(key.x509_encoder()); - if(!encoder.get()) - throw Encoding_Error("X509::encode: Key does not support encoding"); - MemoryVector<byte> der = DER_Encoder() .start_cons(SEQUENCE) - .encode(encoder->alg_id()) - .encode(encoder->key_bits(), BIT_STRING) + .encode(key.algorithm_identifier()) + .encode(key.x509_subject_public_key(), BIT_STRING) .end_cons() .get_contents(); @@ -89,25 +84,7 @@ Public_Key* load_key(DataSource& source) if(key_bits.empty()) throw Decoding_Error("X.509 public key decoding failed"); - const std::string alg_name = OIDS::lookup(alg_id.oid); - if(alg_name == "") - throw Decoding_Error("Unknown algorithm OID: " + - alg_id.oid.as_string()); - - std::unique_ptr<Public_Key> key_obj(get_public_key(alg_name)); - if(!key_obj.get()) - throw Decoding_Error("Unknown PK algorithm/OID: " + alg_name + ", " + - alg_id.oid.as_string()); - - std::unique_ptr<X509_Decoder> decoder(key_obj->x509_decoder()); - - if(!decoder.get()) - throw Decoding_Error("Key does not support X.509 decoding"); - - decoder->alg_id(alg_id); - decoder->key_bits(key_bits); - - return key_obj.release(); + return make_public_key(alg_id, key_bits); } catch(Decoding_Error) { @@ -152,17 +129,18 @@ Public_Key* copy_key(const Public_Key& key) Key_Constraints find_constraints(const Public_Key& pub_key, Key_Constraints limits) { - const Public_Key* key = &pub_key; - u32bit constraints = 0; + const std::string name = pub_key.algo_name(); - if(dynamic_cast<const PK_Encrypting_Key*>(key)) - constraints |= KEY_ENCIPHERMENT | DATA_ENCIPHERMENT; + u32bit constraints = 0; - if(dynamic_cast<const PK_Key_Agreement_Key*>(key)) + if(name == "DH" || name == "ECDH") constraints |= KEY_AGREEMENT; - if(dynamic_cast<const PK_Verifying_wo_MR_Key*>(key) || - dynamic_cast<const PK_Verifying_with_MR_Key*>(key)) + if(name == "RSA" || name == "ElGamal") + constraints |= KEY_ENCIPHERMENT | DATA_ENCIPHERMENT; + + if(name == "RSA" || name == "RW" || name == "NR" || + name == "DSA" || name == "ECDSA") constraints |= DIGITAL_SIGNATURE | NON_REPUDIATION; if(limits) diff --git a/src/pubkey/pk_codecs/x509_key.h b/src/pubkey/x509_key.h index 9404b7ecc..13f11646e 100644 --- a/src/pubkey/pk_codecs/x509_key.h +++ b/src/pubkey/x509_key.h @@ -16,36 +16,10 @@ namespace Botan { /** -* This class represents abstract X.509 public key encoders. -*/ -class BOTAN_DLL X509_Encoder - { - public: - virtual AlgorithmIdentifier alg_id() const = 0; - virtual MemoryVector<byte> key_bits() const = 0; - virtual ~X509_Encoder() {} - }; - -/** -* This class represents abstract X.509 public key decoders. -*/ -class BOTAN_DLL X509_Decoder - { - public: - virtual void alg_id(const AlgorithmIdentifier&) = 0; - virtual void key_bits(const MemoryRegion<byte>&) = 0; - virtual ~X509_Decoder() {} - }; - -/** * This namespace contains functions for handling X509 objects. */ namespace X509 { -/* -* X.509 Public Key Encoding/Decoding -*/ - /** * Encode a key into a pipe. * @param key the public key to encode diff --git a/src/ssl/c_kex.cpp b/src/ssl/c_kex.cpp index 802946bb9..9e59beefc 100644 --- a/src/ssl/c_kex.cpp +++ b/src/ssl/c_kex.cpp @@ -1,15 +1,15 @@ /** -* Client Key Exchange Message -* (C) 2004-2008 Jack Lloyd +* Client Key Exchange Message +* (C) 2004-2010 Jack Lloyd * * Released under the terms of the Botan license */ #include <botan/tls_messages.h> +#include <botan/pubkey.h> #include <botan/dh.h> #include <botan/rsa.h> #include <botan/rng.h> -#include <botan/look_pk.h> #include <botan/loadstor.h> #include <memory> @@ -25,28 +25,28 @@ Client_Key_Exchange::Client_Key_Exchange(RandomNumberGenerator& rng, Version_Code using_version, Version_Code pref_version) { - const DH_PublicKey* dh_pub = dynamic_cast<const DH_PublicKey*>(pub_key); - const RSA_PublicKey* rsa_pub = dynamic_cast<const RSA_PublicKey*>(pub_key); - include_length = true; - if(dh_pub) + if(const DH_PublicKey* dh_pub = dynamic_cast<const DH_PublicKey*>(pub_key)) { DH_PrivateKey priv_key(rng, dh_pub->get_domain()); - pre_master = priv_key.derive_key(dh_pub->get_y()); + + 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(rsa_pub) + else if(const RSA_PublicKey* rsa_pub = dynamic_cast<const RSA_PublicKey*>(pub_key)) { pre_master.resize(48); rng.randomize(pre_master, 48); pre_master[0] = (pref_version >> 8) & 0xFF; pre_master[1] = (pref_version ) & 0xFF; - std::auto_ptr<PK_Encryptor> encryptor(get_pk_encryptor(*rsa_pub, - "PKCS1v15")); + PK_Encryptor_EME encryptor(*rsa_pub, "PKCS1v15"); - key_material = encryptor->encrypt(pre_master, rng); + key_material = encryptor.encrypt(pre_master, rng); if(using_version == SSL_V3) include_length = false; @@ -120,16 +120,15 @@ Client_Key_Exchange::pre_master_secret(RandomNumberGenerator& rng, const Private_Key* priv_key, Version_Code version) { - const DH_PrivateKey* dh_priv = dynamic_cast<const DH_PrivateKey*>(priv_key); - const RSA_PrivateKey* rsa_priv = - dynamic_cast<const RSA_PrivateKey*>(priv_key); - if(dh_priv) + if(const DH_PrivateKey* dh_priv = dynamic_cast<const DH_PrivateKey*>(priv_key)) { try { - pre_master = dh_priv->derive_key(key_material, key_material.size()); + PK_Key_Agreement ka(*dh_priv, "Raw"); + + pre_master = ka.derive_key(0, key_material).bits_of(); } - catch(std::exception& e) + catch(...) { pre_master.resize(dh_priv->public_value().size()); rng.randomize(pre_master, pre_master.size()); @@ -137,19 +136,18 @@ Client_Key_Exchange::pre_master_secret(RandomNumberGenerator& rng, return pre_master; } - else if(rsa_priv) + else if(const RSA_PrivateKey* rsa_priv = dynamic_cast<const RSA_PrivateKey*>(priv_key)) { - std::auto_ptr<PK_Decryptor> decryptor(get_pk_decryptor(*rsa_priv, - "PKCS1v15")); + PK_Decryptor_EME decryptor(*rsa_priv, "PKCS1v15"); try { - pre_master = decryptor->decrypt(key_material); + 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(std::exception) + catch(...) { pre_master.resize(48); rng.randomize(pre_master, pre_master.size()); diff --git a/src/ssl/cert_ver.cpp b/src/ssl/cert_ver.cpp index 5ac28dd2e..7e17dbfab 100644 --- a/src/ssl/cert_ver.cpp +++ b/src/ssl/cert_ver.cpp @@ -1,12 +1,12 @@ /** -* Certificate Verify Message -* (C) 2004-2006 Jack Lloyd +* Certificate Verify Message +* (C) 2004-2010 Jack Lloyd * * Released under the terms of the Botan license */ #include <botan/tls_messages.h> -#include <botan/look_pk.h> +#include <botan/pubkey.h> #include <botan/rsa.h> #include <botan/dsa.h> #include <botan/loadstor.h> @@ -22,32 +22,24 @@ Certificate_Verify::Certificate_Verify(RandomNumberGenerator& rng, HandshakeHash& hash, const Private_Key* priv_key) { - const PK_Signing_Key* sign_key = - dynamic_cast<const PK_Signing_Key*>(priv_key); + std::string padding = ""; + Signature_Format format = IEEE_1363; - if(sign_key) + if(priv_key->algo_name() == "RSA") + padding = "EMSA3(TLS.Digest.0)"; + else if(priv_key->algo_name() == "DSA") { - PK_Signer* signer = 0; - try - { - if(dynamic_cast<const RSA_PrivateKey*>(sign_key)) - signer = get_pk_signer(*sign_key, "EMSA3(TLS.Digest.0)"); - else if(dynamic_cast<const DSA_PrivateKey*>(sign_key)) - signer = get_pk_signer(*sign_key, "EMSA1(SHA-1)"); - else - throw Invalid_Argument("Unknown PK algo for TLS signature"); - - signature = signer->sign_message(hash.final(), rng); - delete signer; - } - catch(...) - { - delete signer; - throw; - } - - send(writer, hash); + 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); } /** @@ -90,20 +82,22 @@ bool Certificate_Verify::verify(const X509_Certificate& cert, std::auto_ptr<Public_Key> key(cert.subject_public_key()); - DSA_PublicKey* dsa_pub = dynamic_cast<DSA_PublicKey*>(key.get()); - RSA_PublicKey* rsa_pub = dynamic_cast<RSA_PublicKey*>(key.get()); + std::string padding = ""; + Signature_Format format = IEEE_1363; - std::auto_ptr<PK_Verifier> verifier; - - if(dsa_pub) - verifier.reset(get_pk_verifier(*dsa_pub, "EMSA1(SHA-1)", DER_SEQUENCE)); - else if(rsa_pub) - verifier.reset(get_pk_verifier(*rsa_pub, "EMSA3(TLS.Digest.0)")); + 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("Client did not provide a RSA/DSA cert"); + throw Invalid_Argument(key->algo_name() + + " is invalid/unknown for TLS signatures"); - // FIXME: WRONG - return verifier->verify_message(hash.final(), signature); + PK_Verifier verifier(*key, padding, format); + return verifier.verify_message(hash.final(), signature); } } diff --git a/src/ssl/s_kex.cpp b/src/ssl/s_kex.cpp index fd49fcb8c..94b17cb7e 100644 --- a/src/ssl/s_kex.cpp +++ b/src/ssl/s_kex.cpp @@ -6,10 +6,10 @@ */ #include <botan/tls_messages.h> +#include <botan/pubkey.h> #include <botan/dh.h> #include <botan/rsa.h> #include <botan/dsa.h> -#include <botan/look_pk.h> #include <botan/loadstor.h> #include <memory> @@ -43,38 +43,27 @@ Server_Key_Exchange::Server_Key_Exchange(RandomNumberGenerator& rng, else throw Invalid_Argument("Bad key for TLS key exchange: not DH or RSA"); - // FIXME: dup of stuff in cert_ver.cpp - // FIXME: it's OK for the server to be anonymous.... - const PK_Signing_Key* sign_key = - dynamic_cast<const PK_Signing_Key*>(priv_key); - - if(!sign_key) - throw Invalid_Argument("Server Kex: Private key not for signing"); - - PK_Signer* signer = 0; - try { - if(dynamic_cast<const RSA_PrivateKey*>(sign_key)) - signer = get_pk_signer(*sign_key, "EMSA3(TLS.Digest.0)"); - else if(dynamic_cast<const DSA_PrivateKey*>(sign_key)) - { - signer = get_pk_signer(*sign_key, "EMSA1(SHA-1)"); - signer->set_output_format(DER_SEQUENCE); - } - else - throw Invalid_Argument("Bad key for TLS signature: not RSA or DSA"); - - signer->update(c_random); - signer->update(s_random); - signer->update(serialize_params()); - signature = signer->signature(rng); - - delete signer; - } - catch(...) + + 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") { - delete signer; - throw; + 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); } @@ -167,29 +156,31 @@ 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()); - DSA_PublicKey* dsa_pub = dynamic_cast<DSA_PublicKey*>(key.get()); - RSA_PublicKey* rsa_pub = dynamic_cast<RSA_PublicKey*>(key.get()); + std::auto_ptr<Public_Key> key(cert.subject_public_key()); - std::auto_ptr<PK_Verifier> verifier; + std::string padding = ""; + Signature_Format format = IEEE_1363; - if(dsa_pub) + if(key->algo_name() == "RSA") + padding = "EMSA3(TLS.Digest.0)"; + else if(key->algo_name() == "DSA") { - verifier.reset(get_pk_verifier(*dsa_pub, "EMSA1(SHA-1)", DER_SEQUENCE)); - verifier->set_input_format(DER_SEQUENCE); + padding == "EMSA1(SHA-1)"; + format = DER_SEQUENCE; } - else if(rsa_pub) - verifier.reset(get_pk_verifier(*rsa_pub, "EMSA3(TLS.Digest.0)")); else - throw Invalid_Argument("Server did not provide a RSA/DSA cert"); + 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); + verifier.update(c_random); + verifier.update(s_random); + verifier.update(params_got); - return verifier->check_signature(signature, signature.size()); + return verifier.check_signature(signature, signature.size()); } } diff --git a/src/stream/salsa20/salsa20.cpp b/src/stream/salsa20/salsa20.cpp index 1b97f4421..a38e6e305 100644 --- a/src/stream/salsa20/salsa20.cpp +++ b/src/stream/salsa20/salsa20.cpp @@ -1,6 +1,6 @@ /* -* Salsa20 -* (C) 1999-2008 Jack Lloyd +* Salsa20 / XSalsa20 +* (C) 1999-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -14,63 +14,68 @@ namespace Botan { namespace { +#define SALSA20_QUARTER_ROUND(x1, x2, x3, x4) \ + do { \ + x2 ^= rotate_left(x1 + x4, 7); \ + x3 ^= rotate_left(x2 + x1, 9); \ + x4 ^= rotate_left(x3 + x2, 13); \ + x1 ^= rotate_left(x4 + x3, 18); \ + } while(0) + +/* +* Generate HSalsa20 cipher stream (for XSalsa20 IV setup) +*/ +void hsalsa20(u32bit output[8], const u32bit input[16]) + { + u32bit x00 = input[ 0], x01 = input[ 1], x02 = input[ 2], x03 = input[ 3], + x04 = input[ 4], x05 = input[ 5], x06 = input[ 6], x07 = input[ 7], + x08 = input[ 8], x09 = input[ 9], x10 = input[10], x11 = input[11], + x12 = input[12], x13 = input[13], x14 = input[14], x15 = input[15]; + + for(u32bit i = 0; i != 10; ++i) + { + SALSA20_QUARTER_ROUND(x00, x04, x08, x12); + SALSA20_QUARTER_ROUND(x05, x09, x13, x01); + SALSA20_QUARTER_ROUND(x10, x14, x02, x06); + SALSA20_QUARTER_ROUND(x15, x03, x07, x11); + + SALSA20_QUARTER_ROUND(x00, x01, x02, x03); + SALSA20_QUARTER_ROUND(x05, x06, x07, x04); + SALSA20_QUARTER_ROUND(x10, x11, x08, x09); + SALSA20_QUARTER_ROUND(x15, x12, x13, x14); + } + + output[0] = x00; + output[1] = x05; + output[2] = x10; + output[3] = x15; + output[4] = x06; + output[5] = x07; + output[6] = x08; + output[7] = x09; + } + /* * Generate Salsa20 cipher stream */ void salsa20(byte output[64], const u32bit input[16]) { - u32bit x00 = input[0]; - u32bit x01 = input[1]; - u32bit x02 = input[2]; - u32bit x03 = input[3]; - u32bit x04 = input[4]; - u32bit x05 = input[5]; - u32bit x06 = input[6]; - u32bit x07 = input[7]; - u32bit x08 = input[8]; - u32bit x09 = input[9]; - u32bit x10 = input[10]; - u32bit x11 = input[11]; - u32bit x12 = input[12]; - u32bit x13 = input[13]; - u32bit x14 = input[14]; - u32bit x15 = input[15]; + u32bit x00 = input[ 0], x01 = input[ 1], x02 = input[ 2], x03 = input[ 3], + x04 = input[ 4], x05 = input[ 5], x06 = input[ 6], x07 = input[ 7], + x08 = input[ 8], x09 = input[ 9], x10 = input[10], x11 = input[11], + x12 = input[12], x13 = input[13], x14 = input[14], x15 = input[15]; for(u32bit i = 0; i != 10; ++i) { - x04 ^= rotate_left(x00 + x12, 7); - x08 ^= rotate_left(x04 + x00, 9); - x12 ^= rotate_left(x08 + x04, 13); - x00 ^= rotate_left(x12 + x08, 18); - x09 ^= rotate_left(x05 + x01, 7); - x13 ^= rotate_left(x09 + x05, 9); - x01 ^= rotate_left(x13 + x09, 13); - x05 ^= rotate_left(x01 + x13, 18); - x14 ^= rotate_left(x10 + x06, 7); - x02 ^= rotate_left(x14 + x10, 9); - x06 ^= rotate_left(x02 + x14, 13); - x10 ^= rotate_left(x06 + x02, 18); - x03 ^= rotate_left(x15 + x11, 7); - x07 ^= rotate_left(x03 + x15, 9); - x11 ^= rotate_left(x07 + x03, 13); - x15 ^= rotate_left(x11 + x07, 18); - - x01 ^= rotate_left(x00 + x03, 7); - x02 ^= rotate_left(x01 + x00, 9); - x03 ^= rotate_left(x02 + x01, 13); - x00 ^= rotate_left(x03 + x02, 18); - x06 ^= rotate_left(x05 + x04, 7); - x07 ^= rotate_left(x06 + x05, 9); - x04 ^= rotate_left(x07 + x06, 13); - x05 ^= rotate_left(x04 + x07, 18); - x11 ^= rotate_left(x10 + x09, 7); - x08 ^= rotate_left(x11 + x10, 9); - x09 ^= rotate_left(x08 + x11, 13); - x10 ^= rotate_left(x09 + x08, 18); - x12 ^= rotate_left(x15 + x14, 7); - x13 ^= rotate_left(x12 + x15, 9); - x14 ^= rotate_left(x13 + x12, 13); - x15 ^= rotate_left(x14 + x13, 18); + SALSA20_QUARTER_ROUND(x00, x04, x08, x12); + SALSA20_QUARTER_ROUND(x05, x09, x13, x01); + SALSA20_QUARTER_ROUND(x10, x14, x02, x06); + SALSA20_QUARTER_ROUND(x15, x03, x07, x11); + + SALSA20_QUARTER_ROUND(x00, x01, x02, x03); + SALSA20_QUARTER_ROUND(x05, x06, x07, x04); + SALSA20_QUARTER_ROUND(x10, x11, x08, x09); + SALSA20_QUARTER_ROUND(x15, x12, x13, x14); } store_le(x00 + input[ 0], output + 4 * 0); @@ -100,11 +105,11 @@ void Salsa20::cipher(const byte in[], byte out[], u32bit length) { while(length >= buffer.size() - position) { - xor_buf(out, in, buffer.begin() + position, buffer.size() - position); + xor_buf(out, in, &buffer[position], buffer.size() - position); length -= (buffer.size() - position); in += (buffer.size() - position); out += (buffer.size() - position); - salsa20(buffer.begin(), state); + salsa20(&buffer[0], state); ++state[8]; if(!state[8]) // if overflow in state[8] @@ -113,7 +118,7 @@ void Salsa20::cipher(const byte in[], byte out[], u32bit length) position = 0; } - xor_buf(out, in, buffer.begin() + position, length); + xor_buf(out, in, &buffer[position], length); position += length; } @@ -174,12 +179,39 @@ void Salsa20::set_iv(const byte iv[], u32bit length) if(!valid_iv_length(length)) throw Invalid_IV_Length(name(), length); - state[6] = load_le<u32bit>(iv, 0); - state[7] = load_le<u32bit>(iv, 1); + if(length == 8) + { + // Salsa20 + state[6] = load_le<u32bit>(iv, 0); + state[7] = load_le<u32bit>(iv, 1); + } + else + { + // XSalsa20 + state[6] = load_le<u32bit>(iv, 0); + state[7] = load_le<u32bit>(iv, 1); + state[8] = load_le<u32bit>(iv, 2); + state[9] = load_le<u32bit>(iv, 3); + + SecureVector<u32bit> hsalsa(8); + hsalsa20(hsalsa, state); + + state[ 1] = hsalsa[0]; + state[ 2] = hsalsa[1]; + state[ 3] = hsalsa[2]; + state[ 4] = hsalsa[3]; + state[ 6] = load_le<u32bit>(iv, 4); + state[ 7] = load_le<u32bit>(iv, 5); + state[11] = hsalsa[4]; + state[12] = hsalsa[5]; + state[13] = hsalsa[6]; + state[14] = hsalsa[7]; + } + state[8] = 0; state[9] = 0; - salsa20(buffer.begin(), state); + salsa20(&buffer[0], state); ++state[8]; if(!state[8]) // if overflow in state[8] ++state[9]; // carry to state[9] @@ -205,12 +237,4 @@ void Salsa20::clear() position = 0; } -/* -* Salsa20 Constructor -*/ -Salsa20::Salsa20() : StreamCipher(16, 32, 16) - { - clear(); - } - } diff --git a/src/stream/salsa20/salsa20.h b/src/stream/salsa20/salsa20.h index 3ca781ea2..af7ddd145 100644 --- a/src/stream/salsa20/salsa20.h +++ b/src/stream/salsa20/salsa20.h @@ -1,6 +1,6 @@ /* -* Salsa20 -* (C) 1999-2008 Jack Lloyd +* Salsa20 / XSalsa20 +* (C) 1999-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -13,7 +13,7 @@ namespace Botan { /* -* Salsa20 +* Salsa20 (and XSalsa20) */ class BOTAN_DLL Salsa20 : public StreamCipher { @@ -23,19 +23,18 @@ class BOTAN_DLL Salsa20 : public StreamCipher void set_iv(const byte iv[], u32bit iv_len); bool valid_iv_length(u32bit iv_len) const - { return (iv_len == 8); } + { return (iv_len == 8 || iv_len == 24); } void clear(); std::string name() const; StreamCipher* clone() const { return new Salsa20; } - Salsa20(); + Salsa20() : StreamCipher(16, 32, 16) { position = 0; } ~Salsa20() { clear(); } private: void key_schedule(const byte key[], u32bit key_len); SecureBuffer<u32bit, 16> state; - SecureBuffer<byte, 64> buffer; u32bit position; }; diff --git a/src/utils/exceptn.h b/src/utils/exceptn.h index 39b18cb0b..2ac88aaf6 100644 --- a/src/utils/exceptn.h +++ b/src/utils/exceptn.h @@ -142,6 +142,15 @@ struct BOTAN_DLL Decoding_Error : public Invalid_Argument }; /* +* Integrity_Failure Exception +*/ +struct BOTAN_DLL Integrity_Failure : public Exception + { + Integrity_Failure(const std::string& what) : + Exception("Integrity failure: " + what) {} + }; + +/* * Invalid_OID Exception */ struct BOTAN_DLL Invalid_OID : public Decoding_Error diff --git a/src/utils/simd_32/simd_32.h b/src/utils/simd_32/simd_32.h index 4bd983f5e..23dce0305 100644 --- a/src/utils/simd_32/simd_32.h +++ b/src/utils/simd_32/simd_32.h @@ -29,16 +29,16 @@ namespace Botan { -inline SIMD_32 rotate_left(SIMD_32 x, u32bit rot) +inline SIMD_32 rotate_left(const SIMD_32& x, u32bit rot) { - x.rotate_left(rot); - return x; + SIMD_32 y = x; + y.rotate_left(rot); + return y; } -inline SIMD_32 rotate_right(SIMD_32 x, u32bit rot) +inline SIMD_32 rotate_right(const SIMD_32& x, u32bit rot) { - x.rotate_right(rot); - return x; + return rotate_left(x, 32 - rot); } } diff --git a/src/utils/time.cpp b/src/utils/time.cpp index 77ad0eec5..bc9aa8a2f 100644 --- a/src/utils/time.cpp +++ b/src/utils/time.cpp @@ -1,6 +1,6 @@ /** * Time Functions -* (C) 1999-2009 Jack Lloyd +* (C) 1999-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -86,11 +86,13 @@ calendar_point calendar_value( 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); @@ -106,7 +108,9 @@ u64bit get_nanoseconds_clock() return (tstamp * 100); // Scale to 1 nanosecond units #else - return combine_timers(std::time(0), std::clock(), CLOCKS_PER_SEC); + + return combine_timers(static_cast<u32bit>(std::time(0)), + std::clock(), CLOCKS_PER_SEC); #endif } diff --git a/src/wrap/python/core.cpp b/src/wrap/python/core.cpp index fe26e16ee..b1be3b71f 100644 --- a/src/wrap/python/core.cpp +++ b/src/wrap/python/core.cpp @@ -166,10 +166,25 @@ std::string python_pbkdf2(const std::string& passphrase, { PKCS5_PBKDF2 pbkdf2(new HMAC(get_hash(hash_fn))); - pbkdf2.set_iterations(iterations); - pbkdf2.change_salt(reinterpret_cast<const byte*>(salt.data()), salt.size()); + return make_string( + pbkdf2.derive_key(output_size, + passphrase, + reinterpret_cast<const byte*>(salt.data()), + salt.size(), + iterations).bits_of()); + } + +std::string python_kdf2(const std::string& param, + const std::string& masterkey, + u32bit outputlength) + { + std::auto_ptr<KDF> kdf(get_kdf("KDF2(SHA-1)")); - return make_string(pbkdf2.derive_key(output_size, passphrase).bits_of()); + return make_string( + kdf->derive_key(outputlength, + reinterpret_cast<const byte*>(masterkey.data()), + masterkey.length(), + param)); } BOOST_PYTHON_MODULE(_botan) @@ -209,6 +224,7 @@ BOOST_PYTHON_MODULE(_botan) python::def("cryptobox_encrypt", cryptobox_encrypt); python::def("cryptobox_decrypt", cryptobox_decrypt); python::def("pbkdf2", python_pbkdf2); + python::def("derive_key", python_kdf2); export_filters(); export_rsa(); |