diff options
Diffstat (limited to 'src')
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; +} |