aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--checks/check.cpp8
-rw-r--r--checks/common.h3
-rw-r--r--checks/cvc_tests.cpp19
-rw-r--r--checks/dolook.cpp21
-rw-r--r--checks/ec_tests.cpp82
-rw-r--r--checks/ecdh.cpp130
-rw-r--r--checks/ecdsa.cpp254
-rw-r--r--checks/eckaeg.cpp286
-rw-r--r--checks/pk.cpp301
-rw-r--r--checks/pk_bench.cpp149
-rw-r--r--checks/pk_valid.dat58
-rw-r--r--checks/validate.cpp22
-rw-r--r--checks/validate.dat82
-rw-r--r--checks/validate.h2
-rw-r--r--checks/x509.cpp8
-rwxr-xr-xconfigure.py2
-rw-r--r--doc/examples/bench.cpp2
-rw-r--r--doc/examples/cpuid.cpp4
-rw-r--r--doc/examples/dh.cpp43
-rw-r--r--doc/examples/dsa_sign.cpp4
-rw-r--r--doc/examples/dsa_ver.cpp12
-rw-r--r--doc/examples/eax_test.cpp8
-rw-r--r--doc/examples/ecdsa.cpp16
-rw-r--r--doc/examples/factor.cpp11
-rw-r--r--doc/examples/fpe.cpp4
-rw-r--r--doc/examples/gen_certs.cpp2
-rw-r--r--doc/examples/hash_quickly.cpp24
-rw-r--r--doc/examples/package.cpp5
-rw-r--r--doc/examples/pqg_gen.cpp1
-rw-r--r--doc/examples/read_ssh.cpp4
-rw-r--r--doc/examples/ressol.cpp86
-rw-r--r--doc/examples/rng_test.cpp32
-rw-r--r--doc/examples/rsa_dec.cpp10
-rw-r--r--doc/examples/rsa_enc.cpp9
-rw-r--r--doc/examples/sig_gen.cpp6
-rw-r--r--doc/examples/tls_client.cpp2
-rw-r--r--doc/examples/x509info.cpp4
-rw-r--r--doc/log.txt6
-rwxr-xr-xdoc/python/cryptobox.py6
-rwxr-xr-xdoc/python/rsa.py5
-rwxr-xr-xdoc/scripts/configure.pl2340
-rw-r--r--doc/tutorial.tex4
-rw-r--r--src/asn1/asn1_oid.cpp10
-rw-r--r--src/build-data/buildh.in1
-rw-r--r--src/build-data/cc/gcc.txt2
-rw-r--r--src/build-data/cc/msvc.txt2
-rw-r--r--src/build-data/makefile/nmake.in8
-rw-r--r--src/build-data/makefile/python.in8
-rw-r--r--src/cert/cvc/cvc_ado.cpp10
-rw-r--r--src/cert/cvc/cvc_ado.h5
-rw-r--r--src/cert/cvc/cvc_ca.cpp44
-rw-r--r--src/cert/cvc/cvc_ca.h51
-rw-r--r--src/cert/cvc/cvc_cert.cpp65
-rw-r--r--src/cert/cvc/cvc_cert.h37
-rw-r--r--src/cert/cvc/cvc_gen_cert.h27
-rw-r--r--src/cert/cvc/cvc_key.h53
-rw-r--r--src/cert/cvc/cvc_req.cpp18
-rw-r--r--src/cert/cvc/cvc_req.h5
-rw-r--r--src/cert/cvc/cvc_self.cpp194
-rw-r--r--src/cert/cvc/eac_asn_obj.h5
-rw-r--r--src/cert/cvc/eac_obj.h112
-rw-r--r--src/cert/cvc/ecdsa_sig.cpp50
-rw-r--r--src/cert/cvc/ecdsa_sig.h62
-rw-r--r--src/cert/cvc/info.txt4
-rw-r--r--src/cert/cvc/signed_obj.cpp41
-rw-r--r--src/cert/cvc/signed_obj.h3
-rw-r--r--src/cert/x509/info.txt1
-rw-r--r--src/cert/x509/x509_ca.cpp18
-rw-r--r--src/cert/x509/x509_obj.cpp21
-rw-r--r--src/cert/x509/x509self.cpp5
-rw-r--r--src/cert/x509/x509stor.cpp22
-rw-r--r--src/cms/cms_dalg.cpp1
-rw-r--r--src/cms/cms_ealg.cpp30
-rw-r--r--src/cms/cms_enc.h2
-rw-r--r--src/cms/info.txt2
-rw-r--r--src/engine/def_engine/def_pk_ops.cpp179
-rw-r--r--src/engine/def_engine/default_engine.h28
-rw-r--r--src/engine/engine.h76
-rw-r--r--src/engine/gnump/gmp_dh.cpp53
-rw-r--r--src/engine/gnump/gmp_dsa.cpp124
-rw-r--r--src/engine/gnump/gmp_elg.cpp92
-rw-r--r--src/engine/gnump/gmp_if.cpp81
-rw-r--r--src/engine/gnump/gmp_nr.cpp107
-rw-r--r--src/engine/gnump/gmp_wrap.h3
-rw-r--r--src/engine/gnump/gnump_engine.h26
-rw-r--r--src/engine/gnump/gnump_pk.cpp350
-rw-r--r--src/engine/gnump/info.txt6
-rw-r--r--src/engine/info.txt1
-rw-r--r--src/engine/openssl/bn_wrap.h3
-rw-r--r--src/engine/openssl/info.txt6
-rw-r--r--src/engine/openssl/openssl_engine.h26
-rw-r--r--src/engine/openssl/openssl_pk.cpp345
-rw-r--r--src/engine/openssl/ossl_dh.cpp60
-rw-r--r--src/engine/openssl/ossl_dsa.cpp126
-rw-r--r--src/engine/openssl/ossl_elg.cpp95
-rw-r--r--src/engine/openssl/ossl_if.cpp85
-rw-r--r--src/engine/openssl/ossl_nr.cpp113
-rw-r--r--src/hash/gost_3411/gost_3411.cpp18
-rw-r--r--src/libstate/info.txt6
-rw-r--r--src/libstate/look_pk.cpp76
-rw-r--r--src/libstate/look_pk.h66
-rw-r--r--src/libstate/oid_lookup/oids.cpp2
-rw-r--r--src/libstate/pk_engine.cpp133
-rw-r--r--src/libstate/pk_engine.h73
-rw-r--r--src/libstate/policy.cpp130
-rw-r--r--src/math/numbertheory/blinding.cpp49
-rw-r--r--src/math/numbertheory/blinding.h34
-rw-r--r--src/math/numbertheory/info.txt2
-rw-r--r--src/math/numbertheory/make_prm.cpp3
-rw-r--r--src/math/numbertheory/point_gfp.cpp29
-rw-r--r--src/math/numbertheory/point_gfp.h7
-rw-r--r--src/math/numbertheory/pow_mod.cpp53
-rw-r--r--src/math/numbertheory/pow_mod.h7
-rw-r--r--src/math/numbertheory/powm_fw.cpp40
-rw-r--r--src/math/numbertheory/powm_mnt.cpp34
-rw-r--r--src/math/numbertheory/reducer.h2
-rw-r--r--src/pubkey/blinding.cpp76
-rw-r--r--src/pubkey/blinding.h53
-rw-r--r--src/pubkey/dh/dh.cpp69
-rw-r--r--src/pubkey/dh/dh.h49
-rw-r--r--src/pubkey/dh/dh_core.cpp65
-rw-r--r--src/pubkey/dh/dh_core.h38
-rw-r--r--src/pubkey/dh/dh_op.h45
-rw-r--r--src/pubkey/dh/info.txt3
-rw-r--r--src/pubkey/dl_algo/dl_algo.cpp128
-rw-r--r--src/pubkey/dl_algo/dl_algo.h41
-rw-r--r--src/pubkey/dl_algo/info.txt1
-rw-r--r--src/pubkey/dlies/dlies.cpp44
-rw-r--r--src/pubkey/dlies/dlies.h7
-rw-r--r--src/pubkey/dsa/dsa.cpp143
-rw-r--r--src/pubkey/dsa/dsa.h79
-rw-r--r--src/pubkey/dsa/dsa_core.cpp63
-rw-r--r--src/pubkey/dsa/dsa_core.h37
-rw-r--r--src/pubkey/dsa/dsa_op.cpp85
-rw-r--r--src/pubkey/dsa/dsa_op.h59
-rw-r--r--src/pubkey/dsa/info.txt12
-rw-r--r--src/pubkey/ec_dompar/ec_dompar.cpp4
-rw-r--r--src/pubkey/ecc_key/ecc_key.cpp179
-rw-r--r--src/pubkey/ecc_key/ecc_key.h58
-rw-r--r--src/pubkey/ecc_key/info.txt1
-rw-r--r--src/pubkey/ecdh/ecdh.cpp36
-rw-r--r--src/pubkey/ecdh/ecdh.h50
-rw-r--r--src/pubkey/ecdsa/ecdsa.cpp81
-rw-r--r--src/pubkey/ecdsa/ecdsa.h97
-rw-r--r--src/pubkey/elgamal/elg_core.cpp93
-rw-r--r--src/pubkey/elgamal/elg_core.h44
-rw-r--r--src/pubkey/elgamal/elg_op.cpp58
-rw-r--r--src/pubkey/elgamal/elg_op.h52
-rw-r--r--src/pubkey/elgamal/elgamal.cpp132
-rw-r--r--src/pubkey/elgamal/elgamal.h66
-rw-r--r--src/pubkey/gost_3410/gost_3410.cpp196
-rw-r--r--src/pubkey/gost_3410/gost_3410.h118
-rw-r--r--src/pubkey/if_algo/if_algo.cpp229
-rw-r--r--src/pubkey/if_algo/if_algo.h40
-rw-r--r--src/pubkey/if_algo/if_core.cpp83
-rw-r--r--src/pubkey/if_algo/if_core.h45
-rw-r--r--src/pubkey/if_algo/if_op.cpp50
-rw-r--r--src/pubkey/if_algo/if_op.h52
-rw-r--r--src/pubkey/if_algo/info.txt13
-rw-r--r--src/pubkey/info.txt11
-rw-r--r--src/pubkey/keypair/keypair.cpp30
-rw-r--r--src/pubkey/keypair/keypair.h8
-rw-r--r--src/pubkey/nr/nr.cpp148
-rw-r--r--src/pubkey/nr/nr.h77
-rw-r--r--src/pubkey/nr/nr_core.cpp62
-rw-r--r--src/pubkey/nr/nr_core.h37
-rw-r--r--src/pubkey/nr/nr_op.cpp75
-rw-r--r--src/pubkey/nr/nr_op.h53
-rw-r--r--src/pubkey/pk_algs.cpp88
-rw-r--r--src/pubkey/pk_algs.h19
-rw-r--r--src/pubkey/pk_codecs/info.txt7
-rw-r--r--src/pubkey/pk_keys.h84
-rw-r--r--src/pubkey/pk_ops.h151
-rw-r--r--src/pubkey/pkcs8.cpp (renamed from src/pubkey/pk_codecs/pkcs8.cpp)26
-rw-r--r--src/pubkey/pkcs8.h (renamed from src/pubkey/pk_codecs/pkcs8.h)43
-rw-r--r--src/pubkey/pubkey.cpp338
-rw-r--r--src/pubkey/pubkey.h265
-rw-r--r--src/pubkey/rsa/rsa.cpp167
-rw-r--r--src/pubkey/rsa/rsa.h110
-rw-r--r--src/pubkey/rw/rw.cpp159
-rw-r--r--src/pubkey/rw/rw.h72
-rw-r--r--src/pubkey/x509_key.cpp (renamed from src/pubkey/pk_codecs/x509_key.cpp)44
-rw-r--r--src/pubkey/x509_key.h (renamed from src/pubkey/pk_codecs/x509_key.h)26
-rw-r--r--src/ssl/c_kex.cpp44
-rw-r--r--src/ssl/cert_ver.cpp68
-rw-r--r--src/ssl/s_kex.cpp81
-rw-r--r--src/stream/salsa20/salsa20.cpp154
-rw-r--r--src/stream/salsa20/salsa20.h11
-rw-r--r--src/utils/exceptn.h9
-rw-r--r--src/utils/simd_32/simd_32.h12
-rw-r--r--src/utils/time.cpp8
-rw-r--r--src/wrap/python/core.cpp22
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 *
-* 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();