aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/algo_factory/algo_factory.cpp3
-rw-r--r--src/algo_factory/algo_factory.h77
-rw-r--r--src/algo_factory/prov_weight.cpp10
-rw-r--r--src/alloc/mem_pool/mem_pool.cpp13
-rw-r--r--src/alloc/system_alloc/defalloc.cpp2
-rw-r--r--src/asn1/ber_dec.cpp2
-rw-r--r--src/asn1/der_enc.cpp4
-rw-r--r--src/block/block_cipher.h13
-rw-r--r--src/block/cascade/cascade.cpp98
-rw-r--r--src/block/cascade/cascade.h41
-rw-r--r--src/block/cascade/info.txt9
-rw-r--r--src/block/idea_sse2/idea_sse2.cpp1
-rw-r--r--src/block/lion/lion.cpp3
-rw-r--r--src/block/noekeon/noekeon.h2
-rw-r--r--src/block/noekeon_simd/info.txt7
-rw-r--r--src/block/noekeon_simd/noekeon_simd.cpp161
-rw-r--r--src/block/noekeon_simd/noekeon_simd.h29
-rw-r--r--src/build-data/arch/amd64.txt2
-rw-r--r--src/build-data/arch/ia32.txt2
-rw-r--r--src/build-data/arch/ppc.txt2
-rw-r--r--src/build-data/arch/ppc64.txt2
-rw-r--r--src/build-data/arch/sparc32.txt2
-rw-r--r--src/build-data/arch/sparc64.txt3
-rw-r--r--src/build-data/buildh.in8
-rw-r--r--src/build-data/makefile/nmake.in2
-rw-r--r--src/build-data/makefile/unix.in4
-rw-r--r--src/build-data/makefile/unix_shr.in4
-rw-r--r--src/cert/cvc/asn1_eac_tm.cpp4
-rw-r--r--src/cert/cvc/cvc_ado.cpp43
-rw-r--r--src/cert/cvc/cvc_ado.h4
-rw-r--r--src/cert/cvc/cvc_ca.cpp3
-rw-r--r--src/cert/cvc/cvc_cert.cpp6
-rw-r--r--src/cert/cvc/cvc_cert.h2
-rw-r--r--src/cert/cvc/cvc_gen_cert.h9
-rw-r--r--src/cert/cvc/cvc_req.cpp15
-rw-r--r--src/cert/cvc/cvc_req.h2
-rw-r--r--src/cert/cvc/cvc_self.cpp18
-rw-r--r--src/cert/cvc/eac_obj.h10
-rw-r--r--src/cert/cvc/freestore.h84
-rw-r--r--src/cert/cvc/info.txt3
-rw-r--r--src/cert/x509/x509_ext.cpp2
-rw-r--r--src/checksum/crc24/crc24.cpp2
-rw-r--r--src/cms/cms_dalg.cpp6
-rw-r--r--src/cms/cms_dec.cpp4
-rw-r--r--src/cms/cms_dec.h6
-rw-r--r--src/cms/cms_ealg.cpp18
-rw-r--r--src/cms/cms_enc.h4
-rw-r--r--src/constructs/aont/package.cpp2
-rw-r--r--src/constructs/cryptobox/cryptobox.cpp16
-rw-r--r--src/constructs/fpe/fpe.cpp2
-rw-r--r--src/constructs/passhash/info.txt9
-rw-r--r--src/constructs/passhash/passhash9.cpp127
-rw-r--r--src/constructs/passhash/passhash9.h35
-rw-r--r--src/engine/aes_isa_eng/aes_isa_engine.cpp18
-rw-r--r--src/engine/def_engine/lookup_block.cpp15
-rw-r--r--src/engine/gnump/gmp_mem.cpp22
-rw-r--r--src/engine/gnump/gnump_engine.h7
-rw-r--r--src/engine/simd_engine/simd_engine.cpp9
-rw-r--r--src/entropy/hres_timer/hres_timer.cpp4
-rw-r--r--src/filters/buf_filt.cpp114
-rw-r--r--src/filters/buf_filt.h40
-rw-r--r--src/filters/bzip2/bzip2.cpp16
-rw-r--r--src/filters/filter.cpp2
-rw-r--r--src/filters/info.txt2
-rw-r--r--src/filters/modes/cbc/cbc.cpp145
-rw-r--r--src/filters/modes/cbc/cbc.h25
-rw-r--r--src/filters/modes/cfb/cfb.h4
-rw-r--r--src/filters/modes/cts/cts.cpp3
-rw-r--r--src/filters/modes/cts/cts.h4
-rw-r--r--src/filters/modes/eax/eax_dec.cpp4
-rw-r--r--src/filters/modes/ecb/ecb.cpp184
-rw-r--r--src/filters/modes/ecb/ecb.h23
-rw-r--r--src/filters/modes/xts/xts.cpp331
-rw-r--r--src/filters/modes/xts/xts.h23
-rw-r--r--src/filters/out_buf.cpp2
-rw-r--r--src/filters/pipe.cpp12
-rw-r--r--src/filters/pipe.h8
-rw-r--r--src/filters/pipe_rw.cpp4
-rw-r--r--src/filters/pk_filts/pk_filts.cpp2
-rw-r--r--src/filters/secqueue.cpp2
-rw-r--r--src/filters/secqueue.h2
-rw-r--r--src/filters/zlib/zlib.cpp15
-rw-r--r--src/hash/md4/md4.h2
-rw-r--r--src/hash/md4_ia32/md4_ia32.cpp1
-rw-r--r--src/hash/md5_ia32/md5_ia32.cpp1
-rw-r--r--src/hash/sha1/sha160.cpp4
-rw-r--r--src/hash/sha1_ia32/sha1_ia32.cpp1
-rw-r--r--src/hash/tiger/tiger.cpp30
-rw-r--r--src/hash/tiger/tiger.h1
-rw-r--r--src/kdf/kdf2/kdf2.cpp2
-rw-r--r--src/kdf/mgf1/mgf1.cpp2
-rw-r--r--src/libstate/libstate.cpp3
-rw-r--r--src/libstate/libstate.h51
-rw-r--r--src/libstate/lookup.cpp179
-rw-r--r--src/libstate/lookup.h131
-rw-r--r--src/libstate/policy.cpp9
-rw-r--r--src/libstate/scan_name.cpp17
-rw-r--r--src/libstate/scan_name.h4
-rw-r--r--src/math/bigint/bigint.cpp2
-rw-r--r--src/math/gfpmath/curve_gfp.cpp147
-rw-r--r--src/math/gfpmath/curve_gfp.h63
-rw-r--r--src/math/gfpmath/gfp_element.cpp248
-rw-r--r--src/math/gfpmath/gfp_element.h106
-rw-r--r--src/math/gfpmath/gfp_modulus.h46
-rw-r--r--src/math/gfpmath/info.txt2
-rw-r--r--src/math/gfpmath/point_gfp.cpp707
-rw-r--r--src/math/gfpmath/point_gfp.h90
-rw-r--r--src/math/numbertheory/powm_mnt.cpp7
-rw-r--r--src/mutex/pthreads/mux_pthr.cpp6
-rw-r--r--src/pbe/pbes1/pbes1.cpp6
-rw-r--r--src/pbe/pbes2/pbes2.cpp6
-rw-r--r--src/pk_pad/eme1/eme1.cpp2
-rw-r--r--src/pubkey/dl_group/dl_group.cpp4
-rw-r--r--src/pubkey/dlies/dlies.cpp2
-rw-r--r--src/pubkey/dsa/dsa.cpp2
-rw-r--r--src/pubkey/ec_dompar/ec_dompar.cpp8
-rw-r--r--src/pubkey/ecc_key/ecc_key.cpp4
-rw-r--r--src/pubkey/ecc_key/ecc_key.h1
-rw-r--r--src/pubkey/ecdsa/ecdsa.cpp4
-rw-r--r--src/pubkey/eckaeg/eckaeg.cpp8
-rw-r--r--src/pubkey/pk_codecs/pkcs8.cpp2
-rw-r--r--src/pubkey/pk_codecs/pkcs8.h10
-rw-r--r--src/pubkey/pubkey.cpp9
-rw-r--r--src/rng/auto_rng/auto_rng.cpp24
-rw-r--r--src/rng/hmac_rng/hmac_rng.cpp2
-rw-r--r--src/rng/randpool/randpool.cpp2
-rw-r--r--src/s2k/info.txt1
-rw-r--r--src/s2k/pbkdf1/pbkdf1.cpp13
-rw-r--r--src/s2k/pbkdf1/pbkdf1.h8
-rw-r--r--src/s2k/pbkdf2/pbkdf2.cpp10
-rw-r--r--src/s2k/pbkdf2/pbkdf2.h8
-rw-r--r--src/s2k/pgps2k/pgp_s2k.cpp7
-rw-r--r--src/s2k/pgps2k/pgp_s2k.h8
-rw-r--r--src/s2k/s2k.cpp55
-rw-r--r--src/s2k/s2k.h63
-rw-r--r--src/selftest/selftest.cpp172
-rw-r--r--src/selftest/selftest.h2
-rw-r--r--src/stream/stream_cipher.h4
-rw-r--r--src/utils/bswap.h25
-rw-r--r--src/utils/cpuid.cpp130
-rw-r--r--src/utils/cpuid.h8
-rw-r--r--src/utils/debug.h37
-rw-r--r--src/utils/exceptn.cpp62
-rw-r--r--src/utils/exceptn.h145
-rw-r--r--src/utils/get_byte.h27
-rw-r--r--src/utils/info.txt3
-rw-r--r--src/utils/loadstor.h11
-rw-r--r--src/utils/mlock.cpp8
-rw-r--r--src/utils/parsing.cpp4
-rw-r--r--src/utils/prefetch.h2
-rw-r--r--src/utils/simd_32/info.txt2
-rw-r--r--src/utils/simd_32/simd_32.h16
-rw-r--r--src/utils/simd_32/simd_altivec.h5
-rw-r--r--src/utils/simd_32/simd_scalar.h8
-rw-r--r--src/utils/simd_32/simd_sse.h5
-rw-r--r--src/wrap/python/filter.cpp10
-rw-r--r--src/wrap/python/python_botan.h5
-rw-r--r--src/wrap/python/x509.cpp10
-rw-r--r--src/wrap/sqlite/codec.cpp123
-rw-r--r--src/wrap/sqlite/codec.h127
-rw-r--r--src/wrap/sqlite/codecext.cpp261
-rw-r--r--src/wrap/sqlite/readme.txt36
-rw-r--r--src/wrap/sqlite/sqlite.diff77
-rw-r--r--src/wrap/sqlite/test_sqlite.cpp101
164 files changed, 2999 insertions, 2542 deletions
diff --git a/src/algo_factory/algo_factory.cpp b/src/algo_factory/algo_factory.cpp
index 38c6387e5..ad8b1215f 100644
--- a/src/algo_factory/algo_factory.cpp
+++ b/src/algo_factory/algo_factory.cpp
@@ -70,8 +70,7 @@ const T* factory_prototype(const std::string& algo_spec,
{
if(provider == "" || engines[i]->provider_name() == provider)
{
- T* impl = engine_get_algo<T>(engines[i], scan_name, af);
- if(impl)
+ if(T* impl = engine_get_algo<T>(engines[i], scan_name, af))
cache->add(impl, algo_spec, engines[i]->provider_name());
}
}
diff --git a/src/algo_factory/algo_factory.h b/src/algo_factory/algo_factory.h
index ac985b72b..3b479c2d7 100644
--- a/src/algo_factory/algo_factory.h
+++ b/src/algo_factory/algo_factory.h
@@ -46,61 +46,110 @@ class BOTAN_DLL Algorithm_Factory
*/
~Algorithm_Factory();
- /*
- * Provider management
+ /**
+ * @param algo_spec the algorithm we are querying
+ * @returns list of providers of this algorithm
*/
std::vector<std::string> providers_of(const std::string& algo_spec);
+ /**
+ * @param algo_spec the algorithm we are setting a provider for
+ * @param provider the provider we would like to use
+ */
void set_preferred_provider(const std::string& algo_spec,
const std::string& provider);
- /*
- * Block cipher operations
+ /**
+ * @param algo_spec the algorithm we want
+ * @param provider the provider we would like to use
+ * @returns pointer to const prototype object, readiny for clone(), or NULL
*/
const BlockCipher*
prototype_block_cipher(const std::string& algo_spec,
const std::string& provider = "");
+ /**
+ * @param algo_spec the algorithm we want
+ * @param provider the provider we would like to use
+ * @returns pointer to freshly created instance of the request algorithm
+ */
BlockCipher* make_block_cipher(const std::string& algo_spec,
const std::string& provider = "");
- void add_block_cipher(BlockCipher* hash, const std::string& provider);
+ /**
+ * @param algo the algorithm to add
+ * @param provider the provider of this algorithm
+ */
+ void add_block_cipher(BlockCipher* algo, const std::string& provider);
- /*
- * Stream cipher operations
+ /**
+ * @param algo_spec the algorithm we want
+ * @param provider the provider we would like to use
+ * @returns pointer to const prototype object, readiny for clone(), or NULL
*/
const StreamCipher*
prototype_stream_cipher(const std::string& algo_spec,
const std::string& provider = "");
+ /**
+ * @param algo_spec the algorithm we want
+ * @param provider the provider we would like to use
+ * @returns pointer to freshly created instance of the request algorithm
+ */
StreamCipher* make_stream_cipher(const std::string& algo_spec,
const std::string& provider = "");
- void add_stream_cipher(StreamCipher* hash, const std::string& provider);
+ /**
+ * @param algo the algorithm to add
+ * @param provider the provider of this algorithm
+ */
+ void add_stream_cipher(StreamCipher* algo, const std::string& provider);
- /*
- * Hash function operations
+ /**
+ * @param algo_spec the algorithm we want
+ * @param provider the provider we would like to use
+ * @returns pointer to const prototype object, readiny for clone(), or NULL
*/
const HashFunction*
prototype_hash_function(const std::string& algo_spec,
const std::string& provider = "");
+ /**
+ * @param algo_spec the algorithm we want
+ * @param provider the provider we would like to use
+ * @returns pointer to freshly created instance of the request algorithm
+ */
HashFunction* make_hash_function(const std::string& algo_spec,
const std::string& provider = "");
- void add_hash_function(HashFunction* hash, const std::string& provider);
+ /**
+ * @param algo the algorithm to add
+ * @param provider the provider of this algorithm
+ */
+ void add_hash_function(HashFunction* algo, const std::string& provider);
- /*
- * MAC operations
+ /**
+ * @param algo_spec the algorithm we want
+ * @param provider the provider we would like to use
+ * @returns pointer to const prototype object, readiny for clone(), or NULL
*/
const MessageAuthenticationCode*
prototype_mac(const std::string& algo_spec,
const std::string& provider = "");
+ /**
+ * @param algo_spec the algorithm we want
+ * @param provider the provider we would like to use
+ * @returns pointer to freshly created instance of the request algorithm
+ */
MessageAuthenticationCode* make_mac(const std::string& algo_spec,
const std::string& provider = "");
- void add_mac(MessageAuthenticationCode* mac,
+ /**
+ * @param algo the algorithm to add
+ * @param provider the provider of this algorithm
+ */
+ void add_mac(MessageAuthenticationCode* algo,
const std::string& provider);
/*
diff --git a/src/algo_factory/prov_weight.cpp b/src/algo_factory/prov_weight.cpp
index c7c2d8d8d..17284d024 100644
--- a/src/algo_factory/prov_weight.cpp
+++ b/src/algo_factory/prov_weight.cpp
@@ -19,15 +19,17 @@ u32bit static_provider_weight(const std::string& prov_name)
* them, set the provider explicitly for the algorithms you want
*/
- if(prov_name == "core") return 5;
- if(prov_name == "ia32") return 6;
- if(prov_name == "amd64") return 7;
+ if(prov_name == "aes_isa") return 9;
if(prov_name == "simd") return 8;
+ if(prov_name == "amd64") return 7;
+ if(prov_name == "ia32") return 6;
+
+ if(prov_name == "core") return 5;
if(prov_name == "openssl") return 2;
if(prov_name == "gmp") return 1;
- return 0; // other
+ return 0; // other/unknown
}
}
diff --git a/src/alloc/mem_pool/mem_pool.cpp b/src/alloc/mem_pool/mem_pool.cpp
index 2945a4cef..4180d2602 100644
--- a/src/alloc/mem_pool/mem_pool.cpp
+++ b/src/alloc/mem_pool/mem_pool.cpp
@@ -15,19 +15,6 @@
namespace Botan {
-namespace {
-
-/*
-* Memory Allocation Exception
-*/
-struct Memory_Exhaustion : public std::bad_alloc
- {
- const char* what() const throw()
- { return "Ran out of memory, allocation failed"; }
- };
-
-}
-
/*
* Memory_Block Constructor
*/
diff --git a/src/alloc/system_alloc/defalloc.cpp b/src/alloc/system_alloc/defalloc.cpp
index faaeb3c58..311057462 100644
--- a/src/alloc/system_alloc/defalloc.cpp
+++ b/src/alloc/system_alloc/defalloc.cpp
@@ -94,7 +94,7 @@ Allocator* Allocator::get(bool locking)
if(alloc)
return alloc;
- throw Exception("Couldn't find an allocator to use in get_allocator");
+ throw Internal_Error("Couldn't find an allocator to use in get_allocator");
}
}
diff --git a/src/asn1/ber_dec.cpp b/src/asn1/ber_dec.cpp
index b34bf8ca2..66a27dd4e 100644
--- a/src/asn1/ber_dec.cpp
+++ b/src/asn1/ber_dec.cpp
@@ -7,7 +7,7 @@
#include <botan/ber_dec.h>
#include <botan/bigint.h>
-#include <botan/loadstor.h>
+#include <botan/get_byte.h>
namespace Botan {
diff --git a/src/asn1/der_enc.cpp b/src/asn1/der_enc.cpp
index 3c318c291..e410292bb 100644
--- a/src/asn1/der_enc.cpp
+++ b/src/asn1/der_enc.cpp
@@ -8,9 +8,9 @@
#include <botan/der_enc.h>
#include <botan/asn1_int.h>
#include <botan/bigint.h>
-#include <botan/loadstor.h>
-#include <botan/internal/bit_ops.h>
+#include <botan/get_byte.h>
#include <botan/parsing.h>
+#include <botan/internal/bit_ops.h>
#include <algorithm>
namespace Botan {
diff --git a/src/block/block_cipher.h b/src/block/block_cipher.h
index e97eebf0f..06e8c5cea 100644
--- a/src/block/block_cipher.h
+++ b/src/block/block_cipher.h
@@ -59,8 +59,21 @@ class BOTAN_DLL BlockCipher : public SymmetricAlgorithm
*/
void decrypt(byte block[]) const { decrypt_n(block, block, 1); }
+ /**
+ * Encrypt one or more blocks
+ * @param in the input buffer (multiple of BLOCK_SIZE)
+ * @param out the output buffer (same size as in)
+ * @param blocks the number of blocks to process
+ */
virtual void encrypt_n(const byte in[], byte out[],
u32bit blocks) const = 0;
+
+ /**
+ * Decrypt one or more blocks
+ * @param in the input buffer (multiple of BLOCK_SIZE)
+ * @param out the output buffer (same size as in)
+ * @param blocks the number of blocks to process
+ */
virtual void decrypt_n(const byte in[], byte out[],
u32bit blocks) const = 0;
diff --git a/src/block/cascade/cascade.cpp b/src/block/cascade/cascade.cpp
new file mode 100644
index 000000000..f72ef7b76
--- /dev/null
+++ b/src/block/cascade/cascade.cpp
@@ -0,0 +1,98 @@
+/*
+* Block Cipher Cascade
+* (C) 2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/cascade.h>
+
+namespace Botan {
+
+void Cascade_Cipher::encrypt_n(const byte in[], byte out[],
+ u32bit blocks) const
+ {
+ u32bit c1_blocks = blocks * (BLOCK_SIZE / cipher1->BLOCK_SIZE);
+ u32bit c2_blocks = blocks * (BLOCK_SIZE / cipher2->BLOCK_SIZE);
+
+ cipher1->encrypt_n(in, out, c1_blocks);
+ cipher2->encrypt_n(out, out, c2_blocks);
+ }
+
+void Cascade_Cipher::decrypt_n(const byte in[], byte out[],
+ u32bit blocks) const
+ {
+ u32bit c1_blocks = blocks * (BLOCK_SIZE / cipher1->BLOCK_SIZE);
+ u32bit c2_blocks = blocks * (BLOCK_SIZE / cipher2->BLOCK_SIZE);
+
+ cipher2->decrypt_n(in, out, c2_blocks);
+ cipher1->decrypt_n(out, out, c1_blocks);
+ }
+
+void Cascade_Cipher::key_schedule(const byte key[], u32bit)
+ {
+ const byte* key2 = key + cipher1->MAXIMUM_KEYLENGTH;
+
+ cipher1->set_key(key , cipher1->MAXIMUM_KEYLENGTH);
+ cipher2->set_key(key2, cipher2->MAXIMUM_KEYLENGTH);
+ }
+
+void Cascade_Cipher::clear()
+ {
+ cipher1->clear();
+ cipher2->clear();
+ }
+
+std::string Cascade_Cipher::name() const
+ {
+ return "Cascade(" + cipher1->name() + "," + cipher2->name() + ")";
+ }
+
+BlockCipher* Cascade_Cipher::clone() const
+ {
+ return new Cascade_Cipher(cipher1->clone(),
+ cipher2->clone());
+ }
+
+namespace {
+
+u32bit euclids_algorithm(u32bit a, u32bit b)
+ {
+ while(b != 0) // gcd
+ {
+ u32bit t = b;
+ b = a % b;
+ a = t;
+ }
+
+ return a;
+ }
+
+u32bit block_size_for_cascade(u32bit bs, u32bit bs2)
+ {
+ if(bs == bs2)
+ return bs;
+
+ u32bit gcd = euclids_algorithm(bs, bs2);
+
+ return (bs * bs2) / gcd;
+ }
+
+}
+
+Cascade_Cipher::Cascade_Cipher(BlockCipher* c1, BlockCipher* c2) :
+ BlockCipher(block_size_for_cascade(c1->BLOCK_SIZE, c2->BLOCK_SIZE),
+ c1->MAXIMUM_KEYLENGTH + c2->MAXIMUM_KEYLENGTH),
+ cipher1(c1), cipher2(c2)
+ {
+ if(BLOCK_SIZE % c1->BLOCK_SIZE || BLOCK_SIZE % c2->BLOCK_SIZE)
+ throw Internal_Error("Failure in " + name() + " constructor");
+ }
+
+Cascade_Cipher::~Cascade_Cipher()
+ {
+ delete cipher1;
+ delete cipher2;
+ }
+
+}
diff --git a/src/block/cascade/cascade.h b/src/block/cascade/cascade.h
new file mode 100644
index 000000000..98c64fb3e
--- /dev/null
+++ b/src/block/cascade/cascade.h
@@ -0,0 +1,41 @@
+/*
+* Block Cipher Cascade
+* (C) 2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CASCADE_H__
+#define BOTAN_CASCADE_H__
+
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* Block Cipher Cascade
+*/
+class BOTAN_DLL Cascade_Cipher : public BlockCipher
+ {
+ public:
+ void encrypt_n(const byte in[], byte out[], u32bit blocks) const;
+ void decrypt_n(const byte in[], byte out[], u32bit blocks) const;
+
+ void clear();
+ std::string name() const;
+ BlockCipher* clone() const;
+
+ Cascade_Cipher(BlockCipher* cipher1, BlockCipher* cipher2);
+
+ ~Cascade_Cipher();
+ private:
+ void key_schedule(const byte[], u32bit);
+
+ BlockCipher* cipher1;
+ BlockCipher* cipher2;
+ };
+
+
+}
+
+#endif
diff --git a/src/block/cascade/info.txt b/src/block/cascade/info.txt
new file mode 100644
index 000000000..0e6f4acdd
--- /dev/null
+++ b/src/block/cascade/info.txt
@@ -0,0 +1,9 @@
+define CASCADE
+
+<header:public>
+cascade.h
+</header:public>
+
+<source>
+cascade.cpp
+</source>
diff --git a/src/block/idea_sse2/idea_sse2.cpp b/src/block/idea_sse2/idea_sse2.cpp
index c00d13ee9..0fe35112d 100644
--- a/src/block/idea_sse2/idea_sse2.cpp
+++ b/src/block/idea_sse2/idea_sse2.cpp
@@ -6,7 +6,6 @@
*/
#include <botan/idea_sse2.h>
-#include <botan/loadstor.h>
#include <emmintrin.h>
namespace Botan {
diff --git a/src/block/lion/lion.cpp b/src/block/lion/lion.cpp
index e590a78ce..d8dfd1fcb 100644
--- a/src/block/lion/lion.cpp
+++ b/src/block/lion/lion.cpp
@@ -116,8 +116,9 @@ Lion::Lion(HashFunction* hash_in, StreamCipher* sc_in, u32bit block_len) :
{
if(2*LEFT_SIZE + 1 > BLOCK_SIZE)
throw Invalid_Argument(name() + ": Chosen block size is too small");
+
if(!cipher->valid_keylength(LEFT_SIZE))
- throw Exception(name() + ": This stream/hash combination is invalid");
+ throw Invalid_Argument(name() + ": This stream/hash combo is invalid");
key1.resize(LEFT_SIZE);
key2.resize(LEFT_SIZE);
diff --git a/src/block/noekeon/noekeon.h b/src/block/noekeon/noekeon.h
index 4532c1be2..22ef65342 100644
--- a/src/block/noekeon/noekeon.h
+++ b/src/block/noekeon/noekeon.h
@@ -26,7 +26,7 @@ class BOTAN_DLL Noekeon : public BlockCipher
BlockCipher* clone() const { return new Noekeon; }
Noekeon() : BlockCipher(16, 16) {}
- private:
+ protected:
void key_schedule(const byte[], u32bit);
static const byte RC[17];
diff --git a/src/block/noekeon_simd/info.txt b/src/block/noekeon_simd/info.txt
new file mode 100644
index 000000000..b73954cff
--- /dev/null
+++ b/src/block/noekeon_simd/info.txt
@@ -0,0 +1,7 @@
+define NOEKEON_SIMD
+
+<requires>
+noekeon
+simd_32
+simd_engine
+</requires>
diff --git a/src/block/noekeon_simd/noekeon_simd.cpp b/src/block/noekeon_simd/noekeon_simd.cpp
new file mode 100644
index 000000000..f44104901
--- /dev/null
+++ b/src/block/noekeon_simd/noekeon_simd.cpp
@@ -0,0 +1,161 @@
+/*
+* Noekeon in SIMD
+* (C) 2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/noekeon_simd.h>
+#include <botan/internal/simd_32.h>
+
+namespace Botan {
+
+/*
+* Noekeon's Theta Operation
+*/
+#define NOK_SIMD_THETA(A0, A1, A2, A3, K0, K1, K2, K3) \
+ do { \
+ SIMD_32 T = A0 ^ A2; \
+ T ^= rotate_left(T, 8) ^ rotate_right(T, 8); \
+ A1 ^= T; \
+ A3 ^= T; \
+ \
+ A0 ^= K0; \
+ A1 ^= K1; \
+ A2 ^= K2; \
+ A3 ^= K3; \
+ \
+ T = A1 ^ A3; \
+ T ^= rotate_left(T, 8) ^ rotate_right(T, 8); \
+ A0 ^= T; \
+ A2 ^= T; \
+ } while(0)
+
+/*
+* Noekeon's Gamma S-Box Layer
+*/
+#define NOK_SIMD_GAMMA(A0, A1, A2, A3) \
+ do \
+ { \
+ A1 ^= A3.andc(~A2); \
+ A0 ^= A2 & A1; \
+ \
+ SIMD_32 T = A3; \
+ A3 = A0; \
+ A0 = T; \
+ \
+ A2 ^= A0 ^ A1 ^ A3; \
+ \
+ A1 ^= A3.andc(~A2); \
+ A0 ^= A2 & A1; \
+ } while(0)
+
+/*
+* Noekeon Encryption
+*/
+void Noekeon_SIMD::encrypt_n(const byte in[], byte out[], u32bit blocks) const
+ {
+ SIMD_32 K0 = SIMD_32(EK[0]);
+ SIMD_32 K1 = SIMD_32(EK[1]);
+ SIMD_32 K2 = SIMD_32(EK[2]);
+ SIMD_32 K3 = SIMD_32(EK[3]);
+
+ while(blocks >= 4)
+ {
+ SIMD_32 A0 = SIMD_32::load_be(in );
+ SIMD_32 A1 = SIMD_32::load_be(in + 16);
+ SIMD_32 A2 = SIMD_32::load_be(in + 32);
+ SIMD_32 A3 = SIMD_32::load_be(in + 48);
+
+ SIMD_32::transpose(A0, A1, A2, A3);
+
+ for(u32bit i = 0; i != 16; ++i)
+ {
+ A0 ^= SIMD_32(RC[i]);
+
+ NOK_SIMD_THETA(A0, A1, A2, A3, K0, K1, K2, K3);
+
+ A1.rotate_left(1);
+ A2.rotate_left(5);
+ A3.rotate_left(2);
+
+ NOK_SIMD_GAMMA(A0, A1, A2, A3);
+
+ A1.rotate_right(1);
+ A2.rotate_right(5);
+ A3.rotate_right(2);
+ }
+
+ A0 ^= SIMD_32(RC[16]);
+ NOK_SIMD_THETA(A0, A1, A2, A3, K0, K1, K2, K3);
+
+ SIMD_32::transpose(A0, A1, A2, A3);
+
+ A0.store_be(out);
+ A1.store_be(out + 16);
+ A2.store_be(out + 32);
+ A3.store_be(out + 48);
+
+ in += 64;
+ out += 64;
+ blocks -= 4;
+ }
+
+ Noekeon::encrypt_n(in, out, blocks);
+ }
+
+/*
+* Noekeon Encryption
+*/
+void Noekeon_SIMD::decrypt_n(const byte in[], byte out[], u32bit blocks) const
+ {
+ SIMD_32 K0 = SIMD_32(DK[0]);
+ SIMD_32 K1 = SIMD_32(DK[1]);
+ SIMD_32 K2 = SIMD_32(DK[2]);
+ SIMD_32 K3 = SIMD_32(DK[3]);
+
+ while(blocks >= 4)
+ {
+ SIMD_32 A0 = SIMD_32::load_be(in );
+ SIMD_32 A1 = SIMD_32::load_be(in + 16);
+ SIMD_32 A2 = SIMD_32::load_be(in + 32);
+ SIMD_32 A3 = SIMD_32::load_be(in + 48);
+
+ SIMD_32::transpose(A0, A1, A2, A3);
+
+ for(u32bit i = 0; i != 16; ++i)
+ {
+ NOK_SIMD_THETA(A0, A1, A2, A3, K0, K1, K2, K3);
+
+ A0 ^= SIMD_32(RC[16-i]);
+
+ A1.rotate_left(1);
+ A2.rotate_left(5);
+ A3.rotate_left(2);
+
+ NOK_SIMD_GAMMA(A0, A1, A2, A3);
+
+ A1.rotate_right(1);
+ A2.rotate_right(5);
+ A3.rotate_right(2);
+ }
+
+ NOK_SIMD_THETA(A0, A1, A2, A3, K0, K1, K2, K3);
+ A0 ^= SIMD_32(RC[0]);
+
+ SIMD_32::transpose(A0, A1, A2, A3);
+
+ A0.store_be(out);
+ A1.store_be(out + 16);
+ A2.store_be(out + 32);
+ A3.store_be(out + 48);
+
+ in += 64;
+ out += 64;
+ blocks -= 4;
+ }
+
+ Noekeon::decrypt_n(in, out, blocks);
+ }
+
+}
diff --git a/src/block/noekeon_simd/noekeon_simd.h b/src/block/noekeon_simd/noekeon_simd.h
new file mode 100644
index 000000000..466c4b741
--- /dev/null
+++ b/src/block/noekeon_simd/noekeon_simd.h
@@ -0,0 +1,29 @@
+/*
+* Noekeon in SIMD
+* (C) 2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_NOEKEON_SIMD_H__
+#define BOTAN_NOEKEON_SIMD_H__
+
+#include <botan/noekeon.h>
+
+namespace Botan {
+
+/*
+* Noekeon
+*/
+class BOTAN_DLL Noekeon_SIMD : public Noekeon
+ {
+ public:
+ void encrypt_n(const byte in[], byte out[], u32bit blocks) const;
+ void decrypt_n(const byte in[], byte out[], u32bit blocks) const;
+
+ BlockCipher* clone() const { return new Noekeon_SIMD; }
+ };
+
+}
+
+#endif
diff --git a/src/build-data/arch/amd64.txt b/src/build-data/arch/amd64.txt
index 58d1d3fa6..b0cf546d7 100644
--- a/src/build-data/arch/amd64.txt
+++ b/src/build-data/arch/amd64.txt
@@ -1,6 +1,8 @@
endian little
unaligned ok
+family x86
+
<aliases>
x86-64
x86_64 # for RPM
diff --git a/src/build-data/arch/ia32.txt b/src/build-data/arch/ia32.txt
index 40066851d..d9b09746d 100644
--- a/src/build-data/arch/ia32.txt
+++ b/src/build-data/arch/ia32.txt
@@ -1,6 +1,8 @@
endian little
unaligned ok
+family x86
+
<aliases>
x86
ix86
diff --git a/src/build-data/arch/ppc.txt b/src/build-data/arch/ppc.txt
index 811eb53e7..dc3ea7829 100644
--- a/src/build-data/arch/ppc.txt
+++ b/src/build-data/arch/ppc.txt
@@ -1,6 +1,8 @@
endian big
unaligned ok
+family ppc
+
<aliases>
powerpc
</aliases>
diff --git a/src/build-data/arch/ppc64.txt b/src/build-data/arch/ppc64.txt
index b99aa9b8b..7a2e6b6b3 100644
--- a/src/build-data/arch/ppc64.txt
+++ b/src/build-data/arch/ppc64.txt
@@ -1,5 +1,7 @@
endian big
+family ppc
+
<aliases>
powerpc64
</aliases>
diff --git a/src/build-data/arch/sparc32.txt b/src/build-data/arch/sparc32.txt
index ae75a2a4b..fc015e520 100644
--- a/src/build-data/arch/sparc32.txt
+++ b/src/build-data/arch/sparc32.txt
@@ -1,5 +1,7 @@
endian big
+family sparc
+
<aliases>
sparc
</aliases>
diff --git a/src/build-data/arch/sparc64.txt b/src/build-data/arch/sparc64.txt
index a1ed16549..e20d0fde6 100644
--- a/src/build-data/arch/sparc64.txt
+++ b/src/build-data/arch/sparc64.txt
@@ -1,3 +1,6 @@
+
+family sparc
+
<submodels>
ultrasparc
ultrasparc3
diff --git a/src/build-data/buildh.in b/src/build-data/buildh.in
index 7588dc99b..231a7aeeb 100644
--- a/src/build-data/buildh.in
+++ b/src/build-data/buildh.in
@@ -27,11 +27,11 @@
*
* CBC and CFB can only use parallel processing in decryption mode
*/
-#define BOTAN_PARALLEL_BLOCKS_ECB 8
-#define BOTAN_PARALLEL_BLOCKS_CBC 8
-#define BOTAN_PARALLEL_BLOCKS_CFB 8
+#define BOTAN_PARALLEL_BLOCKS_ECB 16
+#define BOTAN_PARALLEL_BLOCKS_CBC 16
+#define BOTAN_PARALLEL_BLOCKS_CFB 16
#define BOTAN_PARALLEL_BLOCKS_CTR 16
-#define BOTAN_PARALLEL_BLOCKS_XTS 8
+#define BOTAN_PARALLEL_BLOCKS_XTS 16
/* PK key consistency checking toggles */
#define BOTAN_PUBLIC_KEY_STRONG_CHECKS_ON_LOAD 1
diff --git a/src/build-data/makefile/nmake.in b/src/build-data/makefile/nmake.in
index 79b80745c..2d89850fd 100644
--- a/src/build-data/makefile/nmake.in
+++ b/src/build-data/makefile/nmake.in
@@ -17,7 +17,7 @@ DESTDIR = %{prefix}
LIBDIR = $(DESTDIR)\%{libdir}
HEADERDIR = $(DESTDIR)\%{includedir}\botan
-DOCDIR = $(DESTDIR)\%{docdir}\Botan-$(VERSION)
+DOCDIR = $(DESTDIR)\%{docdir}\botan-$(VERSION)
### Aliases for Common Programs
AR = %{ar_command}
diff --git a/src/build-data/makefile/unix.in b/src/build-data/makefile/unix.in
index 22ff919cc..c525aa6bf 100644
--- a/src/build-data/makefile/unix.in
+++ b/src/build-data/makefile/unix.in
@@ -16,7 +16,7 @@ DESTDIR = %{prefix}
BINDIR = $(DESTDIR)/bin
LIBDIR = $(DESTDIR)/%{libdir}
HEADERDIR = $(DESTDIR)/%{includedir}/botan
-DOCDIR = $(DESTDIR)/%{docdir}/Botan-$(VERSION)
+DOCDIR = $(DESTDIR)/%{docdir}/botan-$(VERSION)
PKGCONF_DIR = $(LIBDIR)/pkgconfig
CONFIG_SCRIPT = %{botan_config}
@@ -76,7 +76,7 @@ $(STATIC_LIB): $(LIBOBJS)
static: $(STATIC_LIB)
doxygen:
- doxygen %{doc_src_dir}/botan.doxy
+ doxygen %{build_dir}/botan.doxy
clean:
$(RM_R) %{build_dir}/lib/* %{build_dir}/checks/*
diff --git a/src/build-data/makefile/unix_shr.in b/src/build-data/makefile/unix_shr.in
index 499b7eb92..aaedeeaf8 100644
--- a/src/build-data/makefile/unix_shr.in
+++ b/src/build-data/makefile/unix_shr.in
@@ -19,7 +19,7 @@ DESTDIR = %{prefix}
BINDIR = $(DESTDIR)/bin
LIBDIR = $(DESTDIR)/%{libdir}
HEADERDIR = $(DESTDIR)/%{includedir}/botan
-DOCDIR = $(DESTDIR)/%{docdir}/Botan-$(VERSION)
+DOCDIR = $(DESTDIR)/%{docdir}/botan-$(VERSION)
PKGCONF_DIR = $(LIBDIR)/pkgconfig
CONFIG_SCRIPT = %{botan_config}
@@ -90,7 +90,7 @@ static: $(STATIC_LIB)
shared: $(SHARED_LIB)
doxygen:
- doxygen %{doc_src_dir}/botan.doxy
+ doxygen %{build_dir}/botan.doxy
clean:
$(RM_R) %{build_dir}/lib/* %{build_dir}/checks/*
diff --git a/src/cert/cvc/asn1_eac_tm.cpp b/src/cert/cvc/asn1_eac_tm.cpp
index dc38e3296..73a2843f7 100644
--- a/src/cert/cvc/asn1_eac_tm.cpp
+++ b/src/cert/cvc/asn1_eac_tm.cpp
@@ -182,9 +182,9 @@ bool EAC_Time::passes_sanity_check() const
return true;
}
-/******************************************
+/*
* modification functions
-******************************************/
+*/
void EAC_Time::add_years(u32bit years)
{
diff --git a/src/cert/cvc/cvc_ado.cpp b/src/cert/cvc/cvc_ado.cpp
index 6e1484e90..fcce0ff82 100644
--- a/src/cert/cvc/cvc_ado.cpp
+++ b/src/cert/cvc/cvc_ado.cpp
@@ -8,11 +8,10 @@
#include <botan/cvc_ado.h>
#include <fstream>
-#include <assert.h>
namespace Botan {
-EAC1_1_ADO::EAC1_1_ADO(std::tr1::shared_ptr<DataSource> in)
+EAC1_1_ADO::EAC1_1_ADO(DataSource& in)
{
init(in);
do_decode();
@@ -20,7 +19,7 @@ EAC1_1_ADO::EAC1_1_ADO(std::tr1::shared_ptr<DataSource> in)
EAC1_1_ADO::EAC1_1_ADO(const std::string& in)
{
- std::tr1::shared_ptr<DataSource> stream(new DataSource_Stream(in, true));
+ DataSource_Stream stream(in, true);
init(stream);
do_decode();
}
@@ -41,7 +40,7 @@ void EAC1_1_ADO::force_decode()
.end_cons()
.get_contents();
- std::tr1::shared_ptr<DataSource> req_source(new DataSource_Memory(req_bits));
+ DataSource_Memory req_source(req_bits);
m_req = EAC1_1_Req(req_source);
sig_algo = m_req.sig_algo;
}
@@ -53,14 +52,13 @@ MemoryVector<byte> EAC1_1_ADO::make_signed(
{
SecureVector<byte> concat_sig =
EAC1_1_obj<EAC1_1_ADO>::make_signature(signer.get(), tbs_bits, rng);
- assert(concat_sig.size() % 2 == 0);
- MemoryVector<byte> result = DER_Encoder()
+
+ return DER_Encoder()
.start_cons(ASN1_Tag(7), APPLICATION)
.raw_bytes(tbs_bits)
.encode(concat_sig, OCTET_STRING, ASN1_Tag(55), APPLICATION)
.end_cons()
.get_contents();
- return result;
}
ASN1_Car EAC1_1_ADO::get_car() const
@@ -68,14 +66,15 @@ ASN1_Car EAC1_1_ADO::get_car() const
return m_car;
}
-void EAC1_1_ADO::decode_info(SharedPtrConverter<DataSource> source,
+void EAC1_1_ADO::decode_info(DataSource& source,
SecureVector<byte> & res_tbs_bits,
ECDSA_Signature & res_sig)
{
SecureVector<byte> concat_sig;
SecureVector<byte> cert_inner_bits;
ASN1_Car car;
- BER_Decoder(*source.get_ptr().get())
+
+ BER_Decoder(source)
.start_cons(ASN1_Tag(7))
.start_cons(ASN1_Tag(33))
.raw_bytes(cert_inner_bits)
@@ -89,28 +88,30 @@ void EAC1_1_ADO::decode_info(SharedPtrConverter<DataSource> source,
.raw_bytes(cert_inner_bits)
.end_cons()
.get_contents();
+
SecureVector<byte> enc_car = DER_Encoder()
.encode(car)
.get_contents();
+
res_tbs_bits = enc_cert;
res_tbs_bits.append(enc_car);
res_sig = decode_concatenation(concat_sig);
-
-
}
+
void EAC1_1_ADO::encode(Pipe& out, X509_Encoding encoding) const
{
- SecureVector<byte> concat_sig(EAC1_1_obj<EAC1_1_ADO>::m_sig.get_concatenation());
- SecureVector<byte> der = DER_Encoder()
- .start_cons(ASN1_Tag(7), APPLICATION)
- .raw_bytes(tbs_bits)
- .encode(concat_sig, OCTET_STRING, ASN1_Tag(55), APPLICATION)
- .end_cons()
- .get_contents();
if(encoding == PEM)
throw Invalid_Argument("EAC1_1_ADO::encode() cannot PEM encode an EAC object");
- else
- out.write(der);
+
+ SecureVector<byte> concat_sig(
+ EAC1_1_obj<EAC1_1_ADO>::m_sig.get_concatenation());
+
+ out.write(DER_Encoder()
+ .start_cons(ASN1_Tag(7), APPLICATION)
+ .raw_bytes(tbs_bits)
+ .encode(concat_sig, OCTET_STRING, ASN1_Tag(55), APPLICATION)
+ .end_cons()
+ .get_contents());
}
SecureVector<byte> EAC1_1_ADO::tbs_data() const
@@ -120,8 +121,6 @@ SecureVector<byte> EAC1_1_ADO::tbs_data() const
bool EAC1_1_ADO::operator==(EAC1_1_ADO const& rhs) const
{
- assert(((this->m_req == rhs.m_req) && (this->tbs_data() == rhs.tbs_data())) ||
- ((this->m_req != rhs.m_req) && (this->tbs_data() != rhs.tbs_data())));
return (this->get_concat_sig() == rhs.get_concat_sig()
&& this->tbs_data() == rhs.tbs_data()
&& this->get_car() == rhs.get_car());
diff --git a/src/cert/cvc/cvc_ado.h b/src/cert/cvc/cvc_ado.h
index a0dbec2a6..80e6a82b7 100644
--- a/src/cert/cvc/cvc_ado.h
+++ b/src/cert/cvc/cvc_ado.h
@@ -38,7 +38,7 @@ class BOTAN_DLL EAC1_1_ADO : public EAC1_1_obj<EAC1_1_ADO>
* Construct a CVC ADO request from a data source
* @param source the data source
*/
- EAC1_1_ADO(std::tr1::shared_ptr<DataSource> source);
+ EAC1_1_ADO(DataSource& source);
/**
* Create a signed CVC ADO request from to be signed (TBS) data
@@ -83,7 +83,7 @@ class BOTAN_DLL EAC1_1_ADO : public EAC1_1_obj<EAC1_1_ADO>
EAC1_1_Req m_req;
void force_decode();
- static void decode_info(SharedPtrConverter<DataSource> source,
+ static void decode_info(DataSource& source,
SecureVector<byte> & res_tbs_bits,
ECDSA_Signature & res_sig);
};
diff --git a/src/cert/cvc/cvc_ca.cpp b/src/cert/cvc/cvc_ca.cpp
index 8ca8db0c2..814df216b 100644
--- a/src/cert/cvc/cvc_ca.cpp
+++ b/src/cert/cvc/cvc_ca.cpp
@@ -37,8 +37,7 @@ EAC1_1_CVC EAC1_1_CVC_CA::make_cert(std::auto_ptr<PK_Signer> signer,
EAC1_1_CVC::build_cert_body(tbs),
rng);
- std::tr1::shared_ptr<DataSource> source(new DataSource_Memory(signed_cert));
-
+ DataSource_Memory source(signed_cert);
return EAC1_1_CVC(source);
}
diff --git a/src/cert/cvc/cvc_cert.cpp b/src/cert/cvc/cvc_cert.cpp
index d2be12df8..94d80af21 100644
--- a/src/cert/cvc/cvc_cert.cpp
+++ b/src/cert/cvc/cvc_cert.cpp
@@ -56,7 +56,7 @@ void EAC1_1_CVC::force_decode()
throw Decoding_Error("CertificateHolderAuthorizationValue was not of length 1");
if(cpi != 0)
- throw Decoding_Error("EAC1_1 certificate´s cpi was not 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
@@ -78,7 +78,7 @@ void EAC1_1_CVC::force_decode()
/*
* CVC Certificate Constructor
*/
-EAC1_1_CVC::EAC1_1_CVC(std::tr1::shared_ptr<DataSource>& in)
+EAC1_1_CVC::EAC1_1_CVC(DataSource& in)
{
init(in);
self_signed = false;
@@ -87,7 +87,7 @@ EAC1_1_CVC::EAC1_1_CVC(std::tr1::shared_ptr<DataSource>& in)
EAC1_1_CVC::EAC1_1_CVC(const std::string& in)
{
- std::tr1::shared_ptr<DataSource> stream(new DataSource_Stream(in, true));
+ DataSource_Stream stream(in, true);
init(stream);
self_signed = false;
do_decode();
diff --git a/src/cert/cvc/cvc_cert.h b/src/cert/cvc/cvc_cert.h
index 17671d332..ae0c21d7b 100644
--- a/src/cert/cvc/cvc_cert.h
+++ b/src/cert/cvc/cvc_cert.h
@@ -59,7 +59,7 @@ class BOTAN_DLL EAC1_1_CVC : public EAC1_1_gen_CVC<EAC1_1_CVC>//Signed_Object
* Construct a CVC from a data source
* @param source the data source
*/
- EAC1_1_CVC(std::tr1::shared_ptr<DataSource>& source);
+ EAC1_1_CVC(DataSource& source);
/**
* Construct a CVC from a file
diff --git a/src/cert/cvc/cvc_gen_cert.h b/src/cert/cvc/cvc_gen_cert.h
index 797970e29..096f7898c 100644
--- a/src/cert/cvc/cvc_gen_cert.h
+++ b/src/cert/cvc/cvc_gen_cert.h
@@ -16,7 +16,6 @@
#include <botan/ecdsa.h>
#include <botan/ecdsa_sig.h>
#include <string>
-#include <assert.h>
namespace Botan {
@@ -87,7 +86,7 @@ class BOTAN_DLL EAC1_1_gen_CVC : public EAC1_1_obj<Derived> // CRTP continuation
ASN1_Chr m_chr;
bool self_signed;
- static void decode_info(SharedPtrConverter<DataSource> source,
+ static void decode_info(DataSource& source,
SecureVector<byte> & res_tbs_bits,
ECDSA_Signature & res_sig);
@@ -109,7 +108,7 @@ template<typename Derived> MemoryVector<byte> EAC1_1_gen_CVC<Derived>::make_sign
RandomNumberGenerator& rng) // static
{
SecureVector<byte> concat_sig = EAC1_1_obj<Derived>::make_signature(signer.get(), tbs_bits, rng);
- assert(concat_sig.size() % 2 == 0);
+
return DER_Encoder()
.start_cons(ASN1_Tag(33), APPLICATION)
.raw_bytes(tbs_bits)
@@ -156,12 +155,12 @@ template<typename Derived> void EAC1_1_gen_CVC<Derived>::encode(Pipe& out, X509_
template<typename Derived>
void EAC1_1_gen_CVC<Derived>::decode_info(
- SharedPtrConverter<DataSource> source,
+ DataSource& source,
SecureVector<byte> & res_tbs_bits,
ECDSA_Signature & res_sig)
{
SecureVector<byte> concat_sig;
- BER_Decoder(*source.get_shared().get())
+ BER_Decoder(source)
.start_cons(ASN1_Tag(33))
.start_cons(ASN1_Tag(78))
.raw_bytes(res_tbs_bits)
diff --git a/src/cert/cvc/cvc_req.cpp b/src/cert/cvc/cvc_req.cpp
index 70a44bacd..78dbdea52 100644
--- a/src/cert/cvc/cvc_req.cpp
+++ b/src/cert/cvc/cvc_req.cpp
@@ -10,19 +10,17 @@
#include <botan/ber_dec.h>
#include <botan/pem.h>
#include <botan/parsing.h>
-#include <assert.h>
#include <botan/cvc_key.h>
#include <botan/oids.h>
#include <botan/look_pk.h>
#include <botan/cvc_req.h>
-#include <botan/freestore.h>
namespace Botan {
bool EAC1_1_Req::operator==(EAC1_1_Req const& rhs) const
{
- return (this->tbs_data() == rhs.tbs_data()
- && this->get_concat_sig() == rhs.get_concat_sig());
+ return (this->tbs_data() == rhs.tbs_data() &&
+ this->get_concat_sig() == rhs.get_concat_sig());
}
void EAC1_1_Req::force_decode()
@@ -36,10 +34,9 @@ void EAC1_1_Req::force_decode()
.end_cons()
.decode(m_chr)
.verify_end();
+
if(cpi != 0)
- {
- throw Decoding_Error("EAC1_1 request´s cpi was not 0");
- }
+ throw Decoding_Error("EAC1_1 requests cpi was not 0");
// FIXME: No EAC support in ECDSA
#if 0
@@ -50,7 +47,7 @@ void EAC1_1_Req::force_decode()
#endif
}
-EAC1_1_Req::EAC1_1_Req(std::tr1::shared_ptr<DataSource> in)
+EAC1_1_Req::EAC1_1_Req(DataSource& in)
{
init(in);
self_signed = true;
@@ -59,7 +56,7 @@ EAC1_1_Req::EAC1_1_Req(std::tr1::shared_ptr<DataSource> in)
EAC1_1_Req::EAC1_1_Req(const std::string& in)
{
- std::tr1::shared_ptr<DataSource> stream(new DataSource_Stream(in, true));
+ DataSource_Stream stream(in, true);
init(stream);
self_signed = true;
do_decode();
diff --git a/src/cert/cvc/cvc_req.h b/src/cert/cvc/cvc_req.h
index 28f03db80..2abc72c9a 100644
--- a/src/cert/cvc/cvc_req.h
+++ b/src/cert/cvc/cvc_req.h
@@ -35,7 +35,7 @@ class BOTAN_DLL EAC1_1_Req : public EAC1_1_gen_CVC<EAC1_1_Req>
* Construct a CVC request from a data source.
* @param source the data source
*/
- EAC1_1_Req(std::tr1::shared_ptr<DataSource> source);
+ EAC1_1_Req(DataSource& source);
/**
* Construct a CVC request from a DER encoded CVC reqeust file.
diff --git a/src/cert/cvc/cvc_self.cpp b/src/cert/cvc/cvc_self.cpp
index 227ff4136..deef351b9 100644
--- a/src/cert/cvc/cvc_self.cpp
+++ b/src/cert/cvc/cvc_self.cpp
@@ -16,14 +16,15 @@
#include <botan/cvc_ado.h>
#include <botan/time.h>
#include <sstream>
+#include <assert.h>
namespace Botan {
namespace {
-/*******************************
+/*
* cvc CHAT values
-*******************************/
+*/
enum CHAT_values{
CVCA = 0xC0,
DVCA_domestic = 0x80,
@@ -42,6 +43,7 @@ std::string padding_and_hash_from_oid(OID const& oid)
padding_and_hash.erase(0, padding_and_hash.find("/",0) + 1);
return padding_and_hash;
}
+
std::string fixed_len_seqnr(u32bit seqnr, u32bit len)
{
std::stringstream ss;
@@ -80,7 +82,7 @@ EAC1_1_CVC create_self_signed_cert(Private_Key const& key,
ASN1_Chr chr(opt.car.value());
AlgorithmIdentifier sig_algo;
- std::string padding_and_hash(eac_cvc_emsa + "(" + opt.hash_alg + ")");
+ std::string padding_and_hash("EMSA1_BSI(" + opt.hash_alg + ")");
sig_algo.oid = OIDS::lookup(priv_key->algo_name() + "/" + padding_and_hash);
sig_algo = AlgorithmIdentifier(sig_algo.oid, AlgorithmIdentifier::USE_NULL_PARAM);
@@ -109,7 +111,7 @@ EAC1_1_Req create_cvc_req(Private_Key const& key,
throw Invalid_Argument("CVC_EAC::create_self_signed_cert(): unsupported key type");
}
AlgorithmIdentifier sig_algo;
- std::string padding_and_hash(eac_cvc_emsa + "(" + hash_alg + ")");
+ std::string padding_and_hash("EMSA1_BSI(" + hash_alg + ")");
sig_algo.oid = OIDS::lookup(priv_key->algo_name() + "/" + padding_and_hash);
sig_algo = AlgorithmIdentifier(sig_algo.oid, AlgorithmIdentifier::USE_NULL_PARAM);
@@ -131,7 +133,8 @@ EAC1_1_Req create_cvc_req(Private_Key const& key,
.get_contents();
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);
- std::tr1::shared_ptr<DataSource> source(new DataSource_Memory(signed_cert));
+
+ DataSource_Memory source(signed_cert);
return EAC1_1_Req(source);
}
@@ -151,7 +154,8 @@ EAC1_1_ADO create_ado_req(Private_Key const& key,
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, tbs_bits, rng);
- std::tr1::shared_ptr<DataSource> source(new DataSource_Memory(signed_cert));
+
+ DataSource_Memory source(signed_cert);
return EAC1_1_ADO(source);
}
@@ -206,7 +210,7 @@ EAC1_1_CVC link_cvca(EAC1_1_CVC const& signer,
}
if (signer.signature_algorithm() != signee.signature_algorithm())
{
- throw Invalid_Argument("link_cvca(): signature algorithms of signer and signee don´t match");
+ throw Invalid_Argument("link_cvca(): signature algorithms of signer and signee don't match");
}
AlgorithmIdentifier sig_algo = signer.signature_algorithm();
std::string padding_and_hash = padding_and_hash_from_oid(sig_algo.oid);
diff --git a/src/cert/cvc/eac_obj.h b/src/cert/cvc/eac_obj.h
index d357adb7d..e4eb895c1 100644
--- a/src/cert/cvc/eac_obj.h
+++ b/src/cert/cvc/eac_obj.h
@@ -18,13 +18,10 @@
#include <botan/oids.h>
#include <botan/look_pk.h>
#include <botan/ecdsa_sig.h>
-#include <botan/freestore.h>
#include <string>
namespace Botan {
-const std::string eac_cvc_emsa("EMSA1_BSI");
-
/*
* TR03110 v1.1 EAC CV Certificate
*/
@@ -52,7 +49,7 @@ class BOTAN_DLL EAC1_1_obj : public EAC_Signed_Object
virtual bool check_signature(Public_Key& pub_key) const;
protected:
- void init(SharedPtrConverter<DataSource> in);
+ void init(DataSource& in);
static SecureVector<byte> make_signature(PK_Signer* signer,
const MemoryRegion<byte>& tbs_bits,
@@ -80,11 +77,12 @@ EAC1_1_obj<Derived>::make_signature(PK_Signer* signer,
return concat_sig;
}
-template<typename Derived> void EAC1_1_obj<Derived>::init(SharedPtrConverter<DataSource> in)
+template<typename Derived>
+void EAC1_1_obj<Derived>::init(DataSource& in)
{
try
{
- Derived::decode_info(in.get_shared(), tbs_bits, m_sig);
+ Derived::decode_info(in, tbs_bits, m_sig);
}
catch(Decoding_Error)
{
diff --git a/src/cert/cvc/freestore.h b/src/cert/cvc/freestore.h
deleted file mode 100644
index 7f8b85388..000000000
--- a/src/cert/cvc/freestore.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
-* (C) 2007 Christoph Ludwig
-*
-* Distributed under the terms of the Botan license
-*/
-
-#ifndef BOTAN_FREESTORE_H__
-#define BOTAN_FREESTORE_H__
-
-#include <botan/build.h>
-
-#if defined(BOTAN_USE_STD_TR1)
- #include <tr1/memory>
-#elif defined(BOTAN_USE_BOOST_TR1)
- #include <boost/tr1/memory.hpp>
-#else
- #error "Please choose a TR1 implementation in build.h"
-#endif
-
-namespace Botan {
-
-/**
-* This class is intended as an function call parameter type and
-* enables convenient automatic conversions between plain and smart
-* pointer types. It internally stores a SharedPointer which can be
-* accessed.
-*/
-template<typename T>
-class BOTAN_DLL SharedPtrConverter
- {
- public:
- typedef std::tr1::shared_ptr<T> SharedPtr;
-
- /**
- * Construct a null pointer equivalent object.
- */
- SharedPtrConverter() : ptr() {}
-
- /**
- * Copy constructor.
- */
- SharedPtrConverter(SharedPtrConverter const& other) :
- ptr(other.ptr) {}
-
- /**
- * Construct a converter object from another pointer type.
- * @param p the pointer which shall be set as the internally stored
- * pointer value of this converter.
- */
- template<typename Ptr>
- SharedPtrConverter(Ptr p)
- : ptr(p) {}
-
- /**
- * Get the internally stored shared pointer.
- * @return the internally stored shared pointer
- */
- SharedPtr const& get_ptr() const { return this->ptr; }
-
- /**
- * Get the internally stored shared pointer.
- * @return the internally stored shared pointer
- */
- SharedPtr get_ptr() { return this->ptr; }
-
- /**
- * Get the internally stored shared pointer.
- * @return the internally stored shared pointer
- */
- SharedPtr const& get_shared() const { return this->ptr; }
-
- /**
- * Get the internally stored shared pointer.
- * @return the internally stored shared pointer
- */
- SharedPtr get_shared() { return this->ptr; }
-
- private:
- SharedPtr ptr;
- };
-
-}
-
-#endif
diff --git a/src/cert/cvc/info.txt b/src/cert/cvc/info.txt
index 2033b9576..f3cf42a0e 100644
--- a/src/cert/cvc/info.txt
+++ b/src/cert/cvc/info.txt
@@ -1,7 +1,5 @@
define CARD_VERIFIABLE_CERTIFICATES
-uses_tr1 yes
-
load_on auto
<header:public>
@@ -15,7 +13,6 @@ cvc_self.h
eac_asn_obj.h
eac_obj.h
ecdsa_sig.h
-freestore.h
signed_obj.h
</header:public>
diff --git a/src/cert/x509/x509_ext.cpp b/src/cert/x509/x509_ext.cpp
index 9a03c9d23..69b21d8b3 100644
--- a/src/cert/x509/x509_ext.cpp
+++ b/src/cert/x509/x509_ext.cpp
@@ -473,7 +473,7 @@ MemoryVector<byte> Certificate_Policies::encode_inner() const
{
// FIXME
#if 1
- throw Exception("Certificate_Policies::encode_inner: Bugged");
+ throw Internal_Error("Certificate_Policies::encode_inner: Bugged");
#else
std::vector<Policy_Information> policies;
diff --git a/src/checksum/crc24/crc24.cpp b/src/checksum/crc24/crc24.cpp
index e50b4d33e..5441020f5 100644
--- a/src/checksum/crc24/crc24.cpp
+++ b/src/checksum/crc24/crc24.cpp
@@ -6,7 +6,7 @@
*/
#include <botan/crc24.h>
-#include <botan/loadstor.h>
+#include <botan/get_byte.h>
namespace Botan {
diff --git a/src/cms/cms_dalg.cpp b/src/cms/cms_dalg.cpp
index 7ed793f4f..1fc4e2faa 100644
--- a/src/cms/cms_dalg.cpp
+++ b/src/cms/cms_dalg.cpp
@@ -195,7 +195,7 @@ void CMS_Decoder::decode_layer()
else if(type == OIDS::lookup("CMS.SignedData"))
{
#if 1
- throw Exception("FIXME: not implemented");
+ throw Internal_Error("FIXME: not implemented");
#else
u32bit version;
@@ -258,11 +258,11 @@ void CMS_Decoder::decode_layer()
}
else if(type == OIDS::lookup("CMS.EnvelopedData"))
{
- throw Exception("FIXME: not implemented");
+ throw Internal_Error("FIXME: not implemented");
}
else if(type == OIDS::lookup("CMS.AuthenticatedData"))
{
- throw Exception("FIXME: not implemented");
+ throw Internal_Error("FIXME: not implemented");
}
else
throw Decoding_Error("CMS: Unknown content ID " + type.as_string());
diff --git a/src/cms/cms_dec.cpp b/src/cms/cms_dec.cpp
index 222399f6c..038d01869 100644
--- a/src/cms/cms_dec.cpp
+++ b/src/cms/cms_dec.cpp
@@ -17,7 +17,7 @@ namespace Botan {
* CMS_Decoder Constructor
*/
CMS_Decoder::CMS_Decoder(DataSource& in, const X509_Store& x509store,
- User_Interface& ui_ref, PKCS8_PrivateKey* key) :
+ User_Interface& ui_ref, Private_Key* key) :
ui(ui_ref), store(x509store)
{
status = GOOD;
@@ -57,7 +57,7 @@ void CMS_Decoder::initial_read(DataSource&)
/*
* Add another private key to use
*/
-void CMS_Decoder::add_key(PKCS8_PrivateKey* key)
+void CMS_Decoder::add_key(Private_Key* key)
{
if(!key)
return;
diff --git a/src/cms/cms_dec.h b/src/cms/cms_dec.h
index 75b61c9cb..a00b44766 100644
--- a/src/cms/cms_dec.h
+++ b/src/cms/cms_dec.h
@@ -37,10 +37,10 @@ class BOTAN_DLL CMS_Decoder
void next_layer() { decode_layer(); }
- void add_key(PKCS8_PrivateKey*);
+ void add_key(Private_Key*);
CMS_Decoder(DataSource&, const X509_Store&, User_Interface&,
- PKCS8_PrivateKey* = 0);
+ Private_Key* = 0);
private:
std::string get_passphrase(const std::string&);
void read_econtent(BER_Decoder&);
@@ -52,7 +52,7 @@ class BOTAN_DLL CMS_Decoder
X509_Store store;
std::vector<std::string> passphrases;
- std::vector<PKCS8_PrivateKey*> keys;
+ std::vector<Private_Key*> keys;
OID type, next_type;
SecureVector<byte> data;
diff --git a/src/cms/cms_ealg.cpp b/src/cms/cms_ealg.cpp
index 2970e8e79..60479a820 100644
--- a/src/cms/cms_ealg.cpp
+++ b/src/cms/cms_ealg.cpp
@@ -97,7 +97,7 @@ void CMS_Encoder::encrypt(RandomNumberGenerator& rng,
{
const std::string cipher = choose_algo(user_cipher, "TripleDES");
- std::auto_ptr<X509_PublicKey> key(to.subject_public_key());
+ std::auto_ptr<Public_Key> key(to.subject_public_key());
const std::string algo = key->algo_name();
Key_Constraints constraints = to.constraints();
@@ -165,10 +165,10 @@ void CMS_Encoder::encrypt_ktri(RandomNumberGenerator& rng,
*/
void CMS_Encoder::encrypt_kari(RandomNumberGenerator&,
const X509_Certificate&,
- X509_PublicKey*,
+ Public_Key*,
const std::string&)
{
- throw Exception("FIXME: unimplemented");
+ throw Internal_Error("FIXME: unimplemented");
#if 0
SymmetricKey cek = setup_key(rng, cipher);
@@ -198,7 +198,7 @@ void CMS_Encoder::encrypt(RandomNumberGenerator& rng,
const SymmetricKey& kek,
const std::string& user_cipher)
{
- throw Exception("FIXME: untested");
+ throw Internal_Error("FIXME: untested");
const std::string cipher = choose_algo(user_cipher, "TripleDES");
SymmetricKey cek = setup_key(rng, cipher);
@@ -232,7 +232,7 @@ void CMS_Encoder::encrypt(RandomNumberGenerator&,
const std::string& user_cipher)
{
const std::string cipher = choose_algo(user_cipher, "TripleDES");
- throw Exception("FIXME: unimplemented");
+ throw Internal_Error("FIXME: unimplemented");
/*
SymmetricKey cek = setup_key(key);
@@ -287,7 +287,7 @@ SecureVector<byte> CMS_Encoder::do_encrypt(RandomNumberGenerator& rng,
* Sign a message
*/
void CMS_Encoder::sign(const X509_Certificate& cert,
- const PKCS8_PrivateKey& key,
+ const Private_Key& key,
RandomNumberGenerator& rng,
const std::vector<X509_Certificate>& chain,
const std::string& hash,
@@ -375,7 +375,7 @@ void CMS_Encoder::authenticate(const X509_Certificate&,
const std::string& mac_algo)
{
const std::string mac = choose_algo(mac_algo, "HMAC(SHA-1)");
- throw Exception("FIXME: unimplemented");
+ throw Internal_Error("FIXME: unimplemented");
}
/*
@@ -385,7 +385,7 @@ void CMS_Encoder::authenticate(const SymmetricKey&,
const std::string& mac_algo)
{
const std::string mac = choose_algo(mac_algo, "HMAC(SHA-1)");
- throw Exception("FIXME: unimplemented");
+ throw Internal_Error("FIXME: unimplemented");
}
/*
@@ -395,7 +395,7 @@ void CMS_Encoder::authenticate(const std::string&,
const std::string& mac_algo)
{
const std::string mac = choose_algo(mac_algo, "HMAC(SHA-1)");
- throw Exception("FIXME: unimplemented");
+ throw Internal_Error("FIXME: unimplemented");
}
}
diff --git a/src/cms/cms_enc.h b/src/cms/cms_enc.h
index 6fdd2b726..b1e18ef7d 100644
--- a/src/cms/cms_enc.h
+++ b/src/cms/cms_enc.h
@@ -36,7 +36,7 @@ class BOTAN_DLL CMS_Encoder
void authenticate(const SymmetricKey&, const std::string& = "");
void sign(const X509_Certificate& cert,
- const PKCS8_PrivateKey& key,
+ const Private_Key& key,
RandomNumberGenerator& rng,
const std::vector<X509_Certificate>& cert_chain,
const std::string& hash,
@@ -62,7 +62,7 @@ class BOTAN_DLL CMS_Encoder
const X509_Certificate&, PK_Encrypting_Key*,
const std::string&);
void encrypt_kari(RandomNumberGenerator&,
- const X509_Certificate&, X509_PublicKey*,
+ const X509_Certificate&, Public_Key*,
const std::string&);
SecureVector<byte> do_encrypt(RandomNumberGenerator& rng,
diff --git a/src/constructs/aont/package.cpp b/src/constructs/aont/package.cpp
index 8d2d7257d..5d1e674ca 100644
--- a/src/constructs/aont/package.cpp
+++ b/src/constructs/aont/package.cpp
@@ -9,7 +9,7 @@
#include <botan/package.h>
#include <botan/filters.h>
#include <botan/ctr.h>
-#include <botan/loadstor.h>
+#include <botan/get_byte.h>
#include <botan/internal/xor_buf.h>
namespace Botan {
diff --git a/src/constructs/cryptobox/cryptobox.cpp b/src/constructs/cryptobox/cryptobox.cpp
index ba7553c55..371b52e66 100644
--- a/src/constructs/cryptobox/cryptobox.cpp
+++ b/src/constructs/cryptobox/cryptobox.cpp
@@ -13,7 +13,7 @@
#include <botan/hmac.h>
#include <botan/pbkdf2.h>
#include <botan/pem.h>
-#include <botan/loadstor.h>
+#include <botan/get_byte.h>
#include <botan/mem_ops.h>
namespace Botan {
@@ -48,10 +48,10 @@ std::string encrypt(const byte input[], u32bit input_len,
rng.randomize(pbkdf_salt.begin(), pbkdf_salt.size());
PKCS5_PBKDF2 pbkdf(new HMAC(new SHA_512));
- pbkdf.change_salt(pbkdf_salt.begin(), pbkdf_salt.size());
- pbkdf.set_iterations(PBKDF_ITERATIONS);
- OctetString mk = pbkdf.derive_key(PBKDF_OUTPUT_LEN, passphrase);
+ OctetString mk = pbkdf.derive_key(PBKDF_OUTPUT_LEN, passphrase,
+ &pbkdf_salt[0], pbkdf_salt.size(),
+ PBKDF_ITERATIONS);
SymmetricKey cipher_key(mk.begin(), CIPHER_KEY_LEN);
SymmetricKey mac_key(mk.begin() + CIPHER_KEY_LEN, MAC_KEY_LEN);
@@ -109,10 +109,10 @@ std::string decrypt(const byte input[], u32bit input_len,
SecureVector<byte> pbkdf_salt(ciphertext + VERSION_CODE_LEN, PBKDF_SALT_LEN);
PKCS5_PBKDF2 pbkdf(new HMAC(new SHA_512));
- pbkdf.change_salt(pbkdf_salt.begin(), pbkdf_salt.size());
- pbkdf.set_iterations(PBKDF_ITERATIONS);
- OctetString mk = pbkdf.derive_key(PBKDF_OUTPUT_LEN, passphrase);
+ OctetString mk = pbkdf.derive_key(PBKDF_OUTPUT_LEN, passphrase,
+ &pbkdf_salt[0], pbkdf_salt.size(),
+ PBKDF_ITERATIONS);
SymmetricKey cipher_key(mk.begin(), CIPHER_KEY_LEN);
SymmetricKey mac_key(mk.begin() + CIPHER_KEY_LEN, MAC_KEY_LEN);
@@ -135,7 +135,7 @@ std::string decrypt(const byte input[], u32bit input_len,
if(!same_mem(computed_mac, ciphertext + VERSION_CODE_LEN + PBKDF_SALT_LEN,
MAC_OUTPUT_LEN))
- throw Integrity_Failure("CryptoBox integrity failure");
+ throw Decoding_Error("CryptoBox integrity failure");
return pipe.read_all_as_string(0);
}
diff --git a/src/constructs/fpe/fpe.cpp b/src/constructs/fpe/fpe.cpp
index 86e56625d..a0b3274b5 100644
--- a/src/constructs/fpe/fpe.cpp
+++ b/src/constructs/fpe/fpe.cpp
@@ -12,7 +12,7 @@
#include <botan/numthry.h>
#include <botan/hmac.h>
#include <botan/sha2_32.h>
-#include <botan/loadstor.h>
+#include <botan/get_byte.h>
#include <stdexcept>
namespace Botan {
diff --git a/src/constructs/passhash/info.txt b/src/constructs/passhash/info.txt
new file mode 100644
index 000000000..f96809f29
--- /dev/null
+++ b/src/constructs/passhash/info.txt
@@ -0,0 +1,9 @@
+define PASSHASH9
+
+<requires>
+libstate
+pbkdf2
+rng
+base64
+</requires>
+
diff --git a/src/constructs/passhash/passhash9.cpp b/src/constructs/passhash/passhash9.cpp
new file mode 100644
index 000000000..9e5ff3257
--- /dev/null
+++ b/src/constructs/passhash/passhash9.cpp
@@ -0,0 +1,127 @@
+/*
+* Passhash9 Password Hashing
+* (C) 2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/passhash9.h>
+#include <botan/loadstor.h>
+#include <botan/libstate.h>
+#include <botan/pbkdf2.h>
+#include <botan/base64.h>
+#include <botan/pipe.h>
+
+namespace Botan {
+
+namespace {
+
+const std::string MAGIC_PREFIX = "$9$";
+
+const u32bit WORKFACTOR_BYTES = 2;
+const u32bit ALGID_BYTES = 1;
+const u32bit SALT_BYTES = 12; // 96 bits of salt
+const u32bit PBKDF_OUTPUT_LEN = 24; // 192 bits output
+
+const u32bit WORK_FACTOR_SCALE = 10000;
+
+MessageAuthenticationCode* get_pbkdf_prf(byte alg_id)
+ {
+ Algorithm_Factory& af = global_state().algorithm_factory();
+
+ if(alg_id == 0)
+ return af.make_mac("HMAC(SHA-1)");
+
+ return 0;
+ }
+
+std::pair<byte, MessageAuthenticationCode*> choose_pbkdf_prf()
+ {
+ byte alg_id = 0;
+ return std::make_pair(alg_id, get_pbkdf_prf(alg_id));
+ }
+
+}
+
+std::string generate_passhash9(const std::string& pass,
+ RandomNumberGenerator& rng,
+ u16bit work_factor)
+ {
+ std::pair<byte, MessageAuthenticationCode*> prf = choose_pbkdf_prf();
+ byte alg_id = prf.first;
+
+ PKCS5_PBKDF2 kdf(prf.second); // takes ownership of pointer
+
+ SecureVector<byte> salt(SALT_BYTES);
+ rng.randomize(&salt[0], salt.size());
+
+ u32bit kdf_iterations = WORK_FACTOR_SCALE * work_factor;
+
+ SecureVector<byte> pbkdf2_output =
+ kdf.derive_key(PBKDF_OUTPUT_LEN, pass,
+ &salt[0], salt.size(),
+ kdf_iterations).bits_of();
+
+ Pipe pipe(new Base64_Encoder);
+ pipe.start_msg();
+ pipe.write(alg_id);
+ pipe.write(get_byte(0, work_factor));
+ pipe.write(get_byte(1, work_factor));
+ pipe.write(salt);
+ pipe.write(pbkdf2_output);
+ pipe.end_msg();
+
+ return MAGIC_PREFIX + pipe.read_all_as_string();
+ }
+
+bool check_passhash9(const std::string& pass, const std::string& hash)
+ {
+ const u32bit BINARY_LENGTH =
+ (ALGID_BYTES + WORKFACTOR_BYTES + PBKDF_OUTPUT_LEN + SALT_BYTES);
+
+ const u32bit BASE64_LENGTH =
+ MAGIC_PREFIX.size() + (BINARY_LENGTH * 8) / 6;
+
+ if(hash.size() != BASE64_LENGTH)
+ return false;
+
+ for(size_t i = 0; i != MAGIC_PREFIX.size(); ++i)
+ if(hash[i] != MAGIC_PREFIX[i])
+ return false;
+
+ Pipe pipe(new Base64_Decoder);
+ pipe.start_msg();
+ pipe.write(hash.c_str() + MAGIC_PREFIX.size());
+ pipe.end_msg();
+
+ SecureVector<byte> bin = pipe.read_all();
+
+ if(bin.size() != BINARY_LENGTH)
+ return false;
+
+ byte alg_id = bin[0];
+
+ u32bit kdf_iterations =
+ WORK_FACTOR_SCALE * load_be<u16bit>(bin + ALGID_BYTES, 0);
+
+ if(kdf_iterations == 0)
+ return false;
+
+ MessageAuthenticationCode* pbkdf_prf = get_pbkdf_prf(alg_id);
+
+ if(pbkdf_prf == 0)
+ return false; // unknown algorithm, reject
+
+ PKCS5_PBKDF2 kdf(pbkdf_prf); // takes ownership of pointer
+
+ SecureVector<byte> cmp = kdf.derive_key(
+ PBKDF_OUTPUT_LEN, pass,
+ &bin[ALGID_BYTES + WORKFACTOR_BYTES], SALT_BYTES,
+ kdf_iterations).bits_of();
+
+ return same_mem(cmp.begin(),
+ bin.begin() + ALGID_BYTES + WORKFACTOR_BYTES + SALT_BYTES,
+ PBKDF_OUTPUT_LEN);
+ }
+
+}
diff --git a/src/constructs/passhash/passhash9.h b/src/constructs/passhash/passhash9.h
new file mode 100644
index 000000000..6020dce42
--- /dev/null
+++ b/src/constructs/passhash/passhash9.h
@@ -0,0 +1,35 @@
+/*
+* Passhash9 Password Hashing
+* (C) 2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PASSHASH9_H__
+#define BOTAN_PASSHASH9_H__
+
+#include <botan/rng.h>
+
+namespace Botan {
+
+/**
+* Create a password hash using PBKDF2
+* @param password the password
+* @param rng a random number generator
+* @Param work_factor how much work to do to slow down guessing attacks
+*/
+std::string BOTAN_DLL generate_passhash9(const std::string& password,
+ RandomNumberGenerator& rng,
+ u16bit work_factor = 10);
+
+/**
+* Check a previously created password hash
+* @param password the password to check against
+* @param hash the stored hash to check against
+*/
+bool BOTAN_DLL check_passhash9(const std::string& password,
+ const std::string& hash);
+
+}
+
+#endif
diff --git a/src/engine/aes_isa_eng/aes_isa_engine.cpp b/src/engine/aes_isa_eng/aes_isa_engine.cpp
index e57e4278d..682dfe6b1 100644
--- a/src/engine/aes_isa_eng/aes_isa_engine.cpp
+++ b/src/engine/aes_isa_eng/aes_isa_engine.cpp
@@ -5,17 +5,13 @@
* Distributed under the terms of the Botan license
*/
-#include <botan/aes_isa_engine.h>
+#include <botan/internal/aes_isa_engine.h>
#include <botan/cpuid.h>
#if defined(BOTAN_HAS_AES_INTEL)
#include <botan/aes_intel.h>
#endif
-#if defined(BOTAN_HAS_AES_VIA)
- #include <botan/aes_via.h>
-#endif
-
namespace Botan {
BlockCipher*
@@ -34,18 +30,6 @@ AES_ISA_Engine::find_block_cipher(const SCAN_Name& request,
}
#endif
-#if defined(BOTAN_HAS_AES_VIA)
- if(CPUID::has_aes_via())
- {
- if(request.algo_name() == "AES-128")
- return new AES_128_VIA;
- if(request.algo_name() == "AES-192")
- return new AES_192_VIA;
- if(request.algo_name() == "AES-256")
- return new AES_256_VIA;
- }
-#endif
-
return 0;
}
diff --git a/src/engine/def_engine/lookup_block.cpp b/src/engine/def_engine/lookup_block.cpp
index cdad76c46..097a471b7 100644
--- a/src/engine/def_engine/lookup_block.cpp
+++ b/src/engine/def_engine/lookup_block.cpp
@@ -22,6 +22,10 @@
#include <botan/cast256.h>
#endif
+#if defined(BOTAN_HAS_CASCADE)
+ #include <botan/cascade.h>
+#endif
+
#if defined(BOTAN_HAS_DES)
#include <botan/des.h>
#include <botan/desx.h>
@@ -240,6 +244,17 @@ Default_Engine::find_block_cipher(const SCAN_Name& request,
}
#endif
+#if defined(BOTAN_HAS_CASCADE)
+ if(request.algo_name() == "Cascade" && request.arg_count() == 2)
+ {
+ const BlockCipher* c1 = af.prototype_block_cipher(request.arg(0));
+ const BlockCipher* c2 = af.prototype_block_cipher(request.arg(1));
+
+ if(c1 && c2)
+ return new Cascade_Cipher(c1->clone(), c2->clone());
+ }
+#endif
+
#if defined(BOTAN_HAS_LION)
if(request.algo_name() == "Lion" && request.arg_count_between(2, 3))
{
diff --git a/src/engine/gnump/gmp_mem.cpp b/src/engine/gnump/gmp_mem.cpp
index 59e0cc4c5..f3650e716 100644
--- a/src/engine/gnump/gmp_mem.cpp
+++ b/src/engine/gnump/gmp_mem.cpp
@@ -1,6 +1,6 @@
/*
* GNU MP Memory Handlers
-* (C) 1999-2007 Jack Lloyd
+* (C) 1999-2010 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
@@ -17,6 +17,7 @@ namespace {
* Allocator used by GNU MP
*/
Allocator* gmp_alloc = 0;
+u32bit gmp_alloc_refcnt = 0;
/*
* Allocation Function for GNU MP
@@ -48,23 +49,28 @@ void gmp_free(void* ptr, size_t n)
}
/*
-* Set the GNU MP memory functions
+* GMP_Engine Constructor
*/
-void GMP_Engine::set_memory_hooks()
+GMP_Engine::GMP_Engine()
{
if(gmp_alloc == 0)
{
gmp_alloc = Allocator::get(true);
mp_set_memory_functions(gmp_malloc, gmp_realloc, gmp_free);
}
+
+ ++gmp_alloc_refcnt;
}
-/*
-* GMP_Engine Constructor
-*/
-GMP_Engine::GMP_Engine()
+GMP_Engine::~GMP_Engine()
{
- set_memory_hooks();
+ --gmp_alloc_refcnt;
+
+ if(gmp_alloc_refcnt == 0)
+ {
+ mp_set_memory_functions(NULL, NULL, NULL);
+ gmp_alloc = 0;
+ }
}
}
diff --git a/src/engine/gnump/gnump_engine.h b/src/engine/gnump/gnump_engine.h
index ec4a7e721..d0b070441 100644
--- a/src/engine/gnump/gnump_engine.h
+++ b/src/engine/gnump/gnump_engine.h
@@ -18,6 +18,9 @@ namespace Botan {
class GMP_Engine : public Engine
{
public:
+ GMP_Engine();
+ ~GMP_Engine();
+
std::string provider_name() const { return "gmp"; }
#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY)
@@ -46,10 +49,6 @@ class GMP_Engine : public Engine
Modular_Exponentiator* mod_exp(const BigInt&,
Power_Mod::Usage_Hints) const;
-
- GMP_Engine();
- private:
- static void set_memory_hooks();
};
}
diff --git a/src/engine/simd_engine/simd_engine.cpp b/src/engine/simd_engine/simd_engine.cpp
index b8ebd6a80..e889ca161 100644
--- a/src/engine/simd_engine/simd_engine.cpp
+++ b/src/engine/simd_engine/simd_engine.cpp
@@ -13,6 +13,10 @@
#include <botan/serp_simd.h>
#endif
+#if defined(BOTAN_HAS_NOEKEON_SIMD)
+ #include <botan/noekeon_simd.h>
+#endif
+
#if defined(BOTAN_HAS_XTEA_SIMD)
#include <botan/xtea_simd.h>
#endif
@@ -36,6 +40,11 @@ SIMD_Engine::find_block_cipher(const SCAN_Name& request,
return new IDEA_SSE2;
#endif
+#if defined(BOTAN_HAS_NOEKEON_SIMD)
+ if(request.algo_name() == "Noekeon" && SIMD_32::enabled())
+ return new Noekeon_SIMD;
+#endif
+
#if defined(BOTAN_HAS_SERPENT_SIMD)
if(request.algo_name() == "Serpent" && SIMD_32::enabled())
return new Serpent_SIMD;
diff --git a/src/entropy/hres_timer/hres_timer.cpp b/src/entropy/hres_timer/hres_timer.cpp
index d06ca7a9d..e1b4928df 100644
--- a/src/entropy/hres_timer/hres_timer.cpp
+++ b/src/entropy/hres_timer/hres_timer.cpp
@@ -31,7 +31,7 @@ void High_Resolution_Timestamp::poll(Entropy_Accumulator& accum)
u64bit rtc = 0;
-#if defined(BOTAN_TARGET_ARCH_IS_IA32) || defined(BOTAN_TARGET_ARCH_IS_AMD64)
+#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
if(CPUID::has_rdtsc()) // not availble on all x86 CPUs
{
u32bit rtc_low = 0, rtc_high = 0;
@@ -39,7 +39,7 @@ void High_Resolution_Timestamp::poll(Entropy_Accumulator& accum)
rtc = (static_cast<u64bit>(rtc_high) << 32) | rtc_low;
}
-#elif defined(BOTAN_TARGET_ARCH_IS_PPC) || defined(BOTAN_TARGET_ARCH_IS_PPC64)
+#elif defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
u32bit rtc_low = 0, rtc_high = 0;
asm volatile("mftbu %0; mftb %1" : "=r" (rtc_high), "=r" (rtc_low));
rtc = (static_cast<u64bit>(rtc_high) << 32) | rtc_low;
diff --git a/src/filters/buf_filt.cpp b/src/filters/buf_filt.cpp
index 0509e76e2..897fd9be7 100644
--- a/src/filters/buf_filt.cpp
+++ b/src/filters/buf_filt.cpp
@@ -1,71 +1,103 @@
/*
-* Buffering Filter
+* Buffered Filter
* (C) 1999-2007 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
#include <botan/buf_filt.h>
-#include <botan/exceptn.h>
-#include <algorithm>
+#include <botan/mem_ops.h>
+#include <botan/internal/rounding.h>
+#include <stdexcept>
namespace Botan {
/*
-* Buffering_Filter Constructor
+* Buffered_Filter Constructor
*/
-Buffering_Filter::Buffering_Filter(u32bit b, u32bit i) : INITIAL_BLOCK_SIZE(i),
- BLOCK_SIZE(b)
+Buffered_Filter::Buffered_Filter(u32bit b, u32bit f) :
+ main_block_mod(b), final_minimum(f)
{
- initial_block_pos = block_pos = 0;
- initial.resize(INITIAL_BLOCK_SIZE);
- block.resize(BLOCK_SIZE);
+ if(main_block_mod == 0)
+ throw std::invalid_argument("main_block_mod == 0");
+
+ if(final_minimum > main_block_mod)
+ throw std::invalid_argument("final_minimum > main_block_mod");
+
+ buffer.resize(2 * main_block_mod);
+ buffer_pos = 0;
}
/*
-* Reset the Buffering Filter
+* Buffer input into blocks, trying to minimize copying
*/
-void Buffering_Filter::end_msg()
+void Buffered_Filter::write(const byte input[], u32bit input_size)
{
- if(initial_block_pos != INITIAL_BLOCK_SIZE)
- throw Exception("Buffering_Filter: Not enough data for first block");
- final_block(block, block_pos);
- initial_block_pos = block_pos = 0;
- initial.clear();
- block.clear();
+ if(!input_size)
+ return;
+
+ if(buffer_pos + input_size >= main_block_mod + final_minimum)
+ {
+ u32bit to_copy = std::min<u32bit>(buffer.size() - buffer_pos, input_size);
+
+ copy_mem(&buffer[buffer_pos], input, to_copy);
+ buffer_pos += to_copy;
+
+ input += to_copy;
+ input_size -= to_copy;
+
+ u32bit total_to_consume =
+ round_down(std::min(buffer_pos,
+ buffer_pos + input_size - final_minimum),
+ main_block_mod);
+
+ buffered_block(&buffer[0], total_to_consume);
+
+ buffer_pos -= total_to_consume;
+
+ copy_mem(&buffer[0], &buffer[total_to_consume], buffer_pos);
+ }
+
+ if(input_size >= final_minimum)
+ {
+ u32bit full_blocks = (input_size - final_minimum) / main_block_mod;
+ u32bit to_copy = full_blocks * main_block_mod;
+
+ if(to_copy)
+ {
+ buffered_block(input, to_copy);
+
+ input += to_copy;
+ input_size -= to_copy;
+ }
+ }
+
+ copy_mem(&buffer[buffer_pos], input, input_size);
+ buffer_pos += input_size;
}
/*
-* Buffer input into blocks
+* Finish/flush operation
*/
-void Buffering_Filter::write(const byte input[], u32bit length)
+void Buffered_Filter::end_msg()
{
- if(initial_block_pos != INITIAL_BLOCK_SIZE)
+ if(buffer_pos < final_minimum)
+ throw std::runtime_error("Buffered_Operation::final - not enough input");
+
+ u32bit spare_blocks = (buffer_pos - final_minimum) / main_block_mod;
+
+ if(spare_blocks)
{
- u32bit copied = std::min(INITIAL_BLOCK_SIZE - initial_block_pos, length);
- initial.copy(initial_block_pos, input, copied);
- input += copied;
- length -= copied;
- initial_block_pos += copied;
- if(initial_block_pos == INITIAL_BLOCK_SIZE)
- initial_block(initial);
+ u32bit spare_bytes = main_block_mod * spare_blocks;
+ buffered_block(&buffer[0], spare_bytes);
+ buffered_final(&buffer[spare_bytes], buffer_pos - spare_bytes);
}
- block.copy(block_pos, input, length);
- if(block_pos + length >= BLOCK_SIZE)
+ else
{
- main_block(block);
- input += (BLOCK_SIZE - block_pos);
- length -= (BLOCK_SIZE - block_pos);
- while(length >= BLOCK_SIZE)
- {
- main_block(input);
- input += BLOCK_SIZE;
- length -= BLOCK_SIZE;
- }
- block.copy(input, length);
- block_pos = 0;
+ buffered_final(&buffer[0], buffer_pos);
}
- block_pos += length;
+
+ buffer_pos = 0;
}
}
diff --git a/src/filters/buf_filt.h b/src/filters/buf_filt.h
index ce3dbc926..de4102844 100644
--- a/src/filters/buf_filt.h
+++ b/src/filters/buf_filt.h
@@ -1,37 +1,39 @@
/*
-* Buffering Filter
+* Buffered Filter
* (C) 1999-2007 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
-#ifndef BOTAN_BUFFERING_FILTER_H__
-#define BOTAN_BUFFERING_FILTER_H__
+#ifndef BOTAN_BUFFERED_FILTER_H__
+#define BOTAN_BUFFERED_FILTER_H__
-#include <botan/filter.h>
+#include <botan/secmem.h>
namespace Botan {
-/**
-* Buffering_Filter: This class represents filters for operations that
-* maintain an internal state.
-*/
-
-class BOTAN_DLL Buffering_Filter : public Filter
+class BOTAN_DLL Buffered_Filter
{
public:
void write(const byte[], u32bit);
- virtual void end_msg();
- Buffering_Filter(u32bit, u32bit = 0);
- virtual ~Buffering_Filter() {}
+ void end_msg();
+
+ Buffered_Filter(u32bit block_size, u32bit final_minimum);
+
+ virtual ~Buffered_Filter() {}
protected:
- virtual void initial_block(const byte[]) {}
- virtual void main_block(const byte[]) = 0;
- virtual void final_block(const byte[], u32bit) = 0;
+ virtual std::string name() const = 0;
+
+ virtual void buffered_block(const byte input[], u32bit length) = 0;
+ virtual void buffered_final(const byte input[], u32bit length) = 0;
+
+ u32bit current_position() const { return buffer_pos; }
+ void buffer_reset() { buffer_pos = 0; }
private:
- const u32bit INITIAL_BLOCK_SIZE, BLOCK_SIZE;
- SecureVector<byte> initial, block;
- u32bit initial_block_pos, block_pos;
+ u32bit main_block_mod, final_minimum;
+
+ SecureVector<byte> buffer;
+ u32bit buffer_pos;
};
}
diff --git a/src/filters/bzip2/bzip2.cpp b/src/filters/bzip2/bzip2.cpp
index 4cdca5355..9dcee8fdf 100644
--- a/src/filters/bzip2/bzip2.cpp
+++ b/src/filters/bzip2/bzip2.cpp
@@ -96,7 +96,7 @@ void Bzip_Compression::start_msg()
clear();
bz = new Bzip_Stream;
if(BZ2_bzCompressInit(&(bz->stream), level, 0, 0) != BZ_OK)
- throw Exception("Bzip_Compression: Memory allocation error");
+ throw Memory_Exhaustion();
}
/*
@@ -196,13 +196,15 @@ void Bzip_Decompression::write(const byte input_arr[], u32bit length)
if(rc != BZ_OK && rc != BZ_STREAM_END)
{
clear();
+
if(rc == BZ_DATA_ERROR)
throw Decoding_Error("Bzip_Decompression: Data integrity error");
- if(rc == BZ_DATA_ERROR_MAGIC)
+ else if(rc == BZ_DATA_ERROR_MAGIC)
throw Decoding_Error("Bzip_Decompression: Invalid input");
- if(rc == BZ_MEM_ERROR)
- throw Exception("Bzip_Decompression: Memory allocation error");
- throw Exception("Bzip_Decompression: Unknown decompress error");
+ else if(rc == BZ_MEM_ERROR)
+ throw Memory_Exhaustion();
+ else
+ throw std::runtime_error("Bzip2 decompression: Unknown error");
}
send(buffer, buffer.size() - bz->stream.avail_out);
@@ -228,7 +230,7 @@ void Bzip_Decompression::start_msg()
bz = new Bzip_Stream;
if(BZ2_bzDecompressInit(&(bz->stream), 0, small_mem) != BZ_OK)
- throw Exception("Bzip_Decompression: Memory allocation error");
+ throw Memory_Exhaustion();
no_writes = true;
}
@@ -252,7 +254,7 @@ void Bzip_Decompression::end_msg()
if(rc != BZ_OK && rc != BZ_STREAM_END)
{
clear();
- throw Exception("Bzip_Decompression: Error finalizing decompression");
+ throw Decoding_Error("Bzip_Decompression: Error finalizing");
}
send(buffer, buffer.size() - bz->stream.avail_out);
diff --git a/src/filters/filter.cpp b/src/filters/filter.cpp
index ca32a3801..ff223ae8c 100644
--- a/src/filters/filter.cpp
+++ b/src/filters/filter.cpp
@@ -6,7 +6,7 @@
*/
#include <botan/filter.h>
-#include <botan/internal/secqueue.h>
+#include <botan/secqueue.h>
#include <botan/exceptn.h>
namespace Botan {
diff --git a/src/filters/info.txt b/src/filters/info.txt
index 94b91371b..95d411c76 100644
--- a/src/filters/info.txt
+++ b/src/filters/info.txt
@@ -24,11 +24,11 @@ filters.h
key_filt.h
pbe.h
pipe.h
+secqueue.h
</header:public>
<header:internal>
out_buf.h
-secqueue.h
</header:internal>
<requires>
diff --git a/src/filters/modes/cbc/cbc.cpp b/src/filters/modes/cbc/cbc.cpp
index 48ecdf509..7722fad2f 100644
--- a/src/filters/modes/cbc/cbc.cpp
+++ b/src/filters/modes/cbc/cbc.cpp
@@ -16,14 +16,13 @@ namespace Botan {
*/
CBC_Encryption::CBC_Encryption(BlockCipher* ciph,
BlockCipherModePaddingMethod* pad) :
+ Buffered_Filter(ciph->BLOCK_SIZE, 0),
cipher(ciph), padder(pad)
{
if(!padder->valid_blocksize(cipher->BLOCK_SIZE))
throw Invalid_Block_Size(name(), padder->name());
- buffer.resize(cipher->BLOCK_SIZE);
state.resize(cipher->BLOCK_SIZE);
- position = 0;
}
/*
@@ -33,14 +32,13 @@ CBC_Encryption::CBC_Encryption(BlockCipher* ciph,
BlockCipherModePaddingMethod* pad,
const SymmetricKey& key,
const InitializationVector& iv) :
+ Buffered_Filter(ciph->BLOCK_SIZE, 0),
cipher(ciph), padder(pad)
{
if(!padder->valid_blocksize(cipher->BLOCK_SIZE))
throw Invalid_Block_Size(name(), padder->name());
- buffer.resize(cipher->BLOCK_SIZE);
state.resize(cipher->BLOCK_SIZE);
- position = 0;
set_key(key);
set_iv(iv);
@@ -55,41 +53,52 @@ void CBC_Encryption::set_iv(const InitializationVector& iv)
throw Invalid_IV_Length(name(), iv.length());
state = iv.bits_of();
- buffer.clear();
- position = 0;
+ buffer_reset();
}
/*
* Encrypt in CBC mode
*/
-void CBC_Encryption::write(const byte input[], u32bit length)
+void CBC_Encryption::buffered_block(const byte input[], u32bit length)
{
- while(length)
+ u32bit blocks = length / state.size();
+
+ for(u32bit i = 0; i != blocks; ++i)
{
- u32bit xored = std::min(cipher->BLOCK_SIZE - position, length);
- xor_buf(state + position, input, xored);
- input += xored;
- length -= xored;
- position += xored;
- if(position == cipher->BLOCK_SIZE)
- {
- cipher->encrypt(state);
- send(state, cipher->BLOCK_SIZE);
- position = 0;
- }
+ xor_buf(state, input + i * cipher->BLOCK_SIZE, state.size());
+ cipher->encrypt(state);
+ send(state, state.size());
}
}
/*
* Finish encrypting in CBC mode
*/
+void CBC_Encryption::buffered_final(const byte input[], u32bit length)
+ {
+ if(length % cipher->BLOCK_SIZE == 0)
+ buffered_block(input, length);
+ else if(length != 0)
+ throw Encoding_Error(name() + ": Did not pad to full blocksize");
+ }
+
+void CBC_Encryption::write(const byte input[], u32bit input_length)
+ {
+ Buffered_Filter::write(input, input_length);
+ }
+
void CBC_Encryption::end_msg()
{
+ u32bit last_block = current_position() % cipher->BLOCK_SIZE;
+
SecureVector<byte> padding(cipher->BLOCK_SIZE);
- padder->pad(padding, padding.size(), position);
- write(padding, padder->pad_bytes(cipher->BLOCK_SIZE, position));
- if(position != 0)
- throw Exception(name() + ": Did not pad to full blocksize");
+ padder->pad(padding, padding.size(), last_block);
+
+ u32bit pad_bytes = padder->pad_bytes(cipher->BLOCK_SIZE, last_block);
+
+ if(pad_bytes)
+ Buffered_Filter::write(padding, pad_bytes);
+ Buffered_Filter::end_msg();
}
/*
@@ -105,15 +114,15 @@ std::string CBC_Encryption::name() const
*/
CBC_Decryption::CBC_Decryption(BlockCipher* ciph,
BlockCipherModePaddingMethod* pad) :
+ Buffered_Filter(BOTAN_PARALLEL_BLOCKS_CBC * ciph->BLOCK_SIZE,
+ ciph->BLOCK_SIZE),
cipher(ciph), padder(pad)
{
if(!padder->valid_blocksize(cipher->BLOCK_SIZE))
throw Invalid_Block_Size(name(), padder->name());
- buffer.resize(cipher->BLOCK_SIZE);
state.resize(cipher->BLOCK_SIZE);
- temp.resize(cipher->BLOCK_SIZE);
- position = 0;
+ temp.resize(BOTAN_PARALLEL_BLOCKS_CBC * cipher->BLOCK_SIZE);
}
/*
@@ -123,15 +132,15 @@ CBC_Decryption::CBC_Decryption(BlockCipher* ciph,
BlockCipherModePaddingMethod* pad,
const SymmetricKey& key,
const InitializationVector& iv) :
+ Buffered_Filter(BOTAN_PARALLEL_BLOCKS_CBC * ciph->BLOCK_SIZE,
+ ciph->BLOCK_SIZE),
cipher(ciph), padder(pad)
{
if(!padder->valid_blocksize(cipher->BLOCK_SIZE))
throw Invalid_Block_Size(name(), padder->name());
- buffer.resize(cipher->BLOCK_SIZE);
state.resize(cipher->BLOCK_SIZE);
- temp.resize(cipher->BLOCK_SIZE);
- position = 0;
+ temp.resize(BOTAN_PARALLEL_BLOCKS_CBC * cipher->BLOCK_SIZE);
set_key(key);
set_iv(iv);
@@ -146,46 +155,74 @@ void CBC_Decryption::set_iv(const InitializationVector& iv)
throw Invalid_IV_Length(name(), iv.length());
state = iv.bits_of();
- buffer.clear();
- position = 0;
+ buffer_reset();
}
/*
* Decrypt in CBC mode
*/
-void CBC_Decryption::write(const byte input[], u32bit length)
+void CBC_Decryption::buffered_block(const byte input[], u32bit length)
{
- while(length)
+ const u32bit blocks_in_temp = temp.size() / cipher->BLOCK_SIZE;
+ u32bit blocks = length / cipher->BLOCK_SIZE;
+
+ while(blocks)
{
- if(position == cipher->BLOCK_SIZE)
- {
- cipher->decrypt(buffer, temp);
- xor_buf(temp, state, cipher->BLOCK_SIZE);
- send(temp, cipher->BLOCK_SIZE);
- state = buffer;
- position = 0;
- }
-
- u32bit added = std::min(cipher->BLOCK_SIZE - position, length);
- buffer.copy(position, input, added);
- input += added;
- length -= added;
- position += added;
+ u32bit to_proc = std::min<u32bit>(blocks, blocks_in_temp);
+
+ cipher->decrypt_n(input, &temp[0], to_proc);
+
+ xor_buf(temp, state, cipher->BLOCK_SIZE);
+
+ for(u32bit i = 1; i < to_proc; ++i)
+ xor_buf(temp + i * cipher->BLOCK_SIZE,
+ input + (i-1) * cipher->BLOCK_SIZE,
+ cipher->BLOCK_SIZE);
+
+ state.set(input + (to_proc - 1) * cipher->BLOCK_SIZE, cipher->BLOCK_SIZE);
+
+ send(temp, to_proc * cipher->BLOCK_SIZE);
+
+ input += to_proc * cipher->BLOCK_SIZE;
+ blocks -= to_proc;
}
}
/*
-* Finish decrypting in CBC mode
+* Finish encrypting in CBC mode
*/
-void CBC_Decryption::end_msg()
+void CBC_Decryption::buffered_final(const byte input[], u32bit length)
{
- if(position != cipher->BLOCK_SIZE)
- throw Decoding_Error(name());
- cipher->decrypt(buffer, temp);
+ if(length == 0 || length % cipher->BLOCK_SIZE != 0)
+ throw Decoding_Error(name() + ": Ciphertext not multiple of block size");
+
+ size_t extra_blocks = (length - 1) / cipher->BLOCK_SIZE;
+
+ buffered_block(input, extra_blocks * cipher->BLOCK_SIZE);
+
+ input += extra_blocks * cipher->BLOCK_SIZE;
+
+ cipher->decrypt(input, temp);
xor_buf(temp, state, cipher->BLOCK_SIZE);
send(temp, padder->unpad(temp, cipher->BLOCK_SIZE));
- state = buffer;
- position = 0;
+
+ state.set(input, state.size());
+ }
+
+/*
+* Decrypt in CBC mode
+*/
+void CBC_Decryption::write(const byte input[], u32bit length)
+ {
+ Buffered_Filter::write(input, length);
+ }
+
+/*
+* Finish decrypting in CBC mode
+*/
+void CBC_Decryption::end_msg()
+ {
+ Buffered_Filter::end_msg();
}
/*
diff --git a/src/filters/modes/cbc/cbc.h b/src/filters/modes/cbc/cbc.h
index 91ab21ab6..6d9092041 100644
--- a/src/filters/modes/cbc/cbc.h
+++ b/src/filters/modes/cbc/cbc.h
@@ -11,13 +11,15 @@
#include <botan/block_cipher.h>
#include <botan/key_filt.h>
#include <botan/mode_pad.h>
+#include <botan/buf_filt.h>
namespace Botan {
/*
* CBC Encryption
*/
-class BOTAN_DLL CBC_Encryption : public Keyed_Filter
+class BOTAN_DLL CBC_Encryption : public Keyed_Filter,
+ private Buffered_Filter
{
public:
std::string name() const;
@@ -37,21 +39,24 @@ class BOTAN_DLL CBC_Encryption : public Keyed_Filter
const SymmetricKey& key,
const InitializationVector& iv);
- ~CBC_Encryption() { delete padder; }
+ ~CBC_Encryption() { delete cipher; delete padder; }
private:
- void write(const byte[], u32bit);
+ void buffered_block(const byte input[], u32bit input_length);
+ void buffered_final(const byte input[], u32bit input_length);
+
+ void write(const byte input[], u32bit input_length);
void end_msg();
BlockCipher* cipher;
const BlockCipherModePaddingMethod* padder;
- SecureVector<byte> buffer, state;
- u32bit position;
+ SecureVector<byte> state;
};
/*
* CBC Decryption
*/
-class BOTAN_DLL CBC_Decryption : public Keyed_Filter
+class BOTAN_DLL CBC_Decryption : public Keyed_Filter,
+ private Buffered_Filter
{
public:
std::string name() const;
@@ -71,15 +76,17 @@ class BOTAN_DLL CBC_Decryption : public Keyed_Filter
const SymmetricKey& key,
const InitializationVector& iv);
- ~CBC_Decryption() { delete padder; }
+ ~CBC_Decryption() { delete cipher; delete padder; }
private:
+ void buffered_block(const byte input[], u32bit input_length);
+ void buffered_final(const byte input[], u32bit input_length);
+
void write(const byte[], u32bit);
void end_msg();
BlockCipher* cipher;
const BlockCipherModePaddingMethod* padder;
- SecureVector<byte> buffer, state, temp;
- u32bit position;
+ SecureVector<byte> state, temp;
};
}
diff --git a/src/filters/modes/cfb/cfb.h b/src/filters/modes/cfb/cfb.h
index 917125e46..249ae21db 100644
--- a/src/filters/modes/cfb/cfb.h
+++ b/src/filters/modes/cfb/cfb.h
@@ -34,6 +34,8 @@ class BOTAN_DLL CFB_Encryption : public Keyed_Filter
const SymmetricKey& key,
const InitializationVector& iv,
u32bit feedback = 0);
+
+ ~CFB_Encryption() { delete cipher; }
private:
void write(const byte[], u32bit);
@@ -63,6 +65,8 @@ class BOTAN_DLL CFB_Decryption : public Keyed_Filter
const SymmetricKey& key,
const InitializationVector& iv,
u32bit feedback = 0);
+
+ ~CFB_Decryption() { delete cipher; }
private:
void write(const byte[], u32bit);
diff --git a/src/filters/modes/cts/cts.cpp b/src/filters/modes/cts/cts.cpp
index 3a15a1d68..b27b9b3c5 100644
--- a/src/filters/modes/cts/cts.cpp
+++ b/src/filters/modes/cts/cts.cpp
@@ -101,7 +101,8 @@ void CTS_Encryption::write(const byte input[], u32bit length)
void CTS_Encryption::end_msg()
{
if(position < cipher->BLOCK_SIZE + 1)
- throw Exception("CTS_Encryption: insufficient data to encrypt");
+ throw Encoding_Error(name() + ": insufficient data to encrypt");
+
xor_buf(state, buffer, cipher->BLOCK_SIZE);
cipher->encrypt(state);
SecureVector<byte> cn = state;
diff --git a/src/filters/modes/cts/cts.h b/src/filters/modes/cts/cts.h
index 4a7513fa0..c15fa9510 100644
--- a/src/filters/modes/cts/cts.h
+++ b/src/filters/modes/cts/cts.h
@@ -33,6 +33,8 @@ class BOTAN_DLL CTS_Encryption : public Keyed_Filter
CTS_Encryption(BlockCipher* cipher,
const SymmetricKey& key,
const InitializationVector& iv);
+
+ ~CTS_Encryption() { delete cipher; }
private:
void write(const byte[], u32bit);
void end_msg();
@@ -63,6 +65,8 @@ class BOTAN_DLL CTS_Decryption : public Keyed_Filter
CTS_Decryption(BlockCipher* cipher,
const SymmetricKey& key,
const InitializationVector& iv);
+
+ ~CTS_Decryption() { delete cipher; }
private:
void write(const byte[], u32bit);
void end_msg();
diff --git a/src/filters/modes/eax/eax_dec.cpp b/src/filters/modes/eax/eax_dec.cpp
index f41327ffc..998773697 100644
--- a/src/filters/modes/eax/eax_dec.cpp
+++ b/src/filters/modes/eax/eax_dec.cpp
@@ -98,13 +98,13 @@ void EAX_Decryption::do_write(const byte input[], u32bit length)
void EAX_Decryption::end_msg()
{
if((queue_end - queue_start) != TAG_SIZE)
- throw Integrity_Failure(name() + ": Message authentication failure");
+ throw Decoding_Error(name() + ": Message authentication failure");
SecureVector<byte> data_mac = cmac->final();
for(u32bit j = 0; j != TAG_SIZE; ++j)
if(queue[queue_start+j] != (data_mac[j] ^ nonce_mac[j] ^ header_mac[j]))
- throw Integrity_Failure(name() + ": Message authentication failure");
+ throw Decoding_Error(name() + ": Message authentication failure");
queue_start = queue_end = 0;
}
diff --git a/src/filters/modes/ecb/ecb.cpp b/src/filters/modes/ecb/ecb.cpp
index bff6d70f4..2ce6576e3 100644
--- a/src/filters/modes/ecb/ecb.cpp
+++ b/src/filters/modes/ecb/ecb.cpp
@@ -1,6 +1,6 @@
/*
* ECB Mode
-* (C) 1999-2007 Jack Lloyd
+* (C) 1999-2009 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
@@ -9,25 +9,17 @@
namespace Botan {
-namespace {
-
-const u32bit PARALLEL_BLOCKS = BOTAN_PARALLEL_BLOCKS_ECB;
-
-}
-
/*
* ECB_Encryption Constructor
*/
ECB_Encryption::ECB_Encryption(BlockCipher* ciph,
- BlockCipherModePaddingMethod* pad)
+ BlockCipherModePaddingMethod* pad) :
+ Buffered_Filter(ciph->BLOCK_SIZE * BOTAN_PARALLEL_BLOCKS_ECB, 0)
{
cipher = ciph;
padder = pad;
- plaintext.resize(cipher->BLOCK_SIZE);
- ciphertext.resize(cipher->BLOCK_SIZE * PARALLEL_BLOCKS);
-
- position = 0;
+ temp.resize(cipher->BLOCK_SIZE * BOTAN_PARALLEL_BLOCKS_ECB);
}
/*
@@ -35,15 +27,13 @@ ECB_Encryption::ECB_Encryption(BlockCipher* ciph,
*/
ECB_Encryption::ECB_Encryption(BlockCipher* ciph,
BlockCipherModePaddingMethod* pad,
- const SymmetricKey& key)
+ const SymmetricKey& key) :
+ Buffered_Filter(ciph->BLOCK_SIZE * BOTAN_PARALLEL_BLOCKS_ECB, 0)
{
cipher = ciph;
padder = pad;
- plaintext.resize(cipher->BLOCK_SIZE);
- ciphertext.resize(cipher->BLOCK_SIZE * PARALLEL_BLOCKS);
-
- position = 0;
+ temp.resize(cipher->BLOCK_SIZE * BOTAN_PARALLEL_BLOCKS_ECB);
cipher->set_key(key);
}
@@ -70,35 +60,7 @@ std::string ECB_Encryption::name() const
*/
void ECB_Encryption::write(const byte input[], u32bit length)
{
- const u32bit BLOCK_SIZE = cipher->BLOCK_SIZE;
-
- if(position)
- {
- plaintext.copy(position, input, length);
-
- if(position + length >= BLOCK_SIZE)
- {
- cipher->encrypt(plaintext, ciphertext);
- send(ciphertext, BLOCK_SIZE);
- input += (BLOCK_SIZE - position);
- length -= (BLOCK_SIZE - position);
- position = 0;
- }
- }
-
- while(length >= BLOCK_SIZE)
- {
- const u32bit to_proc =
- std::min<u32bit>(length, ciphertext.size()) / BLOCK_SIZE;
-
- cipher->encrypt_n(input, ciphertext, to_proc);
- send(ciphertext, to_proc * BLOCK_SIZE);
- input += to_proc * BLOCK_SIZE;
- length -= to_proc * BLOCK_SIZE;
- }
-
- plaintext.copy(position, input, length);
- position += length;
+ Buffered_Filter::write(input, length);
}
/*
@@ -106,12 +68,41 @@ void ECB_Encryption::write(const byte input[], u32bit length)
*/
void ECB_Encryption::end_msg()
{
- const u32bit BLOCK_SIZE = cipher->BLOCK_SIZE;
+ u32bit last_block = current_position() % cipher->BLOCK_SIZE;
+
+ SecureVector<byte> padding(cipher->BLOCK_SIZE);
+ padder->pad(padding, padding.size(), last_block);
+
+ u32bit pad_bytes = padder->pad_bytes(cipher->BLOCK_SIZE, last_block);
+
+ if(pad_bytes)
+ Buffered_Filter::write(padding, pad_bytes);
+ Buffered_Filter::end_msg();
+ }
+
+void ECB_Encryption::buffered_block(const byte input[], u32bit input_length)
+ {
+ const u32bit blocks_in_temp = temp.size() / cipher->BLOCK_SIZE;
+ u32bit blocks = input_length / cipher->BLOCK_SIZE;
+
+ while(blocks)
+ {
+ u32bit to_proc = std::min<u32bit>(blocks, blocks_in_temp);
+
+ cipher->encrypt_n(input, &temp[0], to_proc);
+
+ send(temp, to_proc * cipher->BLOCK_SIZE);
+
+ input += to_proc * cipher->BLOCK_SIZE;
+ blocks -= to_proc;
+ }
+ }
- SecureVector<byte> padding(BLOCK_SIZE);
- padder->pad(padding, padding.size(), position);
- write(padding, padder->pad_bytes(BLOCK_SIZE, position));
- if(position != 0)
+void ECB_Encryption::buffered_final(const byte input[], u32bit input_length)
+ {
+ if(input_length % cipher->BLOCK_SIZE == 0)
+ buffered_block(input, input_length);
+ else if(input_length != 0)
throw Encoding_Error(name() + ": Did not pad to full blocksize");
}
@@ -119,15 +110,13 @@ void ECB_Encryption::end_msg()
* ECB_Decryption Constructor
*/
ECB_Decryption::ECB_Decryption(BlockCipher* ciph,
- BlockCipherModePaddingMethod* pad)
+ BlockCipherModePaddingMethod* pad) :
+ Buffered_Filter(ciph->BLOCK_SIZE * BOTAN_PARALLEL_BLOCKS_ECB, 1)
{
cipher = ciph;
padder = pad;
- ciphertext.resize(cipher->BLOCK_SIZE);
- plaintext.resize(cipher->BLOCK_SIZE * PARALLEL_BLOCKS);
-
- position = 0;
+ temp.resize(cipher->BLOCK_SIZE * BOTAN_PARALLEL_BLOCKS_ECB);
}
/*
@@ -135,15 +124,13 @@ ECB_Decryption::ECB_Decryption(BlockCipher* ciph,
*/
ECB_Decryption::ECB_Decryption(BlockCipher* ciph,
BlockCipherModePaddingMethod* pad,
- const SymmetricKey& key)
+ const SymmetricKey& key) :
+ Buffered_Filter(ciph->BLOCK_SIZE * BOTAN_PARALLEL_BLOCKS_ECB, 1)
{
cipher = ciph;
padder = pad;
- ciphertext.resize(cipher->BLOCK_SIZE);
- plaintext.resize(cipher->BLOCK_SIZE * PARALLEL_BLOCKS);
-
- position = 0;
+ temp.resize(cipher->BLOCK_SIZE * BOTAN_PARALLEL_BLOCKS_ECB);
cipher->set_key(key);
}
@@ -170,53 +157,54 @@ std::string ECB_Decryption::name() const
*/
void ECB_Decryption::write(const byte input[], u32bit length)
{
- const u32bit BLOCK_SIZE = cipher->BLOCK_SIZE;
+ Buffered_Filter::write(input, length);
+ }
- if(position)
- {
- ciphertext.copy(position, input, length);
-
- if(position + length > BLOCK_SIZE)
- {
- cipher->decrypt(ciphertext, plaintext);
- send(plaintext, BLOCK_SIZE);
- input += (BLOCK_SIZE - position);
- length -= (BLOCK_SIZE - position);
- position = 0;
- }
- }
+/*
+* Finish decrypting in ECB mode
+*/
+void ECB_Decryption::end_msg()
+ {
+ Buffered_Filter::end_msg();
+ }
- while(length > BLOCK_SIZE)
+/*
+* Decrypt in ECB mode
+*/
+void ECB_Decryption::buffered_block(const byte input[], u32bit length)
+ {
+ const u32bit blocks_in_temp = temp.size() / cipher->BLOCK_SIZE;
+ u32bit blocks = length / cipher->BLOCK_SIZE;
+
+ while(blocks)
{
- /* Always leave at least 1 byte left over, to ensure that (as long
- as the input message actually is a multiple of the block size)
- we will have the full final block left over in end_msg so as
- to remove the padding
- */
- const u32bit to_proc =
- std::min<u32bit>(length - 1, plaintext.size()) / BLOCK_SIZE;
-
- cipher->decrypt_n(input, plaintext, to_proc);
- send(plaintext, to_proc * BLOCK_SIZE);
- input += to_proc * BLOCK_SIZE;
- length -= to_proc * BLOCK_SIZE;
- }
+ u32bit to_proc = std::min<u32bit>(blocks, blocks_in_temp);
- ciphertext.copy(position, input, length);
- position += length;
+ cipher->decrypt_n(input, &temp[0], to_proc);
+
+ send(temp, to_proc * cipher->BLOCK_SIZE);
+
+ input += to_proc * cipher->BLOCK_SIZE;
+ blocks -= to_proc;
+ }
}
/*
-* Finish decrypting in ECB mode
+* Finish encrypting in ECB mode
*/
-void ECB_Decryption::end_msg()
+void ECB_Decryption::buffered_final(const byte input[], u32bit length)
{
- if(position != cipher->BLOCK_SIZE)
- throw Decoding_Error(name());
+ if(length == 0 || length % cipher->BLOCK_SIZE != 0)
+ throw Decoding_Error(name() + ": Ciphertext not multiple of block size");
+
+ size_t extra_blocks = (length - 1) / cipher->BLOCK_SIZE;
+
+ buffered_block(input, extra_blocks * cipher->BLOCK_SIZE);
+
+ input += extra_blocks * cipher->BLOCK_SIZE;
- cipher->decrypt(ciphertext);
- send(ciphertext, padder->unpad(ciphertext, cipher->BLOCK_SIZE));
- position = 0;
+ cipher->decrypt(input, temp);
+ send(temp, padder->unpad(temp, cipher->BLOCK_SIZE));
}
}
diff --git a/src/filters/modes/ecb/ecb.h b/src/filters/modes/ecb/ecb.h
index 2b3b3fe83..2b88191c7 100644
--- a/src/filters/modes/ecb/ecb.h
+++ b/src/filters/modes/ecb/ecb.h
@@ -11,13 +11,15 @@
#include <botan/block_cipher.h>
#include <botan/mode_pad.h>
#include <botan/key_filt.h>
+#include <botan/buf_filt.h>
namespace Botan {
/*
* ECB Encryption
*/
-class BOTAN_DLL ECB_Encryption : public Keyed_Filter
+class BOTAN_DLL ECB_Encryption : public Keyed_Filter,
+ private Buffered_Filter
{
public:
std::string name() const;
@@ -36,19 +38,22 @@ class BOTAN_DLL ECB_Encryption : public Keyed_Filter
~ECB_Encryption();
private:
- void write(const byte[], u32bit);
+ void buffered_block(const byte input[], u32bit input_length);
+ void buffered_final(const byte input[], u32bit input_length);
+
+ void write(const byte input[], u32bit input_length);
void end_msg();
BlockCipher* cipher;
BlockCipherModePaddingMethod* padder;
- SecureVector<byte> plaintext, ciphertext;
- u32bit position;
+ SecureVector<byte> temp;
};
/*
* ECB Decryption
*/
-class BOTAN_DLL ECB_Decryption : public Keyed_Filter
+class BOTAN_DLL ECB_Decryption : public Keyed_Filter,
+ public Buffered_Filter
{
public:
std::string name() const;
@@ -67,13 +72,15 @@ class BOTAN_DLL ECB_Decryption : public Keyed_Filter
~ECB_Decryption();
private:
- void write(const byte[], u32bit);
+ void buffered_block(const byte input[], u32bit input_length);
+ void buffered_final(const byte input[], u32bit input_length);
+
+ void write(const byte input[], u32bit input_length);
void end_msg();
BlockCipher* cipher;
BlockCipherModePaddingMethod* padder;
- SecureVector<byte> plaintext, ciphertext;
- u32bit position;
+ SecureVector<byte> temp;
};
}
diff --git a/src/filters/modes/xts/xts.cpp b/src/filters/modes/xts/xts.cpp
index c9b77e1eb..aeef4e88d 100644
--- a/src/filters/modes/xts/xts.cpp
+++ b/src/filters/modes/xts/xts.cpp
@@ -16,7 +16,7 @@ namespace {
void poly_double(byte tweak[], u32bit size)
{
- const byte polynomial = 0x87; // for 128 bit ciphers
+ const byte polynomial = (size == 16) ? 0x87 : 0x1B;
byte carry = 0;
for(u32bit i = 0; i != size; ++i)
@@ -35,15 +35,16 @@ void poly_double(byte tweak[], u32bit size)
/*
* XTS_Encryption constructor
*/
-XTS_Encryption::XTS_Encryption(BlockCipher* ciph) : cipher(ciph)
+XTS_Encryption::XTS_Encryption(BlockCipher* ciph) :
+ Buffered_Filter(BOTAN_PARALLEL_BLOCKS_XTS * ciph->BLOCK_SIZE,
+ ciph->BLOCK_SIZE + 1),
+ cipher(ciph)
{
- if(cipher->BLOCK_SIZE != 16)
+ if(cipher->BLOCK_SIZE != 8 && cipher->BLOCK_SIZE != 16)
throw std::invalid_argument("Bad cipher for XTS: " + cipher->name());
cipher2 = cipher->clone();
- tweak.resize(cipher->BLOCK_SIZE);
- buffer.resize(2 * cipher->BLOCK_SIZE);
- position = 0;
+ tweak.resize(BOTAN_PARALLEL_BLOCKS_XTS * cipher->BLOCK_SIZE);
}
/*
@@ -51,15 +52,16 @@ XTS_Encryption::XTS_Encryption(BlockCipher* ciph) : cipher(ciph)
*/
XTS_Encryption::XTS_Encryption(BlockCipher* ciph,
const SymmetricKey& key,
- const InitializationVector& iv) : cipher(ciph)
+ const InitializationVector& iv) :
+ Buffered_Filter(BOTAN_PARALLEL_BLOCKS_XTS * ciph->BLOCK_SIZE,
+ ciph->BLOCK_SIZE + 1),
+ cipher(ciph)
{
- if(cipher->BLOCK_SIZE != 16)
- throw std::invalid_argument("Bad cipher for XTS: " + cipher->name());
+ if(cipher->BLOCK_SIZE != 8 && cipher->BLOCK_SIZE != 16)
+ throw std::invalid_argument("Bad cipher for XTS: " + cipher->name());
cipher2 = cipher->clone();
- tweak.resize(cipher->BLOCK_SIZE);
- buffer.resize(2 * cipher->BLOCK_SIZE);
- position = 0;
+ tweak.resize(BOTAN_PARALLEL_BLOCKS_XTS * cipher->BLOCK_SIZE);
set_key(key);
set_iv(iv);
@@ -78,11 +80,22 @@ std::string XTS_Encryption::name() const
*/
void XTS_Encryption::set_iv(const InitializationVector& iv)
{
- if(iv.length() != tweak.size())
+ if(iv.length() != cipher->BLOCK_SIZE)
throw Invalid_IV_Length(name(), iv.length());
- tweak = iv.bits_of();
+ const u32bit blocks_in_tweak = tweak.size() / cipher->BLOCK_SIZE;
+
+ tweak.copy(iv.begin(), iv.length());
cipher2->encrypt(tweak);
+
+ for(u32bit i = 1; i < blocks_in_tweak; ++i)
+ {
+ tweak.copy(i*cipher->BLOCK_SIZE,
+ tweak.begin() + (i-1)*cipher->BLOCK_SIZE,
+ cipher->BLOCK_SIZE);
+
+ poly_double(&tweak[i*cipher->BLOCK_SIZE], cipher->BLOCK_SIZE);
+ }
}
void XTS_Encryption::set_key(const SymmetricKey& key)
@@ -96,110 +109,116 @@ void XTS_Encryption::set_key(const SymmetricKey& key)
cipher2->set_key(key.begin() + key_half, key_half);
}
-void XTS_Encryption::encrypt(const byte block[])
- {
- /*
- * We can always use the first 16 bytes of buffer as temp space,
- * since either the input block is buffer (in which case this is
- * just buffer ^= tweak) or it not, in which case we already read
- * and used the data there and are processing new input. Kind of
- * subtle/nasty, but saves allocating a distinct temp buf.
- */
-
- xor_buf(buffer, block, tweak, cipher->BLOCK_SIZE);
- cipher->encrypt(buffer);
- xor_buf(buffer, tweak, cipher->BLOCK_SIZE);
-
- poly_double(tweak, cipher->BLOCK_SIZE);
-
- send(buffer, cipher->BLOCK_SIZE);
- }
-
/*
* Encrypt in XTS mode
*/
void XTS_Encryption::write(const byte input[], u32bit length)
{
- const u32bit BLOCK_SIZE = cipher->BLOCK_SIZE;
+ Buffered_Filter::write(input, length);
+ }
+/*
+* Finish encrypting in XTS mode
+*/
+void XTS_Encryption::end_msg()
+ {
+ Buffered_Filter::end_msg();
+ }
- u32bit copied = std::min(buffer.size() - position, length);
- buffer.copy(position, input, copied);
- length -= copied;
- input += copied;
- position += copied;
+void XTS_Encryption::buffered_block(const byte input[], u32bit length)
+ {
+ const u32bit blocks_in_tweak = tweak.size() / cipher->BLOCK_SIZE;
+ u32bit blocks = length / cipher->BLOCK_SIZE;
- if(length == 0) return;
+ SecureVector<byte> temp(tweak.size());
- encrypt(buffer);
- if(length > BLOCK_SIZE)
+ while(blocks)
{
- encrypt(buffer + BLOCK_SIZE);
- while(length > buffer.size())
+ u32bit to_proc = std::min(blocks, blocks_in_tweak);
+ u32bit to_proc_bytes = to_proc * cipher->BLOCK_SIZE;
+
+ xor_buf(temp, input, tweak, to_proc_bytes);
+
+ cipher->encrypt_n(&temp[0], &temp[0], to_proc);
+
+ xor_buf(temp, tweak, to_proc_bytes);
+
+ send(temp, to_proc_bytes);
+
+ tweak.copy(&tweak[(to_proc-1)*cipher->BLOCK_SIZE],
+ cipher->BLOCK_SIZE);
+ poly_double(&tweak[0], cipher->BLOCK_SIZE);
+
+ for(u32bit i = 1; i < blocks_in_tweak; ++i)
{
- encrypt(input);
- length -= BLOCK_SIZE;
- input += BLOCK_SIZE;
+ tweak.copy(i*cipher->BLOCK_SIZE,
+ tweak.begin() + (i-1)*cipher->BLOCK_SIZE,
+ cipher->BLOCK_SIZE);
+
+ poly_double(&tweak[i*cipher->BLOCK_SIZE], cipher->BLOCK_SIZE);
}
- position = 0;
- }
- else
- {
- copy_mem(buffer.begin(), buffer + BLOCK_SIZE, BLOCK_SIZE);
- position = BLOCK_SIZE;
+
+ input += to_proc * cipher->BLOCK_SIZE;
+ blocks -= to_proc;
}
- buffer.copy(position, input, length);
- position += length;
}
/*
* Finish encrypting in XTS mode
*/
-void XTS_Encryption::end_msg()
+void XTS_Encryption::buffered_final(const byte input[], u32bit length)
{
- const u32bit BLOCK_SIZE = cipher->BLOCK_SIZE;
+ if(length <= cipher->BLOCK_SIZE)
+ throw Encoding_Error("XTS_Encryption: insufficient data to encrypt");
- if(position < BLOCK_SIZE)
- throw Exception("XTS_Encryption: insufficient data to encrypt");
- else if(position == BLOCK_SIZE)
- {
- encrypt(buffer);
- }
- else if(position == 2*BLOCK_SIZE)
+ if(length % cipher->BLOCK_SIZE == 0)
{
- encrypt(buffer);
- encrypt(buffer + BLOCK_SIZE);
+ buffered_block(input, length);
}
else
{ // steal ciphertext
- xor_buf(buffer, tweak, cipher->BLOCK_SIZE);
- cipher->encrypt(buffer);
- xor_buf(buffer, tweak, cipher->BLOCK_SIZE);
+
+ u32bit leftover_blocks =
+ ((length / cipher->BLOCK_SIZE) - 1) * cipher->BLOCK_SIZE;
+
+ buffered_block(input, leftover_blocks);
+
+ input += leftover_blocks;
+ length -= leftover_blocks;
+
+ SecureVector<byte> temp(input, length);
+
+ xor_buf(temp, tweak, cipher->BLOCK_SIZE);
+ cipher->encrypt(temp);
+ xor_buf(temp, tweak, cipher->BLOCK_SIZE);
poly_double(tweak, cipher->BLOCK_SIZE);
- for(u32bit i = 0; i != position - cipher->BLOCK_SIZE; ++i)
- std::swap(buffer[i], buffer[i + cipher->BLOCK_SIZE]);
+ for(u32bit i = 0; i != length - cipher->BLOCK_SIZE; ++i)
+ std::swap(temp[i], temp[i + cipher->BLOCK_SIZE]);
- xor_buf(buffer, tweak, cipher->BLOCK_SIZE);
- cipher->encrypt(buffer);
- xor_buf(buffer, tweak, cipher->BLOCK_SIZE);
+ xor_buf(temp, tweak, cipher->BLOCK_SIZE);
+ cipher->encrypt(temp);
+ xor_buf(temp, tweak, cipher->BLOCK_SIZE);
- send(buffer, position);
+ send(temp, temp.size());
}
- position = 0;
+ buffer_reset();
}
/*
* XTS_Decryption constructor
*/
-XTS_Decryption::XTS_Decryption(BlockCipher* ciph)
+XTS_Decryption::XTS_Decryption(BlockCipher* ciph) :
+ Buffered_Filter(BOTAN_PARALLEL_BLOCKS_XTS * ciph->BLOCK_SIZE,
+ ciph->BLOCK_SIZE + 1),
+ cipher(ciph)
{
- cipher = ciph;
+ if(cipher->BLOCK_SIZE != 8 && cipher->BLOCK_SIZE != 16)
+ throw std::invalid_argument("Bad cipher for XTS: " + cipher->name());
+
cipher2 = ciph->clone();
- tweak.resize(cipher->BLOCK_SIZE);
- buffer.resize(2 * cipher->BLOCK_SIZE);
- position = 0;
+ tweak.resize(BOTAN_PARALLEL_BLOCKS_XTS * cipher->BLOCK_SIZE);
}
/*
@@ -207,13 +226,16 @@ XTS_Decryption::XTS_Decryption(BlockCipher* ciph)
*/
XTS_Decryption::XTS_Decryption(BlockCipher* ciph,
const SymmetricKey& key,
- const InitializationVector& iv)
+ const InitializationVector& iv) :
+ Buffered_Filter(BOTAN_PARALLEL_BLOCKS_XTS * ciph->BLOCK_SIZE,
+ ciph->BLOCK_SIZE + 1),
+ cipher(ciph)
{
- cipher = ciph;
+ if(cipher->BLOCK_SIZE != 8 && cipher->BLOCK_SIZE != 16)
+ throw std::invalid_argument("Bad cipher for XTS: " + cipher->name());
+
cipher2 = ciph->clone();
- tweak.resize(cipher->BLOCK_SIZE);
- buffer.resize(2 * cipher->BLOCK_SIZE);
- position = 0;
+ tweak.resize(BOTAN_PARALLEL_BLOCKS_XTS * cipher->BLOCK_SIZE);
set_key(key);
set_iv(iv);
@@ -232,11 +254,22 @@ std::string XTS_Decryption::name() const
*/
void XTS_Decryption::set_iv(const InitializationVector& iv)
{
- if(iv.length() != tweak.size())
+ if(iv.length() != cipher->BLOCK_SIZE)
throw Invalid_IV_Length(name(), iv.length());
- tweak = iv.bits_of();
+ const u32bit blocks_in_tweak = tweak.size() / cipher->BLOCK_SIZE;
+
+ tweak.copy(iv.begin(), iv.length());
cipher2->encrypt(tweak);
+
+ for(u32bit i = 1; i < blocks_in_tweak; ++i)
+ {
+ tweak.copy(i*cipher->BLOCK_SIZE,
+ tweak.begin() + (i-1)*cipher->BLOCK_SIZE,
+ cipher->BLOCK_SIZE);
+
+ poly_double(&tweak[i*cipher->BLOCK_SIZE], cipher->BLOCK_SIZE);
+ }
}
void XTS_Decryption::set_key(const SymmetricKey& key)
@@ -251,94 +284,98 @@ void XTS_Decryption::set_key(const SymmetricKey& key)
}
/*
-* Decrypt a block
+* Decrypt in XTS mode
*/
-void XTS_Decryption::decrypt(const byte block[])
+void XTS_Decryption::write(const byte input[], u32bit length)
{
- xor_buf(buffer, block, tweak, cipher->BLOCK_SIZE);
- cipher->decrypt(buffer);
- xor_buf(buffer, tweak, cipher->BLOCK_SIZE);
-
- poly_double(tweak, cipher->BLOCK_SIZE);
-
- send(buffer, cipher->BLOCK_SIZE);
+ Buffered_Filter::write(input, length);
}
/*
-* Decrypt in XTS mode
+* Finish decrypting in XTS mode
*/
-void XTS_Decryption::write(const byte input[], u32bit length)
+void XTS_Decryption::end_msg()
{
- const u32bit BLOCK_SIZE = cipher->BLOCK_SIZE;
+ Buffered_Filter::end_msg();
+ }
- u32bit copied = std::min(buffer.size() - position, length);
- buffer.copy(position, input, copied);
- length -= copied;
- input += copied;
- position += copied;
+void XTS_Decryption::buffered_block(const byte input[], u32bit input_length)
+ {
+ const u32bit blocks_in_tweak = tweak.size() / cipher->BLOCK_SIZE;
+ u32bit blocks = input_length / cipher->BLOCK_SIZE;
- if(length == 0) return;
+ SecureVector<byte> temp(tweak.size());
- decrypt(buffer);
- if(length > BLOCK_SIZE)
+ while(blocks)
{
- decrypt(buffer + BLOCK_SIZE);
- while(length > 2*BLOCK_SIZE)
+ u32bit to_proc = std::min(blocks, blocks_in_tweak);
+ u32bit to_proc_bytes = to_proc * cipher->BLOCK_SIZE;
+
+ xor_buf(temp, input, tweak, to_proc_bytes);
+
+ cipher->decrypt_n(&temp[0], &temp[0], to_proc);
+
+ xor_buf(temp, tweak, to_proc_bytes);
+
+ send(temp, to_proc_bytes);
+
+ tweak.copy(&tweak[(to_proc-1)*cipher->BLOCK_SIZE],
+ cipher->BLOCK_SIZE);
+ poly_double(&tweak[0], cipher->BLOCK_SIZE);
+
+ for(u32bit i = 1; i < blocks_in_tweak; ++i)
{
- decrypt(input);
- length -= BLOCK_SIZE;
- input += BLOCK_SIZE;
+ tweak.copy(i*cipher->BLOCK_SIZE,
+ tweak.begin() + (i-1)*cipher->BLOCK_SIZE,
+ cipher->BLOCK_SIZE);
+
+ poly_double(&tweak[i*cipher->BLOCK_SIZE], cipher->BLOCK_SIZE);
}
- position = 0;
- }
- else
- {
- copy_mem(buffer.begin(), buffer + BLOCK_SIZE, BLOCK_SIZE);
- position = BLOCK_SIZE;
+
+ input += to_proc * cipher->BLOCK_SIZE;
+ blocks -= to_proc;
}
- buffer.copy(position, input, length);
- position += length;
}
-/*
-* Finish decrypting in XTS mode
-*/
-void XTS_Decryption::end_msg()
+void XTS_Decryption::buffered_final(const byte input[], u32bit length)
{
- const u32bit BLOCK_SIZE = cipher->BLOCK_SIZE;
+ if(length <= cipher->BLOCK_SIZE)
+ throw Decoding_Error("XTS_Decryption: insufficient data to decrypt");
- if(position < BLOCK_SIZE)
- throw Exception("XTS_Decryption: insufficient data to decrypt");
- else if(position == BLOCK_SIZE)
+ if(length % cipher->BLOCK_SIZE == 0)
{
- decrypt(buffer);
- }
- else if(position == 2*BLOCK_SIZE)
- {
- decrypt(buffer);
- decrypt(buffer + BLOCK_SIZE);
+ buffered_block(input, length);
}
else
{
- SecureVector<byte> tweak2 = tweak;
+ u32bit leftover_blocks =
+ ((length / cipher->BLOCK_SIZE) - 1) * cipher->BLOCK_SIZE;
+
+ buffered_block(input, leftover_blocks);
+
+ input += leftover_blocks;
+ length -= leftover_blocks;
+
+ SecureVector<byte> temp(input, length);
+ SecureVector<byte> tweak_copy(&tweak[0], cipher->BLOCK_SIZE);
- poly_double(tweak2, cipher->BLOCK_SIZE);
+ poly_double(tweak_copy, cipher->BLOCK_SIZE);
- xor_buf(buffer, tweak2, cipher->BLOCK_SIZE);
- cipher->decrypt(buffer);
- xor_buf(buffer, tweak2, cipher->BLOCK_SIZE);
+ xor_buf(temp, tweak_copy, cipher->BLOCK_SIZE);
+ cipher->decrypt(temp);
+ xor_buf(temp, tweak_copy, cipher->BLOCK_SIZE);
- for(u32bit i = 0; i != position - cipher->BLOCK_SIZE; ++i)
- std::swap(buffer[i], buffer[i + cipher->BLOCK_SIZE]);
+ for(u32bit i = 0; i != length - cipher->BLOCK_SIZE; ++i)
+ std::swap(temp[i], temp[i + cipher->BLOCK_SIZE]);
- xor_buf(buffer, tweak, cipher->BLOCK_SIZE);
- cipher->decrypt(buffer);
- xor_buf(buffer, tweak, cipher->BLOCK_SIZE);
+ xor_buf(temp, tweak, cipher->BLOCK_SIZE);
+ cipher->decrypt(temp);
+ xor_buf(temp, tweak, cipher->BLOCK_SIZE);
- send(buffer, position);
+ send(temp, length);
}
- position = 0;
+ buffer_reset();
}
}
diff --git a/src/filters/modes/xts/xts.h b/src/filters/modes/xts/xts.h
index 9badd3666..a01b1da1d 100644
--- a/src/filters/modes/xts/xts.h
+++ b/src/filters/modes/xts/xts.h
@@ -8,15 +8,17 @@
#ifndef BOTAN_XTS_H__
#define BOTAN_XTS_H__
-#include <botan/key_filt.h>
#include <botan/block_cipher.h>
+#include <botan/key_filt.h>
+#include <botan/buf_filt.h>
namespace Botan {
/*
* XTS Encryption
*/
-class BOTAN_DLL XTS_Encryption : public Keyed_Filter
+class BOTAN_DLL XTS_Encryption : public Keyed_Filter,
+ private Buffered_Filter
{
public:
void set_key(const SymmetricKey& key);
@@ -37,19 +39,20 @@ class BOTAN_DLL XTS_Encryption : public Keyed_Filter
private:
void write(const byte[], u32bit);
void end_msg();
- void encrypt(const byte block[]);
+
+ void buffered_block(const byte input[], u32bit input_length);
+ void buffered_final(const byte input[], u32bit input_length);
BlockCipher* cipher;
BlockCipher* cipher2;
SecureVector<byte> tweak;
- SecureVector<byte> buffer;
- u32bit position;
};
/*
* XTS Decryption
*/
-class BOTAN_DLL XTS_Decryption : public Keyed_Filter
+class BOTAN_DLL XTS_Decryption : public Keyed_Filter,
+ private Buffered_Filter
{
public:
void set_key(const SymmetricKey& key);
@@ -65,16 +68,18 @@ class BOTAN_DLL XTS_Decryption : public Keyed_Filter
XTS_Decryption(BlockCipher* ciph,
const SymmetricKey& key,
const InitializationVector& iv);
+
+ ~XTS_Decryption() { delete cipher; delete cipher2; }
private:
void write(const byte[], u32bit);
void end_msg();
- void decrypt(const byte[]);
+
+ void buffered_block(const byte input[], u32bit input_length);
+ void buffered_final(const byte input[], u32bit input_length);
BlockCipher* cipher;
BlockCipher* cipher2;
SecureVector<byte> tweak;
- SecureVector<byte> buffer;
- u32bit position;
};
}
diff --git a/src/filters/out_buf.cpp b/src/filters/out_buf.cpp
index 80189eb3c..e3ea0cfb5 100644
--- a/src/filters/out_buf.cpp
+++ b/src/filters/out_buf.cpp
@@ -6,7 +6,7 @@
*/
#include <botan/internal/out_buf.h>
-#include <botan/internal/secqueue.h>
+#include <botan/secqueue.h>
namespace Botan {
diff --git a/src/filters/pipe.cpp b/src/filters/pipe.cpp
index 80b6f27aa..77e4ae283 100644
--- a/src/filters/pipe.cpp
+++ b/src/filters/pipe.cpp
@@ -7,21 +7,11 @@
#include <botan/pipe.h>
#include <botan/internal/out_buf.h>
-#include <botan/internal/secqueue.h>
+#include <botan/secqueue.h>
#include <botan/parsing.h>
namespace Botan {
-/*
-* Constructor for Invalid_Message_Number
-*/
-Pipe::Invalid_Message_Number::Invalid_Message_Number(const std::string& where,
- message_id msg)
- {
- set_msg("Pipe::" + where + ": Invalid message number " +
- to_string(msg));
- }
-
namespace {
/*
diff --git a/src/filters/pipe.h b/src/filters/pipe.h
index ba17e7e68..9af21a13f 100644
--- a/src/filters/pipe.h
+++ b/src/filters/pipe.h
@@ -28,10 +28,12 @@ class BOTAN_DLL Pipe : public DataSource
public:
typedef u32bit message_id;
- class BOTAN_DLL Invalid_Message_Number : public Invalid_Argument
+ struct BOTAN_DLL Invalid_Message_Number : public Invalid_Argument
{
- public:
- Invalid_Message_Number(const std::string&, message_id);
+ Invalid_Message_Number(const std::string& where, message_id msg) :
+ Invalid_Argument("Pipe::" + where + ": Invalid message number " +
+ to_string(msg))
+ {}
};
static const message_id LAST_MESSAGE;
diff --git a/src/filters/pipe_rw.cpp b/src/filters/pipe_rw.cpp
index 756a1cf09..20119c75b 100644
--- a/src/filters/pipe_rw.cpp
+++ b/src/filters/pipe_rw.cpp
@@ -7,7 +7,7 @@
#include <botan/pipe.h>
#include <botan/internal/out_buf.h>
-#include <botan/internal/secqueue.h>
+#include <botan/secqueue.h>
namespace Botan {
@@ -34,7 +34,7 @@ Pipe::message_id Pipe::get_message_no(const std::string& func_name,
void Pipe::write(const byte input[], u32bit length)
{
if(!inside_msg)
- throw Exception("Cannot write to a Pipe while it is not processing");
+ throw Invalid_State("Cannot write to a Pipe while it is not processing");
pipe->write(input, length);
}
diff --git a/src/filters/pk_filts/pk_filts.cpp b/src/filters/pk_filts/pk_filts.cpp
index d604436e0..05b45227f 100644
--- a/src/filters/pk_filts/pk_filts.cpp
+++ b/src/filters/pk_filts/pk_filts.cpp
@@ -73,7 +73,7 @@ void PK_Verifier_Filter::write(const byte input[], u32bit length)
void PK_Verifier_Filter::end_msg()
{
if(signature.empty())
- throw Exception("PK_Verifier_Filter: No signature to check against");
+ throw Invalid_State("PK_Verifier_Filter: No signature to check against");
bool is_valid = verifier->check_signature(signature, signature.size());
send((is_valid ? 1 : 0));
}
diff --git a/src/filters/secqueue.cpp b/src/filters/secqueue.cpp
index 74897805c..f63ef898c 100644
--- a/src/filters/secqueue.cpp
+++ b/src/filters/secqueue.cpp
@@ -5,7 +5,7 @@
* Distributed under the terms of the Botan license
*/
-#include <botan/internal/secqueue.h>
+#include <botan/secqueue.h>
#include <algorithm>
namespace Botan {
diff --git a/src/filters/secqueue.h b/src/filters/secqueue.h
index 75f650030..fc1fc213a 100644
--- a/src/filters/secqueue.h
+++ b/src/filters/secqueue.h
@@ -16,7 +16,7 @@ namespace Botan {
/*
* SecureQueue
*/
-class SecureQueue : public Fanout_Filter, public DataSource
+class BOTAN_DLL SecureQueue : public Fanout_Filter, public DataSource
{
public:
void write(const byte[], u32bit);
diff --git a/src/filters/zlib/zlib.cpp b/src/filters/zlib/zlib.cpp
index 246e32924..171caa73f 100644
--- a/src/filters/zlib/zlib.cpp
+++ b/src/filters/zlib/zlib.cpp
@@ -95,7 +95,7 @@ void Zlib_Compression::start_msg()
clear();
zlib = new Zlib_Stream;
if(deflateInit(&(zlib->stream), level) != Z_OK)
- throw Exception("Zlib_Compression: Memory allocation error");
+ throw Memory_Exhaustion();
}
/*
@@ -187,7 +187,7 @@ void Zlib_Decompression::start_msg()
clear();
zlib = new Zlib_Stream;
if(inflateInit(&(zlib->stream)) != Z_OK)
- throw Exception("Zlib_Decompression: Memory allocation error");
+ throw Memory_Exhaustion();
}
/*
@@ -215,11 +215,12 @@ void Zlib_Decompression::write(const byte input_arr[], u32bit length)
clear();
if(rc == Z_DATA_ERROR)
throw Decoding_Error("Zlib_Decompression: Data integrity error");
- if(rc == Z_NEED_DICT)
+ else if(rc == Z_NEED_DICT)
throw Decoding_Error("Zlib_Decompression: Need preset dictionary");
- if(rc == Z_MEM_ERROR)
- throw Exception("Zlib_Decompression: Memory allocation error");
- throw Exception("Zlib_Decompression: Unknown decompress error");
+ else if(rc == Z_MEM_ERROR)
+ throw Memory_Exhaustion();
+ else
+ throw std::runtime_error("Zlib decompression: Unknown error");
}
send(buffer.begin(), buffer.size() - zlib->stream.avail_out);
@@ -258,7 +259,7 @@ void Zlib_Decompression::end_msg()
if(rc != Z_OK && rc != Z_STREAM_END)
{
clear();
- throw Exception("Zlib_Decompression: Error finalizing decompression");
+ throw Decoding_Error("Zlib_Decompression: Error finalizing");
}
send(buffer.begin(), buffer.size() - zlib->stream.avail_out);
diff --git a/src/hash/md4/md4.h b/src/hash/md4/md4.h
index 0b76a70e4..0bff5a4ce 100644
--- a/src/hash/md4/md4.h
+++ b/src/hash/md4/md4.h
@@ -27,7 +27,7 @@ class BOTAN_DLL MD4 : public MDx_HashFunction
void hash_old(const byte[]);
void copy_out(byte[]);
- SecureBuffer<u32bit, 48> M;
+ SecureBuffer<u32bit, 16> M;
SecureBuffer<u32bit, 4> digest;
};
diff --git a/src/hash/md4_ia32/md4_ia32.cpp b/src/hash/md4_ia32/md4_ia32.cpp
index 12fe71da4..8a60d8f0e 100644
--- a/src/hash/md4_ia32/md4_ia32.cpp
+++ b/src/hash/md4_ia32/md4_ia32.cpp
@@ -6,7 +6,6 @@
*/
#include <botan/md4_ia32.h>
-#include <botan/loadstor.h>
namespace Botan {
diff --git a/src/hash/md5_ia32/md5_ia32.cpp b/src/hash/md5_ia32/md5_ia32.cpp
index 443569b3b..affd0b8f7 100644
--- a/src/hash/md5_ia32/md5_ia32.cpp
+++ b/src/hash/md5_ia32/md5_ia32.cpp
@@ -6,7 +6,6 @@
*/
#include <botan/md5_ia32.h>
-#include <botan/loadstor.h>
namespace Botan {
diff --git a/src/hash/sha1/sha160.cpp b/src/hash/sha1/sha160.cpp
index ff44593f6..1ad08d483 100644
--- a/src/hash/sha1/sha160.cpp
+++ b/src/hash/sha1/sha160.cpp
@@ -134,8 +134,8 @@ void SHA_160::compress_n(const byte input[], u32bit blocks)
*/
void SHA_160::copy_out(byte output[])
{
- for(u32bit j = 0; j != OUTPUT_LENGTH; j += 4)
- store_be(digest[j/4], output + j);
+ for(u32bit i = 0; i != OUTPUT_LENGTH; i += 4)
+ store_be(digest[i/4], output + i);
}
/*
diff --git a/src/hash/sha1_ia32/sha1_ia32.cpp b/src/hash/sha1_ia32/sha1_ia32.cpp
index 0fa0b6bf2..6eecdab56 100644
--- a/src/hash/sha1_ia32/sha1_ia32.cpp
+++ b/src/hash/sha1_ia32/sha1_ia32.cpp
@@ -6,7 +6,6 @@
*/
#include <botan/sha1_ia32.h>
-#include <botan/loadstor.h>
namespace Botan {
diff --git a/src/hash/tiger/tiger.cpp b/src/hash/tiger/tiger.cpp
index 4f4d4dc83..3013ab38e 100644
--- a/src/hash/tiger/tiger.cpp
+++ b/src/hash/tiger/tiger.cpp
@@ -12,6 +12,23 @@
namespace Botan {
+namespace {
+
+/*
+* Tiger Mixing Function
+*/
+inline void mix(u64bit X[8])
+ {
+ X[0] -= X[7] ^ 0xA5A5A5A5A5A5A5A5; X[1] ^= X[0];
+ X[2] += X[1]; X[3] -= X[2] ^ ((~X[1]) << 19); X[4] ^= X[3];
+ X[5] += X[4]; X[6] -= X[5] ^ ((~X[4]) >> 23); X[7] ^= X[6];
+ X[0] += X[7]; X[1] -= X[0] ^ ((~X[7]) << 19); X[2] ^= X[1];
+ X[3] += X[2]; X[4] -= X[3] ^ ((~X[2]) >> 23); X[5] ^= X[4];
+ X[6] += X[5]; X[7] -= X[6] ^ 0x0123456789ABCDEF;
+ }
+
+}
+
/*
* Tiger Compression Function
*/
@@ -114,19 +131,6 @@ void Tiger::pass(u64bit& A, u64bit& B, u64bit& C, u64bit X[8], byte mul)
}
/*
-* Tiger Mixing Function
-*/
-void Tiger::mix(u64bit X[8])
- {
- X[0] -= X[7] ^ 0xA5A5A5A5A5A5A5A5; X[1] ^= X[0];
- X[2] += X[1]; X[3] -= X[2] ^ ((~X[1]) << 19); X[4] ^= X[3];
- X[5] += X[4]; X[6] -= X[5] ^ ((~X[4]) >> 23); X[7] ^= X[6];
- X[0] += X[7]; X[1] -= X[0] ^ ((~X[7]) << 19); X[2] ^= X[1];
- X[3] += X[2]; X[4] -= X[3] ^ ((~X[2]) >> 23); X[5] ^= X[4];
- X[6] += X[5]; X[7] -= X[6] ^ 0x0123456789ABCDEF;
- }
-
-/*
* Clear memory of sensitive data
*/
void Tiger::clear()
diff --git a/src/hash/tiger/tiger.h b/src/hash/tiger/tiger.h
index 86ddcd270..20dcf99ff 100644
--- a/src/hash/tiger/tiger.h
+++ b/src/hash/tiger/tiger.h
@@ -27,7 +27,6 @@ class BOTAN_DLL Tiger : public MDx_HashFunction
void copy_out(byte[]);
static void pass(u64bit&, u64bit&, u64bit&, u64bit[8], byte);
- static void mix(u64bit[8]);
static const u64bit SBOX1[256];
static const u64bit SBOX2[256];
diff --git a/src/kdf/kdf2/kdf2.cpp b/src/kdf/kdf2/kdf2.cpp
index 167f64436..7cc1d7416 100644
--- a/src/kdf/kdf2/kdf2.cpp
+++ b/src/kdf/kdf2/kdf2.cpp
@@ -6,7 +6,7 @@
*/
#include <botan/kdf2.h>
-#include <botan/loadstor.h>
+#include <botan/get_byte.h>
namespace Botan {
diff --git a/src/kdf/mgf1/mgf1.cpp b/src/kdf/mgf1/mgf1.cpp
index a8c7e5fa3..340e87a7c 100644
--- a/src/kdf/mgf1/mgf1.cpp
+++ b/src/kdf/mgf1/mgf1.cpp
@@ -6,7 +6,7 @@
*/
#include <botan/mgf1.h>
-#include <botan/loadstor.h>
+#include <botan/get_byte.h>
#include <botan/exceptn.h>
#include <botan/internal/xor_buf.h>
#include <algorithm>
diff --git a/src/libstate/libstate.cpp b/src/libstate/libstate.cpp
index 9ac15e381..919b12494 100644
--- a/src/libstate/libstate.cpp
+++ b/src/libstate/libstate.cpp
@@ -316,8 +316,7 @@ void Library_State::initialize(bool thread_safe)
m_algorithm_factory = new Algorithm_Factory(engines, *mutex_factory);
#if defined(BOTAN_HAS_SELFTESTS)
- if(!passes_self_tests(algorithm_factory()))
- throw Self_Test_Failure("Startup self tests failed");
+ confirm_startup_self_tests(algorithm_factory());
#endif
}
diff --git a/src/libstate/libstate.h b/src/libstate/libstate.h
index a0421953e..d5c442214 100644
--- a/src/libstate/libstate.h
+++ b/src/libstate/libstate.h
@@ -18,6 +18,8 @@
namespace Botan {
+class Mutex;
+
/*
* Global State Container Base
*/
@@ -29,11 +31,28 @@ class BOTAN_DLL Library_State
void initialize(bool thread_safe);
+ /**
+ * @return the global Algorithm_Factory
+ */
Algorithm_Factory& algorithm_factory();
- Allocator* get_allocator(const std::string& = "") const;
- void add_allocator(Allocator*);
- void set_default_allocator(const std::string&);
+ /**
+ * @param name the name of the allocator
+ * @return allocator matching this name, or NULL
+ */
+ Allocator* get_allocator(const std::string& name = "") const;
+
+ /**
+ * Add a new allocator to the list of available ones
+ * @param alloc the allocator to add
+ */
+ void add_allocator(Allocator* alloc);
+
+ /**
+ * Set the default allocator
+ * @param name the name of the allocator to use as the default
+ */
+ void set_default_allocator(const std::string& name);
/**
* Get a parameter value as std::string.
@@ -52,7 +71,8 @@ class BOTAN_DLL Library_State
* @result true if the parameters value is set,
* false otherwise
*/
- bool is_set(const std::string& section, const std::string& key) const;
+ bool is_set(const std::string& section,
+ const std::string& key) const;
/**
* Set a configuration parameter.
@@ -62,8 +82,10 @@ class BOTAN_DLL Library_State
* will be overwritten even if it is already set, otherwise
* no existing values will be overwritten.
*/
- void set(const std::string& section, const std::string& key,
- const std::string& value, bool overwrite = true);
+ void set(const std::string& section,
+ const std::string& key,
+ const std::string& value,
+ bool overwrite = true);
/**
* Get a parameters value out of the "conf" section (
@@ -77,23 +99,28 @@ class BOTAN_DLL Library_State
* @param key the key of the option to set
* @param value the value to set
*/
- void set_option(const std::string& key, const std::string& value);
+ void set_option(const std::string& key,
+ const std::string& value);
/**
* Add a parameter value to the "alias" section.
* @param key the name of the parameter which shall have a new alias
* @param value the new alias
*/
- void add_alias(const std::string&, const std::string&);
+ void add_alias(const std::string& key,
+ const std::string& value);
/**
* Resolve an alias.
* @param alias the alias to resolve.
* @return what the alias stands for
*/
- std::string deref_alias(const std::string&) const;
+ std::string deref_alias(const std::string& alias) const;
- class Mutex* get_mutex() const;
+ /**
+ * @return a newly created Mutex (free with delete)
+ */
+ Mutex* get_mutex() const;
private:
void load_default_config();
@@ -103,9 +130,9 @@ class BOTAN_DLL Library_State
class Mutex_Factory* mutex_factory;
std::map<std::string, std::string> config;
- class Mutex* config_lock;
+ Mutex* config_lock;
- class Mutex* allocator_lock;
+ Mutex* allocator_lock;
std::map<std::string, Allocator*> alloc_factory;
mutable Allocator* cached_default_allocator;
std::vector<Allocator*> allocators;
diff --git a/src/libstate/lookup.cpp b/src/libstate/lookup.cpp
index 9016dbe6e..01f4a3d42 100644
--- a/src/libstate/lookup.cpp
+++ b/src/libstate/lookup.cpp
@@ -12,138 +12,34 @@
namespace Botan {
/**
-* Acquire a block cipher
-*/
-const BlockCipher* retrieve_block_cipher(const std::string& algo_spec)
- {
- Algorithm_Factory& af = global_state().algorithm_factory();
- return af.prototype_block_cipher(algo_spec);
- }
-
-/**
-* Get a block cipher by name
-*/
-BlockCipher* get_block_cipher(const std::string& algo_spec)
- {
- Algorithm_Factory& af = global_state().algorithm_factory();
- return af.make_block_cipher(algo_spec);
- }
-
-/**
-* Acquire a stream cipher
-*/
-const StreamCipher* retrieve_stream_cipher(const std::string& algo_spec)
- {
- Algorithm_Factory& af = global_state().algorithm_factory();
- return af.prototype_stream_cipher(algo_spec);
- }
-
-/**
-* Get a stream cipher by name
-*/
-StreamCipher* get_stream_cipher(const std::string& algo_spec)
- {
- Algorithm_Factory& af = global_state().algorithm_factory();
- return af.make_stream_cipher(algo_spec);
- }
-
-/**
-* Acquire a hash function
-*/
-const HashFunction* retrieve_hash(const std::string& algo_spec)
- {
- Algorithm_Factory& af = global_state().algorithm_factory();
- return af.prototype_hash_function(algo_spec);
- }
-
-/**
-* Get a hash function by name
-*/
-HashFunction* get_hash(const std::string& algo_spec)
- {
- Algorithm_Factory& af = global_state().algorithm_factory();
- return af.make_hash_function(algo_spec);
- }
-
-/**
-* Query if Botan has the named hash function
-*/
-bool have_hash(const std::string& algo_spec)
- {
- Algorithm_Factory& af = global_state().algorithm_factory();
- return (af.prototype_hash_function(algo_spec) != 0);
- }
-
-/**
-* Acquire an authentication code
-*/
-const MessageAuthenticationCode* retrieve_mac(const std::string& algo_spec)
- {
- Algorithm_Factory& af = global_state().algorithm_factory();
- return af.prototype_mac(algo_spec);
- }
-
-/**
-* Get a MAC by name
-*/
-MessageAuthenticationCode* get_mac(const std::string& algo_spec)
- {
- Algorithm_Factory& af = global_state().algorithm_factory();
- return af.make_mac(algo_spec);
- }
-
-/**
-* Query if Botan has the named MAC
-*/
-bool have_mac(const std::string& algo_spec)
- {
- Algorithm_Factory& af = global_state().algorithm_factory();
- return (af.prototype_mac(algo_spec) != 0);
- }
-
-/**
* Query if an algorithm exists
*/
bool have_algorithm(const std::string& name)
{
- if(retrieve_block_cipher(name))
+ Algorithm_Factory& af = global_state().algorithm_factory();
+
+ if(af.prototype_block_cipher(name))
return true;
- if(retrieve_stream_cipher(name))
+ if(af.prototype_stream_cipher(name))
return true;
- if(retrieve_hash(name))
+ if(af.prototype_hash_function(name))
return true;
- if(retrieve_mac(name))
+ if(af.prototype_mac(name))
return true;
return false;
}
/**
-* Query if Botan has the named block cipher
-*/
-bool have_block_cipher(const std::string& name)
- {
- return (retrieve_block_cipher(name) != 0);
- }
-
-/**
-* Query if Botan has the named stream cipher
-*/
-bool have_stream_cipher(const std::string& name)
- {
- return (retrieve_stream_cipher(name) != 0);
- }
-
-/**
* Query the block size of a cipher or hash
*/
u32bit block_size_of(const std::string& name)
{
- const BlockCipher* cipher = retrieve_block_cipher(name);
- if(cipher)
+ Algorithm_Factory& af = global_state().algorithm_factory();
+
+ if(const BlockCipher* cipher = af.prototype_block_cipher(name))
return cipher->BLOCK_SIZE;
- const HashFunction* hash = retrieve_hash(name);
- if(hash)
+ if(const HashFunction* hash = af.prototype_hash_function(name))
return hash->HASH_BLOCK_SIZE;
throw Algorithm_Not_Found(name);
@@ -154,12 +50,12 @@ u32bit block_size_of(const std::string& name)
*/
u32bit output_length_of(const std::string& name)
{
- const HashFunction* hash = retrieve_hash(name);
- if(hash)
+ Algorithm_Factory& af = global_state().algorithm_factory();
+
+ if(const HashFunction* hash = af.prototype_hash_function(name))
return hash->OUTPUT_LENGTH;
- const MessageAuthenticationCode* mac = retrieve_mac(name);
- if(mac)
+ if(const MessageAuthenticationCode* mac = af.prototype_mac(name))
return mac->OUTPUT_LENGTH;
throw Algorithm_Not_Found(name);
@@ -170,16 +66,15 @@ u32bit output_length_of(const std::string& name)
*/
bool valid_keylength_for(u32bit key_len, const std::string& name)
{
- const BlockCipher* bc = retrieve_block_cipher(name);
- if(bc)
+ Algorithm_Factory& af = global_state().algorithm_factory();
+
+ if(const BlockCipher* bc = af.prototype_block_cipher(name))
return bc->valid_keylength(key_len);
- const StreamCipher* sc = retrieve_stream_cipher(name);
- if(sc)
+ if(const StreamCipher* sc = af.prototype_stream_cipher(name))
return sc->valid_keylength(key_len);
- const MessageAuthenticationCode* mac = retrieve_mac(name);
- if(mac)
+ if(const MessageAuthenticationCode* mac = af.prototype_mac(name))
return mac->valid_keylength(key_len);
throw Algorithm_Not_Found(name);
@@ -190,16 +85,15 @@ bool valid_keylength_for(u32bit key_len, const std::string& name)
*/
u32bit min_keylength_of(const std::string& name)
{
- const BlockCipher* bc = retrieve_block_cipher(name);
- if(bc)
+ Algorithm_Factory& af = global_state().algorithm_factory();
+
+ if(const BlockCipher* bc = af.prototype_block_cipher(name))
return bc->MINIMUM_KEYLENGTH;
- const StreamCipher* sc = retrieve_stream_cipher(name);
- if(sc)
+ if(const StreamCipher* sc = af.prototype_stream_cipher(name))
return sc->MINIMUM_KEYLENGTH;
- const MessageAuthenticationCode* mac = retrieve_mac(name);
- if(mac)
+ if(const MessageAuthenticationCode* mac = af.prototype_mac(name))
return mac->MINIMUM_KEYLENGTH;
throw Algorithm_Not_Found(name);
@@ -210,16 +104,15 @@ u32bit min_keylength_of(const std::string& name)
*/
u32bit max_keylength_of(const std::string& name)
{
- const BlockCipher* bc = retrieve_block_cipher(name);
- if(bc)
+ Algorithm_Factory& af = global_state().algorithm_factory();
+
+ if(const BlockCipher* bc = af.prototype_block_cipher(name))
return bc->MAXIMUM_KEYLENGTH;
- const StreamCipher* sc = retrieve_stream_cipher(name);
- if(sc)
+ if(const StreamCipher* sc = af.prototype_stream_cipher(name))
return sc->MAXIMUM_KEYLENGTH;
- const MessageAuthenticationCode* mac = retrieve_mac(name);
- if(mac)
+ if(const MessageAuthenticationCode* mac = af.prototype_mac(name))
return mac->MAXIMUM_KEYLENGTH;
throw Algorithm_Not_Found(name);
@@ -230,16 +123,15 @@ u32bit max_keylength_of(const std::string& name)
*/
u32bit keylength_multiple_of(const std::string& name)
{
- const BlockCipher* bc = retrieve_block_cipher(name);
- if(bc)
+ Algorithm_Factory& af = global_state().algorithm_factory();
+
+ if(const BlockCipher* bc = af.prototype_block_cipher(name))
return bc->KEYLENGTH_MULTIPLE;
- const StreamCipher* sc = retrieve_stream_cipher(name);
- if(sc)
+ if(const StreamCipher* sc = af.prototype_stream_cipher(name))
return sc->KEYLENGTH_MULTIPLE;
- const MessageAuthenticationCode* mac = retrieve_mac(name);
- if(mac)
+ if(const MessageAuthenticationCode* mac = af.prototype_mac(name))
return mac->KEYLENGTH_MULTIPLE;
throw Algorithm_Not_Found(name);
@@ -257,8 +149,7 @@ Keyed_Filter* get_cipher(const std::string& algo_spec,
while(Engine* engine = i.next())
{
- Keyed_Filter* algo = engine->get_cipher(algo_spec, direction, af);
- if(algo)
+ if(Keyed_Filter* algo = engine->get_cipher(algo_spec, direction, af))
return algo;
}
diff --git a/src/libstate/lookup.h b/src/libstate/lookup.h
index 0f48dddfb..5f10bb3f8 100644
--- a/src/libstate/lookup.h
+++ b/src/libstate/lookup.h
@@ -8,17 +8,14 @@
#ifndef BOTAN_LOOKUP_H__
#define BOTAN_LOOKUP_H__
-#include <botan/block_cipher.h>
-#include <botan/stream_cipher.h>
-#include <botan/hash.h>
-#include <botan/mac.h>
-#include <botan/s2k.h>
-
+#include <botan/libstate.h>
+#include <botan/engine.h>
#include <botan/filters.h>
#include <botan/mode_pad.h>
#include <botan/kdf.h>
#include <botan/eme.h>
#include <botan/emsa.h>
+#include <botan/s2k.h>
namespace Botan {
@@ -28,59 +25,90 @@ namespace Botan {
// NOTE: these functions return internally stored objects, library
// retains ownership
-BOTAN_DLL const BlockCipher*
-retrieve_block_cipher(const std::string&);
-
-BOTAN_DLL const StreamCipher*
-retrieve_stream_cipher(const std::string&);
-
-BOTAN_DLL const HashFunction*
-retrieve_hash(const std::string&);
-
-BOTAN_DLL const MessageAuthenticationCode*
-retrieve_mac(const std::string&);
+inline const BlockCipher*
+retrieve_block_cipher(const std::string& algo_spec)
+ {
+ Algorithm_Factory& af = global_state().algorithm_factory();
+ return af.prototype_block_cipher(algo_spec);
+ }
+
+inline const StreamCipher*
+retrieve_stream_cipher(const std::string& algo_spec)
+ {
+ Algorithm_Factory& af = global_state().algorithm_factory();
+ return af.prototype_stream_cipher(algo_spec);
+ }
+
+inline const HashFunction*
+retrieve_hash(const std::string& algo_spec)
+ {
+ Algorithm_Factory& af = global_state().algorithm_factory();
+ return af.prototype_hash_function(algo_spec);
+ }
+
+inline const MessageAuthenticationCode*
+retrieve_mac(const std::string& algo_spec)
+ {
+ Algorithm_Factory& af = global_state().algorithm_factory();
+ return af.prototype_mac(algo_spec);
+ }
/*
* Get an algorithm object
+* NOTE: these functions create and return new objects, letting the
+* caller assume ownership of them
*/
-// NOTE: these functions create and return new objects, letting the
-// caller assume ownership of them
/**
* Block cipher factory method.
* @param algo_spec the name of the desired block cipher
* @return a pointer to the block cipher object
*/
-BOTAN_DLL BlockCipher* get_block_cipher(const std::string& name);
-
+inline BlockCipher* get_block_cipher(const std::string& algo_spec)
+ {
+ Algorithm_Factory& af = global_state().algorithm_factory();
+ return af.make_block_cipher(algo_spec);
+ }
/**
* Stream cipher factory method.
* @param algo_spec the name of the desired stream cipher
* @return a pointer to the stream cipher object
*/
-BOTAN_DLL StreamCipher* get_stream_cipher(const std::string& name);
+inline StreamCipher* get_stream_cipher(const std::string& algo_spec)
+ {
+ Algorithm_Factory& af = global_state().algorithm_factory();
+ return af.make_stream_cipher(algo_spec);
+ }
/**
* Hash function factory method.
* @param algo_spec the name of the desired hash function
* @return a pointer to the hash function object
*/
-BOTAN_DLL HashFunction* get_hash(const std::string& name);
+inline HashFunction* get_hash(const std::string& algo_spec)
+ {
+ Algorithm_Factory& af = global_state().algorithm_factory();
+ return af.make_hash_function(algo_spec);
+ }
/**
* MAC factory method.
* @param algo_spec the name of the desired MAC
* @return a pointer to the MAC object
*/
-BOTAN_DLL MessageAuthenticationCode* get_mac(const std::string& name);
+inline MessageAuthenticationCode* get_mac(const std::string& algo_spec)
+ {
+ Algorithm_Factory& af = global_state().algorithm_factory();
+ return af.make_mac(algo_spec);
+ }
/**
* String to key algorithm factory method.
* @param name the name of the desired string to key (S2K) algorithm
* @return a pointer to the string to key algorithm object
*/
-BOTAN_DLL S2K* get_s2k(const std::string& name);
+BOTAN_DLL S2K* get_s2k(const std::string& algo_spec);
/*
* Get an EMSA/EME/KDF/MGF function
@@ -93,7 +121,7 @@ BOTAN_DLL S2K* get_s2k(const std::string& name);
* @param name the name of the EME to create
* @return a pointer to the desired EME object
*/
-BOTAN_DLL EME* get_eme(const std::string& name);
+BOTAN_DLL EME* get_eme(const std::string& algo_spec);
/**
* Factory method for EMSA (message-encoding methods for signatures
@@ -101,14 +129,14 @@ BOTAN_DLL EME* get_eme(const std::string& name);
* @param name the name of the EME to create
* @return a pointer to the desired EME object
*/
-BOTAN_DLL EMSA* get_emsa(const std::string& name);
+BOTAN_DLL EMSA* get_emsa(const std::string& algo_spec);
/**
* Factory method for KDF (key derivation function)
* @param name the name of the KDF to create
* @return a pointer to the desired KDF object
*/
-BOTAN_DLL KDF* get_kdf(const std::string& name);
+BOTAN_DLL KDF* get_kdf(const std::string& algo_spec);
/*
* Get a cipher object
@@ -120,8 +148,8 @@ BOTAN_DLL KDF* get_kdf(const std::string& name);
* @param key the key to be used for encryption/decryption performed by
* the filter
* @param iv the initialization vector to be used
-* @param direction determines whether the filter will be an encrypting or decrypting
-* filter
+* @param direction determines whether the filter will be an encrypting
+* or decrypting filter
* @return a pointer to the encryption or decryption filter
*/
BOTAN_DLL Keyed_Filter* get_cipher(const std::string& name,
@@ -133,8 +161,8 @@ BOTAN_DLL Keyed_Filter* get_cipher(const std::string& name,
* @param algo_spec the name of the desired cipher
* @param key the key to be used for encryption/decryption performed by
* the filter
-* @param direction determines whether the filter will be an encrypting or decrypting
-* filter
+* @param direction determines whether the filter will be an encrypting
+* or decrypting filter
* @return a pointer to the encryption or decryption filter
*/
BOTAN_DLL Keyed_Filter* get_cipher(const std::string& name,
@@ -156,35 +184,51 @@ BOTAN_DLL Keyed_Filter* get_cipher(const std::string& name, Cipher_Dir dir);
* @param name the name of the algorithm to check for
* @return true if the algorithm exists, false otherwise
*/
-BOTAN_DLL bool have_algorithm(const std::string& name);
+BOTAN_DLL bool have_algorithm(const std::string& algo_spec);
/**
* Check if a block cipher algorithm exists.
* @param name the name of the algorithm to check for
* @return true if the algorithm exists, false otherwise
*/
-BOTAN_DLL bool have_block_cipher(const std::string& name);
+inline bool have_block_cipher(const std::string& algo_spec)
+ {
+ Algorithm_Factory& af = global_state().algorithm_factory();
+ return (af.prototype_block_cipher(algo_spec) != 0);
+ }
/**
* Check if a stream cipher algorithm exists.
* @param name the name of the algorithm to check for
* @return true if the algorithm exists, false otherwise
*/
-BOTAN_DLL bool have_stream_cipher(const std::string& name);
+inline bool have_stream_cipher(const std::string& algo_spec)
+ {
+ Algorithm_Factory& af = global_state().algorithm_factory();
+ return (af.prototype_stream_cipher(algo_spec) != 0);
+ }
/**
* Check if a hash algorithm exists.
* @param algo_spec the name of the algorithm to check for
* @return true if the algorithm exists, false otherwise
*/
-BOTAN_DLL bool have_hash(const std::string& name);
+inline bool have_hash(const std::string& algo_spec)
+ {
+ Algorithm_Factory& af = global_state().algorithm_factory();
+ return (af.prototype_hash_function(algo_spec) != 0);
+ }
/**
* Check if a MAC algorithm exists.
* @param algo_spec the name of the algorithm to check for
* @return true if the algorithm exists, false otherwise
*/
-BOTAN_DLL bool have_mac(const std::string& name);
+inline bool have_mac(const std::string& algo_spec)
+ {
+ Algorithm_Factory& af = global_state().algorithm_factory();
+ return (af.prototype_mac(algo_spec) != 0);
+ }
/*
* Query information about an algorithm
@@ -195,14 +239,14 @@ BOTAN_DLL bool have_mac(const std::string& name);
* @param name the name of the algorithm
* @return the block size of the specified algorithm
*/
-BOTAN_DLL u32bit block_size_of(const std::string& name);
+BOTAN_DLL u32bit block_size_of(const std::string& algo_spec);
/**
* Find out the output length of a certain symmetric algorithm.
* @param name the name of the algorithm
* @return the output length of the specified algorithm
*/
-BOTAN_DLL u32bit output_length_of(const std::string& name);
+BOTAN_DLL u32bit output_length_of(const std::string& algo_spec);
/**
* Find out the whether a certain key length is allowd for a given
@@ -211,28 +255,29 @@ BOTAN_DLL u32bit output_length_of(const std::string& name);
* @param name the name of the algorithm
* @return true if the key length is valid for that algorithm, false otherwise
*/
-BOTAN_DLL bool valid_keylength_for(u32bit keylen, const std::string& name);
+BOTAN_DLL bool valid_keylength_for(u32bit keylen,
+ const std::string& algo_spec);
/**
* Find out the minimum key size of a certain symmetric algorithm.
* @param name the name of the algorithm
* @return the minimum key length of the specified algorithm
*/
-BOTAN_DLL u32bit min_keylength_of(const std::string& name);
+BOTAN_DLL u32bit min_keylength_of(const std::string& algo_spec);
/**
* Find out the maximum key size of a certain symmetric algorithm.
* @param name the name of the algorithm
* @return the maximum key length of the specified algorithm
*/
-BOTAN_DLL u32bit max_keylength_of(const std::string& name);
+BOTAN_DLL u32bit max_keylength_of(const std::string& algo_spec);
/**
* Find out the size any valid key is a multiple of for a certain algorithm.
* @param name the name of the algorithm
* @return the size any valid key is a multiple of
*/
-BOTAN_DLL u32bit keylength_multiple_of(const std::string& name);
+BOTAN_DLL u32bit keylength_multiple_of(const std::string& algo_spec);
}
diff --git a/src/libstate/policy.cpp b/src/libstate/policy.cpp
index 45c99e674..3e9c8e122 100644
--- a/src/libstate/policy.cpp
+++ b/src/libstate/policy.cpp
@@ -48,6 +48,8 @@ void set_default_oids(Library_State& config)
add_oid(config, "2.16.840.1.101.3.4.1.2", "AES-128/CBC");
add_oid(config, "2.16.840.1.101.3.4.1.22", "AES-192/CBC");
add_oid(config, "2.16.840.1.101.3.4.1.42", "AES-256/CBC");
+ add_oid(config, "1.2.410.200004.1.4", "SEED/CBC"); // RFC 4010
+ add_oid(config, "1.3.6.1.4.1.25258.3.1", "Serpent/CBC");
/* Hash Functions */
add_oid(config, "1.2.840.113549.2.5", "MD5");
@@ -59,6 +61,13 @@ void set_default_oids(Library_State& config)
add_oid(config, "2.16.840.1.101.3.4.2.2", "SHA-384");
add_oid(config, "2.16.840.1.101.3.4.2.3", "SHA-512");
+ /* MACs */
+ add_oid(config, "1.2.840.113549.2.7", "HMAC(SHA-1)");
+ add_oid(config, "1.2.840.113549.2.8", "HMAC(SHA-224)");
+ add_oid(config, "1.2.840.113549.2.9", "HMAC(SHA-256)");
+ add_oid(config, "1.2.840.113549.2.10", "HMAC(SHA-384)");
+ add_oid(config, "1.2.840.113549.2.11", "HMAC(SHA-512)");
+
/* Key Wrap */
add_oid(config, "1.2.840.113549.1.9.16.3.6", "KeyWrap.TripleDES");
add_oid(config, "1.2.840.113549.1.9.16.3.7", "KeyWrap.RC2");
diff --git a/src/libstate/scan_name.cpp b/src/libstate/scan_name.cpp
index 9e046e8ea..eccb15565 100644
--- a/src/libstate/scan_name.cpp
+++ b/src/libstate/scan_name.cpp
@@ -63,7 +63,7 @@ deref_aliases(const std::pair<u32bit, std::string>& in)
}
-SCAN_Name::SCAN_Name(const std::string& algo_spec)
+SCAN_Name::SCAN_Name(std::string algo_spec)
{
orig_algo_spec = algo_spec;
@@ -71,6 +71,10 @@ SCAN_Name::SCAN_Name(const std::string& algo_spec)
u32bit level = 0;
std::pair<u32bit, std::string> accum = std::make_pair(level, "");
+ std::string decoding_error = "Bad SCAN name '" + algo_spec + "': ";
+
+ algo_spec = global_state().deref_alias(algo_spec);
+
for(u32bit i = 0; i != algo_spec.size(); ++i)
{
char c = algo_spec[i];
@@ -82,7 +86,7 @@ SCAN_Name::SCAN_Name(const std::string& algo_spec)
else if(c == ')')
{
if(level == 0)
- throw Decoding_Error("Bad SCAN name " + algo_spec);
+ throw Decoding_Error(decoding_error + "Mismatched parens");
--level;
}
@@ -102,8 +106,11 @@ SCAN_Name::SCAN_Name(const std::string& algo_spec)
if(accum.second != "")
name.push_back(deref_aliases(accum));
- if(level != 0 || name.size() == 0)
- throw Decoding_Error("Bad SCAN name " + algo_spec);
+ if(level != 0)
+ throw Decoding_Error(decoding_error + "Missing close paren");
+
+ if(name.size() == 0)
+ throw Decoding_Error(decoding_error + "Empty name");
alg_name = name[0].second;
@@ -146,7 +153,7 @@ std::string SCAN_Name::algo_name_and_args() const
std::string SCAN_Name::arg(u32bit i) const
{
if(i >= arg_count())
- throw std::range_error("SCAN_Name::argument");
+ throw std::range_error("SCAN_Name::argument - i out of range");
return args[i];
}
diff --git a/src/libstate/scan_name.h b/src/libstate/scan_name.h
index 7992d7498..4350dca86 100644
--- a/src/libstate/scan_name.h
+++ b/src/libstate/scan_name.h
@@ -23,9 +23,9 @@ class BOTAN_DLL SCAN_Name
{
public:
/**
- @param algo_spec A SCAN name
+ @param algo_spec A SCAN-format name
*/
- SCAN_Name(const std::string& algo_spec);
+ SCAN_Name(std::string algo_spec);
/**
@return the original input string
diff --git a/src/math/bigint/bigint.cpp b/src/math/bigint/bigint.cpp
index 70bb11a83..09ac2a75d 100644
--- a/src/math/bigint/bigint.cpp
+++ b/src/math/bigint/bigint.cpp
@@ -7,7 +7,7 @@
#include <botan/bigint.h>
#include <botan/internal/mp_core.h>
-#include <botan/loadstor.h>
+#include <botan/get_byte.h>
#include <botan/parsing.h>
#include <botan/internal/rounding.h>
diff --git a/src/math/gfpmath/curve_gfp.cpp b/src/math/gfpmath/curve_gfp.cpp
index 3cdb08a65..e6e69ab0f 100644
--- a/src/math/gfpmath/curve_gfp.cpp
+++ b/src/math/gfpmath/curve_gfp.cpp
@@ -2,7 +2,7 @@
* Elliptic curves over GF(p)
*
* (C) 2007 Martin Doering, Christoph Ludwig, Falko Strenzke
-* 2008 Jack Lloyd
+* 2008-2010 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
@@ -14,147 +14,40 @@
namespace Botan {
-void CurveGFp::set_shrd_mod(const std::tr1::shared_ptr<GFpModulus> mod)
- {
- mp_mod = mod;
- mA.turn_off_sp_red_mul();// m.m. is not needed, must be trf. back
- mB.turn_off_sp_red_mul();// m.m. is not needed, must be trf. back
- //ok, above we destroy any evantually computated montg. mult. values,
- // but that won't influence performance in usual applications
- mA.set_shrd_mod(mod);
- mB.set_shrd_mod(mod);
- }
-
CurveGFp::CurveGFp(const GFpElement& a, const GFpElement& b,
- const BigInt& p)
- : mA(a),
- mB(b)
+ const BigInt& p) :
+ modulus(p), mA(a), mB(b),
+ mres_a(mA), mres_b(mB), mres_one(p, 1)
{
- if(!((p == mA.get_p()) && (p == mB.get_p())))
- {
+ if(p != mA.get_p() || p != mB.get_p())
throw Invalid_Argument("could not construct curve: moduli of arguments differ");
- }
- std::tr1::shared_ptr<GFpModulus> p_mod = std::tr1::shared_ptr<GFpModulus>(new GFpModulus(p));
- // the above is the creation of the GFpModuls object which will be shared point-wide
- // (in the context of a point of course)
- set_shrd_mod(p_mod);
- }
-// copy constructor
-CurveGFp::CurveGFp(const CurveGFp& other)
- : mA(other.get_a()),
- mB(other.get_b())
- {
- mp_mod = std::tr1::shared_ptr<GFpModulus>(new GFpModulus(*other.mp_mod));
- assert(mp_mod->p_equal_to(mA.get_p()));
- assert(mp_mod->p_equal_to(mB.get_p()));
- set_shrd_mod(mp_mod);
- if(other.mp_mres_a.get())
- {
- mp_mres_a = std::tr1::shared_ptr<GFpElement>(new GFpElement(*other.mp_mres_a));
- }
- if(other.mp_mres_b.get())
- {
- mp_mres_b = std::tr1::shared_ptr<GFpElement>(new GFpElement(*other.mp_mres_b));
- }
- if(other.mp_mres_one.get())
- {
- mp_mres_one = std::tr1::shared_ptr<GFpElement>(new GFpElement(*other.mp_mres_one));
- }
-
- }
-// assignment operator
-const CurveGFp& CurveGFp::operator=(const CurveGFp& other)
- {
- // for exception safety...
- GFpElement a_tmp = other.mA;
- GFpElement b_tmp = other.mB;
- mA.swap(a_tmp);
- mB.swap(b_tmp);
-
- std::tr1::shared_ptr<GFpModulus> p_mod = std::tr1::shared_ptr<GFpModulus>(new GFpModulus(*other.mp_mod));
- set_shrd_mod(p_mod);
-
- // exception safety note: no problem if we have a throw from here on...
- if(other.mp_mres_a.get())
- {
- mp_mres_a = std::tr1::shared_ptr<GFpElement>(new GFpElement(*other.mp_mres_a));
- }
- if(other.mp_mres_b.get())
- {
- mp_mres_b = std::tr1::shared_ptr<GFpElement>(new GFpElement(*other.mp_mres_b));
- }
- if(other.mp_mres_one.get())
- {
- mp_mres_one = std::tr1::shared_ptr<GFpElement>(new GFpElement(*other.mp_mres_one));
- }
- return *this;
- }
-
-// getters
-const GFpElement& CurveGFp::get_a() const
- {
- return mA;
- }
+ mres_a.turn_on_sp_red_mul();
+ mres_a.get_mres();
-const GFpElement& CurveGFp::get_b() const
- {
- return mB;
- }
+ mres_b.turn_on_sp_red_mul();
+ mres_b.get_mres();
-const BigInt CurveGFp::get_p() const
- {
- assert(mp_mod.get() != 0);
- return mp_mod->get_p();
+ mres_one.turn_on_sp_red_mul();
+ mres_one.get_mres();
}
// swaps the states of *this and other, does not throw
void CurveGFp::swap(CurveGFp& other)
{
- mA.swap(other.mA);
- mB.swap(other.mB);
- mp_mod.swap(other.mp_mod);
- std::swap(mp_mres_a, other.mp_mres_a);
- std::swap(mp_mres_b, other.mp_mres_b);
- std::swap(mp_mres_one, other.mp_mres_one);
- }
-
-GFpElement const CurveGFp::get_mres_a() const
- {
- if(mp_mres_a.get() == 0)
- {
- mp_mres_a = std::tr1::shared_ptr<GFpElement>(new GFpElement(mA));
- mp_mres_a->turn_on_sp_red_mul();
- mp_mres_a->get_mres();
- }
- return GFpElement(*mp_mres_a);
- }
-
-GFpElement const CurveGFp::get_mres_b() const
- {
- if(mp_mres_b.get() == 0)
- {
- mp_mres_b = std::tr1::shared_ptr<GFpElement>(new GFpElement(mB));
- mp_mres_b->turn_on_sp_red_mul();
- mp_mres_b->get_mres();
- }
- return GFpElement(*mp_mres_b);
- }
-
-std::tr1::shared_ptr<GFpElement const> const CurveGFp::get_mres_one() const
- {
- if(mp_mres_one.get() == 0)
- {
- mp_mres_one = std::tr1::shared_ptr<GFpElement>(new GFpElement(mp_mod->get_p(), 1));
- mp_mres_one->turn_on_sp_red_mul();
- mp_mres_one->get_mres();
- }
- return mp_mres_one;
+ std::swap(mA, other.mA);
+ std::swap(mB, other.mB);
+ std::swap(modulus, other.modulus);
+ std::swap(mres_a, other.mres_a);
+ std::swap(mres_b, other.mres_b);
+ std::swap(mres_one, other.mres_one);
}
bool operator==(const CurveGFp& lhs, const CurveGFp& rhs)
{
- return (lhs.get_p() == rhs.get_p() && lhs.get_a() == rhs.get_a() && lhs.get_b() == rhs.get_b());
+ return (lhs.get_p() == rhs.get_p() &&
+ lhs.get_a() == rhs.get_a() &&
+ lhs.get_b() == rhs.get_b());
}
std::ostream& operator<<(std::ostream& output, const CurveGFp& elem)
diff --git a/src/math/gfpmath/curve_gfp.h b/src/math/gfpmath/curve_gfp.h
index 53bbc1f3c..5641e80d1 100644
--- a/src/math/gfpmath/curve_gfp.h
+++ b/src/math/gfpmath/curve_gfp.h
@@ -2,6 +2,7 @@
* Elliptic curves over GF(p)
*
* (C) 2007 Martin Doering, Christoph Ludwig, Falko Strenzke
+* 2010 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
@@ -9,7 +10,6 @@
#ifndef BOTAN_GFP_CURVE_H__
#define BOTAN_GFP_CURVE_H__
-#include <botan/bigint.h>
#include <botan/gfp_element.h>
#include <iosfwd>
@@ -31,28 +31,8 @@ class BOTAN_DLL CurveGFp
CurveGFp(const GFpElement& a, const GFpElement& b,
const BigInt& p);
- /**
- * Copy constructor
- * @param other The curve to clone
- */
- CurveGFp(const CurveGFp& other);
-
- /**
- * Assignment operator
- * @param other The curve to use as source for the assignment
- */
- const CurveGFp& operator=(const CurveGFp& other);
-
- /**
- * Set the shared GFpModulus object.
- * Warning: do not use this function unless you know in detail how
- * the sharing of values
- * in the various EC related objects works.
- * Do NOT spread pointers to a GFpModulus over different threads!
- * @param mod a shared pointer to a GFpModulus object suitable for
- * *this.
- */
- void set_shrd_mod(const std::tr1::shared_ptr<GFpModulus> mod);
+ // CurveGFp(const CurveGFp& other) = default;
+ // CurveGFp& operator=(const CurveGFp& other) = default;
// getters
@@ -60,13 +40,13 @@ class BOTAN_DLL CurveGFp
* Get coefficient a
* @result coefficient a
*/
- const GFpElement& get_a() const;
+ const GFpElement& get_a() const { return mA; }
/**
* Get coefficient b
* @result coefficient b
*/
- const GFpElement& get_b() const;
+ const GFpElement& get_b() const { return mB; }
/**
* Get the GFpElement coefficient a transformed
@@ -75,7 +55,7 @@ class BOTAN_DLL CurveGFp
* function.
* @result the coefficient a, transformed to its m-residue
*/
- GFpElement const get_mres_a() const;
+ const GFpElement& get_mres_a() const { return mres_a; }
/**
* Get the GFpElement coefficient b transformed
@@ -84,8 +64,7 @@ class BOTAN_DLL CurveGFp
* function.
* @result the coefficient b, transformed to its m-residue
*/
- GFpElement const get_mres_b() const;
-
+ const GFpElement& get_mres_b() const { return mres_b; }
/**
* Get the GFpElement 1 transformed
@@ -94,31 +73,13 @@ class BOTAN_DLL CurveGFp
* function.
* @result the GFpElement 1, transformed to its m-residue
*/
- std::tr1::shared_ptr<GFpElement const> const get_mres_one() const;
+ const GFpElement& get_mres_one() { return mres_one; }
/**
* Get prime modulus of the field of the curve
* @result prime modulus of the field of the curve
*/
- BigInt const get_p() const;
- /*inline std::tr1::shared_ptr<BigInt> const get_ptr_p() const
- {
- return mp_p;
- }*/
-
- /**
- * Retrieve a shared pointer to the curves GFpModulus object for
- * efficient storage and computation of montgomery multiplication
- * related data members and functions. Warning: do not use this
- * function unless you know in detail how the sharing of values
- * in the various EC related objects works. Do NOT spread
- * pointers to a GFpModulus over different threads!
- * @result a shared pointer to a GFpModulus object
- */
- inline std::tr1::shared_ptr<GFpModulus> const get_ptr_mod() const
- {
- return mp_mod;
- }
+ const BigInt& get_p() const { return modulus.get_p(); }
/**
* swaps the states of *this and other, does not throw
@@ -127,12 +88,10 @@ class BOTAN_DLL CurveGFp
void swap(CurveGFp& other);
private:
- std::tr1::shared_ptr<GFpModulus> mp_mod;
+ GFpModulus modulus;
GFpElement mA;
GFpElement mB;
- mutable std::tr1::shared_ptr<GFpElement> mp_mres_a;
- mutable std::tr1::shared_ptr<GFpElement> mp_mres_b;
- mutable std::tr1::shared_ptr<GFpElement> mp_mres_one;
+ GFpElement mres_a, mres_b, mres_one;
};
// relational operators
diff --git a/src/math/gfpmath/gfp_element.cpp b/src/math/gfpmath/gfp_element.cpp
index 233f2e4cd..3bb4d0002 100644
--- a/src/math/gfpmath/gfp_element.cpp
+++ b/src/math/gfpmath/gfp_element.cpp
@@ -165,47 +165,20 @@ BigInt montg_trf_to_ordres(const BigInt& m_res, const BigInt& m, const BigInt& r
}
-GFpElement::GFpElement(const BigInt& p, const BigInt& value, bool use_montgm)
- : mp_mod(),
- m_value(value %p),
- m_use_montgm(use_montgm),
- m_is_trf(false)
- {
- assert(mp_mod.get() == 0);
- mp_mod = std::tr1::shared_ptr<GFpModulus>(new GFpModulus(p));
- assert(mp_mod->m_p_dash == 0);
+GFpElement::GFpElement(const BigInt& p, const BigInt& value, bool use_montgomery)
+ : modulus(p), m_value(value %p), m_use_montgm(use_montgomery), m_is_trf(false)
+ {
if(m_use_montgm)
ensure_montgm_precomp();
}
-GFpElement::GFpElement(std::tr1::shared_ptr<GFpModulus> const mod, const BigInt& value, bool use_montgm)
- : mp_mod(),
- m_value(value % mod->m_p),
- m_use_montgm(use_montgm),
- m_is_trf(false)
- {
- assert(mp_mod.get() == 0);
- mp_mod = mod;
- }
-
-GFpElement::GFpElement(const GFpElement& other)
- : m_value(other.m_value),
- m_use_montgm(other.m_use_montgm),
- m_is_trf(other.m_is_trf)
-
- {
- //creates an independent copy
- assert((other.m_is_trf && other.m_use_montgm) || !other.m_is_trf);
- mp_mod.reset(new GFpModulus(*other.mp_mod)); // copy-ctor of GFpModulus
- }
-
-void GFpElement::turn_on_sp_red_mul() const
+void GFpElement::turn_on_sp_red_mul()
{
ensure_montgm_precomp();
m_use_montgm = true;
}
-void GFpElement::turn_off_sp_red_mul() const
+void GFpElement::turn_off_sp_red_mul()
{
if(m_is_trf)
{
@@ -216,40 +189,25 @@ void GFpElement::turn_off_sp_red_mul() const
m_use_montgm = false;
}
-void GFpElement::ensure_montgm_precomp() const
+void GFpElement::ensure_montgm_precomp()
{
- if((!mp_mod->m_r.is_zero()) && (!mp_mod->m_r_inv.is_zero()) && (!mp_mod->m_p_dash.is_zero()))
+ if((!modulus.get_r().is_zero()) && (!modulus.get_r_inv().is_zero()) && (!modulus.get_p_dash().is_zero()))
{
// values are already set, nothing more to do
}
else
{
- BigInt tmp_r(montgm_calc_r_oddmod(mp_mod->m_p));
-
- BigInt tmp_r_inv(inverse_mod(tmp_r, mp_mod->m_p));
+ BigInt tmp_r(montgm_calc_r_oddmod(modulus.get_p()));
- BigInt tmp_p_dash(montgm_calc_m_dash(tmp_r, mp_mod->m_p, tmp_r_inv));
+ BigInt tmp_r_inv(inverse_mod(tmp_r, modulus.get_p()));
- mp_mod->m_r.grow_reg(tmp_r.size());
- mp_mod->m_r_inv.grow_reg(tmp_r_inv.size());
- mp_mod->m_p_dash.grow_reg(tmp_p_dash.size());
+ BigInt tmp_p_dash(montgm_calc_m_dash(tmp_r, modulus.get_p(), tmp_r_inv));
- mp_mod->m_r = tmp_r;
- mp_mod->m_r_inv = tmp_r_inv;
- mp_mod->m_p_dash = tmp_p_dash;
-
- assert(!mp_mod->m_r.is_zero());
- assert(!mp_mod->m_r_inv.is_zero());
- assert(!mp_mod->m_p_dash.is_zero());
+ modulus.reset_values(tmp_p_dash, tmp_r, tmp_r_inv);
}
}
-void GFpElement::set_shrd_mod(std::tr1::shared_ptr<GFpModulus> const p_mod)
- {
- mp_mod = p_mod;
- }
-
void GFpElement::trf_to_mres() const
{
if(!m_use_montgm)
@@ -257,27 +215,27 @@ void GFpElement::trf_to_mres() const
throw Illegal_Transformation("GFpElement is not allowed to be transformed to m-residue");
}
assert(m_is_trf == false);
- assert(!mp_mod->m_r_inv.is_zero());
- assert(!mp_mod->m_p_dash.is_zero());
- m_value = montg_trf_to_mres(m_value, mp_mod->m_r, mp_mod->m_p);
+ assert(!modulus.get_r_inv().is_zero());
+ assert(!modulus.get_p_dash().is_zero());
+ m_value = montg_trf_to_mres(m_value, modulus.get_r(), modulus.get_p());
m_is_trf = true;
}
void GFpElement::trf_to_ordres() const
{
assert(m_is_trf == true);
- m_value = montg_trf_to_ordres(m_value, mp_mod->m_p, mp_mod->m_r_inv);
+ m_value = montg_trf_to_ordres(m_value, modulus.get_p(), modulus.get_r_inv());
m_is_trf = false;
}
bool GFpElement::align_operands_res(const GFpElement& lhs, const GFpElement& rhs) //static
{
- assert(lhs.mp_mod->m_p == rhs.mp_mod->m_p);
+ assert(lhs.modulus.get_p() == rhs.modulus.get_p());
if(lhs.m_use_montgm && rhs.m_use_montgm)
{
- assert(rhs.mp_mod->m_p_dash == lhs.mp_mod->m_p_dash);
- assert(rhs.mp_mod->m_r == lhs.mp_mod->m_r);
- assert(rhs.mp_mod->m_r_inv == lhs.mp_mod->m_r_inv);
+ assert(rhs.modulus.get_p_dash() == lhs.modulus.get_p_dash());
+ assert(rhs.modulus.get_r() == lhs.modulus.get_r());
+ assert(rhs.modulus.get_r_inv() == lhs.modulus.get_r_inv());
if(!lhs.m_is_trf && !rhs.m_is_trf)
{
return false;
@@ -327,7 +285,7 @@ bool GFpElement::is_trf_to_mres() const
const BigInt& GFpElement::get_p() const
{
- return (mp_mod->m_p);
+ return (modulus.get_p());
}
const BigInt& GFpElement::get_value() const
@@ -345,7 +303,7 @@ const BigInt& GFpElement::get_mres() const
if(!m_use_montgm)
{
// does the following exception really make sense?
- // wouldn´t it be better to simply turn on montg.mult. when
+ // wouldn't it be better to simply turn on montg.mult. when
// this explicit request is made?
throw Illegal_Transformation("GFpElement is not allowed to be transformed to m-residue");
}
@@ -357,107 +315,17 @@ const BigInt& GFpElement::get_mres() const
return m_value;
}
-const GFpElement& GFpElement::operator=(const GFpElement& other)
- {
- m_value.grow_reg(other.m_value.size()); // grow first for exception safety
-
- //m_value = other.m_value;
-
- // m_use_montgm = other.m_use_montgm;
- // m_is_trf = other.m_is_trf;
- // we want to keep the member pointers, which might be part of a "sharing group"
- // but we may not simply overwrite the BigInt values with those of the argument!!
- // if ours already contains precomputations, it would be hazardous to
- // set them back to zero.
- // thus we first check for equality of the moduli,
- // then whether either of the two objects already contains
- // precomputed values.
-
- // we also deal with the case were the pointers themsevles are equal:
- if(mp_mod.get() == other.mp_mod.get())
- {
- // everything ok, we are in the same sharing group anyway, nothing to do
- m_value = other.m_value; // cannot throw
- m_use_montgm = other.m_use_montgm;
- m_is_trf = other.m_is_trf;
- return *this;
- }
- if(mp_mod->m_p != other.mp_mod->m_p)
- {
- // the moduli are different, this is a special case
- // which will not occur in usual applications,
- // so we don´t hesitate to simply create new objects
- // (we do want to create an independent copy)
- mp_mod.reset(new GFpModulus(*other.mp_mod)); // this could throw,
- // and because of this
- // we haven't modified
- // anything so far
- m_value = other.m_value; // can't throw
- m_use_montgm = other.m_use_montgm;
- m_is_trf = other.m_is_trf;
- return *this;
- }
- // exception safety note: from now on we are on the safe
- // side with respect to the modulus,
- // so we can assign the value now:
- m_value = other.m_value;
- m_use_montgm = other.m_use_montgm;
- m_is_trf = other.m_is_trf;
- // the moduli are equal, but we deal with different sharing groups.
- // we will NOT fuse the sharing goups
- // and we will NOT reset already precomputed values
- if(mp_mod->has_precomputations())
- {
- // our own sharing group already has precomputed values,
- // so nothing to do.
- return *this;
- }
- else
- {
- // let´s see whether the argument has something for us...
- if(other.mp_mod->has_precomputations())
- {
- // fetch them for our sharing group
- // exc. safety note: grow first
- mp_mod->m_p_dash.grow_reg(other.mp_mod->m_p_dash.size());
- mp_mod->m_r.grow_reg(other.mp_mod->m_r.size());
- mp_mod->m_r_inv.grow_reg(other.mp_mod->m_r_inv.size());
-
- mp_mod->m_p_dash = other.mp_mod->m_p_dash;
- mp_mod->m_r = other.mp_mod->m_r;
- mp_mod->m_r_inv = other.mp_mod->m_r_inv;
- return *this;
- }
- }
- // our precomputations aren´t set, the arguments neither,
- // so we let them alone
- return *this;
- }
-
-void GFpElement::share_assign(const GFpElement& other)
- {
- assert((other.m_is_trf && other.m_use_montgm) || !other.m_is_trf);
-
- // use grow_to to make it exc safe
- m_value.grow_reg(other.m_value.size());
- m_value = other.m_value;
-
- m_use_montgm = other.m_use_montgm;
- m_is_trf = other.m_is_trf;
- mp_mod = other.mp_mod; // cannot throw
- }
-
GFpElement& GFpElement::operator+=(const GFpElement& rhs)
{
GFpElement::align_operands_res(*this, rhs);
- workspace = m_value;
+ BigInt workspace = m_value;
workspace += rhs.m_value;
- if(workspace >= mp_mod->m_p)
- workspace -= mp_mod->m_p;
+ if(workspace >= modulus.get_p())
+ workspace -= modulus.get_p();
m_value = workspace;
- assert(m_value < mp_mod->m_p);
+ assert(m_value < modulus.get_p());
assert(m_value >= 0);
return *this;
@@ -467,39 +335,39 @@ GFpElement& GFpElement::operator-=(const GFpElement& rhs)
{
GFpElement::align_operands_res(*this, rhs);
- workspace = m_value;
+ BigInt workspace = m_value;
workspace -= rhs.m_value;
if(workspace.is_negative())
- workspace += mp_mod->m_p;
+ workspace += modulus.get_p();
m_value = workspace;
- assert(m_value < mp_mod->m_p);
+ assert(m_value < modulus.get_p());
assert(m_value >= 0);
return *this;
}
GFpElement& GFpElement::operator*= (u32bit rhs)
{
- workspace = m_value;
+ BigInt workspace = m_value;
workspace *= rhs;
- workspace %= mp_mod->m_p;
+ workspace %= modulus.get_p();
m_value = workspace;
return *this;
}
GFpElement& GFpElement::operator*=(const GFpElement& rhs)
{
- assert(rhs.mp_mod->m_p == mp_mod->m_p);
+ assert(rhs.modulus.get_p() == modulus.get_p());
// here, we do not use align_operands_res() for one simple reason:
// we want to enforce the transformation to an m-residue, otherwise it would
// never happen
if(m_use_montgm && rhs.m_use_montgm)
{
- assert(rhs.mp_mod->m_p == mp_mod->m_p); // is montgm. mult is on, then precomps must be there
- assert(rhs.mp_mod->m_p_dash == mp_mod->m_p_dash);
- assert(rhs.mp_mod->m_r == mp_mod->m_r);
+ assert(rhs.modulus.get_p() == modulus.get_p()); // is montgm. mult is on, then precomps must be there
+ assert(rhs.modulus.get_p_dash() == modulus.get_p_dash());
+ assert(rhs.modulus.get_r() == modulus.get_r());
if(!m_is_trf)
{
trf_to_mres();
@@ -508,8 +376,8 @@ GFpElement& GFpElement::operator*=(const GFpElement& rhs)
{
rhs.trf_to_mres();
}
- workspace = m_value;
- montg_mult(m_value, workspace, rhs.m_value, mp_mod->m_p, mp_mod->m_p_dash, mp_mod->m_r);
+ BigInt workspace = m_value;
+ montg_mult(m_value, workspace, rhs.m_value, modulus.get_p(), modulus.get_p_dash(), modulus.get_r());
}
else // ordinary multiplication
{
@@ -524,9 +392,9 @@ GFpElement& GFpElement::operator*=(const GFpElement& rhs)
rhs.trf_to_ordres();
}
- workspace = m_value;
+ BigInt workspace = m_value;
workspace *= rhs.m_value;
- workspace %= mp_mod->m_p;
+ workspace %= modulus.get_p();
m_value = workspace;
}
return *this;
@@ -536,18 +404,17 @@ GFpElement& GFpElement::operator/=(const GFpElement& rhs)
{
bool use_mres = GFpElement::align_operands_res(*this, rhs);
assert((this->m_is_trf && rhs.m_is_trf) || !(this->m_is_trf && rhs.m_is_trf));
- // (internal note: see C86)
+
if(use_mres)
{
assert(m_use_montgm && rhs.m_use_montgm);
GFpElement rhs_ordres(rhs);
rhs_ordres.trf_to_ordres();
rhs_ordres.inverse_in_place();
- workspace = m_value;
- workspace *= rhs_ordres.get_value();
- workspace %= mp_mod->m_p;
+ BigInt workspace = m_value;
+ workspace *= rhs_ordres.get_value();
+ workspace %= modulus.get_p();
m_value = workspace;
-
}
else
{
@@ -566,30 +433,31 @@ bool GFpElement::is_zero()
GFpElement& GFpElement::inverse_in_place()
{
- m_value = inverse_mod(m_value, mp_mod->m_p);
+ m_value = inverse_mod(m_value, modulus.get_p());
+
if(m_is_trf)
{
assert(m_use_montgm);
- m_value *= mp_mod->m_r;
- m_value *= mp_mod->m_r;
- m_value %= mp_mod->m_p;
+ m_value *= modulus.get_r();
+ m_value *= modulus.get_r();
+ m_value %= modulus.get_p();
}
- assert(m_value <= mp_mod->m_p);
+ assert(m_value <= modulus.get_p());
return *this;
}
GFpElement& GFpElement::negate()
{
- m_value = mp_mod->m_p - m_value;
- assert(m_value <= mp_mod->m_p);
+ m_value = modulus.get_p() - m_value;
+ assert(m_value <= modulus.get_p());
return *this;
}
void GFpElement::swap(GFpElement& other)
{
- m_value.swap(other.m_value);
- mp_mod.swap(other.mp_mod);
+ std::swap(m_value, other.m_value);
+ std::swap(modulus, other.modulus);
std::swap<bool>(m_use_montgm,other.m_use_montgm);
std::swap<bool>(m_is_trf,other.m_is_trf);
}
@@ -601,15 +469,9 @@ std::ostream& operator<<(std::ostream& output, const GFpElement& elem)
bool operator==(const GFpElement& lhs, const GFpElement& rhs)
{
- // for effeciency reasons we firstly check whether
- //the modulus pointers are different in the first place:
- if(lhs.get_ptr_mod() != rhs.get_ptr_mod())
- {
- if(lhs.get_p() != rhs.get_p())
- {
- return false;
- }
- }
+ if(lhs.get_p() != rhs.get_p())
+ return false;
+
// so the modulus is equal, now check the values
bool use_mres = GFpElement::align_operands_res(lhs, rhs);
diff --git a/src/math/gfpmath/gfp_element.h b/src/math/gfpmath/gfp_element.h
index c6cfc9d32..538d41a47 100644
--- a/src/math/gfpmath/gfp_element.h
+++ b/src/math/gfpmath/gfp_element.h
@@ -2,6 +2,7 @@
* Arithmetic for prime fields GF(p)
*
* (C) 2007 Martin Doering, Christoph Ludwig, Falko Strenzke
+* 2009-2010 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
@@ -13,14 +14,6 @@
#include <botan/gfp_modulus.h>
#include <iosfwd>
-#if defined(BOTAN_USE_STD_TR1)
- #include <tr1/memory>
-#elif defined(BOTAN_USE_BOOST_TR1)
- #include <boost/tr1/memory.hpp>
-#else
- #error "Please choose a TR1 implementation in build.h"
-#endif
-
namespace Botan {
struct BOTAN_DLL Illegal_Transformation : public Exception
@@ -45,57 +38,21 @@ class BOTAN_DLL GFpElement
* @param value the element value
* @param use_montgm whether this object will use Montgomery multiplication
*/
- explicit GFpElement (const BigInt& p, const BigInt& value, bool use_montgm = false);
-
-
- /** construct an element of GF(p) with the given value (defaults
- * to 0). use_montg defaults to false and determines wether
- * montgomery multiplications will be use when applying operators
- * '*' , '*='. Use this constructor for efficient use of
- * Montgomery multiplication in a context with a fixed a modulus.
- * Warning: do not use this function unless you know in detail
- * about the implications of using the shared GFpModulus objects!
- * @param mod shared pointer to the GFpModulus to be shared
- * @param value the element value
- * @param use_montgm whether this object will use Montgomery multiplication
- */
- explicit GFpElement(std::tr1::shared_ptr<GFpModulus> const mod,
- const BigInt& value, bool use_mongm = false);
+ GFpElement(const BigInt& p, const BigInt& value, bool use_montgm = true);
- /**
- * Copy constructor
- * @param other The element to clone
- */
- GFpElement(const GFpElement& other);
-
- /**
- * Assignment operator.
- * makes *this a totally independent object
- * (gives *this independent modulus specific values).
-
- * @param other The element to assign to our object
- */
- const GFpElement& operator=(const GFpElement& other);
+ // GFpElement(const GFpElement& other) = default;
- /**
- * Works like the assignment operator, but lets
- * *this share the modulus dependend value with other.
- * Warning: do not use this function unless you know in detail about
- * the implications of using
- * the shared GFpModulus objects!
- * @param other The element to assign to our object
- */
- void share_assign(const GFpElement& other);
+ // const GFpElement& operator=(const GFpElement& other) = default;
/**
* Switch Montgomery multiplcation optimizations ON
*/
- void turn_on_sp_red_mul() const;
+ void turn_on_sp_red_mul();
/**
* Switch Montgomery multiplcation optimizations OFF
*/
- void turn_off_sp_red_mul() const;
+ void turn_off_sp_red_mul();
/**
* += Operator
@@ -129,7 +86,7 @@ class BOTAN_DLL GFpElement
* @param rhs the value to multiply with the local value
* @result *this
*/
- GFpElement& operator*= (u32bit rhs);
+ GFpElement& operator*=(u32bit rhs);
/**
* Negate internal value(*this *= -1 )
@@ -164,31 +121,9 @@ class BOTAN_DLL GFpElement
const BigInt& get_value() const;
/**
- * Returns the shared pointer to the GFpModulus of *this.
- * Warning: do not use this function unless you know in detail about
- * the implications of using
- * the shared GFpModulus objects!
- * @result the shared pointer to the GFpModulus of *this
- */
- inline std::tr1::shared_ptr<GFpModulus> const get_ptr_mod() const
- {
- return mp_mod;
- }
-
-
- /**
- * Sets the shared pointer to the GFpModulus of *this.
- * Warning: do not use this function unless you know in detail about
- * the implications of using
- * the shared GFpModulus objects!
- * @param mod a shared pointer to a GFpModulus that will be held in *this
- */
- void set_shrd_mod(std::tr1::shared_ptr<GFpModulus> const mod);
-
- /**
- * Tells whether this GFpElement is currently transformed to it´ m-residue,
+ * Tells whether this GFpElement is currently transformed to an m-residue,
* i.e. in the form x_bar = x * r mod m.
- * @result true if it is currently transformed to it´s m-residue.
+ * @result true if it is currently transformed to its m-residue.
*/
bool is_trf_to_mres() const;
@@ -213,7 +148,7 @@ class BOTAN_DLL GFpElement
* in ordinary residue representation (returns false).
* m-residue is prefered in case of ambiguity.
* does not toggle m_use_montgm of the arguments.
- * Don´t be confused about the constness of the arguments:
+ * Don't be confused about the constness of the arguments:
* the transformation between normal residue and m-residue is
* considered as leaving the object const.
* @param lhs the first operand to be aligned
@@ -223,31 +158,22 @@ class BOTAN_DLL GFpElement
*/
static bool align_operands_res(const GFpElement& lhs, const GFpElement& rhs);
- //friend declarations for non-member functions
-
- friend class Point_Coords_GFp;
-
/**
* swaps the states of *this and other, does not throw!
* @param other The value to swap with
*/
void swap(GFpElement& other);
private:
- void ensure_montgm_precomp() const;
+ void ensure_montgm_precomp();
void trf_to_mres() const;
void trf_to_ordres() const;
- std::tr1::shared_ptr<GFpModulus> mp_mod;
+ GFpModulus modulus;
mutable BigInt m_value; // ordinary residue or m-residue respectively
- mutable BigInt workspace;
- // *****************************************
// data members for montgomery multiplication
- mutable bool m_use_montgm;
- //mutable BigInt m_mres;
- // this bool tells use whether the m_mres carries
- // the actual value (in this case mValue doesn´t)
- mutable bool m_is_trf;
+ bool m_use_montgm;
+ mutable bool m_is_trf; // if m_value is montgomery
};
// relational operators
@@ -264,8 +190,8 @@ GFpElement BOTAN_DLL operator-(const GFpElement& lhs);
GFpElement BOTAN_DLL operator*(const GFpElement& lhs, const GFpElement& rhs);
GFpElement BOTAN_DLL operator/(const GFpElement& lhs, const GFpElement& rhs);
-GFpElement BOTAN_DLL operator* (const GFpElement& lhs, u32bit rhs);
-GFpElement BOTAN_DLL operator* (u32bit rhs, const GFpElement& lhs);
+GFpElement BOTAN_DLL operator*(const GFpElement& lhs, u32bit rhs);
+GFpElement BOTAN_DLL operator*(u32bit rhs, const GFpElement& lhs);
/**
diff --git a/src/math/gfpmath/gfp_modulus.h b/src/math/gfpmath/gfp_modulus.h
index 4773a8b89..fcdd13ee1 100644
--- a/src/math/gfpmath/gfp_modulus.h
+++ b/src/math/gfpmath/gfp_modulus.h
@@ -13,7 +13,7 @@
namespace Botan {
-class BOTAN_DLL GFpElement;
+class GFpElement;
/**
* This class represents a GFpElement modulus including the modulus
@@ -22,24 +22,26 @@ class BOTAN_DLL GFpElement;
class BOTAN_DLL GFpModulus
{
public:
- friend class GFpElement;
/**
* Construct a GF(P)-Modulus from a BigInt
*/
- GFpModulus(BigInt p)
+ GFpModulus(const BigInt& p)
: m_p(p),
m_p_dash(),
m_r(),
m_r_inv()
{}
+ // GFpModulus(const GFpModulus& other) = default;
+ // GFpModulus& operator=(const GFpModulus& other) = default;
+
/**
* Tells whether the precomputations necessary for the use of the
* montgomery multiplication have yet been established.
* @result true if the precomputated value are already available.
*/
- inline bool has_precomputations() const
+ bool has_precomputations() const
{
return(!m_p_dash.is_zero() && !m_r.is_zero() && !m_r_inv.is_zero());
}
@@ -48,12 +50,12 @@ class BOTAN_DLL GFpModulus
* Swaps this with another GFpModulus, does not throw.
* @param other the GFpModulus to swap *this with.
*/
- inline void swap(GFpModulus& other)
+ void swap(GFpModulus& other)
{
- m_p.swap(other.m_p);
- m_p_dash.swap(other.m_p_dash);
- m_r.swap(other.m_r);
- m_r_inv.swap(other.m_r_inv);
+ std::swap(m_p, other.m_p);
+ std::swap(m_p_dash, other.m_p_dash);
+ std::swap(m_r, other.m_r);
+ std::swap(m_r_inv, other.m_r_inv);
}
/**
@@ -61,7 +63,7 @@ class BOTAN_DLL GFpModulus
* @param mod the modulus to compare this with
* @result true if the modulus of *this and the argument are equal.
*/
- inline bool p_equal_to(const BigInt& mod) const
+ bool p_equal_to(const BigInt& mod) const
{
return (m_p == mod);
}
@@ -70,7 +72,7 @@ class BOTAN_DLL GFpModulus
* Return the modulus of this GFpModulus.
* @result the modulus of *this.
*/
- inline const BigInt& get_p() const
+ const BigInt& get_p() const
{
return m_p;
}
@@ -81,7 +83,7 @@ class BOTAN_DLL GFpModulus
* performed!
* @result r
*/
- inline const BigInt& get_r() const
+ const BigInt& get_r() const
{
return m_r;
}
@@ -92,7 +94,7 @@ class BOTAN_DLL GFpModulus
* performed!
* @result r^{-1}
*/
- inline const BigInt& get_r_inv() const
+ const BigInt& get_r_inv() const
{
return m_r_inv;
}
@@ -103,17 +105,25 @@ class BOTAN_DLL GFpModulus
* performed!
* @result p'
*/
- inline const BigInt& get_p_dash() const
+ const BigInt& get_p_dash() const
{
return m_p_dash;
}
- // default cp-ctor, op= are fine
+
+ void reset_values(const BigInt& new_p_dash,
+ const BigInt& new_r,
+ const BigInt& new_r_inv)
+ {
+ m_p_dash = new_p_dash;
+ m_r = new_r;
+ m_r_inv = new_r_inv;
+ }
private:
BigInt m_p; // the modulus itself
- mutable BigInt m_p_dash;
- mutable BigInt m_r;
- mutable BigInt m_r_inv;
+ BigInt m_p_dash;
+ BigInt m_r;
+ BigInt m_r_inv;
};
}
diff --git a/src/math/gfpmath/info.txt b/src/math/gfpmath/info.txt
index a02dbc044..b7b430805 100644
--- a/src/math/gfpmath/info.txt
+++ b/src/math/gfpmath/info.txt
@@ -1,7 +1,5 @@
define BIGINT_GFP
-uses_tr1 yes
-
<header:public>
curve_gfp.h
gfp_element.h
diff --git a/src/math/gfpmath/point_gfp.cpp b/src/math/gfpmath/point_gfp.cpp
index f95add9f7..4b2de7913 100644
--- a/src/math/gfpmath/point_gfp.cpp
+++ b/src/math/gfpmath/point_gfp.cpp
@@ -13,295 +13,114 @@
namespace Botan {
// construct the point at infinity or a random point
-PointGFp::PointGFp(const CurveGFp& curve)
- : mC(curve),
- mX(curve.get_p(), 0),
- mY(curve.get_p(), 1),
- mZ(curve.get_p(), 0),
- mZpow2(curve.get_p(),0),
- mZpow3(curve.get_p(),0),
- mAZpow4(curve.get_p(),0),
- mZpow2_set(false),
- mZpow3_set(false),
- mAZpow4_set(false)
+PointGFp::PointGFp(const CurveGFp& curve) :
+ mC(curve),
+ mX(curve.get_p(), 0),
+ mY(curve.get_p(), 1),
+ mZ(curve.get_p(), 0)
{
- // first set the point wide pointer
-
- set_shrd_mod(mC.get_ptr_mod());
-
}
// construct a point given its jacobian projective coordinates
PointGFp::PointGFp(const CurveGFp& curve, const GFpElement& x,
- const GFpElement& y, const GFpElement& z)
- : mC(curve),
- mX(x),
- mY(y),
- mZ(z),
- mZpow2(curve.get_p(),0),
- mZpow3(curve.get_p(),0),
- mAZpow4(curve.get_p(),0),
- mZpow2_set(false),
- mZpow3_set(false),
- mAZpow4_set(false)
- {
- set_shrd_mod(mC.get_ptr_mod());
- }
-PointGFp::PointGFp ( const CurveGFp& curve, const GFpElement& x,
- const GFpElement& y )
- :mC(curve),
- mX(x),
- mY(y),
- mZ(curve.get_p(),1),
- mZpow2(curve.get_p(),0),
- mZpow3(curve.get_p(),0),
- mAZpow4(curve.get_p(),0),
- mZpow2_set(false),
- mZpow3_set(false),
- mAZpow4_set(false)
- {
- set_shrd_mod(mC.get_ptr_mod());
- }
-
-// copy constructor
-PointGFp::PointGFp(const PointGFp& other)
- : mC(other.mC),
- mX(other.mX),
- mY(other.mY),
- mZ(other.mZ),
- mZpow2(other.mZpow2),
- mZpow3(other.mZpow3),
- mAZpow4(other.mAZpow4),
- mZpow2_set(other.mZpow2_set),
- mZpow3_set(other.mZpow3_set),
- mAZpow4_set(other.mAZpow4_set)
+ const GFpElement& y, const GFpElement& z) :
+ mC(curve),
+ mX(x),
+ mY(y),
+ mZ(z)
{
- set_shrd_mod(mC.get_ptr_mod());
}
-// assignment operator
-const PointGFp& PointGFp::operator=(PointGFp const& other)
+PointGFp::PointGFp(const CurveGFp& curve,
+ const GFpElement& x,
+ const GFpElement& y) :
+ mC(curve),
+ mX(x),
+ mY(y),
+ mZ(curve.get_p(),1)
{
- mC = other.get_curve();
- mX = other.get_jac_proj_x();
- mY = other.get_jac_proj_y();
- mZ = other.get_jac_proj_z();
- mZpow2 = GFpElement(other.mZpow2);
- mZpow3 = GFpElement(other.mZpow3);
- mAZpow4 = GFpElement(other.mAZpow4);
- mZpow2_set = other.mZpow2_set;
- mZpow3_set = other.mZpow3_set;
- mAZpow4_set = other.mAZpow4_set;
- set_shrd_mod(mC.get_ptr_mod());
- return *this;
- }
-
-const PointGFp& PointGFp::assign_within_same_curve(PointGFp const& other)
- {
- mX = other.get_jac_proj_x();
- mY = other.get_jac_proj_y();
- mZ = other.get_jac_proj_z();
- mZpow2_set = false;
- mZpow3_set = false;
- mAZpow4_set = false;
- // the rest stays!
- return *this;
- }
-
-void PointGFp::set_shrd_mod(std::tr1::shared_ptr<GFpModulus> p_mod)
- {
- mX.set_shrd_mod(p_mod);
- mY.set_shrd_mod(p_mod);
- mZ.set_shrd_mod(p_mod);
- mZpow2.set_shrd_mod(p_mod);
- mZpow3.set_shrd_mod(p_mod);
- mAZpow4.set_shrd_mod(p_mod);
- }
-
-void PointGFp::ensure_worksp() const
- {
- if (mp_worksp_gfp_el.get() != 0)
- {
- if ((*mp_worksp_gfp_el).size() == GFPEL_WKSP_SIZE)
- {
- return;
- }
- else
- {
- throw Invalid_State("encountered incorrect size for PointGFp´s GFpElement workspace");
- }
- }
-
- mp_worksp_gfp_el = std::tr1::shared_ptr<std::vector<GFpElement> >(new std::vector<GFpElement>);
- mp_worksp_gfp_el->reserve(9);
- for (u32bit i=0; i<GFPEL_WKSP_SIZE; i++)
- {
- mp_worksp_gfp_el->push_back(GFpElement(1,0));
-
- }
}
// arithmetic operators
PointGFp& PointGFp::operator+=(const PointGFp& rhs)
{
- if (is_zero())
+ if(is_zero())
{
*this = rhs;
return *this;
}
- if (rhs.is_zero())
+ if(rhs.is_zero())
{
return *this;
}
- ensure_worksp();
-
- if (rhs.mZ == *(mC.get_mres_one()))
- {
- //U1 = mX;
- (*mp_worksp_gfp_el)[0].share_assign(mX);
-
- //S1 = mY;
- (*mp_worksp_gfp_el)[2].share_assign(mY);
- }
- else
- {
- if ((!rhs.mZpow2_set) || (!rhs.mZpow3_set))
- {
- rhs.mZpow2 = rhs.mZ;
- rhs.mZpow2 *= rhs.mZ;
- rhs.mZpow3 = rhs.mZpow2;
- rhs.mZpow3 *= rhs.mZ;
-
- rhs.mZpow2_set = true;
- rhs.mZpow3_set = true;
- }
- //U1 = mX * rhs.mZpow2;
- (*mp_worksp_gfp_el)[0].share_assign(mX);
- (*mp_worksp_gfp_el)[0] *= rhs.mZpow2;
- //S1 = mY * rhs.mZpow3;
- (*mp_worksp_gfp_el)[2].share_assign(mY);
- (*mp_worksp_gfp_el)[2] *= rhs.mZpow3;
+ GFpElement U1 = mX;
+ GFpElement S1 = mY;
- }
- if (mZ == *(mC.get_mres_one()))
+ if(rhs.mZ != mC.get_mres_one())
{
- //U2 = rhs.mX;
- (*mp_worksp_gfp_el)[1].share_assign(rhs.mX);
+ GFpElement rhs_z2 = rhs.mZ * rhs.mZ;
- //S2 = rhs.mY;
- (*mp_worksp_gfp_el)[3].share_assign(rhs.mY);
+ U1 *= rhs_z2;
+ S1 *= rhs_z2 * rhs.mZ;
}
- else
- {
- if ((!mZpow2_set) || (!mZpow3_set))
- {
- // precomputation can´t be used, because *this changes anyway
- mZpow2 = mZ;
- mZpow2 *= mZ;
- mZpow3 = mZpow2;
- mZpow3 *= mZ;
- }
- //U2 = rhs.mX * mZpow2;
- (*mp_worksp_gfp_el)[1].share_assign(rhs.mX);
- (*mp_worksp_gfp_el)[1] *= mZpow2;
+ GFpElement U2 = rhs.mX;
+ GFpElement S2 = rhs.mY;
- //S2 = rhs.mY * mZpow3;
- (*mp_worksp_gfp_el)[3].share_assign(rhs.mY);
- (*mp_worksp_gfp_el)[3] *= mZpow3;
+ if(mZ != mC.get_mres_one())
+ {
+ GFpElement lhs_z2 = mZ * mZ;
+ U2 *= lhs_z2;
+ S2 *= lhs_z2 * mZ;
}
- //GFpElement H(U2 - U1);
-
- (*mp_worksp_gfp_el)[4].share_assign((*mp_worksp_gfp_el)[1]);
- (*mp_worksp_gfp_el)[4] -= (*mp_worksp_gfp_el)[0];
- //GFpElement r(S2 - S1);
- (*mp_worksp_gfp_el)[5].share_assign((*mp_worksp_gfp_el)[3]);
- (*mp_worksp_gfp_el)[5] -= (*mp_worksp_gfp_el)[2];
-
- //if(H.is_zero())
- if ((*mp_worksp_gfp_el)[4].is_zero())
+ GFpElement H(U2 - U1);
+ GFpElement r(S2 - S1);
+ if(H.is_zero())
{
- if ((*mp_worksp_gfp_el)[5].is_zero())
-
+ if(r.is_zero())
{
mult2_in_place();
return *this;
}
+
*this = PointGFp(mC); // setting myself to zero
return *this;
}
- //U2 = H * H;
- (*mp_worksp_gfp_el)[1].share_assign((*mp_worksp_gfp_el)[4]);
- (*mp_worksp_gfp_el)[1] *= (*mp_worksp_gfp_el)[4];
+ U2 = H * H;
- //S2 = U2 * H;
- (*mp_worksp_gfp_el)[3].share_assign((*mp_worksp_gfp_el)[1]);
- (*mp_worksp_gfp_el)[3] *= (*mp_worksp_gfp_el)[4];
+ S2 = U2 * H;
- //U2 *= U1;
- (*mp_worksp_gfp_el)[1] *= (*mp_worksp_gfp_el)[0];
+ U2 *= U1;
- //GFpElement x(r*r - S2 - (U2+U2));
- (*mp_worksp_gfp_el)[6].share_assign((*mp_worksp_gfp_el)[5]);
- (*mp_worksp_gfp_el)[6] *= (*mp_worksp_gfp_el)[5];
- (*mp_worksp_gfp_el)[6] -= (*mp_worksp_gfp_el)[3];
- (*mp_worksp_gfp_el)[6] -= (*mp_worksp_gfp_el)[1];
- (*mp_worksp_gfp_el)[6] -= (*mp_worksp_gfp_el)[1];
+ GFpElement x(r*r - S2 - (U2+U2));
- //GFpElement z(S1 * S2);
- (*mp_worksp_gfp_el)[8].share_assign((*mp_worksp_gfp_el)[2]);
- (*mp_worksp_gfp_el)[8] *= (*mp_worksp_gfp_el)[3];
+ GFpElement z(S1 * S2);
- //GFpElement y(r * (U2-x) - z);
- (*mp_worksp_gfp_el)[7].share_assign((*mp_worksp_gfp_el)[1]);
- (*mp_worksp_gfp_el)[7] -= (*mp_worksp_gfp_el)[6];
- (*mp_worksp_gfp_el)[7] *= (*mp_worksp_gfp_el)[5];
- (*mp_worksp_gfp_el)[7] -= (*mp_worksp_gfp_el)[8];
+ GFpElement y(r * (U2-x) - z);
- if (mZ == *(mC.get_mres_one()))
+ if(mZ == mC.get_mres_one())
{
- if (rhs.mZ != *(mC.get_mres_one()))
- {
- //z = rhs.mZ * H;
- (*mp_worksp_gfp_el)[8].share_assign(rhs.mZ);
- (*mp_worksp_gfp_el)[8] *= (*mp_worksp_gfp_el)[4];
- }
+ if(rhs.mZ != mC.get_mres_one())
+ z = rhs.mZ * H;
else
- {
- //z = H;
- (*mp_worksp_gfp_el)[8].share_assign((*mp_worksp_gfp_el)[4]);
- }
+ z = H;
}
- else if (rhs.mZ != *(mC.get_mres_one()))
+ else if(rhs.mZ != mC.get_mres_one())
{
- //U1 = mZ * rhs.mZ;
- (*mp_worksp_gfp_el)[0].share_assign(mZ);
- (*mp_worksp_gfp_el)[0] *= rhs.mZ;
-
- //z = U1 * H;
- (*mp_worksp_gfp_el)[8].share_assign((*mp_worksp_gfp_el)[0]);
- (*mp_worksp_gfp_el)[8] *= (*mp_worksp_gfp_el)[4];
-
+ U1 = mZ * rhs.mZ;
+ z = U1 * H;
}
else
- {
- //z = mZ * H;
- (*mp_worksp_gfp_el)[8].share_assign(mZ);
- (*mp_worksp_gfp_el)[8] *= (*mp_worksp_gfp_el)[4];
+ z = mZ * H;
- }
- mZpow2_set = false;
- mZpow3_set = false;
- mAZpow4_set = false;
-
- mX = (*mp_worksp_gfp_el)[6];
- mY = (*mp_worksp_gfp_el)[7];
- mZ = (*mp_worksp_gfp_el)[8];
+ mX = x;
+ mY = y;
+ mZ = z;
return *this;
@@ -310,7 +129,7 @@ PointGFp& PointGFp::operator-=(const PointGFp& rhs)
{
PointGFp minus_rhs = PointGFp(rhs).negate();
- if (is_zero())
+ if(is_zero())
{
*this = minus_rhs;
}
@@ -336,92 +155,39 @@ PointGFp& PointGFp::mult_this_secure(const BigInt& scalar,
// use montgomery mult. in this operation
this->turn_on_sp_red_mul();
- std::tr1::shared_ptr<PointGFp> H(new PointGFp(this->mC));
- std::tr1::shared_ptr<PointGFp> tmp; // used for AADA
+ PointGFp H(mC);
PointGFp P(*this);
BigInt m(scalar);
- if (m < BigInt(0))
+ if(m < BigInt(0))
{
m = -m;
P.negate();
}
- if (P.is_zero() || (m == BigInt(0)))
+ if(P.is_zero() || (m == BigInt(0)))
{
- *this = *H;
+ *this = H;
return *this;
}
- if (m == BigInt(1))
- {
+ if(m == BigInt(1))
return *this;
- }
- //
-#ifdef CM_AADA
-#ifndef CM_RAND_EXP
- int max_secr_bits = max_secr.bits();
-#endif
-#endif
-
- int mul_bits = m.bits(); // this is used for a determined number of loop runs in
- // the mult_loop where leading zero´s are padded if necessary.
- // Here we assign the value that will be used when no countermeasures are specified
-#ifdef CM_RAND_EXP
- u32bit rand_r_bit_len = 20; // Coron(99) proposes 20 bit for r
-#ifdef CM_AADA
+ int mul_bits = m.bits();
- BigInt r_max(1);
-
-#endif // CM_AADA
-
- // use randomized exponent
-#ifdef TA_COLL_T
- static BigInt r_randexp;
- if (new_rand)
+ for(int i = mul_bits - 1; i >= 0; i--)
{
- r_randexp = random_integer(rand_r_bit_len);
- }
- //assert(!r_randexp.is_zero());
-#else
- BigInt r_randexp(random_integer(rand_r_bit_len));
-#endif
-
- m += r_randexp * point_order;
- // determine mul_bits...
-#ifdef CM_AADA
- // AADA with rand. Exp.
- //assert(rand_r_bit_len > 0);
- r_max <<= rand_r_bit_len;
- r_max -= 1;
- //assert(r_max.bits() == rand_r_bit_len);
- mul_bits = (max_secr + point_order * r_max).bits();
-#else
- // rand. Exp. without AADA
- mul_bits = m.bits();
-#endif // CM_AADA
-
-
-#endif // CM_RAND_EXP
-
- // determine mul_bits...
-#if (CM_AADA == 1 && CM_RAND_EXP != 1)
-
- mul_bits = max_secr_bits;
-#endif // CM_AADA without CM_RAND_EXP
-
- //assert(mul_bits != 0);
+ H.mult2_in_place();
+ if(m.get_bit(i))
+ H += P;
+ }
- H = mult_loop(mul_bits-1, m, H, tmp, P);
+ if(!H.is_zero()) // cannot convert if H == O
+ *this = H.get_z_to_one();
+ else
+ *this = H;
- if (!H->is_zero()) // cannot convert if H == O
- {
- *this = H->get_z_to_one();
- }else
- {
- *this = *H;
- }
mX.turn_off_sp_red_mul();
mY.turn_off_sp_red_mul();
mZ.turn_off_sp_red_mul();
@@ -439,226 +205,100 @@ PointGFp& PointGFp::operator*=(const BigInt& scalar)
PointGFp P(*this);
P.turn_on_sp_red_mul();
BigInt m(scalar);
- if (m < BigInt(0))
+
+ if(m < BigInt(0))
{
m = -m;
P.negate();
}
- if (P.is_zero() || (m == BigInt(0)))
+
+ if(P.is_zero() || (m == BigInt(0)))
{
*this = H;
return *this;
}
- if (m == BigInt(1))
- {
- //*this == P already
+
+ if(m == BigInt(1)) //*this == P already
return *this;
- }
const int l = m.bits() - 1;
- for (int i=l; i >=0; i--)
+ for(int i = l; i >= 0; --i)
{
-
H.mult2_in_place();
- if (m.get_bit(i))
- {
+ if(m.get_bit(i))
H += P;
- }
}
- if (!H.is_zero()) // cannot convert if H == O
- {
+ if(!H.is_zero()) // cannot convert if H == O
*this = H.get_z_to_one();
- }else
- {
+ else
*this = H;
- }
- return *this;
- }
-
-inline std::tr1::shared_ptr<PointGFp> PointGFp::mult_loop(int l,
- const BigInt& m,
- std::tr1::shared_ptr<PointGFp> H,
- std::tr1::shared_ptr<PointGFp> tmp,
- const PointGFp& P)
- {
- //assert(l >= (int)m.bits()- 1);
- tmp = H;
- std::tr1::shared_ptr<PointGFp> to_add(new PointGFp(P)); // we just need some point
- // so that we can use op=
- // inside the loop
- for (int i=l; i >=0; i--)
- {
- H->mult2_in_place();
-
-#ifndef CM_AADA
-
- if (m.get_bit(i))
- {
- *H += P;
- }
-#else // (CM_AADA is in)
-
- if (H.get() == to_add.get())
- {
- to_add = tmp; // otherwise all pointers might point to the same object
- // and we always need two objects to be able to switch around
- }
- to_add->assign_within_same_curve(*H);
- tmp = H;
- *tmp += P; // tmp already points to H
-
- if (m.get_bit(i))
- {
- H = tmp; // NOTE: assign the pointer, not the value!
- // (so that the operation is fast and thus as difficult
- // to detect as possible)
- }
- else
- {
- H = to_add; // NOTE: this is necessary, because the assignment
- // "*tmp = ..." already changed what H pointed to
-
-
- }
-#endif // CM_AADA
- }
- return H;
+ return *this;
}
PointGFp& PointGFp::negate()
{
- if (!is_zero())
- {
+ if(!is_zero())
mY.negate();
- }
+
return *this;
}
// *this *= 2
PointGFp& PointGFp::mult2_in_place()
{
- if (is_zero())
- {
+ if(is_zero())
return *this;
- }
- if (mY.is_zero())
+ else if(mY.is_zero())
{
-
*this = PointGFp(mC); // setting myself to zero
return *this;
}
- ensure_worksp();
- (*mp_worksp_gfp_el)[0].share_assign(mY);
- (*mp_worksp_gfp_el)[0] *= mY;
+ GFpElement Y_squared = mY*mY;
- //GFpElement S(mX * z);
- (*mp_worksp_gfp_el)[1].share_assign(mX);
- (*mp_worksp_gfp_el)[1] *= (*mp_worksp_gfp_el)[0];
+ GFpElement S = mX * Y_squared;
- //GFpElement x(S + S);
- (*mp_worksp_gfp_el)[2].share_assign((*mp_worksp_gfp_el)[1]);
- (*mp_worksp_gfp_el)[2] += (*mp_worksp_gfp_el)[1];
+ GFpElement x = S + S;
- //S = x + x;
- (*mp_worksp_gfp_el)[1].share_assign((*mp_worksp_gfp_el)[2]);
- (*mp_worksp_gfp_el)[1] += (*mp_worksp_gfp_el)[2];
+ S = x + x;
- if (!mAZpow4_set)
+ GFpElement a_z4 = mC.get_mres_a();
+ if(mZ != mC.get_mres_one())
{
- if (mZ == *(mC.get_mres_one()))
- {
- mAZpow4 = mC.get_mres_a();
- mAZpow4_set = true;
- }
- else
- {
- if (!mZpow2_set)
- {
- mZpow2 = mZ;
- mZpow2 *= mZ;
+ GFpElement z2 = mZ * mZ;
+ a_z4 *= z2;
+ a_z4 *= z2;
+ }
- mZpow2_set = true;
- }
- //x = mZpow2 * mZpow2;
- (*mp_worksp_gfp_el)[2].share_assign(mZpow2);
- (*mp_worksp_gfp_el)[2] *= mZpow2;
+ GFpElement y(mX * mX);
- //mAZpow4 = mC.get_mres_a() * x;
- mAZpow4 = mC.get_mres_a();
- mAZpow4 *= (*mp_worksp_gfp_el)[2];
+ GFpElement M(y + y + y + a_z4);
- }
+ x = M * M - (S+S);
- }
+ y = Y_squared * Y_squared;
- //GFpElement y(mX * mX);
- (*mp_worksp_gfp_el)[3].share_assign(mX);
- (*mp_worksp_gfp_el)[3] *= mX;
-
- //GFpElement M(y + y + y + mAZpow4);
- (*mp_worksp_gfp_el)[4].share_assign((*mp_worksp_gfp_el)[3]);
- (*mp_worksp_gfp_el)[4] += (*mp_worksp_gfp_el)[3];
- (*mp_worksp_gfp_el)[4] += (*mp_worksp_gfp_el)[3];
- (*mp_worksp_gfp_el)[4] += mAZpow4;
-
- //x = M * M - (S+S);
- (*mp_worksp_gfp_el)[2].share_assign((*mp_worksp_gfp_el)[4]);
- (*mp_worksp_gfp_el)[2] *= (*mp_worksp_gfp_el)[4];
- (*mp_worksp_gfp_el)[2] -= (*mp_worksp_gfp_el)[1];
- (*mp_worksp_gfp_el)[2] -= (*mp_worksp_gfp_el)[1];
-
- //y = z * z;
- (*mp_worksp_gfp_el)[3].share_assign((*mp_worksp_gfp_el)[0]);
- (*mp_worksp_gfp_el)[3] *= (*mp_worksp_gfp_el)[0];
-
- //GFpElement U(y + y);
- (*mp_worksp_gfp_el)[5].share_assign((*mp_worksp_gfp_el)[3]);
- (*mp_worksp_gfp_el)[5] += (*mp_worksp_gfp_el)[3];
-
- //z = U + U;
- (*mp_worksp_gfp_el)[0].share_assign((*mp_worksp_gfp_el)[5]);
- (*mp_worksp_gfp_el)[0] += (*mp_worksp_gfp_el)[5];
-
- //U = z + z;
- (*mp_worksp_gfp_el)[5].share_assign((*mp_worksp_gfp_el)[0]);
- (*mp_worksp_gfp_el)[5] += (*mp_worksp_gfp_el)[0];
-
- //y = M * (S - x) - U;
- (*mp_worksp_gfp_el)[3].share_assign((*mp_worksp_gfp_el)[1]);
- (*mp_worksp_gfp_el)[3] -= (*mp_worksp_gfp_el)[2];
- (*mp_worksp_gfp_el)[3] *= (*mp_worksp_gfp_el)[4];
- (*mp_worksp_gfp_el)[3] -= (*mp_worksp_gfp_el)[5];
-
- if (mZ != *(mC.get_mres_one()))
- {
- //z = mY * mZ;
- (*mp_worksp_gfp_el)[0].share_assign(mY);
- (*mp_worksp_gfp_el)[0] *= mZ;
+ GFpElement U(y + y);
- }
+ GFpElement z = U + U;
+
+ U = z + z;
+
+ y = M * (S - x) - U;
+
+ if(mZ != mC.get_mres_one())
+ z = mY * mZ;
else
- {
- //z = mY;
- (*mp_worksp_gfp_el)[0].share_assign(mY);
+ z = mY;
+
+ z = z + z;
+
+ mX = x;
+ mY = y;
+ mZ = z;
- }
- //z = z + z;
- (*mp_worksp_gfp_el)[6].share_assign((*mp_worksp_gfp_el)[0]);
- (*mp_worksp_gfp_el)[0] += (*mp_worksp_gfp_el)[6];
-
- //mX = x;
- //mY = y;
- //mZ = z;
- mX = (*mp_worksp_gfp_el)[2];
- mY = (*mp_worksp_gfp_el)[3];
- mZ = (*mp_worksp_gfp_el)[0];
-
- mZpow2_set = false;
- mZpow3_set = false;
- mAZpow4_set = false;
return *this;
}
@@ -676,19 +316,14 @@ void PointGFp::turn_on_sp_red_mul() const
mX.get_mres();
mY.get_mres();
mZ.get_mres();
-
- mZpow2.turn_on_sp_red_mul();
- mZpow3.turn_on_sp_red_mul();
- mAZpow4.turn_on_sp_red_mul();
}
-// getters
/**
* returns a point equivalent to *this but were
* Z has value one, i.e. x and y correspond to
* their values in affine coordinates
*/
-PointGFp const PointGFp::get_z_to_one() const
+PointGFp PointGFp::get_z_to_one() const
{
return PointGFp(*this).set_z_to_one();
}
@@ -701,7 +336,7 @@ PointGFp const PointGFp::get_z_to_one() const
*/
const PointGFp& PointGFp::set_z_to_one() const
{
- if (!(mZ.get_value() == BigInt(1)) && !(mZ.get_value() == BigInt(0)))
+ if(!(mZ.get_value() == BigInt(1)) && !(mZ.get_value() == BigInt(0)))
{
GFpElement z = inverse(mZ);
GFpElement z2 = z * z;
@@ -714,7 +349,7 @@ const PointGFp& PointGFp::set_z_to_one() const
}
else
{
- if (mZ.get_value() == BigInt(0))
+ if(mZ.get_value() == BigInt(0))
{
throw Illegal_Transformation("cannot convert Z to one");
}
@@ -722,58 +357,35 @@ const PointGFp& PointGFp::set_z_to_one() const
return *this; // mZ = 1 already
}
-const CurveGFp PointGFp::get_curve() const
+GFpElement PointGFp::get_affine_x() const
{
- return mC;
- }
-
-GFpElement const PointGFp::get_affine_x() const
- {
-
- if (is_zero())
- {
+ if(is_zero())
throw Illegal_Transformation("cannot convert to affine");
- }
- /*if(!mZpow2_set)
- {*/
- mZpow2 = mZ * mZ;
- mZpow2_set = true;
- //}
- //assert(mZpow2 == mZ*mZ);
- GFpElement z2 = mZpow2;
+ GFpElement z2 = mZ * mZ;
return mX * z2.inverse_in_place();
}
-GFpElement const PointGFp::get_affine_y() const
+GFpElement PointGFp::get_affine_y() const
{
-
- if (is_zero())
- {
+ if(is_zero())
throw Illegal_Transformation("cannot convert to affine");
- }
- /*if(!mZpow3_set )
- {*/
- mZpow3 = mZ * mZ * mZ;
- mZpow3_set = true;
- //}
- //assert(mZpow3 == mZ * mZ *mZ);
- GFpElement z3 = mZpow3;
+ GFpElement z3 = mZ * mZ * mZ;
return mY * z3.inverse_in_place();
}
-GFpElement const PointGFp::get_jac_proj_x() const
+GFpElement PointGFp::get_jac_proj_x() const
{
return GFpElement(mX);
}
-GFpElement const PointGFp::get_jac_proj_y() const
+GFpElement PointGFp::get_jac_proj_y() const
{
return GFpElement(mY);
}
-GFpElement const PointGFp::get_jac_proj_z() const
+GFpElement PointGFp::get_jac_proj_z() const
{
return GFpElement(mZ);
}
@@ -794,14 +406,14 @@ bool PointGFp::is_zero() const
void PointGFp::check_invariants() const
{
- if (is_zero())
+ if(is_zero())
{
return;
}
const GFpElement y2 = mY * mY;
const GFpElement x3 = mX * mX * mX;
- if (mZ.get_value() == BigInt(1))
+ if(mZ.get_value() == BigInt(1))
{
GFpElement ax = mC.get_a() * mX;
if(y2 != (x3 + ax + mC.get_b()))
@@ -811,16 +423,13 @@ void PointGFp::check_invariants() const
}
- mZpow2 = mZ * mZ;
- mZpow2_set = true;
- mZpow3 = mZpow2 * mZ;
- mZpow3_set = true;
- mAZpow4 = mZpow3 * mZ * mC.get_a();
- mAZpow4_set = true;
- const GFpElement aXZ4 = mAZpow4 * mX;
- const GFpElement bZ6 = mC.get_b() * mZpow3 * mZpow3;
+ GFpElement Zpow2 = mZ * mZ;
+ GFpElement Zpow3 = Zpow2 * mZ;
+ GFpElement AZpow4 = Zpow3 * mZ * mC.get_a();
+ const GFpElement aXZ4 = AZpow4 * mX;
+ const GFpElement bZ6 = mC.get_b() * Zpow3 * Zpow3;
- if (y2 != (x3 + aXZ4 + bZ6))
+ if(y2 != (x3 + aXZ4 + bZ6))
throw Illegal_Point();
}
@@ -831,12 +440,6 @@ void PointGFp::swap(PointGFp& other)
mX.swap(other.mX);
mY.swap(other.mY);
mZ.swap(other.mZ);
- mZpow2.swap(other.mZpow2);
- mZpow3.swap(other.mZpow3);
- mAZpow4.swap(other.mAZpow4);
- std::swap<bool>(mZpow2_set, other.mZpow2_set);
- std::swap<bool>(mZpow3_set, other.mZpow3_set);
- std::swap<bool>(mAZpow4_set, other.mAZpow4_set);
}
PointGFp mult2(const PointGFp& point)
@@ -846,11 +449,11 @@ PointGFp mult2(const PointGFp& point)
bool operator==(const PointGFp& lhs, PointGFp const& rhs)
{
- if (lhs.is_zero() && rhs.is_zero())
+ if(lhs.is_zero() && rhs.is_zero())
{
return true;
}
- if ((lhs.is_zero() && !rhs.is_zero()) || (!lhs.is_zero() && rhs.is_zero()))
+ if((lhs.is_zero() && !rhs.is_zero()) || (!lhs.is_zero() && rhs.is_zero()))
{
return false;
}
@@ -906,22 +509,22 @@ PointGFp mult_point_secure(const PointGFp& point, const BigInt& scalar,
SecureVector<byte> EC2OSP(const PointGFp& point, byte format)
{
SecureVector<byte> result;
- if (format == PointGFp::UNCOMPRESSED)
+ if(format == PointGFp::UNCOMPRESSED)
{
result = encode_uncompressed(point);
}
- else if (format == PointGFp::COMPRESSED)
+ else if(format == PointGFp::COMPRESSED)
{
result = encode_compressed(point);
}
- else if (format == PointGFp::HYBRID)
+ else if(format == PointGFp::HYBRID)
{
result = encode_hybrid(point);
}
else
{
- throw Format_Error("illegal point encoding format specification");
+ throw Invalid_Argument("illegal point encoding format specification");
}
return result;
}
@@ -929,7 +532,7 @@ SecureVector<byte> encode_compressed(const PointGFp& point)
{
- if (point.is_zero())
+ if(point.is_zero())
{
SecureVector<byte> result (1);
result[0] = 0;
@@ -938,7 +541,7 @@ SecureVector<byte> encode_compressed(const PointGFp& point)
}
u32bit l = point.get_curve().get_p().bits();
int dummy = l & 7;
- if (dummy != 0)
+ if(dummy != 0)
{
l += 8 - dummy;
}
@@ -949,7 +552,7 @@ SecureVector<byte> encode_compressed(const PointGFp& point)
SecureVector<byte> bX = BigInt::encode_1363(x, l);
result.copy(1, bX.begin(), bX.size());
BigInt y = point.get_affine_y().get_value();
- if (y.get_bit(0))
+ if(y.get_bit(0))
{
result[0] |= 1;
}
@@ -959,7 +562,7 @@ SecureVector<byte> encode_compressed(const PointGFp& point)
SecureVector<byte> encode_uncompressed(const PointGFp& point)
{
- if (point.is_zero())
+ if(point.is_zero())
{
SecureVector<byte> result (1);
result[0] = 0;
@@ -967,7 +570,7 @@ SecureVector<byte> encode_uncompressed(const PointGFp& point)
}
u32bit l = point.get_curve().get_p().bits();
int dummy = l & 7;
- if (dummy != 0)
+ if(dummy != 0)
{
l += 8 - dummy;
}
@@ -986,7 +589,7 @@ SecureVector<byte> encode_uncompressed(const PointGFp& point)
SecureVector<byte> encode_hybrid(const PointGFp& point)
{
- if (point.is_zero())
+ if(point.is_zero())
{
SecureVector<byte> result (1);
result[0] = 0;
@@ -994,7 +597,7 @@ SecureVector<byte> encode_hybrid(const PointGFp& point)
}
u32bit l = point.get_curve().get_p().bits();
int dummy = l & 7;
- if (dummy != 0)
+ if(dummy != 0)
{
l += 8 - dummy;
}
@@ -1007,7 +610,7 @@ SecureVector<byte> encode_hybrid(const PointGFp& point)
SecureVector<byte> bY = BigInt::encode_1363(y, l);
result.copy(1, bX.begin(), bX.size());
result.copy(l+1, bY.begin(), bY.size());
- if (y.get_bit(0))
+ if(y.get_bit(0))
{
result[0] |= 1;
}
@@ -1016,7 +619,7 @@ SecureVector<byte> encode_hybrid(const PointGFp& point)
PointGFp OS2ECP(MemoryRegion<byte> const& os, const CurveGFp& curve)
{
- if (os.size() == 1 && os[0] == 0)
+ if(os.size() == 1 && os[0] == 0)
{
return PointGFp(curve); // return zero
}
@@ -1038,10 +641,6 @@ PointGFp OS2ECP(MemoryRegion<byte> const& os, const CurveGFp& curve)
bX = SecureVector<byte>(os.size() - 1);
bX.copy(os.begin()+1, os.size()-1);
- /* Problem wäre, wenn decode() das erste bit als Vorzeichen interpretiert.
- *---------------------
- * AW(FS): decode() interpretiert das erste Bit nicht als Vorzeichen
- */
bi_dec_x = BigInt::decode(bX, bX.size());
x = GFpElement(curve.get_p(), bi_dec_x);
bool yMod2;
@@ -1072,13 +671,13 @@ PointGFp OS2ECP(MemoryRegion<byte> const& os, const CurveGFp& curve)
bX.copy(os.begin() + 1, l);
bY.copy(os.begin()+1+l, l);
yMod2 = (pc & 0x01) == 1;
- if (!(PointGFp::decompress(yMod2, x, curve) == y))
+ if(!(PointGFp::decompress(yMod2, x, curve) == y))
{
throw Illegal_Point("error during decoding hybrid format");
}
break;
default:
- throw Format_Error("encountered illegal format specification while decoding point");
+ throw Invalid_Argument("encountered illegal format specification while decoding point");
}
z = GFpElement(curve.get_p(), BigInt(1));
//assert((x.is_trf_to_mres() && x.is_use_montgm()) || !x.is_trf_to_mres());
@@ -1107,7 +706,7 @@ GFpElement PointGFp::decompress(bool yMod2, const GFpElement& x,
throw Illegal_Point("error during decompression");
bool zMod2 = z.get_bit(0);
- if ((zMod2 && ! yMod2) || (!zMod2 && yMod2))
+ if((zMod2 && ! yMod2) || (!zMod2 && yMod2))
{
z = curve.get_p() - z;
}
diff --git a/src/math/gfpmath/point_gfp.h b/src/math/gfpmath/point_gfp.h
index 0c7bb8428..276635f56 100644
--- a/src/math/gfpmath/point_gfp.h
+++ b/src/math/gfpmath/point_gfp.h
@@ -2,7 +2,7 @@
* Arithmetic for point groups of elliptic curves over GF(p)
*
* (C) 2007 Martin Doering, Christoph Ludwig, Falko Strenzke
-* 2008 Jack Lloyd
+* 2008-2010 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
@@ -11,9 +11,6 @@
#define BOTAN_POINT_GFP_H__
#include <botan/curve_gfp.h>
-#include <botan/gfp_element.h>
-#include <botan/bigint.h>
-#include <botan/exceptn.h>
#include <vector>
namespace Botan {
@@ -24,7 +21,7 @@ struct BOTAN_DLL Illegal_Point : public Exception
};
/**
-* This class represents one point on a curve of GF(p).
+* This class represents one point on a curve of GF(p)
*/
class BOTAN_DLL PointGFp
{
@@ -48,7 +45,7 @@ class BOTAN_DLL PointGFp
* Construct the point O
* @param curve The base curve
*/
- explicit PointGFp(const CurveGFp& curve);
+ PointGFp(const CurveGFp& curve);
/**
* Construct a point given its affine coordinates
@@ -56,8 +53,9 @@ class BOTAN_DLL PointGFp
* @param x affine x coordinate
* @param y affine y coordinate
*/
- explicit PointGFp(const CurveGFp& curve, GFpElement const& x,
- GFpElement const& y);
+ PointGFp(const CurveGFp& curve,
+ const GFpElement& x,
+ const GFpElement& y);
/**
* Construct a point given its jacobian projective coordinates
@@ -66,28 +64,13 @@ class BOTAN_DLL PointGFp
* @param y jacobian projective y coordinate
* @param z jacobian projective y coordinate
*/
- explicit PointGFp(const CurveGFp& curve, GFpElement const& x,
- GFpElement const& y, GFpElement const& z);
-
- /**
- * copy constructor
- * @param other the value to clone
- */
- PointGFp(const PointGFp& other);
-
- /**
- * assignment operator
- * @param other The point to use as source for the assignment
- */
- const PointGFp& operator=(const PointGFp& other);
-
- /**
- * assign another point which is on the same curve as *this
- * @param other The point to use as source for the assignment
- */
- const PointGFp& assign_within_same_curve(const PointGFp& other);
-
+ PointGFp(const CurveGFp& curve,
+ const GFpElement& x,
+ const GFpElement& y,
+ const GFpElement& z);
+ //PointGFp(const PointGFp& other) = default;
+ //PointGFp& operator=(const PointGFp& other) = default;
/**
* += Operator
@@ -126,8 +109,7 @@ class BOTAN_DLL PointGFp
*/
PointGFp& mult_this_secure(const BigInt& scalar,
const BigInt& point_order,
- const BigInt& max_secr
- );
+ const BigInt& max_secr);
/**
* Negate internal value(*this *= -1 )
@@ -162,43 +144,43 @@ class BOTAN_DLL PointGFp
* thus x and y have just the affine values.
* @result *this
*/
- PointGFp const get_z_to_one() const;
+ PointGFp get_z_to_one() const;
/**
* Return base curve of this point
* @result the curve over GF(p) of this point
*/
- CurveGFp const get_curve() const;
+ const CurveGFp& get_curve() const { return mC; }
/**
* get affine x coordinate
* @result affine x coordinate
*/
- GFpElement const get_affine_x() const;
+ GFpElement get_affine_x() const;
/**
* get affine y coordinate
* @result affine y coordinate
*/
- GFpElement const get_affine_y() const;
+ GFpElement get_affine_y() const;
/**
* get the jacobian projective x coordinate
* @result jacobian projective x coordinate
*/
- GFpElement const get_jac_proj_x() const;
+ GFpElement get_jac_proj_x() const;
/**
* get the jacobian projective y coordinate
* @result jacobian projective y coordinate
*/
- GFpElement const get_jac_proj_y() const;
+ GFpElement get_jac_proj_y() const;
/**
* get the jacobian projective z coordinate
* @result jacobian projective z coordinate
*/
- GFpElement const get_jac_proj_z() const;
+ GFpElement get_jac_proj_z() const;
/**
* Is this the point at infinity?
@@ -214,49 +196,19 @@ class BOTAN_DLL PointGFp
*/
void check_invariants() const;
-
/**
- * swaps the states of *this and other, does not throw!
+ * swaps the states of *this and other, does not throw!
* @param other the object to swap values with
*/
void swap(PointGFp& other);
- /**
- * Sets the shared pointer to the GFpModulus that will be
- * held in *this, specifically the various members of *this.
- * Warning: do not use this function unless you know in detail about
- * the implications of using
- * the shared GFpModulus objects!
- * Do NOT spread a shared pointer to GFpModulus over different
- * threads!
- * @param mod a shared pointer to a GFpModulus that will
- * be held in the members *this
- */
- void set_shrd_mod(std::tr1::shared_ptr<GFpModulus> p_mod);
-
static GFpElement decompress(bool yMod2, GFpElement const& x, const CurveGFp& curve);
private:
- static const u32bit GFPEL_WKSP_SIZE = 9;
- void ensure_worksp() const;
-
- inline std::tr1::shared_ptr<PointGFp> mult_loop(int l, const BigInt& m,
- std::tr1::shared_ptr<PointGFp> H,
- std::tr1::shared_ptr<PointGFp> tmp,
- const PointGFp& P);
-
CurveGFp mC;
mutable GFpElement mX; // NOTE: these values must be mutable (affine<->proj)
mutable GFpElement mY;
mutable GFpElement mZ;
- mutable GFpElement mZpow2; // mZ^2
- mutable GFpElement mZpow3; // mZ^3
- mutable GFpElement mAZpow4; // mA*mZ^4
- mutable bool mZpow2_set;
- mutable bool mZpow3_set;
- mutable bool mAZpow4_set;
- mutable std::tr1::shared_ptr<std::vector<GFpElement> > mp_worksp_gfp_el;
-
};
// relational operators
diff --git a/src/math/numbertheory/powm_mnt.cpp b/src/math/numbertheory/powm_mnt.cpp
index e356387c0..2d18ccdef 100644
--- a/src/math/numbertheory/powm_mnt.cpp
+++ b/src/math/numbertheory/powm_mnt.cpp
@@ -156,10 +156,9 @@ BigInt Montgomery_Exponentiator::execute() const
Montgomery_Exponentiator::Montgomery_Exponentiator(const BigInt& mod,
Power_Mod::Usage_Hints hints)
{
- if(!mod.is_positive())
- throw Exception("Montgomery_Exponentiator: modulus must be positive");
- if(mod.is_even())
- throw Exception("Montgomery_Exponentiator: modulus must be odd");
+ // Montgomery reduction only works for positive odd moduli
+ if(!mod.is_positive() || mod.is_even())
+ throw Invalid_Argument("Montgomery_Exponentiator: invalid modulus");
window_bits = 0;
this->hints = hints;
diff --git a/src/mutex/pthreads/mux_pthr.cpp b/src/mutex/pthreads/mux_pthr.cpp
index 75a116fe8..165132239 100644
--- a/src/mutex/pthreads/mux_pthr.cpp
+++ b/src/mutex/pthreads/mux_pthr.cpp
@@ -28,19 +28,19 @@ Mutex* Pthread_Mutex_Factory::make()
void lock()
{
if(pthread_mutex_lock(&mutex) != 0)
- throw Exception("Pthread_Mutex::lock: Error occured");
+ throw Invalid_State("Pthread_Mutex::lock: Error occured");
}
void unlock()
{
if(pthread_mutex_unlock(&mutex) != 0)
- throw Exception("Pthread_Mutex::unlock: Error occured");
+ throw Invalid_State("Pthread_Mutex::unlock: Error occured");
}
Pthread_Mutex()
{
if(pthread_mutex_init(&mutex, 0) != 0)
- throw Exception("Pthread_Mutex: initialization failed");
+ throw Invalid_State("Pthread_Mutex: initialization failed");
}
~Pthread_Mutex()
diff --git a/src/pbe/pbes1/pbes1.cpp b/src/pbe/pbes1/pbes1.cpp
index 1d851d1a5..36cfaa6b4 100644
--- a/src/pbe/pbes1/pbes1.cpp
+++ b/src/pbe/pbes1/pbes1.cpp
@@ -80,9 +80,9 @@ void PBE_PKCS5v15::set_key(const std::string& passphrase)
{
PKCS5_PBKDF1 pbkdf(hash_function->clone());
- pbkdf.set_iterations(iterations);
- pbkdf.change_salt(salt, salt.size());
- SymmetricKey key_and_iv = pbkdf.derive_key(16, passphrase);
+ SymmetricKey key_and_iv = pbkdf.derive_key(16, passphrase,
+ &salt[0], salt.size(),
+ iterations);
key.set(key_and_iv.begin(), 8);
iv.set(key_and_iv.begin() + 8, 8);
diff --git a/src/pbe/pbes2/pbes2.cpp b/src/pbe/pbes2/pbes2.cpp
index bd24c449b..63772263f 100644
--- a/src/pbe/pbes2/pbes2.cpp
+++ b/src/pbe/pbes2/pbes2.cpp
@@ -87,9 +87,9 @@ void PBE_PKCS5v20::set_key(const std::string& passphrase)
{
PKCS5_PBKDF2 pbkdf(new HMAC(hash_function->clone()));
- pbkdf.set_iterations(iterations);
- pbkdf.change_salt(salt, salt.size());
- key = pbkdf.derive_key(key_length, passphrase).bits_of();
+ key = pbkdf.derive_key(key_length, passphrase,
+ &salt[0], salt.size(),
+ iterations).bits_of();
}
/**
diff --git a/src/pk_pad/eme1/eme1.cpp b/src/pk_pad/eme1/eme1.cpp
index 13f68f8e4..d99ffaf58 100644
--- a/src/pk_pad/eme1/eme1.cpp
+++ b/src/pk_pad/eme1/eme1.cpp
@@ -21,7 +21,7 @@ SecureVector<byte> EME1::pad(const byte in[], u32bit in_length,
key_length /= 8;
if(in_length > key_length - 2*HASH_LENGTH - 1)
- throw Exception("EME1: Input is too large");
+ throw Invalid_Argument("EME1: Input is too large");
SecureVector<byte> out(key_length);
diff --git a/src/pubkey/dl_group/dl_group.cpp b/src/pubkey/dl_group/dl_group.cpp
index a2e239783..7940e69b2 100644
--- a/src/pubkey/dl_group/dl_group.cpp
+++ b/src/pubkey/dl_group/dl_group.cpp
@@ -193,7 +193,7 @@ const BigInt& DL_Group::get_q() const
{
init_check();
if(q == 0)
- throw Format_Error("DLP group has no q prime specified");
+ throw Invalid_State("DLP group has no q prime specified");
return q;
}
@@ -325,7 +325,7 @@ BigInt DL_Group::make_dsa_generator(const BigInt& p, const BigInt& q)
}
if(g == 1)
- throw Exception("DL_Group: Couldn't create a suitable generator");
+ throw Internal_Error("DL_Group: Couldn't create a suitable generator");
return g;
}
diff --git a/src/pubkey/dlies/dlies.cpp b/src/pubkey/dlies/dlies.cpp
index 3a3ab52ee..6ef3292e1 100644
--- a/src/pubkey/dlies/dlies.cpp
+++ b/src/pubkey/dlies/dlies.cpp
@@ -127,7 +127,7 @@ SecureVector<byte> DLIES_Decryptor::dec(const byte msg[], u32bit length) const
mac->update(0);
SecureVector<byte> T2 = mac->final();
if(T != T2)
- throw Integrity_Failure("DLIES: message authentication failed");
+ throw Decoding_Error("DLIES: message authentication failed");
xor_buf(C, K.begin() + mac_keylen, C.size());
diff --git a/src/pubkey/dsa/dsa.cpp b/src/pubkey/dsa/dsa.cpp
index b0688ae0d..5be3e1d48 100644
--- a/src/pubkey/dsa/dsa.cpp
+++ b/src/pubkey/dsa/dsa.cpp
@@ -97,6 +97,8 @@ SecureVector<byte> DSA_PrivateKey::sign(const byte in[], u32bit length,
{
const BigInt& q = group_q();
+ rng.add_entropy(in, length);
+
BigInt k;
do
k.randomize(rng, q.bits());
diff --git a/src/pubkey/ec_dompar/ec_dompar.cpp b/src/pubkey/ec_dompar/ec_dompar.cpp
index 6c688f34e..3719153f0 100644
--- a/src/pubkey/ec_dompar/ec_dompar.cpp
+++ b/src/pubkey/ec_dompar/ec_dompar.cpp
@@ -564,18 +564,16 @@ EC_Domain_Params decode_ber_ec_dompar(SecureVector<byte> const& encoded)
{
BER_Decoder dec(encoded);
BER_Object obj = dec.get_next_object();
- ASN1_Tag tag = obj.type_tag;
- std::auto_ptr<EC_Domain_Params> p_result;
- if(tag == OBJECT_ID)
+ if(obj.type_tag == OBJECT_ID)
{
OID dom_par_oid;
BER_Decoder(encoded).decode(dom_par_oid);
return EC_Domain_Params(get_ec_dompar(dom_par_oid.as_string()));
}
- else if(tag == SEQUENCE)
+ else if(obj.type_tag == SEQUENCE)
return EC_Domain_Params(decode_ber_ec_dompar_explicit(encoded));
- else if(tag == NULL_TAG)
+ else if(obj.type_tag == NULL_TAG)
throw Decoding_Error("cannot decode ECDSA parameters that are ImplicitCA");
throw Decoding_Error("encountered unexpected when trying to decode domain parameters");
diff --git a/src/pubkey/ecc_key/ecc_key.cpp b/src/pubkey/ecc_key/ecc_key.cpp
index 677a5088e..b7f58eecc 100644
--- a/src/pubkey/ecc_key/ecc_key.cpp
+++ b/src/pubkey/ecc_key/ecc_key.cpp
@@ -134,9 +134,9 @@ void EC_PublicKey::set_parameter_encoding(EC_dompar_enc type)
m_param_enc = type;
}
-/********************************
+/*
* EC_PrivateKey
-********************************/
+*/
void EC_PrivateKey::affirm_init() const // virtual
{
if(m_private_value == 0)
diff --git a/src/pubkey/ecc_key/ecc_key.h b/src/pubkey/ecc_key/ecc_key.h
index 0ca9a0e75..c1a227bf2 100644
--- a/src/pubkey/ecc_key/ecc_key.h
+++ b/src/pubkey/ecc_key/ecc_key.h
@@ -16,6 +16,7 @@
#include <botan/ec_dompar.h>
#include <botan/x509_key.h>
#include <botan/pkcs8.h>
+#include <memory>
namespace Botan {
diff --git a/src/pubkey/ecdsa/ecdsa.cpp b/src/pubkey/ecdsa/ecdsa.cpp
index 9d352c70f..6116f7b13 100644
--- a/src/pubkey/ecdsa/ecdsa.cpp
+++ b/src/pubkey/ecdsa/ecdsa.cpp
@@ -156,9 +156,9 @@ u32bit ECDSA_PublicKey::max_input_bits() const
return mp_dom_pars->get_order().bits();
}
-/*************************
+/*
* ECDSA_PrivateKey
-*************************/
+*/
void ECDSA_PrivateKey::affirm_init() const // virtual
{
EC_PrivateKey::affirm_init();
diff --git a/src/pubkey/eckaeg/eckaeg.cpp b/src/pubkey/eckaeg/eckaeg.cpp
index dc6eb925b..3e0f717e0 100644
--- a/src/pubkey/eckaeg/eckaeg.cpp
+++ b/src/pubkey/eckaeg/eckaeg.cpp
@@ -16,9 +16,9 @@
namespace Botan {
-/*********************************
+/*
* ECKAEG_PublicKey
-*********************************/
+*/
void ECKAEG_PublicKey::affirm_init() const // virtual
{
@@ -72,9 +72,9 @@ ECKAEG_PublicKey::ECKAEG_PublicKey(EC_Domain_Params const& dom_par, PointGFp con
m_eckaeg_core = ECKAEG_Core(*mp_dom_pars, BigInt(0), *mp_public_point);
}
-/*********************************
+/*
* ECKAEG_PrivateKey
-*********************************/
+*/
void ECKAEG_PrivateKey::affirm_init() const // virtual
{
EC_PrivateKey::affirm_init();
diff --git a/src/pubkey/pk_codecs/pkcs8.cpp b/src/pubkey/pk_codecs/pkcs8.cpp
index f287e1e63..d0954df39 100644
--- a/src/pubkey/pk_codecs/pkcs8.cpp
+++ b/src/pubkey/pk_codecs/pkcs8.cpp
@@ -168,7 +168,7 @@ void encrypt_key(const Private_Key& key,
const std::string& pass, const std::string& pbe_algo,
X509_Encoding encoding)
{
- const std::string DEFAULT_PBE = "PBE-PKCS5v20(SHA-1,TripleDES/CBC)";
+ const std::string DEFAULT_PBE = "PBE-PKCS5v20(SHA-1,AES-128/CBC)";
Pipe raw_key;
raw_key.start_msg();
diff --git a/src/pubkey/pk_codecs/pkcs8.h b/src/pubkey/pk_codecs/pkcs8.h
index 28008bdba..adfad0e63 100644
--- a/src/pubkey/pk_codecs/pkcs8.h
+++ b/src/pubkey/pk_codecs/pkcs8.h
@@ -82,9 +82,8 @@ BOTAN_DLL void encode(const Private_Key& key, Pipe& pipe,
* @param pipe the pipe to feed the encoded key into
* @param pass the password to use for encryption
* @param rng the rng to use
-* @param pbe_algo the name of the desired password-based encryption algorithm.
-* Provide an empty string to use the default PBE defined in the configuration
-* under base/default_pbe.
+* @param pbe_algo the name of the desired password-based encryption algorithm;
+ if empty ("") a reasonable (portable/secure) default will be chosen.
* @param enc the encoding type to use
*/
BOTAN_DLL void encrypt_key(const Private_Key& key,
@@ -108,9 +107,8 @@ BOTAN_DLL std::string PEM_encode(const Private_Key& key);
* @param key the key to encode
* @param rng the rng to use
* @param pass the password to use for encryption
-* @param pbe_algo the name of the desired password-based encryption algorithm.
-* Provide an empty string to use the default PBE defined in the configuration
-* under base/default_pbe.
+* @param pbe_algo the name of the desired password-based encryption algorithm;
+ if empty ("") a reasonable (portable/secure) default will be chosen.
*/
BOTAN_DLL std::string PEM_encode(const Private_Key& key,
RandomNumberGenerator& rng,
diff --git a/src/pubkey/pubkey.cpp b/src/pubkey/pubkey.cpp
index 44e31159c..dc0a505f5 100644
--- a/src/pubkey/pubkey.cpp
+++ b/src/pubkey/pubkey.cpp
@@ -73,7 +73,7 @@ PK_Encryptor_MR_with_EME::enc(const byte msg[],
message.set(msg, length);
if(8*(message.size() - 1) + high_bit(message[0]) > key.max_input_bits())
- throw Exception("PK_Encryptor_MR_with_EME: Input is too large");
+ throw Invalid_Argument("PK_Encryptor_MR_with_EME: Input is too large");
return key.encrypt(message, message.size(), rng);
}
@@ -113,11 +113,7 @@ SecureVector<byte> PK_Decryptor_MR_with_EME::dec(const byte msg[],
}
catch(Invalid_Argument)
{
- throw Exception("PK_Decryptor_MR_with_EME: Input is invalid");
- }
- catch(Decoding_Error)
- {
- throw Exception("PK_Decryptor_MR_with_EME: Input is invalid");
+ throw Decoding_Error("PK_Decryptor_MR_with_EME: Input is invalid");
}
}
@@ -331,7 +327,6 @@ bool PK_Verifier::check_signature(const byte sig[], u32bit length)
to_string(sig_format));
}
catch(Invalid_Argument) { return false; }
- catch(Decoding_Error) { return false; }
}
/*
diff --git a/src/rng/auto_rng/auto_rng.cpp b/src/rng/auto_rng/auto_rng.cpp
index 5befc9d14..78a7ca21d 100644
--- a/src/rng/auto_rng/auto_rng.cpp
+++ b/src/rng/auto_rng/auto_rng.cpp
@@ -6,10 +6,8 @@
*/
#include <botan/auto_rng.h>
+#include <botan/libstate.h>
#include <botan/parsing.h>
-#include <botan/hmac.h>
-#include <botan/sha2_32.h>
-#include <botan/sha2_64.h>
#if defined(BOTAN_HAS_RANDPOOL)
#include <botan/randpool.h>
@@ -23,10 +21,6 @@
#include <botan/x931_rng.h>
#endif
-#if defined(BOTAN_HAS_AES)
- #include <botan/aes.h>
-#endif
-
#if defined(BOTAN_HAS_ENTROPY_SRC_HIGH_RESOLUTION_TIMER)
#include <botan/internal/hres_timer.h>
#endif
@@ -115,10 +109,18 @@ AutoSeeded_RNG::AutoSeeded_RNG(u32bit poll_bits)
{
rng = 0;
+ Algorithm_Factory& af = global_state().algorithm_factory();
+
#if defined(BOTAN_HAS_HMAC_RNG)
- rng = new HMAC_RNG(new HMAC(new SHA_512), new HMAC(new SHA_256));
+
+ rng = new HMAC_RNG(af.make_mac("HMAC(SHA-512)"),
+ af.make_mac("HMAC(SHA-256)"));
+
#elif defined(BOTAN_HAS_RANDPOOL) && defined(BOTAN_HAS_AES)
- rng = new Randpool(new AES_256, new HMAC(new SHA_256));
+
+ rng = new Randpool(af.make_block_cipher("AES-256"),
+ af.make_mac("HMAC(SHA-256)"));
+
#endif
if(!rng)
@@ -126,7 +128,9 @@ AutoSeeded_RNG::AutoSeeded_RNG(u32bit poll_bits)
/* If X9.31 is available, use it to wrap the other RNG as a failsafe */
#if defined(BOTAN_HAS_X931_RNG) && defined(BOTAN_HAS_AES)
- rng = new ANSI_X931_RNG(new AES_256, rng);
+
+ rng = new ANSI_X931_RNG(af.make_block_cipher("AES-256"), rng);
+
#endif
add_entropy_sources(rng);
diff --git a/src/rng/hmac_rng/hmac_rng.cpp b/src/rng/hmac_rng/hmac_rng.cpp
index 995ec9259..84a7b1c13 100644
--- a/src/rng/hmac_rng/hmac_rng.cpp
+++ b/src/rng/hmac_rng/hmac_rng.cpp
@@ -6,7 +6,7 @@
*/
#include <botan/hmac_rng.h>
-#include <botan/loadstor.h>
+#include <botan/get_byte.h>
#include <botan/internal/xor_buf.h>
#include <botan/internal/stl_util.h>
#include <algorithm>
diff --git a/src/rng/randpool/randpool.cpp b/src/rng/randpool/randpool.cpp
index f6479b2dd..9a4d77e55 100644
--- a/src/rng/randpool/randpool.cpp
+++ b/src/rng/randpool/randpool.cpp
@@ -6,7 +6,7 @@
*/
#include <botan/randpool.h>
-#include <botan/loadstor.h>
+#include <botan/get_byte.h>
#include <botan/internal/xor_buf.h>
#include <botan/internal/stl_util.h>
#include <algorithm>
diff --git a/src/s2k/info.txt b/src/s2k/info.txt
index 1d5226524..861b6f760 100644
--- a/src/s2k/info.txt
+++ b/src/s2k/info.txt
@@ -1,4 +1,3 @@
<requires>
-rng
sym_algo
</requires>
diff --git a/src/s2k/pbkdf1/pbkdf1.cpp b/src/s2k/pbkdf1/pbkdf1.cpp
index 04e3aa453..a8270e26f 100644
--- a/src/s2k/pbkdf1/pbkdf1.cpp
+++ b/src/s2k/pbkdf1/pbkdf1.cpp
@@ -6,22 +6,23 @@
*/
#include <botan/pbkdf1.h>
+#include <botan/exceptn.h>
namespace Botan {
/*
* Return a PKCS#5 PBKDF1 derived key
*/
-OctetString PKCS5_PBKDF1::derive(u32bit key_len,
- const std::string& passphrase,
- const byte salt[], u32bit salt_size,
- u32bit iterations) const
+OctetString PKCS5_PBKDF1::derive_key(u32bit key_len,
+ const std::string& passphrase,
+ const byte salt[], u32bit salt_size,
+ u32bit iterations) const
{
if(iterations == 0)
- throw Invalid_Argument("PKCS#5 PBKDF1: Invalid iteration count");
+ throw Invalid_Argument("PKCS5_PBKDF1: Invalid iteration count");
if(key_len > hash->OUTPUT_LENGTH)
- throw Exception("PKCS#5 PBKDF1: Requested output length too long");
+ throw Invalid_Argument("PKCS5_PBKDF1: Requested output length too long");
hash->update(passphrase);
hash->update(salt, salt_size);
diff --git a/src/s2k/pbkdf1/pbkdf1.h b/src/s2k/pbkdf1/pbkdf1.h
index 4e5cafdb0..053a2dbe1 100644
--- a/src/s2k/pbkdf1/pbkdf1.h
+++ b/src/s2k/pbkdf1/pbkdf1.h
@@ -22,6 +22,11 @@ class BOTAN_DLL PKCS5_PBKDF1 : public S2K
std::string name() const;
S2K* clone() const;
+ OctetString derive_key(u32bit output_len,
+ const std::string& passphrase,
+ const byte salt[], u32bit salt_len,
+ u32bit iterations) const;
+
/**
* Create a PKCS #5 instance using the specified hash function.
* @param hash a pointer to a hash function object to use
@@ -33,9 +38,6 @@ class BOTAN_DLL PKCS5_PBKDF1 : public S2K
~PKCS5_PBKDF1() { delete hash; }
private:
- OctetString derive(u32bit, const std::string&,
- const byte[], u32bit, u32bit) const;
-
HashFunction* hash;
};
diff --git a/src/s2k/pbkdf2/pbkdf2.cpp b/src/s2k/pbkdf2/pbkdf2.cpp
index 6f790c06b..f1fc6e29f 100644
--- a/src/s2k/pbkdf2/pbkdf2.cpp
+++ b/src/s2k/pbkdf2/pbkdf2.cpp
@@ -6,7 +6,7 @@
*/
#include <botan/pbkdf2.h>
-#include <botan/loadstor.h>
+#include <botan/get_byte.h>
#include <botan/internal/xor_buf.h>
namespace Botan {
@@ -14,10 +14,10 @@ namespace Botan {
/*
* Return a PKCS#5 PBKDF2 derived key
*/
-OctetString PKCS5_PBKDF2::derive(u32bit key_len,
- const std::string& passphrase,
- const byte salt[], u32bit salt_size,
- u32bit iterations) const
+OctetString PKCS5_PBKDF2::derive_key(u32bit key_len,
+ const std::string& passphrase,
+ const byte salt[], u32bit salt_size,
+ u32bit iterations) const
{
if(iterations == 0)
throw Invalid_Argument("PKCS#5 PBKDF2: Invalid iteration count");
diff --git a/src/s2k/pbkdf2/pbkdf2.h b/src/s2k/pbkdf2/pbkdf2.h
index 7510338bb..b6d231916 100644
--- a/src/s2k/pbkdf2/pbkdf2.h
+++ b/src/s2k/pbkdf2/pbkdf2.h
@@ -22,6 +22,11 @@ class BOTAN_DLL PKCS5_PBKDF2 : public S2K
std::string name() const;
S2K* clone() const;
+ OctetString derive_key(u32bit output_len,
+ const std::string& passphrase,
+ const byte salt[], u32bit salt_len,
+ u32bit iterations) const;
+
/**
* Create a PKCS #5 instance using the specified message auth code
* @param mac the MAC to use
@@ -29,9 +34,6 @@ class BOTAN_DLL PKCS5_PBKDF2 : public S2K
PKCS5_PBKDF2(MessageAuthenticationCode* mac);
~PKCS5_PBKDF2();
private:
- OctetString derive(u32bit, const std::string&,
- const byte[], u32bit, u32bit) const;
-
MessageAuthenticationCode* mac;
};
diff --git a/src/s2k/pgps2k/pgp_s2k.cpp b/src/s2k/pgps2k/pgp_s2k.cpp
index 86394d84d..49ff6892c 100644
--- a/src/s2k/pgps2k/pgp_s2k.cpp
+++ b/src/s2k/pgps2k/pgp_s2k.cpp
@@ -14,9 +14,10 @@ namespace Botan {
/*
* Derive a key using the OpenPGP S2K algorithm
*/
-OctetString OpenPGP_S2K::derive(u32bit key_len, const std::string& passphrase,
- const byte salt_buf[], u32bit salt_size,
- u32bit iterations) const
+OctetString OpenPGP_S2K::derive_key(u32bit key_len,
+ const std::string& passphrase,
+ const byte salt_buf[], u32bit salt_size,
+ u32bit iterations) const
{
SecureVector<byte> key(key_len), hash_buf;
diff --git a/src/s2k/pgps2k/pgp_s2k.h b/src/s2k/pgps2k/pgp_s2k.h
index 00e95f7fa..7f25623f3 100644
--- a/src/s2k/pgps2k/pgp_s2k.h
+++ b/src/s2k/pgps2k/pgp_s2k.h
@@ -22,12 +22,14 @@ class BOTAN_DLL OpenPGP_S2K : public S2K
std::string name() const;
S2K* clone() const;
+ OctetString derive_key(u32bit output_len,
+ const std::string& passphrase,
+ const byte salt[], u32bit salt_len,
+ u32bit iterations) const;
+
OpenPGP_S2K(HashFunction* hash_in) : hash(hash_in) {}
~OpenPGP_S2K() { delete hash; }
private:
- OctetString derive(u32bit, const std::string&,
- const byte[], u32bit, u32bit) const;
-
HashFunction* hash;
};
diff --git a/src/s2k/s2k.cpp b/src/s2k/s2k.cpp
deleted file mode 100644
index 42064529d..000000000
--- a/src/s2k/s2k.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
-* S2K
-* (C) 1999-2007 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-#include <botan/s2k.h>
-
-namespace Botan {
-
-/*
-* Derive a key from a passphrase
-*/
-OctetString S2K::derive_key(u32bit key_len,
- const std::string& passphrase) const
- {
- return derive(key_len, passphrase, salt, salt.size(), iterations());
- }
-
-/*
-* Set the number of iterations
-*/
-void S2K::set_iterations(u32bit i)
- {
- iter = i;
- }
-
-/*
-* Change the salt
-*/
-void S2K::change_salt(const byte new_salt[], u32bit length)
- {
- salt.set(new_salt, length);
- }
-
-/*
-* Change the salt
-*/
-void S2K::change_salt(const MemoryRegion<byte>& new_salt)
- {
- change_salt(new_salt.begin(), new_salt.size());
- }
-
-/*
-* Create a new random salt
-*/
-void S2K::new_random_salt(RandomNumberGenerator& rng,
- u32bit length)
- {
- salt.resize(length);
- rng.randomize(salt, length);
- }
-
-}
diff --git a/src/s2k/s2k.h b/src/s2k/s2k.h
index 7af92519b..055ef8911 100644
--- a/src/s2k/s2k.h
+++ b/src/s2k/s2k.h
@@ -9,7 +9,6 @@
#define BOTAN_S2K_H__
#include <botan/symkey.h>
-#include <botan/rng.h>
namespace Botan {
@@ -19,9 +18,9 @@ namespace Botan {
class BOTAN_DLL S2K
{
public:
+
/**
- * Create a copy of this object.
- * @return an auto_ptr to a copy of this object
+ * @return a new instance of this same algorithm
*/
virtual S2K* clone() const = 0;
@@ -39,62 +38,22 @@ class BOTAN_DLL S2K
/**
* Derive a key from a passphrase with this S2K object. It will use
* the salt value and number of iterations configured in this object.
- * @param key_len the desired length of the key to produce
+ * @param output_len the desired length of the key to produce
* @param passphrase the password to derive the key from
+ * @param salt the randomly chosen salt
+ * @param salt_len length of salt in bytes
+ * @param iterations the number of iterations to use (use 10K or more)
*/
- OctetString derive_key(u32bit key_len,
- const std::string& passphrase) const;
-
- /**
- * Set the number of iterations for the one-way function during
- * key generation.
- * @param n the desired number of iterations
- */
- void set_iterations(u32bit n);
-
- /**
- * Set a new salt value.
- * @param new_salt a byte array defining the new salt value
- * @param len the length of the above byte array
- */
- void change_salt(const byte new_salt[], u32bit len);
-
- /**
- * Set a new salt value.
- * @param new_salt the new salt value
- */
- void change_salt(const MemoryRegion<byte>& new_salt);
+ virtual OctetString derive_key(u32bit output_len,
+ const std::string& passphrase,
+ const byte salt[], u32bit salt_len,
+ u32bit iterations) const = 0;
- /**
- * Create a new random salt value using the rng
- * @param rng the random number generator to use
- * @param len the desired length of the new salt value
- */
- void new_random_salt(RandomNumberGenerator& rng, u32bit len);
-
- /**
- * Get the number of iterations for the key derivation currently
- * configured in this S2K object.
- * @return the current number of iterations
- */
- u32bit iterations() const { return iter; }
-
- /**
- * Get the currently configured salt value of this S2K object.
- * @return the current salt value
- */
- SecureVector<byte> current_salt() const { return salt; }
-
- S2K() { iter = 0; }
+ S2K() {}
virtual ~S2K() {}
private:
S2K(const S2K&) {}
S2K& operator=(const S2K&) { return (*this); }
-
- virtual OctetString derive(u32bit, const std::string&,
- const byte[], u32bit, u32bit) const = 0;
- SecureVector<byte> salt;
- u32bit iter;
};
}
diff --git a/src/selftest/selftest.cpp b/src/selftest/selftest.cpp
index 291643f2c..215569cbb 100644
--- a/src/selftest/selftest.cpp
+++ b/src/selftest/selftest.cpp
@@ -198,89 +198,97 @@ void cipher_kat(Algorithm_Factory& af,
* Perform Self Tests
*/
bool passes_self_tests(Algorithm_Factory& af)
- {
- try
- {
- cipher_kat(af, "DES",
- "0123456789ABCDEF", "1234567890ABCDEF",
- "4E6F77206973207468652074696D6520666F7220616C6C20",
- "3FA40E8A984D48156A271787AB8883F9893D51EC4B563B53",
- "E5C7CDDE872BF27C43E934008C389C0F683788499A7C05F6",
- "F3096249C7F46E51A69E839B1A92F78403467133898EA622",
- "F3096249C7F46E5135F24A242EEB3D3F3D6D5BE3255AF8C3",
- "F3096249C7F46E51163A8CA0FFC94C27FA2F80F480B86F75");
-
- cipher_kat(af, "TripleDES",
- "385D7189A5C3D485E1370AA5D408082B5CCCCB5E19F2D90E",
- "C141B5FCCD28DC8A",
- "6E1BD7C6120947A464A6AAB293A0F89A563D8D40D3461B68",
- "64EAAD4ACBB9CEAD6C7615E7C7E4792FE587D91F20C7D2F4",
- "6235A461AFD312973E3B4F7AA7D23E34E03371F8E8C376C9",
- "E26BA806A59B0330DE40CA38E77A3E494BE2B212F6DD624B",
- "E26BA806A59B03307DE2BCC25A08BA40A8BA335F5D604C62",
- "E26BA806A59B03303C62C2EFF32D3ACDD5D5F35EBCC53371");
-
- cipher_kat(af, "AES-128",
- "2B7E151628AED2A6ABF7158809CF4F3C",
- "000102030405060708090A0B0C0D0E0F",
- "6BC1BEE22E409F96E93D7E117393172A"
- "AE2D8A571E03AC9C9EB76FAC45AF8E51",
- "3AD77BB40D7A3660A89ECAF32466EF97"
- "F5D3D58503B9699DE785895A96FDBAAF",
- "7649ABAC8119B246CEE98E9B12E9197D"
- "5086CB9B507219EE95DB113A917678B2",
- "3B3FD92EB72DAD20333449F8E83CFB4A"
- "C8A64537A0B3A93FCDE3CDAD9F1CE58B",
- "3B3FD92EB72DAD20333449F8E83CFB4A"
- "7789508D16918F03F53C52DAC54ED825",
- "3B3FD92EB72DAD20333449F8E83CFB4A"
- "010C041999E03F36448624483E582D0E");
-
- hash_test(af, "SHA-1",
- "", "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709");
-
- hash_test(af, "SHA-1",
- "616263", "A9993E364706816ABA3E25717850C26C9CD0D89D");
-
- hash_test(af, "SHA-1",
- "6162636462636465636465666465666765666768666768696768696A"
- "68696A6B696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F7071",
- "84983E441C3BD26EBAAE4AA1F95129E5E54670F1");
-
- mac_test(af, "HMAC(SHA-1)",
- "4869205468657265",
- "B617318655057264E28BC0B6FB378C8EF146BE00",
- "0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B");
-
- hash_test(af, "SHA-256",
- "",
- "E3B0C44298FC1C149AFBF4C8996FB924"
- "27AE41E4649B934CA495991B7852B855");
-
- hash_test(af, "SHA-256",
- "616263",
- "BA7816BF8F01CFEA414140DE5DAE2223"
- "B00361A396177A9CB410FF61F20015AD");
-
- hash_test(af, "SHA-256",
- "6162636462636465636465666465666765666768666768696768696A"
- "68696A6B696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F7071",
- "248D6A61D20638B8E5C026930C3E6039"
- "A33CE45964FF2167F6ECEDD419DB06C1");
-
- mac_test(af, "HMAC(SHA-256)",
- "4869205468657265",
- "198A607EB44BFBC69903A0F1CF2BBDC5"
- "BA0AA3F3D9AE3C1C7A3B1696A0B68CF7",
- "0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B"
- "0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B");
- }
- catch(Self_Test_Failure)
- {
- return false;
- }
+ {
+ try
+ {
+ confirm_startup_self_tests(af);
+ }
+ catch(Self_Test_Failure)
+ {
+ return false;
+ }
- return true;
+ return true;
+ }
+
+/*
+* Perform Self Tests
+*/
+void confirm_startup_self_tests(Algorithm_Factory& af)
+ {
+ cipher_kat(af, "DES",
+ "0123456789ABCDEF", "1234567890ABCDEF",
+ "4E6F77206973207468652074696D6520666F7220616C6C20",
+ "3FA40E8A984D48156A271787AB8883F9893D51EC4B563B53",
+ "E5C7CDDE872BF27C43E934008C389C0F683788499A7C05F6",
+ "F3096249C7F46E51A69E839B1A92F78403467133898EA622",
+ "F3096249C7F46E5135F24A242EEB3D3F3D6D5BE3255AF8C3",
+ "F3096249C7F46E51163A8CA0FFC94C27FA2F80F480B86F75");
+
+ cipher_kat(af, "TripleDES",
+ "385D7189A5C3D485E1370AA5D408082B5CCCCB5E19F2D90E",
+ "C141B5FCCD28DC8A",
+ "6E1BD7C6120947A464A6AAB293A0F89A563D8D40D3461B68",
+ "64EAAD4ACBB9CEAD6C7615E7C7E4792FE587D91F20C7D2F4",
+ "6235A461AFD312973E3B4F7AA7D23E34E03371F8E8C376C9",
+ "E26BA806A59B0330DE40CA38E77A3E494BE2B212F6DD624B",
+ "E26BA806A59B03307DE2BCC25A08BA40A8BA335F5D604C62",
+ "E26BA806A59B03303C62C2EFF32D3ACDD5D5F35EBCC53371");
+
+ cipher_kat(af, "AES-128",
+ "2B7E151628AED2A6ABF7158809CF4F3C",
+ "000102030405060708090A0B0C0D0E0F",
+ "6BC1BEE22E409F96E93D7E117393172A"
+ "AE2D8A571E03AC9C9EB76FAC45AF8E51",
+ "3AD77BB40D7A3660A89ECAF32466EF97"
+ "F5D3D58503B9699DE785895A96FDBAAF",
+ "7649ABAC8119B246CEE98E9B12E9197D"
+ "5086CB9B507219EE95DB113A917678B2",
+ "3B3FD92EB72DAD20333449F8E83CFB4A"
+ "C8A64537A0B3A93FCDE3CDAD9F1CE58B",
+ "3B3FD92EB72DAD20333449F8E83CFB4A"
+ "7789508D16918F03F53C52DAC54ED825",
+ "3B3FD92EB72DAD20333449F8E83CFB4A"
+ "010C041999E03F36448624483E582D0E");
+
+ hash_test(af, "SHA-1",
+ "", "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709");
+
+ hash_test(af, "SHA-1",
+ "616263", "A9993E364706816ABA3E25717850C26C9CD0D89D");
+
+ hash_test(af, "SHA-1",
+ "6162636462636465636465666465666765666768666768696768696A"
+ "68696A6B696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F7071",
+ "84983E441C3BD26EBAAE4AA1F95129E5E54670F1");
+
+ mac_test(af, "HMAC(SHA-1)",
+ "4869205468657265",
+ "B617318655057264E28BC0B6FB378C8EF146BE00",
+ "0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B");
+
+ hash_test(af, "SHA-256",
+ "",
+ "E3B0C44298FC1C149AFBF4C8996FB924"
+ "27AE41E4649B934CA495991B7852B855");
+
+ hash_test(af, "SHA-256",
+ "616263",
+ "BA7816BF8F01CFEA414140DE5DAE2223"
+ "B00361A396177A9CB410FF61F20015AD");
+
+ hash_test(af, "SHA-256",
+ "6162636462636465636465666465666765666768666768696768696A"
+ "68696A6B696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F7071",
+ "248D6A61D20638B8E5C026930C3E6039"
+ "A33CE45964FF2167F6ECEDD419DB06C1");
+
+ mac_test(af, "HMAC(SHA-256)",
+ "4869205468657265",
+ "198A607EB44BFBC69903A0F1CF2BBDC5"
+ "BA0AA3F3D9AE3C1C7A3B1696A0B68CF7",
+ "0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B"
+ "0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B");
}
}
diff --git a/src/selftest/selftest.h b/src/selftest/selftest.h
index 4cb6e23d7..df71e6f8e 100644
--- a/src/selftest/selftest.h
+++ b/src/selftest/selftest.h
@@ -18,6 +18,8 @@ namespace Botan {
/*
* Self Tests
*/
+BOTAN_DLL void confirm_startup_self_tests(Algorithm_Factory& af);
+
BOTAN_DLL bool passes_self_tests(Algorithm_Factory& af);
BOTAN_DLL std::map<std::string, bool>
diff --git a/src/stream/stream_cipher.h b/src/stream/stream_cipher.h
index 29c16c8b5..cb6fb3481 100644
--- a/src/stream/stream_cipher.h
+++ b/src/stream/stream_cipher.h
@@ -42,8 +42,8 @@ class BOTAN_DLL StreamCipher : public SymmetricAlgorithm
virtual void set_iv(const byte[], u32bit iv_len)
{
if(iv_len)
- throw Exception("The stream cipher " + name() +
- " does not support resyncronization");
+ throw Invalid_Argument("The stream cipher " + name() +
+ " does not support resyncronization");
}
/**
diff --git a/src/utils/bswap.h b/src/utils/bswap.h
index 96ec4982a..fcb0fa7ea 100644
--- a/src/utils/bswap.h
+++ b/src/utils/bswap.h
@@ -16,10 +16,6 @@
#include <emmintrin.h>
#endif
-#if defined(BOTAN_TARGET_CPU_HAS_SSSE3)
- #include <tmmintrin.h>
-#endif
-
namespace Botan {
/*
@@ -32,8 +28,7 @@ inline u16bit reverse_bytes(u16bit input)
inline u32bit reverse_bytes(u32bit input)
{
-#if BOTAN_USE_GCC_INLINE_ASM && (defined(BOTAN_TARGET_ARCH_IS_IA32) || \
- defined(BOTAN_TARGET_ARCH_IS_AMD64))
+#if BOTAN_USE_GCC_INLINE_ASM && defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
// GCC-style inline assembly for x86 or x86-64
asm("bswapl %0" : "=r" (input) : "0" (input));
@@ -83,23 +78,7 @@ inline void bswap_4(T x[4])
x[3] = reverse_bytes(x[3]);
}
-#if defined(BOTAN_TARGET_CPU_HAS_SSSE3)
-
-template<>
-inline void bswap_4(u32bit x[4])
- {
- const __m128i bswap_mask = _mm_set_epi8(
- 12, 13, 14, 15,
- 8, 9, 10, 11,
- 4, 5, 6, 7,
- 0, 1, 2, 3);
-
- __m128i T = _mm_loadu_si128((const __m128i*)x);
- T = _mm_shuffle_epi8(T, bswap_mask);
- _mm_storeu_si128((__m128i*)x, T);
- }
-
-#elif defined(BOTAN_TARGET_CPU_HAS_SSE2)
+#if defined(BOTAN_TARGET_CPU_HAS_SSE2)
template<>
inline void bswap_4(u32bit x[4])
diff --git a/src/utils/cpuid.cpp b/src/utils/cpuid.cpp
index 2ba7f9b77..8d801b75f 100644
--- a/src/utils/cpuid.cpp
+++ b/src/utils/cpuid.cpp
@@ -7,10 +7,14 @@
#include <botan/cpuid.h>
#include <botan/types.h>
-#include <botan/loadstor.h>
+#include <botan/get_byte.h>
#include <botan/mem_ops.h>
-#if defined(BOTAN_TARGET_ARCH_IS_IA32) || defined(BOTAN_TARGET_ARCH_IS_AMD64)
+#if defined(BOTAN_TARGET_OS_IS_DARWIN)
+ #include <sys/sysctl.h>
+#endif
+
+#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
#if defined(BOTAN_BUILD_COMPILER_IS_MSVC)
@@ -64,6 +68,73 @@ u32bit get_x86_cache_line_size()
return 32; // default cache line guess
}
+#if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
+
+bool altivec_check_sysctl()
+ {
+#if defined(BOTAN_TARGET_OS_IS_DARWIN)
+
+ // From Apple's docs
+ int sels[2] = { CTL_HW, HW_VECTORUNIT };
+ int vector_type = 0;
+ size_t length = sizeof(vector_type);
+ int error = sysctl(sels, 2, &vector_type, &length, NULL, 0);
+
+ if(error == 0 && vector_type > 0)
+ return true;
+#endif
+
+ return false;
+ }
+
+bool altivec_check_pvr_emul()
+ {
+ bool altivec_capable = false;
+
+#if defined(BOTAN_TARGET_OS_IS_LINUX) || defined(BOTAN_TARGET_OS_IS_NETBSD)
+
+ /*
+ On PowerPC, MSR 287 is PVR, the Processor Version Number
+ Normally it is only accessible to ring 0, but Linux and NetBSD
+ (others, too, maybe?) will trap and emulate it for us.
+
+ PVR identifiers for various AltiVec enabled CPUs. Taken from
+ PearPC and Linux sources, mostly.
+ */
+
+ const u16bit PVR_G4_7400 = 0x000C;
+ const u16bit PVR_G5_970 = 0x0039;
+ const u16bit PVR_G5_970FX = 0x003C;
+ const u16bit PVR_G5_970MP = 0x0044;
+ const u16bit PVR_G5_970GX = 0x0045;
+ const u16bit PVR_POWER6 = 0x003E;
+ const u16bit PVR_CELL_PPU = 0x0070;
+
+ // Motorola produced G4s with PVR 0x800[0123C] (at least)
+ const u16bit PVR_G4_74xx_24 = 0x800;
+
+ u32bit pvr = 0;
+
+ asm volatile("mfspr %0, 287" : "=r" (pvr));
+
+ // Top 16 bit suffice to identify model
+ pvr >>= 16;
+
+ altivec_capable |= (pvr == PVR_G4_7400);
+ altivec_capable |= ((pvr >> 4) == PVR_G4_74xx_24);
+ altivec_capable |= (pvr == PVR_G5_970);
+ altivec_capable |= (pvr == PVR_G5_970FX);
+ altivec_capable |= (pvr == PVR_G5_970MP);
+ altivec_capable |= (pvr == PVR_G5_970GX);
+ altivec_capable |= (pvr == PVR_POWER6);
+ altivec_capable |= (pvr == PVR_CELL_PPU);
+#endif
+
+ return altivec_capable;
+ }
+
+#endif
+
}
/*
@@ -105,58 +176,9 @@ bool CPUID::has_altivec()
if(first_time)
{
-#if defined(BOTAN_TARGET_ARCH_IS_PPC) || defined(BOTAN_TARGET_ARCH_IS_PPC64)
-
- /*
- PVR identifiers for various AltiVec enabled CPUs. Taken from
- PearPC and Linux sources, mostly.
- */
- const u16bit PVR_G4_7400 = 0x000C;
- const u16bit PVR_G5_970 = 0x0039;
- const u16bit PVR_G5_970FX = 0x003C;
- const u16bit PVR_G5_970MP = 0x0044;
- const u16bit PVR_G5_970GX = 0x0045;
- const u16bit PVR_POWER6 = 0x003E;
- const u16bit PVR_CELL_PPU = 0x0070;
-
- // Motorola produced G4s with PVR 0x800[0123C] (at least)
- const u16bit PVR_G4_74xx_24 = 0x800;
-
- /*
- On PowerPC, MSR 287 is PVR, the Processor Version Number
-
- Normally it is only accessible to ring 0, but Linux and NetBSD
- (at least) will trap and emulate it for us. This is roughly 20x
- saner than every other approach I've seen for AltiVec detection
- (all of which are entirely OS specific, to boot).
-
- Apparently OS X doesn't support this, but then again OS X
- doesn't really support PPC anymore, so I'm not worrying about it.
-
- For OSes that aren't (known to) support the emulation, skip the
- call, leaving pvr as 0 which will cause all subsequent model
- number checks to fail (and we'll assume no AltiVec)
- */
-
-#if defined(BOTAN_TARGET_OS_IS_LINUX) || defined(BOTAN_TARGET_OS_IS_NETBSD)
- #define BOTAN_TARGET_OS_SUPPORTS_MFSPR_EMUL
-#endif
-
- u32bit pvr = 0;
-
-#if defined(BOTAN_TARGET_OS_SUPPORTS_MFSPR_EMUL)
- asm volatile("mfspr %0, 287" : "=r" (pvr));
-#endif
- // Top 16 bit suffice to identify model
- pvr >>= 16;
-
- altivec_capable |= (pvr == PVR_G4_7400);
- altivec_capable |= ((pvr >> 8) == PVR_G4_74xx_24);
- altivec_capable |= (pvr == PVR_G5_970);
- altivec_capable |= (pvr == PVR_G5_970FX);
- altivec_capable |= (pvr == PVR_G5_970MP);
- altivec_capable |= (pvr == PVR_G5_970GX);
- altivec_capable |= (pvr == PVR_CELL_PPU);
+#if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
+ if(altivec_check_sysctl() || altivec_check_pvr_emul())
+ altivec_capable = true;
#endif
first_time = false;
diff --git a/src/utils/cpuid.h b/src/utils/cpuid.h
index 2c9599899..1de97f129 100644
--- a/src/utils/cpuid.h
+++ b/src/utils/cpuid.h
@@ -21,7 +21,7 @@ class BOTAN_DLL CPUID
CPUID_SSSE3_BIT = 41,
CPUID_SSE41_BIT = 51,
CPUID_SSE42_BIT = 52,
- CPUID_INTEL_AES_BIT = 57,
+ CPUID_INTEL_AES_BIT = 57
};
/**
@@ -66,12 +66,6 @@ class BOTAN_DLL CPUID
{ return ((x86_processor_flags() >> CPUID_INTEL_AES_BIT) & 1); }
/**
- * Check if the processor supports VIA's AES instructions
- * (not implemented)
- */
- static bool has_aes_via() { return false; }
-
- /**
* Check if the processor supports AltiVec/VMX
*/
static bool has_altivec();
diff --git a/src/utils/debug.h b/src/utils/debug.h
new file mode 100644
index 000000000..271e0047b
--- /dev/null
+++ b/src/utils/debug.h
@@ -0,0 +1,37 @@
+/**
+* Internal-use debugging functions for Botan
+* (C) 2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_DEBUG_H__
+#define BOTAN_DEBUG_H__
+
+#include <botan/secmem.h>
+#include <cstdio>
+
+namespace Botan {
+
+namespace Debug {
+
+inline void print_vec(const std::string& name,
+ const byte array[], size_t array_len)
+ {
+ std::printf("%s = ", name.c_str());
+ for(size_t i = 0; i != array_len; ++i)
+ std::printf("%02X", array[i]);
+ std::printf("\n");
+ }
+
+inline void print_vec(const std::string& name,
+ const MemoryRegion<byte>& vec)
+ {
+ print_vec(name, &vec[0], vec.size());
+ }
+
+}
+
+}
+
+#endif
diff --git a/src/utils/exceptn.cpp b/src/utils/exceptn.cpp
deleted file mode 100644
index 753d63424..000000000
--- a/src/utils/exceptn.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
-* Exceptions
-* (C) 1999-2007 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-#include <botan/exceptn.h>
-#include <botan/parsing.h>
-
-namespace Botan {
-
-/*
-* Constructor for Invalid_Key_Length
-*/
-Invalid_Key_Length::Invalid_Key_Length(const std::string& name, u32bit length)
- {
- set_msg(name + " cannot accept a key of length " + to_string(length));
- }
-
-/*
-* Constructor for Invalid_Block_Size
-*/
-Invalid_Block_Size::Invalid_Block_Size(const std::string& mode,
- const std::string& pad)
- {
- set_msg("Padding method " + pad + " cannot be used with " + mode);
- }
-
-/*
-* Constructor for Invalid_IV_Length
-*/
-Invalid_IV_Length::Invalid_IV_Length(const std::string& mode, u32bit bad_len)
- {
- set_msg("IV length " + to_string(bad_len) + " is invalid for " + mode);
- }
-
-/*
-* Constructor for Algorithm_Not_Found
-*/
-Algorithm_Not_Found::Algorithm_Not_Found(const std::string& name)
- {
- set_msg("Could not find any algorithm named \"" + name + "\"");
- }
-
-/*
-* Constructor for Invalid_Algorithm_Name
-*/
-Invalid_Algorithm_Name::Invalid_Algorithm_Name(const std::string& name)
- {
- set_msg("Invalid algorithm name: " + name);
- }
-
-/*
-* Constructor for Config_Error
-*/
-Config_Error::Config_Error(const std::string& err, u32bit line)
- {
- set_msg("Config error at line " + to_string(line) + ": " + err);
- }
-
-}
diff --git a/src/utils/exceptn.h b/src/utils/exceptn.h
index a55d842bc..86efebc7c 100644
--- a/src/utils/exceptn.h
+++ b/src/utils/exceptn.h
@@ -1,6 +1,6 @@
/*
* Exceptions
-* (C) 1999-2007 Jack Lloyd
+* (C) 1999-2009 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
@@ -9,32 +9,44 @@
#define BOTAN_EXCEPTION_H__
#include <botan/types.h>
+#include <botan/parsing.h>
#include <exception>
+#include <stdexcept>
#include <string>
namespace Botan {
+typedef std::runtime_error Exception;
+typedef std::invalid_argument Invalid_Argument;
+
/*
-* Exception Base Class
+* Invalid_State Exception
*/
-class BOTAN_DLL Exception : public std::exception
+struct BOTAN_DLL Invalid_State : public Exception
{
- public:
- const char* what() const throw() { return msg.c_str(); }
- Exception(const std::string& m = "Unknown error") { set_msg(m); }
- virtual ~Exception() throw() {}
- protected:
- void set_msg(const std::string& m) { msg = "Botan: " + m; }
- private:
- std::string msg;
+ Invalid_State(const std::string& err) :
+ Exception(err)
+ {}
};
/*
-* Invalid_Argument Exception
+* Lookup_Error Exception
*/
-struct BOTAN_DLL Invalid_Argument : public Exception
+struct BOTAN_DLL Lookup_Error : public Exception
{
- Invalid_Argument(const std::string& err = "") : Exception(err) {}
+ Lookup_Error(const std::string& err) :
+ Exception(err)
+ {}
+ };
+
+/*
+* Internal_Error Exception
+*/
+struct BOTAN_DLL Internal_Error : public Exception
+ {
+ Internal_Error(const std::string& err) :
+ Exception("Internal error: " + err)
+ {}
};
/*
@@ -42,7 +54,10 @@ struct BOTAN_DLL Invalid_Argument : public Exception
*/
struct BOTAN_DLL Invalid_Key_Length : public Invalid_Argument
{
- Invalid_Key_Length(const std::string&, u32bit);
+ Invalid_Key_Length(const std::string& name, u32bit length) :
+ Invalid_Argument(name + " cannot accept a key of length " +
+ to_string(length))
+ {}
};
/*
@@ -50,7 +65,11 @@ struct BOTAN_DLL Invalid_Key_Length : public Invalid_Argument
*/
struct BOTAN_DLL Invalid_Block_Size : public Invalid_Argument
{
- Invalid_Block_Size(const std::string&, const std::string&);
+ Invalid_Block_Size(const std::string& mode,
+ const std::string& pad) :
+ Invalid_Argument("Padding method " + pad +
+ " cannot be used with " + mode)
+ {}
};
/*
@@ -58,15 +77,10 @@ struct BOTAN_DLL Invalid_Block_Size : public Invalid_Argument
*/
struct BOTAN_DLL Invalid_IV_Length : public Invalid_Argument
{
- Invalid_IV_Length(const std::string&, u32bit);
- };
-
-/*
-* Invalid_State Exception
-*/
-struct BOTAN_DLL Invalid_State : public Exception
- {
- Invalid_State(const std::string& err) : Exception(err) {}
+ Invalid_IV_Length(const std::string& mode, u32bit bad_len) :
+ Invalid_Argument("IV length " + to_string(bad_len) +
+ " is invalid for " + mode)
+ {}
};
/*
@@ -75,7 +89,8 @@ struct BOTAN_DLL Invalid_State : public Exception
struct BOTAN_DLL PRNG_Unseeded : public Invalid_State
{
PRNG_Unseeded(const std::string& algo) :
- Invalid_State("PRNG not seeded: " + algo) {}
+ Invalid_State("PRNG not seeded: " + algo)
+ {}
};
/*
@@ -84,57 +99,46 @@ struct BOTAN_DLL PRNG_Unseeded : public Invalid_State
struct BOTAN_DLL Policy_Violation : public Invalid_State
{
Policy_Violation(const std::string& err) :
- Invalid_State("Policy violation: " + err) {}
- };
-
-/*
-* Lookup_Error Exception
-*/
-struct BOTAN_DLL Lookup_Error : public Exception
- {
- Lookup_Error(const std::string& err) : Exception(err) {}
+ Invalid_State("Policy violation: " + err)
+ {}
};
/*
* Algorithm_Not_Found Exception
*/
-struct BOTAN_DLL Algorithm_Not_Found : public Exception
+struct BOTAN_DLL Algorithm_Not_Found : public Lookup_Error
{
- Algorithm_Not_Found(const std::string&);
- };
-
-/*
-* Format_Error Exception
-*/
-struct BOTAN_DLL Format_Error : public Exception
- {
- Format_Error(const std::string& err = "") : Exception(err) {}
+ Algorithm_Not_Found(const std::string& name) :
+ Lookup_Error("Could not find any algorithm named \"" + name + "\"")
+ {}
};
/*
* Invalid_Algorithm_Name Exception
*/
-struct BOTAN_DLL Invalid_Algorithm_Name : public Format_Error
+struct BOTAN_DLL Invalid_Algorithm_Name : public Invalid_Argument
{
- Invalid_Algorithm_Name(const std::string&);
+ Invalid_Algorithm_Name(const std::string& name):
+ Invalid_Argument("Invalid algorithm name: " + name)
+ {}
};
/*
* Encoding_Error Exception
*/
-struct BOTAN_DLL Encoding_Error : public Format_Error
+struct BOTAN_DLL Encoding_Error : public Invalid_Argument
{
Encoding_Error(const std::string& name) :
- Format_Error("Encoding error: " + name) {}
+ Invalid_Argument("Encoding error: " + name) {}
};
/*
* Decoding_Error Exception
*/
-struct BOTAN_DLL Decoding_Error : public Format_Error
+struct BOTAN_DLL Decoding_Error : public Invalid_Argument
{
Decoding_Error(const std::string& name) :
- Format_Error("Decoding error: " + name) {}
+ Invalid_Argument("Decoding error: " + name) {}
};
/*
@@ -152,44 +156,27 @@ struct BOTAN_DLL Invalid_OID : public Decoding_Error
struct BOTAN_DLL Stream_IO_Error : public Exception
{
Stream_IO_Error(const std::string& err) :
- Exception("I/O error: " + err) {}
+ Exception("I/O error: " + err)
+ {}
};
/*
-* Configuration Error Exception
-*/
-struct BOTAN_DLL Config_Error : public Format_Error
- {
- Config_Error(const std::string& err) :
- Format_Error("Config error: " + err) {}
- Config_Error(const std::string&, u32bit);
- };
-
-/*
-* Integrity Failure Exception
-*/
-struct BOTAN_DLL Integrity_Failure : public Exception
- {
- Integrity_Failure(const std::string& err) :
- Exception("Integrity failure: " + err) {}
- };
-
-/*
-* Internal_Error Exception
+* Self Test Failure Exception
*/
-struct BOTAN_DLL Internal_Error : public Exception
+struct BOTAN_DLL Self_Test_Failure : public Internal_Error
{
- Internal_Error(const std::string& err) :
- Exception("Internal error: " + err) {}
+ Self_Test_Failure(const std::string& err) :
+ Internal_Error("Self test failed: " + err)
+ {}
};
/*
-* Self Test Failure Exception
+* Memory Allocation Exception
*/
-struct BOTAN_DLL Self_Test_Failure : public Internal_Error
+struct BOTAN_DLL Memory_Exhaustion : public std::bad_alloc
{
- Self_Test_Failure(const std::string& err) :
- Internal_Error("Self test failed: " + err) {}
+ const char* what() const throw()
+ { return "Ran out of memory, allocation failed"; }
};
}
diff --git a/src/utils/get_byte.h b/src/utils/get_byte.h
new file mode 100644
index 000000000..fce87af83
--- /dev/null
+++ b/src/utils/get_byte.h
@@ -0,0 +1,27 @@
+/*
+* Read out bytes
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_GET_BYTE_H__
+#define BOTAN_GET_BYTE_H__
+
+#include <botan/types.h>
+
+namespace Botan {
+
+/*
+* Byte Extraction Function
+*/
+template<typename T> inline byte get_byte(u32bit byte_num, T input)
+ {
+ return static_cast<byte>(
+ input >> ((sizeof(T)-1-(byte_num&(sizeof(T)-1))) << 3)
+ );
+ }
+
+}
+
+#endif
diff --git a/src/utils/info.txt b/src/utils/info.txt
index 93ece2e78..2fb3e79a5 100644
--- a/src/utils/info.txt
+++ b/src/utils/info.txt
@@ -5,7 +5,6 @@ load_on always
<source>
charset.cpp
cpuid.cpp
-exceptn.cpp
mlock.cpp
parsing.cpp
time.cpp
@@ -15,6 +14,7 @@ version.cpp
<header:internal>
bit_ops.h
+debug.h
mlock.h
prefetch.h
rounding.h
@@ -35,6 +35,7 @@ time.h
types.h
ui.h
version.h
+get_byte.h
</header:public>
<libs>
diff --git a/src/utils/loadstor.h b/src/utils/loadstor.h
index bd2acc87d..ffd27540d 100644
--- a/src/utils/loadstor.h
+++ b/src/utils/loadstor.h
@@ -11,6 +11,7 @@
#include <botan/types.h>
#include <botan/bswap.h>
+#include <botan/get_byte.h>
#include <cstring>
#if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
@@ -38,16 +39,6 @@
namespace Botan {
/*
-* Byte Extraction Function
-*/
-template<typename T> inline byte get_byte(u32bit byte_num, T input)
- {
- return static_cast<byte>(
- input >> ((sizeof(T)-1-(byte_num&(sizeof(T)-1))) << 3)
- );
- }
-
-/*
* Byte to Word Conversions
*/
inline u16bit make_u16bit(byte i0, byte i1)
diff --git a/src/utils/mlock.cpp b/src/utils/mlock.cpp
index bb3a38d4e..5d6fc3591 100644
--- a/src/utils/mlock.cpp
+++ b/src/utils/mlock.cpp
@@ -22,9 +22,9 @@ namespace Botan {
bool lock_mem(void* ptr, u32bit bytes)
{
#if defined(BOTAN_TARGET_OS_HAS_POSIX_MLOCK)
- return (mlock(ptr, bytes) == 0);
+ return (::mlock(ptr, bytes) == 0);
#elif defined(BOTAN_TARGET_OS_HAS_WIN32_VIRTUAL_LOCK)
- return (VirtualLock(ptr, bytes) != 0);
+ return (::VirtualLock(ptr, bytes) != 0);
#else
return false;
#endif
@@ -36,9 +36,9 @@ bool lock_mem(void* ptr, u32bit bytes)
void unlock_mem(void* ptr, u32bit bytes)
{
#if defined(BOTAN_TARGET_OS_HAS_POSIX_MLOCK)
- munlock(ptr, bytes);
+ ::munlock(ptr, bytes);
#elif defined(BOTAN_TARGET_OS_HAS_WIN32_VIRTUAL_LOCK)
- VirtualUnlock(ptr, bytes);
+ ::VirtualUnlock(ptr, bytes);
#endif
}
diff --git a/src/utils/parsing.cpp b/src/utils/parsing.cpp
index 58a8e0b38..e8259ac52 100644
--- a/src/utils/parsing.cpp
+++ b/src/utils/parsing.cpp
@@ -8,7 +8,7 @@
#include <botan/parsing.h>
#include <botan/exceptn.h>
#include <botan/charset.h>
-#include <botan/loadstor.h>
+#include <botan/get_byte.h>
namespace Botan {
@@ -168,7 +168,7 @@ std::vector<std::string> split_on(const std::string& str, char delim)
}
if(substr == "")
- throw Format_Error("Unable to split string: " + str);
+ throw Invalid_Argument("Unable to split string: " + str);
elems.push_back(substr);
return elems;
diff --git a/src/utils/prefetch.h b/src/utils/prefetch.h
index 7afdbda0a..ede196692 100644
--- a/src/utils/prefetch.h
+++ b/src/utils/prefetch.h
@@ -32,7 +32,7 @@ inline void readwrite(const T* addr, u32bit length)
const u32bit Ts_per_cache_line = CPUID::cache_line_size() / sizeof(T);
for(u32bit i = 0; i <= length; i += Ts_per_cache_line)
- __builtin_prefetch(addr + i, 0);
+ __builtin_prefetch(addr + i, 1);
#endif
}
diff --git a/src/utils/simd_32/info.txt b/src/utils/simd_32/info.txt
index 08cbdfa52..362e90235 100644
--- a/src/utils/simd_32/info.txt
+++ b/src/utils/simd_32/info.txt
@@ -1,7 +1,5 @@
define SIMD_32
-load_on always
-
<header:internal>
simd_32.h
simd_sse.h
diff --git a/src/utils/simd_32/simd_32.h b/src/utils/simd_32/simd_32.h
index 38ea078d0..4bd983f5e 100644
--- a/src/utils/simd_32/simd_32.h
+++ b/src/utils/simd_32/simd_32.h
@@ -27,4 +27,20 @@
#endif
+namespace Botan {
+
+inline SIMD_32 rotate_left(SIMD_32 x, u32bit rot)
+ {
+ x.rotate_left(rot);
+ return x;
+ }
+
+inline SIMD_32 rotate_right(SIMD_32 x, u32bit rot)
+ {
+ x.rotate_right(rot);
+ return x;
+ }
+
+}
+
#endif
diff --git a/src/utils/simd_32/simd_altivec.h b/src/utils/simd_32/simd_altivec.h
index 9cc5c1068..859a48a5f 100644
--- a/src/utils/simd_32/simd_altivec.h
+++ b/src/utils/simd_32/simd_altivec.h
@@ -145,6 +145,11 @@ class SIMD_Altivec
reg = vec_or(reg, other.reg);
}
+ SIMD_Altivec operator&(const SIMD_Altivec& other)
+ {
+ return vec_and(reg, other.reg);
+ }
+
void operator&=(const SIMD_Altivec& other)
{
reg = vec_and(reg, other.reg);
diff --git a/src/utils/simd_32/simd_scalar.h b/src/utils/simd_32/simd_scalar.h
index 148b76c35..5cf1a11c3 100644
--- a/src/utils/simd_32/simd_scalar.h
+++ b/src/utils/simd_32/simd_scalar.h
@@ -142,6 +142,14 @@ class SIMD_Scalar
R3 |= other.R3;
}
+ SIMD_Scalar operator&(const SIMD_Scalar& other)
+ {
+ return SIMD_Scalar(R0 & other.R0,
+ R1 & other.R1,
+ R2 & other.R2,
+ R3 & other.R3);
+ }
+
void operator&=(const SIMD_Scalar& other)
{
R0 &= other.R0;
diff --git a/src/utils/simd_32/simd_sse.h b/src/utils/simd_32/simd_sse.h
index 31bbce2c7..0189c2e4d 100644
--- a/src/utils/simd_32/simd_sse.h
+++ b/src/utils/simd_32/simd_sse.h
@@ -101,6 +101,11 @@ class SIMD_SSE2
reg = _mm_or_si128(reg, other.reg);
}
+ SIMD_SSE2 operator&(const SIMD_SSE2& other)
+ {
+ return _mm_and_si128(reg, other.reg);
+ }
+
void operator&=(const SIMD_SSE2& other)
{
reg = _mm_and_si128(reg, other.reg);
diff --git a/src/wrap/python/filter.cpp b/src/wrap/python/filter.cpp
index a678af9e5..48a3f84eb 100644
--- a/src/wrap/python/filter.cpp
+++ b/src/wrap/python/filter.cpp
@@ -1,7 +1,9 @@
-/*************************************************
-* Boost.Python module definition *
-* (C) 1999-2007 Jack Lloyd *
-*************************************************/
+/*
+* Boost.Python module definition
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
#include <boost/python.hpp>
using namespace boost::python;
diff --git a/src/wrap/python/python_botan.h b/src/wrap/python/python_botan.h
index 646c2e2c1..a7a2e505e 100644
--- a/src/wrap/python/python_botan.h
+++ b/src/wrap/python/python_botan.h
@@ -1,3 +1,8 @@
+/*
+* (C) 2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
#ifndef BOTAN_BOOST_PYTHON_COMMON_H__
#define BOTAN_BOOST_PYTHON_COMMON_H__
diff --git a/src/wrap/python/x509.cpp b/src/wrap/python/x509.cpp
index 90c2bba1c..c2c9533c8 100644
--- a/src/wrap/python/x509.cpp
+++ b/src/wrap/python/x509.cpp
@@ -1,7 +1,9 @@
-/*************************************************
-* Boost.Python module definition *
-* (C) 1999-2007 Jack Lloyd *
-*************************************************/
+/*
+* Boost.Python module definition
+* (C) 2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
#include <botan/oids.h>
#include <botan/pipe.h>
diff --git a/src/wrap/sqlite/codec.cpp b/src/wrap/sqlite/codec.cpp
new file mode 100644
index 000000000..5dfcea82e
--- /dev/null
+++ b/src/wrap/sqlite/codec.cpp
@@ -0,0 +1,123 @@
+/*
+ * Codec class for SQLite3 encryption codec.
+ * (C) 2010 Olivier de Gaalon
+ *
+ * Distributed under the terms of the Botan license
+ */
+
+#include "codec.h"
+#include <botan/init.h>
+
+Codec::Codec(void *db)
+{
+ InitializeCodec(db);
+}
+
+Codec::Codec(const Codec& other, void *db)
+{
+ //Only used to copy main db key for an attached db
+ InitializeCodec(db);
+ m_hasReadKey = other.m_hasReadKey;
+ m_hasWriteKey = other.m_hasWriteKey;
+ m_readKey = other.m_readKey;
+ m_ivReadKey = other.m_ivReadKey;
+ m_writeKey = other.m_writeKey;
+ m_ivWriteKey = other.m_ivWriteKey;
+}
+
+void
+Codec::InitializeCodec(void *db)
+{
+ bool botanInitialized = false;
+ Library_State* state = swap_global_state(0);
+ if(state)
+ {
+ botanInitialized = true;
+ swap_global_state(state); // should return NULL FIXME: what if not?
+ }
+
+ if (!botanInitialized)
+ LibraryInitializer::initialize();
+
+ m_hasReadKey = false;
+ m_hasWriteKey = false;
+ m_db = db;
+
+ m_encipherFilter = get_cipher(BLOCK_CIPHER_STR, ENCRYPTION);
+ m_decipherFilter = get_cipher(BLOCK_CIPHER_STR, DECRYPTION);
+ m_cmac = new MAC_Filter(MAC_STR);
+ m_encipherPipe.append(m_encipherFilter);
+ m_decipherPipe.append(m_decipherFilter);
+ m_macPipe.append(m_cmac);
+}
+
+void
+Codec::GenerateWriteKey(const char* userPassword, int passwordLength)
+{
+ S2K* s2k = get_s2k(S2K_STR);
+ s2k->set_iterations(S2K_ITERATIONS);
+ s2k->change_salt((const byte*)SALT_STR.c_str(), SALT_SIZE);
+
+ SymmetricKey masterKey =
+ s2k->derive_key(KEY_SIZE + IV_DERIVATION_KEY_SIZE, std::string(userPassword, passwordLength));
+
+ m_writeKey = SymmetricKey(masterKey.bits_of(), KEY_SIZE);
+ m_ivWriteKey = SymmetricKey(masterKey.bits_of() + KEY_SIZE, IV_DERIVATION_KEY_SIZE);
+
+ m_hasWriteKey = true;
+}
+
+void
+Codec::DropWriteKey()
+{
+ m_hasWriteKey = false;
+}
+
+void
+Codec::SetReadIsWrite()
+{
+ m_readKey = m_writeKey;
+ m_ivReadKey = m_ivWriteKey;
+ m_hasReadKey = m_hasWriteKey;
+}
+
+void
+Codec::SetWriteIsRead()
+{
+ m_writeKey = m_readKey;
+ m_ivWriteKey = m_ivReadKey;
+ m_hasWriteKey = m_hasReadKey;
+}
+
+unsigned char *
+Codec::Encrypt(int page, unsigned char* data, bool useWriteKey)
+{
+ memcpy(m_page, data, m_pageSize);
+
+ m_encipherFilter->set_key(useWriteKey ? m_writeKey : m_readKey);
+ m_encipherFilter->set_iv(GetIVForPage(page, useWriteKey));
+ m_encipherPipe.process_msg(m_page, m_pageSize);
+ m_encipherPipe.read(m_page, m_encipherPipe.remaining(Pipe::LAST_MESSAGE), Pipe::LAST_MESSAGE);
+
+ return m_page; //return location of newly ciphered data
+}
+
+void
+Codec::Decrypt(int page, unsigned char* data)
+{
+ m_decipherFilter->set_key(m_readKey);
+ m_decipherFilter->set_iv(GetIVForPage(page, false));
+ m_decipherPipe.process_msg(data, m_pageSize);
+ m_decipherPipe.read(data, m_decipherPipe.remaining(Pipe::LAST_MESSAGE), Pipe::LAST_MESSAGE);
+}
+
+InitializationVector
+Codec::GetIVForPage(u32bit page, bool useWriteKey)
+{
+ static unsigned char* intiv[4];
+ store_le(page, (byte*)intiv);
+ m_cmac->set_key(useWriteKey ? m_ivWriteKey : m_ivReadKey);
+ m_macPipe.process_msg((byte*)intiv, 4);
+ return m_macPipe.read_all(Pipe::LAST_MESSAGE);
+}
+
diff --git a/src/wrap/sqlite/codec.h b/src/wrap/sqlite/codec.h
new file mode 100644
index 000000000..8b753be62
--- /dev/null
+++ b/src/wrap/sqlite/codec.h
@@ -0,0 +1,127 @@
+/*
+ * Codec class for SQLite3 encryption codec.
+ * (C) 2010 Olivier de Gaalon
+ *
+ * Distributed under the terms of the Botan license
+ */
+
+#ifndef _CODEC_H_
+#define _CODEC_H_
+
+#include <string>
+#include <botan/botan.h>
+#include <botan/loadstor.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(__BORLANDC__)
+#define __STDC__ 1
+#endif
+
+#include "./sqliteInt.h"
+
+#if defined(__BORLANDC__)
+#undef __STDC__
+#endif
+
+/* ATTENTION: Macro similar to that in pager.c
+ * Needed because pager is forward declared when needed most
+ * TODO: Check in case of new version of SQLite
+ * ... but it's VERY unlikely to change (it'd break all past DBs)
+ */
+#include "./os.h"
+#define CODEC_PAGER_MJ_PGNO(x) ((PENDING_BYTE/(x))+1)
+
+#ifdef __cplusplus
+} /* End of the 'extern "C"' block */
+#endif
+
+using namespace std;
+using namespace Botan;
+
+/*These constants can be used to tweak the codec behavior as follows
+ *Note that once you've encrypted a database with these settings,
+ *recompiling with any different settings will give you a library that
+ *cannot read that database, even given the same passphrase.*/
+
+//BLOCK_CIPHER_STR: Cipher and mode used for encrypting the database
+//make sure to add "/NoPadding" for modes that use padding schemes
+const string BLOCK_CIPHER_STR = "Twofish/XTS";
+
+//S2K_STR: Key derivation function used to derive both the encryption
+//and IV derivation keys from the given database passphrase
+const string S2K_STR = "PBKDF2(SHA-160)";
+
+//SALT_STR: Hard coded salt used to derive the key from the passphrase.
+const string SALT_STR = "&g#nB'9]";
+
+//MAC_STR: CMAC used to derive the IV that is used for db page
+//encryption
+const string MAC_STR = "CMAC(Twofish)";
+
+//S2K_ITERATIONS: Number of hash iterations used in the key derivation
+//process.
+const int S2K_ITERATIONS = 10000;
+
+//SALT_SIZE: Size of the salt in bytes (as given in SALT_STR)
+const int SALT_SIZE = 64/8; //64 bit, 8 byte salt
+
+//KEY_SIZE: Size of the encryption key. Note that XTS splits the key
+//between two ciphers, so if you're using XTS, double the intended key
+//size. (ie, "AES-128/XTS" should have a 256 bit KEY_SIZE)
+const int KEY_SIZE = 512/8; //512 bit, 64 byte key. (256 bit XTS key)
+
+//IV_DERIVATION_KEY_SIZE: Size of the key used with the CMAC (MAC_STR)
+//above.
+const int IV_DERIVATION_KEY_SIZE = 256/8; //256 bit, 32 byte key
+
+class Codec
+{
+public:
+ Codec(void *db);
+ Codec(const Codec& other, void *db);
+
+ void GenerateWriteKey(const char* userPassword, int passwordLength);
+ void DropWriteKey();
+ void SetWriteIsRead();
+ void SetReadIsWrite();
+
+ unsigned char* Encrypt(int page, unsigned char* data, bool useWriteKey);
+ void Decrypt(int page, unsigned char* data);
+
+ void SetPageSize(int pageSize) { m_pageSize = pageSize; }
+
+ bool HasReadKey() { return m_hasReadKey; }
+ bool HasWriteKey() { return m_hasWriteKey; }
+ void* GetDB() { return m_db; }
+
+private:
+ bool m_hasReadKey;
+ bool m_hasWriteKey;
+
+ SymmetricKey
+ m_readKey,
+ m_writeKey,
+ m_ivReadKey,
+ m_ivWriteKey;
+
+ Pipe
+ m_encipherPipe,
+ m_decipherPipe,
+ m_macPipe;
+
+ Keyed_Filter *m_encipherFilter;
+ Keyed_Filter *m_decipherFilter;
+ MAC_Filter *m_cmac;
+
+ int m_pageSize;
+ unsigned char m_page[SQLITE_MAX_PAGE_SIZE];
+ void* m_db;
+
+ InitializationVector GetIVForPage(u32bit page, bool useWriteKey);
+ void InitializeCodec(void *db);
+};
+
+#endif
diff --git a/src/wrap/sqlite/codecext.cpp b/src/wrap/sqlite/codecext.cpp
new file mode 100644
index 000000000..e542df975
--- /dev/null
+++ b/src/wrap/sqlite/codecext.cpp
@@ -0,0 +1,261 @@
+/*
+ * SQLite3 encryption extention codec
+ * (C) 2010 Olivier de Gaalon
+ *
+ * Distributed under the terms of the Botan license
+ */
+
+#ifndef SQLITE_OMIT_DISKIO
+#ifdef SQLITE_HAS_CODEC
+
+#include "codec.h"
+#include "sqlite3.h"
+
+// Required to implement, called from pragma.c, guessing that "see" is related to the
+// "SQLite Encryption Extension" (the semi-official, for-pay, encryption codec)
+extern "C"
+void sqlite3_activate_see(const char *info) { }
+
+// Free the encryption codec, called from pager.c (address passed in sqlite3PagerSetCodec)
+extern "C"
+void sqlite3PagerFreeCodec(void *pCodec)
+{
+ if (pCodec)
+ delete (Codec*) pCodec;
+}
+
+// Report the page size to the codec, called from pager.c (address passed in sqlite3PagerSetCodec)
+extern "C"
+void sqlite3CodecSizeChange(void *pCodec, int pageSize, int nReserve)
+{
+ Codec* codec = (Codec*) pCodec;
+ codec->SetPageSize(pageSize);
+}
+
+// Encrypt/Decrypt functionality, called by pager.c
+extern "C"
+void* sqlite3Codec(void* pCodec, void* data, Pgno nPageNum, int nMode)
+{
+ if (pCodec == NULL) //Db not encrypted
+ return data;
+
+ Codec* codec = (Codec*) pCodec;
+
+ try
+ {
+ switch(nMode)
+ {
+ case 0: // Undo a "case 7" journal file encryption
+ case 2: // Reload a page
+ case 3: // Load a page
+ if (codec->HasReadKey())
+ codec->Decrypt(nPageNum, (unsigned char*) data);
+ break;
+ case 6: // Encrypt a page for the main database file
+ if (codec->HasWriteKey())
+ data = codec->Encrypt(nPageNum, (unsigned char*) data, true);
+ break;
+ case 7: // Encrypt a page for the journal file
+ /*
+ *Under normal circumstances, the readkey is the same as the writekey. However,
+ *when the database is being rekeyed, the readkey is not the same as the writekey.
+ *(The writekey is the "destination key" for the rekey operation and the readkey
+ *is the key the db is currently encrypted with)
+ *Therefore, for case 7, when the rollback is being written, always encrypt using
+ *the database's readkey, which is guaranteed to be the same key that was used to
+ *read and write the original data.
+ */
+ if (codec->HasReadKey())
+ data = codec->Encrypt(nPageNum, (unsigned char*) data, false);
+ break;
+ }
+ }
+ catch(Botan::Exception e)
+ {
+ sqlite3Error((sqlite3*)codec->GetDB(), SQLITE_ERROR, "Botan Error: %s", e.what());
+ }
+
+ return data;
+}
+
+//These functions are defined in pager.c
+extern "C" void* sqlite3PagerGetCodec(Pager *pPager);
+extern "C" void sqlite3PagerSetCodec(
+ Pager *pPager,
+ void *(*xCodec)(void*,void*,Pgno,int),
+ void (*xCodecSizeChng)(void*,int,int),
+ void (*xCodecFree)(void*),
+ void *pCodec
+);
+
+
+extern "C"
+int sqlite3CodecAttach(sqlite3* db, int nDb, const void* zKey, int nKey)
+{
+ try {
+ if (zKey == NULL || nKey <= 0)
+ {
+ // No key specified, could mean either use the main db's encryption or no encryption
+ if (nDb != 0 && nKey < 0)
+ {
+ //Is an attached database, therefore use the key of main database, if main database is encrypted
+ Codec* mainCodec = (Codec*) sqlite3PagerGetCodec(sqlite3BtreePager(db->aDb[0].pBt));
+ if (mainCodec != NULL)
+ {
+ Codec* codec = new Codec(*mainCodec, db);
+ sqlite3PagerSetCodec(sqlite3BtreePager(db->aDb[nDb].pBt),
+ sqlite3Codec,
+ sqlite3CodecSizeChange,
+ sqlite3PagerFreeCodec, codec);
+ }
+ }
+ }
+ else
+ {
+ // Key specified, setup encryption key for database
+ Codec* codec = new Codec(db);
+ codec->GenerateWriteKey((const char*) zKey, nKey);
+ codec->SetReadIsWrite();
+ sqlite3PagerSetCodec(sqlite3BtreePager(db->aDb[nDb].pBt),
+ sqlite3Codec,
+ sqlite3CodecSizeChange,
+ sqlite3PagerFreeCodec, codec);
+ }
+ }
+ catch(Botan::Exception e) {
+ sqlite3Error(db, SQLITE_ERROR, "Botan Error: %s", e.what());
+ return SQLITE_ERROR;
+ }
+ return SQLITE_OK;
+}
+
+extern "C"
+void sqlite3CodecGetKey(sqlite3* db, int nDb, void** zKey, int* nKey)
+{
+ // The unencrypted password is not stored for security reasons
+ // therefore always return NULL
+ *zKey = NULL;
+ *nKey = -1;
+}
+
+extern "C"
+int sqlite3_key(sqlite3 *db, const void *zKey, int nKey)
+{
+ // The key is only set for the main database, not the temp database
+ return sqlite3CodecAttach(db, 0, zKey, nKey);
+}
+
+extern "C"
+int sqlite3_rekey(sqlite3 *db, const void *zKey, int nKey)
+{
+ // Changes the encryption key for an existing database.
+ int rc = SQLITE_ERROR;
+ Btree* pbt = db->aDb[0].pBt;
+ Pager* pPager = sqlite3BtreePager(pbt);
+ Codec* codec = (Codec*) sqlite3PagerGetCodec(pPager);
+
+ if ((zKey == NULL || nKey == 0) && codec == NULL)
+ {
+ // Database not encrypted and key not specified. Do nothing
+ return SQLITE_OK;
+ }
+
+ if (codec == NULL)
+ {
+ // Database not encrypted, but key specified. Encrypt database
+ try {
+ codec = new Codec(db);
+ codec->GenerateWriteKey((const char*) zKey, nKey);
+ } catch (Botan::Exception e) {
+ sqlite3Error(db, SQLITE_ERROR, "Botan Error %s", e.what());
+ return SQLITE_ERROR;
+ }
+ sqlite3PagerSetCodec(pPager, sqlite3Codec, sqlite3CodecSizeChange, sqlite3PagerFreeCodec, codec);
+ }
+ else if (zKey == NULL || nKey == 0)
+ {
+ // Database encrypted, but key not specified. Decrypt database
+ // Keep read key, drop write key
+ codec->DropWriteKey();
+ }
+ else
+ {
+ // Database encrypted and key specified. Re-encrypt database with new key
+ // Keep read key, change write key to new key
+ try {
+ codec->GenerateWriteKey((const char*) zKey, nKey);
+ } catch (Botan::Exception e) {
+ sqlite3Error(db, SQLITE_ERROR, "Botan Error %s", e.what());
+ return SQLITE_ERROR;
+ }
+ }
+
+ // Start transaction
+ rc = sqlite3BtreeBeginTrans(pbt, 1);
+ if (rc == SQLITE_OK)
+ {
+ // Rewrite all pages using the new encryption key (if specified)
+ int nPageCount = -1;
+ int rc = sqlite3PagerPagecount(pPager, &nPageCount);
+ Pgno nPage = (Pgno) nPageCount;
+ int pageSize = sqlite3BtreeGetPageSize(pbt);
+ //Can't use SQLite3 macro here since pager is forward declared...sigh
+ Pgno nSkip = CODEC_PAGER_MJ_PGNO(pageSize);
+ DbPage *pPage;
+
+ for (Pgno n = 1; rc == SQLITE_OK && n <= nPage; n++)
+ {
+ if (n == nSkip)
+ continue;
+
+ rc = sqlite3PagerGet(pPager, n, &pPage);
+
+ if (!rc)
+ {
+ rc = sqlite3PagerWrite(pPage);
+ sqlite3PagerUnref(pPage);
+ }
+ else
+ sqlite3Error(db, SQLITE_ERROR, "%s", "Error while rekeying database page. Transaction Canceled.");
+ }
+ }
+ else
+ sqlite3Error(db, SQLITE_ERROR, "%s", "Error beginning rekey transaction. Make sure that the current encryption key is correct.");
+
+ if (rc == SQLITE_OK)
+ {
+ // All good, commit
+ rc = sqlite3BtreeCommit(pbt);
+
+ if (rc == SQLITE_OK)
+ {
+ //Database rekeyed and committed successfully, update read key
+ if (codec->HasWriteKey())
+ codec->SetReadIsWrite();
+ else //No write key == no longer encrypted
+ sqlite3PagerSetCodec(pPager, NULL, NULL, NULL, NULL);
+ }
+ else
+ {
+ //FIXME: can't trigger this, not sure if rollback is needed, reference implementation didn't rollback
+ sqlite3Error(db, SQLITE_ERROR, "%s", "Could not commit rekey transaction.");
+ }
+ }
+ else
+ {
+ // Rollback, rekey failed
+ sqlite3BtreeRollback(pbt);
+
+ // go back to read key
+ if (codec->HasReadKey())
+ codec->SetWriteIsRead();
+ else //Database wasn't encrypted to start with
+ sqlite3PagerSetCodec(pPager, NULL, NULL, NULL, NULL);
+ }
+
+ return rc;
+}
+
+#endif // SQLITE_HAS_CODEC
+
+#endif // SQLITE_OMIT_DISKIO
diff --git a/src/wrap/sqlite/readme.txt b/src/wrap/sqlite/readme.txt
new file mode 100644
index 000000000..e131f9e91
--- /dev/null
+++ b/src/wrap/sqlite/readme.txt
@@ -0,0 +1,36 @@
+Build instructions for Botan SQLite3 codec
+---
+
+1. Requires Botan 1.8.8 or later (earlier versions OK if you switch to
+ CBC mode from XTS)
+
+2. Download SQLite3 version 3.6.17 or later, get the version "as
+ extracted from the source control system", NOT the amalgamation.
+
+3. Apply the patch "sqlite.diff" [*]:
+ $ patch -p0 < ../sqlite.diff
+ patching file Makefile.in
+ patching file src/pager.c
+
+ If the patch to pager.c fails for some reason (ie, changes in
+ SQLite3), all that need be done is remove the "static" keyword from
+ the functions sqlite3PagerSetCodec and sqlite3PagerGetCodec.
+
+5. Create a folder called "botan" in the SQLite3 src dir and copy
+ "codec.cpp", "codec.h", and "codecext.cpp" into it.
+
+6. As desired, edit the constants in codec.h to tweak the encryption
+ type to your needs. (Currently, Twofish/XTS with 256 bit key)
+
+7. Run ./configure in the SQLite3 root directory with the
+ "--disable-amalgamation" and (if desired) "--disable-shared"
+ arguments, and then run make.
+
+And to make sure it all worked...
+
+8. Make the test_sqlite.cpp file:
+ $ g++ test_sqlite.cpp -o test_sqlite -lbotan /path/to/libsqlite3.a
+9. Run it
+ $ ./test_sqlite
+10. Look for "All seems good"
+
diff --git a/src/wrap/sqlite/sqlite.diff b/src/wrap/sqlite/sqlite.diff
new file mode 100644
index 000000000..1a3ef764c
--- /dev/null
+++ b/src/wrap/sqlite/sqlite.diff
@@ -0,0 +1,77 @@
+--- Makefile.in.orig 2009-10-30 09:34:59.000000000 -0400
++++ Makefile.in 2010-01-21 22:51:22.000000000 -0500
+@@ -133,7 +133,10 @@
+ GCOV_LDFLAGS1 = -lgcov
+ USE_GCOV = @USE_GCOV@
+ LTCOMPILE_EXTRAS += $(GCOV_CFLAGS$(USE_GCOV))
++LTCOMPILE_EXTRAS += -DSQLITE_HAS_CODEC
+ LTLINK_EXTRAS += $(GCOV_LDFLAGS$(USE_GCOV))
++LTLINK_EXTRAS += -lstdc++
++LTLINK_EXTRAS += -lbotan
+
+
+ # The directory into which to store package information for
+@@ -176,7 +179,8 @@
+ table.lo tokenize.lo trigger.lo update.lo \
+ util.lo vacuum.lo \
+ vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo \
+- walker.lo where.lo utf.lo vtab.lo
++ walker.lo where.lo utf.lo vtab.lo \
++ codec.lo codecext.lo
+
+ # Object files for the amalgamation.
+ #
+@@ -275,7 +279,10 @@
+ $(TOP)/src/vdbeInt.h \
+ $(TOP)/src/vtab.c \
+ $(TOP)/src/walker.c \
+- $(TOP)/src/where.c
++ $(TOP)/src/where.c \
++ $(TOP)/src/botan/codec.cpp \
++ $(TOP)/src/botan/codecext.cpp \
++ $(TOP)/src/botan/codec.h
+
+ # Generated source code files
+ #
+@@ -411,6 +418,7 @@
+ $(TOP)/src/sqlite3ext.h \
+ $(TOP)/src/sqliteInt.h \
+ $(TOP)/src/vdbe.h \
++ $(TOP)/src/botan/codec.h \
+ $(TOP)/src/vdbeInt.h \
+ parse.h \
+ config.h
+@@ -622,6 +630,13 @@
+ notify.lo: $(TOP)/src/notify.c $(HDR)
+ $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/notify.c
+
++codec.lo: $(TOP)/src/botan/codec.cpp $(HDR) $(TOP)/src/botan/codec.h
++ $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/botan/codec.cpp
++
++codecext.lo: $(TOP)/src/botan/codecext.cpp $(HDR) $(TOP)/src/botan/codec.h
++ $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/botan/codecext.cpp
++
++
+ pager.lo: $(TOP)/src/pager.c $(HDR) $(TOP)/src/pager.h
+ $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/pager.c
+
+--- src/pager.c.orig 2009-10-30 17:01:07.000000000 -0400
++++ src/pager.c 2010-01-21 22:51:53.000000000 -0500
+@@ -5046,7 +5046,7 @@
+ /*
+ ** Set or retrieve the codec for this pager
+ */
+-static void sqlite3PagerSetCodec(
++void sqlite3PagerSetCodec(
+ Pager *pPager,
+ void *(*xCodec)(void*,void*,Pgno,int),
+ void (*xCodecSizeChng)(void*,int,int),
+@@ -5060,7 +5060,7 @@
+ pPager->pCodec = pCodec;
+ pagerReportSize(pPager);
+ }
+-static void *sqlite3PagerGetCodec(Pager *pPager){
++void *sqlite3PagerGetCodec(Pager *pPager){
+ return pPager->pCodec;
+ }
+ #endif
diff --git a/src/wrap/sqlite/test_sqlite.cpp b/src/wrap/sqlite/test_sqlite.cpp
new file mode 100644
index 000000000..8d8cad946
--- /dev/null
+++ b/src/wrap/sqlite/test_sqlite.cpp
@@ -0,0 +1,101 @@
+/*
+ * Quick and dirty test for SQLite3 encryption codec.
+ * (C) 2010 Olivier de Gaalon
+ *
+ * Distributed under the terms of the Botan license
+ */
+
+#include <sqlite3.h>
+#include <stdio.h>
+
+namespace SQL
+{
+ const char * CREATE_TABLE_TEST =
+ "create table 'test' (id INTEGER PRIMARY KEY, name TEXT, creationtime TEXT);";
+ const char * CREATE_TABLE_TEST2 =
+ "create table 'test2' (id INTEGER PRIMARY KEY, name TEXT, creationtime TEXT);";
+ const char * INSERT_INTO_TEST =
+ "INSERT INTO test (name, creationtime) VALUES ('widget', '1st time');\
+ INSERT INTO test (name, creationtime) VALUES ('widget', '2nd time');\
+ INSERT INTO test (name, creationtime) VALUES ('widget', '3rd time');\
+ INSERT INTO test (name, creationtime) VALUES ('widget', '4th time');\
+ INSERT INTO test (name, creationtime) VALUES ('widget', '5th time');";
+ const char * INSERT_INTO_TEST2 =
+ "INSERT INTO test2 (name, creationtime) VALUES ('widget2', '1st time2');\
+ INSERT INTO test2 (name, creationtime) VALUES ('widget2', '2nd time2');\
+ INSERT INTO test2 (name, creationtime) VALUES ('widget2', '3rd time2');\
+ INSERT INTO test2 (name, creationtime) VALUES ('widget2', '4th time2');\
+ INSERT INTO test2 (name, creationtime) VALUES ('widget2', '5th time2');";
+ const char * SELECT_FROM_TEST =
+ "SELECT * FROM test;";
+ const char * SELECT_FROM_TEST2 =
+ "SELECT * FROM test2;";
+};
+
+static int callback(void *NotUsed, int argc, char **argv, char **azColName){
+ int i;
+ fprintf(stderr, "\t");
+ for(i=0; i<argc; i++){
+ fprintf(stderr, "%s = %s | ", azColName[i], argv[i] ? argv[i] : "NULL");
+ }
+ fprintf(stderr, "\n");
+ return 0;
+}
+
+int main(int argc, char** argv)
+{
+ sqlite3 * db;
+ const char * key = "testkey";
+ const char * dbname = "./testdb";
+ int keylen = 7;
+ char * error=0;
+
+ fprintf(stderr, "Creating Database \"%s\"\n", dbname);
+ int rc = sqlite3_open(dbname, &db);
+ if (rc != SQLITE_OK) { fprintf(stderr, "Can't open/create database: %s\n", sqlite3_errmsg(db)); return 1; }
+
+ fprintf(stderr, "Keying Database with key \"%s\"\n", key);
+ rc = sqlite3_key(db, key, keylen);
+ if (rc != SQLITE_OK) { fprintf(stderr, "Can't key database: %s\n", sqlite3_errmsg(db)); return 1; }
+
+ fprintf(stderr, "Creating table \"test\"\n");
+ rc = sqlite3_exec(db, SQL::CREATE_TABLE_TEST, 0, 0, &error);
+ if (rc != SQLITE_OK) { fprintf(stderr, "SQL error: %s\n", error); return 1; }
+
+ fprintf(stderr, "Creating table \"test2\"\n");
+ rc = sqlite3_exec(db, SQL::CREATE_TABLE_TEST2, 0, 0, &error);
+ if (rc != SQLITE_OK) { fprintf(stderr, "SQL error: %s\n", error); return 1; }
+
+ fprintf(stderr, "Inserting into table \"test\"\n");
+ rc = sqlite3_exec(db, SQL::INSERT_INTO_TEST, 0, 0, &error);
+ if (rc != SQLITE_OK) { fprintf(stderr, "SQL error: %s\n", error); return 1; }
+
+ fprintf(stderr, "Inserting into table \"test2\"\n");
+ rc = sqlite3_exec(db, SQL::INSERT_INTO_TEST2, 0, 0, &error);
+ if (rc != SQLITE_OK) { fprintf(stderr, "SQL error: %s\n", error); return 1; }
+
+ fprintf(stderr, "Closing Database \"%s\"\n", dbname);
+ sqlite3_close(db);
+
+ fprintf(stderr, "Opening Database \"%s\"\n", dbname);
+ rc = sqlite3_open(dbname, &db);
+ if (rc != SQLITE_OK) { fprintf(stderr, "Can't open/create database: %s\n", sqlite3_errmsg(db)); return 1; }
+
+ fprintf(stderr, "Keying Database with key \"%s\"\n", key);
+ rc = sqlite3_key(db, key, keylen);
+ if (rc != SQLITE_OK) { fprintf(stderr, "Can't key database: %s\n", sqlite3_errmsg(db)); return 1; }
+
+ fprintf(stderr, "Selecting all from test\n");
+ rc = sqlite3_exec(db, SQL::SELECT_FROM_TEST, callback, 0, &error);
+ if (rc != SQLITE_OK) { fprintf(stderr, "SQL error: %s\n", error); return 1; }
+
+ fprintf(stderr, "Selecting all from test2\n");
+ rc = sqlite3_exec(db, SQL::SELECT_FROM_TEST2, callback, 0, &error);
+ if (rc != SQLITE_OK) { fprintf(stderr, "SQL error: %s\n", error); return 1; }
+
+ fprintf(stderr, "Closing Database \"%s\"\n", dbname);
+ sqlite3_close(db);
+
+ fprintf(stderr, "All Seems Good \n");
+ return 0;
+}