diff options
93 files changed, 676 insertions, 383 deletions
diff --git a/configure.py b/configure.py index 024711a1c..1e91a35e3 100755 --- a/configure.py +++ b/configure.py @@ -40,8 +40,8 @@ class BuildConfigurationInformation(object): """ version_major = 1 version_minor = 9 - version_patch = 5 - version_so_patch = 5 + version_patch = 6 + version_so_patch = 6 version_suffix = '-dev' version_string = '%d.%d.%d%s' % ( @@ -506,6 +506,12 @@ class ModuleInfo(object): def compatible_compiler(self, cc): return self.cc == [] or cc in self.cc + def tr1_ok(self, with_tr1): + if self.uses_tr1: + return with_tr1 in ['boost', 'system'] + else: + return True + def dependencies(self): # utils is an implicit dep (contains types, etc) deps = self.requires + ['utils'] @@ -1022,6 +1028,8 @@ def choose_modules_to_use(modules, archinfo, options): cannot_use_because(modname, 'incompatible OS') elif not module.compatible_compiler(options.compiler): cannot_use_because(modname, 'incompatible compiler') + elif not module.tr1_ok(options.with_tr1): + cannot_use_because(modname, 'missing TR1') else: if module.load_on == 'never': diff --git a/doc/examples/factor.cpp b/doc/examples/factor.cpp index b0105426b..c4d37c92b 100644 --- a/doc/examples/factor.cpp +++ b/doc/examples/factor.cpp @@ -101,7 +101,7 @@ std::vector<BigInt> factorize(const BigInt& n_in, while(n != 1) { - if(is_prime(n, rng)) + if(check_prime(n, rng)) { factors.push_back(n); break; diff --git a/doc/examples/xor_ciph.cpp b/doc/examples/new_engine.cpp index 3174e103e..2f412a6b9 100644 --- a/doc/examples/xor_ciph.cpp +++ b/doc/examples/new_engine.cpp @@ -1,15 +1,13 @@ /* +* Adding an application specific engine * (C) 2004,2008 Jack Lloyd * * Distributed under the terms of the Botan license */ -/* - Adding a simple XOR cipher to the internal tables -*/ - #include <botan/stream_cipher.h> -#include <botan/init.h> +#include <botan/engine.h> + using namespace Botan; class XOR_Cipher : public StreamCipher @@ -25,43 +23,49 @@ class XOR_Cipher : public StreamCipher XOR_Cipher() : StreamCipher(1, 32) { mask_pos = 0; } private: - void cipher(const byte[], byte[], u32bit); - void key_schedule(const byte[], u32bit); + void cipher(const byte in[], byte out[], u32bit length) + { + for(u32bit j = 0; j != length; j++) + { + out[j] = in[j] ^ mask[mask_pos]; + mask_pos = (mask_pos + 1) % mask.size(); + } + } + + void key_schedule(const byte key[], u32bit length) + { + mask.set(key, length); + } SecureVector<byte> mask; u32bit mask_pos; }; -void XOR_Cipher::cipher(const byte in[], byte out[], u32bit length) +class Application_Engine : public Engine { - for(u32bit j = 0; j != length; j++) - { - out[j] = in[j] ^ mask[mask_pos]; - mask_pos = (mask_pos + 1) % mask.size(); - } - } - -void XOR_Cipher::key_schedule(const byte key[], u32bit length) - { - mask.set(key, length); - } + public: + std::string provider_name() const { return "application"; } + + StreamCipher* find_stream_cipher(const SCAN_Name& request, + Algorithm_Factory&) const + { + if(request.algo_name() == "XOR") + return new XOR_Cipher; + return 0; + } + }; -#include <fstream> +#include <botan/botan.h> #include <iostream> #include <string> -#include <vector> -#include <cstring> - -#include <botan/lookup.h> -#include <botan/filters.h> -#include <botan/libstate.h> int main() { Botan::LibraryInitializer init; - global_state().algorithm_factory().add_stream_cipher(new XOR_Cipher, "app"); + global_state().algorithm_factory().add_engine( + new Application_Engine); // a hex key value SymmetricKey key("010203040506070809101112AAFF"); diff --git a/doc/log.txt b/doc/log.txt index 770bfaf5b..89e95aa14 100644 --- a/doc/log.txt +++ b/doc/log.txt @@ -1,10 +1,19 @@ -* 1.9.5-dev, ????-??-?? +* 1.9.6-dev, ????-??-?? + - TLS: Add support for TLS v1.1 + - TLS: Support server name indicator extension + - TLS: Fix server handshake + - TLS: Fix server using DSA certificates + +* 1.9.5, 2010-03-29 - Numerous ECC optimizations - Fix GOST 34.10-2001 X.509 key loading - Allow PK_Signer's fault protection checks to be toggled off - Avoid using pool-based locking allocator if we can't mlock - Remove all runtime options + - New BER_Decoder::{decode_and_check, decode_octet_string_bigint} + - Remove SecureBuffer in favor of SecureVector length parameter + - HMAC_RNG: Perform a poll along with user-supplied entropy - Fix crash in MemoryRegion if Allocator::get failed - Fix small compilation problem on FreeBSD diff --git a/readme.txt b/readme.txt index 3b3729123..c4549912c 100644 --- a/readme.txt +++ b/readme.txt @@ -1,4 +1,4 @@ -Botan 1.9.5-dev, ????-??-?? +Botan 1.9.6-dev, ????-??-?? Botan is a C++ class library for performing a wide variety of cryptographic operations. diff --git a/src/algo_factory/algo_factory.cpp b/src/algo_factory/algo_factory.cpp index 05de330c3..07a072f22 100644 --- a/src/algo_factory/algo_factory.cpp +++ b/src/algo_factory/algo_factory.cpp @@ -83,10 +83,8 @@ const T* factory_prototype(const std::string& algo_spec, /** * Setup caches */ -Algorithm_Factory::Algorithm_Factory(const std::vector<Engine*>& engines_in) +Algorithm_Factory::Algorithm_Factory() { - engines = engines_in; - block_cipher_cache = new Algorithm_Cache<BlockCipher>(); stream_cipher_cache = new Algorithm_Cache<StreamCipher>(); hash_cache = new Algorithm_Cache<HashFunction>(); @@ -107,6 +105,11 @@ Algorithm_Factory::~Algorithm_Factory() delete mac_cache; } +void Algorithm_Factory::add_engine(Engine* engine) + { + engines.push_back(engine); + } + /** * Set the preferred provider for an algorithm */ diff --git a/src/algo_factory/algo_factory.h b/src/algo_factory/algo_factory.h index 8c1c47060..92653ab66 100644 --- a/src/algo_factory/algo_factory.h +++ b/src/algo_factory/algo_factory.h @@ -34,10 +34,9 @@ class BOTAN_DLL Algorithm_Factory public: /** * Constructor - * @param engines_in the list of engines to use * @param mf a mutex factory */ - Algorithm_Factory(const std::vector<Engine*>& engines_in); + Algorithm_Factory(); /** * Destructor @@ -45,6 +44,11 @@ class BOTAN_DLL Algorithm_Factory ~Algorithm_Factory(); /** + * @param engine to add (Algorithm_Factory takes ownership) + */ + void add_engine(class Engine* engine); + + /** * @param algo_spec the algorithm we are querying * @returns list of providers of this algorithm */ diff --git a/src/alloc/secmem.h b/src/alloc/secmem.h index 42b5c7a2d..c50df924d 100644 --- a/src/alloc/secmem.h +++ b/src/alloc/secmem.h @@ -179,11 +179,13 @@ class MemoryRegion void resize(u32bit n); /** - * Preallocate memory, so that this buffer can grow up to size n without - * having to perform any actual memory allocations. (This is - * the same principle as for std::vector::reserve().) + * Change the size to n elements. If n is >= size(), preexisting + * elements remain unchanged, with later elements + * zero-initialized. If n < size(), then the last (size() - N) + * elements are removed. + * @param n the new size */ - void grow_to(u32bit N); + void grow_to(u32bit n); /** * Swap this buffer with another object. @@ -333,11 +335,9 @@ class MemoryVector : public MemoryRegion<T> * This class represents variable length buffers using the operating * systems capability to lock memory, i.e. keeping it from being * swapped out to disk. In this way, a security hole allowing attackers -* to find swapped out secret keys is closed. Please refer to -* Botan::InitializerOptions::secure_memory() for restrictions and -* further details. +* to find swapped out secret keys is closed. */ -template<typename T> +template<typename T, u32bit INITIAL_LEN = 0> class SecureVector : public MemoryRegion<T> { public: @@ -353,7 +353,8 @@ class SecureVector : public MemoryRegion<T> * Create a buffer of the specified length. * @param n the length of the buffer to create. */ - SecureVector(u32bit n = 0) { MemoryRegion<T>::init(true, n); } + SecureVector(u32bit n = INITIAL_LEN) + { MemoryRegion<T>::init(true, n); } /** * Create a buffer with the specified contents. @@ -382,44 +383,6 @@ class SecureVector : public MemoryRegion<T> { MemoryRegion<T>::init(true); set(in1); append(in2); } }; -/** -* This class represents fixed length buffers using the operating -* systems capability to lock memory, i.e. keeping it from being -* swapped out to disk. In this way, a security hole allowing attackers -* to find swapped out secret keys is closed. Please refer to -* Botan::InitializerOptions::secure_memory() for restrictions and -* further details. -*/ -template<typename T, u32bit L> -class SecureBuffer : public MemoryRegion<T> - { - public: - /** - * Copy the contents of another buffer into this buffer. - * @param in the buffer to copy the contents from - * @return a reference to *this - */ - SecureBuffer<T,L>& operator=(const SecureBuffer<T,L>& in) - { if(this != &in) set(in); return (*this); } - - /** - * Create a buffer of the length L. - */ - SecureBuffer() { MemoryRegion<T>::init(true, L); } - - /** - * Create a buffer of size L with the specified contents. - * @param in the array containing the data to be initially copied - * into the newly created buffer - * @param n the size of the array in - */ - SecureBuffer(const T in[], u32bit n) - { MemoryRegion<T>::init(true, L); copy(in, n); } - private: - SecureBuffer<T, L>& operator=(const MemoryRegion<T>& in) - { if(this != &in) set(in); return (*this); } - }; - } #endif diff --git a/src/block/aes/aes.cpp b/src/block/aes/aes.cpp index 721c4ac75..df2674f34 100644 --- a/src/block/aes/aes.cpp +++ b/src/block/aes/aes.cpp @@ -594,7 +594,7 @@ void AES::key_schedule(const byte key[], u32bit length) ROUNDS = (length / 4) + 6; - SecureBuffer<u32bit, 64> XEK, XDK; + SecureVector<u32bit, 64> XEK, XDK; const u32bit X = length / 4; for(u32bit j = 0; j != X; ++j) diff --git a/src/block/aes/aes.h b/src/block/aes/aes.h index 4ff3360de..45026f732 100644 --- a/src/block/aes/aes.h +++ b/src/block/aes/aes.h @@ -33,11 +33,11 @@ class BOTAN_DLL AES : public BlockCipher u32bit ROUNDS; - SecureBuffer<u32bit, 56> EK; - SecureBuffer<byte, 16> ME; + SecureVector<u32bit, 56> EK; + SecureVector<byte, 16> ME; - SecureBuffer<u32bit, 56> DK; - SecureBuffer<byte, 16> MD; + SecureVector<u32bit, 56> DK; + SecureVector<byte, 16> MD; }; /** diff --git a/src/block/aes_intel/aes_intel.h b/src/block/aes_intel/aes_intel.h index 239516e24..a3ebf153b 100644 --- a/src/block/aes_intel/aes_intel.h +++ b/src/block/aes_intel/aes_intel.h @@ -31,7 +31,7 @@ class BOTAN_DLL AES_128_Intel : public BlockCipher private: void key_schedule(const byte[], u32bit); - SecureBuffer<u32bit, 44> EK, DK; + SecureVector<u32bit, 44> EK, DK; }; /** @@ -53,7 +53,7 @@ class BOTAN_DLL AES_192_Intel : public BlockCipher private: void key_schedule(const byte[], u32bit); - SecureBuffer<u32bit, 52> EK, DK; + SecureVector<u32bit, 52> EK, DK; }; /** @@ -75,7 +75,7 @@ class BOTAN_DLL AES_256_Intel : public BlockCipher private: void key_schedule(const byte[], u32bit); - SecureBuffer<u32bit, 60> EK, DK; + SecureVector<u32bit, 60> EK, DK; }; } diff --git a/src/block/blowfish/blowfish.h b/src/block/blowfish/blowfish.h index 5419308ca..2306f0e37 100644 --- a/src/block/blowfish/blowfish.h +++ b/src/block/blowfish/blowfish.h @@ -33,8 +33,8 @@ class BOTAN_DLL Blowfish : public BlockCipher static const u32bit P_INIT[18]; static const u32bit S_INIT[1024]; - SecureBuffer<u32bit, 1024> S; - SecureBuffer<u32bit, 18> P; + SecureVector<u32bit, 1024> S; + SecureVector<u32bit, 18> P; }; } diff --git a/src/block/cast/cast128.cpp b/src/block/cast/cast128.cpp index 887dcf994..cabde4b4f 100644 --- a/src/block/cast/cast128.cpp +++ b/src/block/cast/cast128.cpp @@ -119,7 +119,7 @@ void CAST_128::decrypt_n(const byte in[], byte out[], u32bit blocks) const void CAST_128::key_schedule(const byte key[], u32bit length) { clear(); - SecureBuffer<u32bit, 4> X; + SecureVector<u32bit, 4> X; for(u32bit j = 0; j != length; ++j) X[j/4] = (X[j/4] << 8) + key[j]; @@ -144,7 +144,7 @@ void CAST_128::key_schedule(u32bit K[16], u32bit X[4]) const u32bit* X; }; - SecureBuffer<u32bit, 4> Z; + SecureVector<u32bit, 4> Z; ByteReader x(X), z(Z); Z[0] = X[0] ^ S5[x(13)] ^ S6[x(15)] ^ S7[x(12)] ^ S8[x(14)] ^ S7[x( 8)]; diff --git a/src/block/cast/cast128.h b/src/block/cast/cast128.h index caffb97ea..048d2e43c 100644 --- a/src/block/cast/cast128.h +++ b/src/block/cast/cast128.h @@ -36,7 +36,7 @@ class BOTAN_DLL CAST_128 : public BlockCipher static const u32bit S7[256]; static const u32bit S8[256]; - SecureBuffer<u32bit, 16> MK, RK; + SecureVector<u32bit, 16> MK, RK; }; extern const u32bit CAST_SBOX1[256]; diff --git a/src/block/cast/cast256.cpp b/src/block/cast/cast256.cpp index 7a4a4e805..8aaf8009f 100644 --- a/src/block/cast/cast256.cpp +++ b/src/block/cast/cast256.cpp @@ -138,7 +138,7 @@ void CAST_256::decrypt_n(const byte in[], byte out[], u32bit blocks) const */ void CAST_256::key_schedule(const byte key[], u32bit length) { - SecureBuffer<u32bit, 8> TMP; + SecureVector<u32bit, 8> TMP; for(u32bit j = 0; j != length; ++j) TMP[j/4] = (TMP[j/4] << 8) + key[j]; diff --git a/src/block/cast/cast256.h b/src/block/cast/cast256.h index 0db3682ba..170d94e77 100644 --- a/src/block/cast/cast256.h +++ b/src/block/cast/cast256.h @@ -32,8 +32,8 @@ class BOTAN_DLL CAST_256 : public BlockCipher static const u32bit KEY_MASK[192]; static const byte KEY_ROT[32]; - SecureBuffer<u32bit, 48> MK; - SecureBuffer<byte, 48> RK; + SecureVector<u32bit, 48> MK; + SecureVector<byte, 48> RK; }; extern const u32bit CAST_SBOX1[256]; diff --git a/src/block/des/des.h b/src/block/des/des.h index b28990178..32dd3daf6 100644 --- a/src/block/des/des.h +++ b/src/block/des/des.h @@ -29,7 +29,7 @@ class BOTAN_DLL DES : public BlockCipher private: void key_schedule(const byte[], u32bit); - SecureBuffer<u32bit, 32> round_key; + SecureVector<u32bit, 32> round_key; }; /* @@ -49,7 +49,7 @@ class BOTAN_DLL TripleDES : public BlockCipher private: void key_schedule(const byte[], u32bit); - SecureBuffer<u32bit, 96> round_key; + SecureVector<u32bit, 96> round_key; }; /* diff --git a/src/block/des/desx.h b/src/block/des/desx.h index 89664d064..440574e9d 100644 --- a/src/block/des/desx.h +++ b/src/block/des/desx.h @@ -28,7 +28,7 @@ class BOTAN_DLL DESX : public BlockCipher DESX() : BlockCipher(8, 24) {} private: void key_schedule(const byte[], u32bit); - SecureBuffer<byte, 8> K1, K2; + SecureVector<byte, 8> K1, K2; DES des; }; diff --git a/src/block/gost_28147/gost_28147.h b/src/block/gost_28147/gost_28147.h index 2b7daaf6a..2ccb3214d 100644 --- a/src/block/gost_28147/gost_28147.h +++ b/src/block/gost_28147/gost_28147.h @@ -52,13 +52,13 @@ class BOTAN_DLL GOST_28147_89 : public BlockCipher GOST_28147_89(const GOST_28147_89_Params& params); private: - GOST_28147_89(const SecureBuffer<u32bit, 1024>& other_SBOX) : + GOST_28147_89(const SecureVector<u32bit, 1024>& other_SBOX) : BlockCipher(8, 32), SBOX(other_SBOX) {} void key_schedule(const byte[], u32bit); - SecureBuffer<u32bit, 1024> SBOX; - SecureBuffer<u32bit, 8> EK; + SecureVector<u32bit, 1024> SBOX; + SecureVector<u32bit, 8> EK; }; } diff --git a/src/block/idea/idea.h b/src/block/idea/idea.h index 89ec117e3..1a9644d4e 100644 --- a/src/block/idea/idea.h +++ b/src/block/idea/idea.h @@ -28,7 +28,7 @@ class BOTAN_DLL IDEA : public BlockCipher IDEA() : BlockCipher(8, 16) {} protected: void key_schedule(const byte[], u32bit); - SecureBuffer<u16bit, 52> EK, DK; + SecureVector<u16bit, 52> EK, DK; }; } diff --git a/src/block/kasumi/kasumi.cpp b/src/block/kasumi/kasumi.cpp index dff6db13c..d7f981b20 100644 --- a/src/block/kasumi/kasumi.cpp +++ b/src/block/kasumi/kasumi.cpp @@ -204,7 +204,7 @@ void KASUMI::key_schedule(const byte key[], u32bit) static const u16bit RC[] = { 0x0123, 0x4567, 0x89AB, 0xCDEF, 0xFEDC, 0xBA98, 0x7654, 0x3210 }; - SecureBuffer<u16bit, 16> K; + SecureVector<u16bit, 16> K; for(u32bit j = 0; j != 8; ++j) { K[j] = load_be<u16bit>(key, j); diff --git a/src/block/kasumi/kasumi.h b/src/block/kasumi/kasumi.h index c3db1cb05..827989a57 100644 --- a/src/block/kasumi/kasumi.h +++ b/src/block/kasumi/kasumi.h @@ -29,7 +29,7 @@ class BOTAN_DLL KASUMI : public BlockCipher private: void key_schedule(const byte[], u32bit); - SecureBuffer<u16bit, 64> EK; + SecureVector<u16bit, 64> EK; }; } diff --git a/src/block/mars/mars.cpp b/src/block/mars/mars.cpp index 6b73ea054..57a224fac 100644 --- a/src/block/mars/mars.cpp +++ b/src/block/mars/mars.cpp @@ -320,7 +320,7 @@ void MARS::decrypt_n(const byte in[], byte out[], u32bit blocks) const */ void MARS::key_schedule(const byte key[], u32bit length) { - SecureBuffer<u32bit, 15> T; + SecureVector<u32bit, 15> T; for(u32bit j = 0; j != length / 4; ++j) T[j] = load_le<u32bit>(key, j); T[length / 4] = length / 4; diff --git a/src/block/mars/mars.h b/src/block/mars/mars.h index 7a598d2bd..f2a6d0197 100644 --- a/src/block/mars/mars.h +++ b/src/block/mars/mars.h @@ -26,7 +26,7 @@ class BOTAN_DLL MARS : public BlockCipher private: void key_schedule(const byte[], u32bit); - SecureBuffer<u32bit, 40> EK; + SecureVector<u32bit, 40> EK; }; } diff --git a/src/block/misty1/misty1.cpp b/src/block/misty1/misty1.cpp index 56cd7446c..bc85d71f9 100644 --- a/src/block/misty1/misty1.cpp +++ b/src/block/misty1/misty1.cpp @@ -204,7 +204,7 @@ void MISTY1::decrypt_n(const byte in[], byte out[], u32bit blocks) const */ void MISTY1::key_schedule(const byte key[], u32bit length) { - SecureBuffer<u16bit, 32> KS; + SecureVector<u16bit, 32> KS; for(u32bit j = 0; j != length / 2; ++j) KS[j] = load_be<u16bit>(key, j); diff --git a/src/block/misty1/misty1.h b/src/block/misty1/misty1.h index 000830915..7b4d91def 100644 --- a/src/block/misty1/misty1.h +++ b/src/block/misty1/misty1.h @@ -29,7 +29,7 @@ class BOTAN_DLL MISTY1 : public BlockCipher private: void key_schedule(const byte[], u32bit); - SecureBuffer<u16bit, 100> EK, DK; + SecureVector<u16bit, 100> EK, DK; }; } diff --git a/src/block/noekeon/noekeon.h b/src/block/noekeon/noekeon.h index 22ef65342..abeecbc64 100644 --- a/src/block/noekeon/noekeon.h +++ b/src/block/noekeon/noekeon.h @@ -31,7 +31,7 @@ class BOTAN_DLL Noekeon : public BlockCipher static const byte RC[17]; - SecureBuffer<u32bit, 4> EK, DK; + SecureVector<u32bit, 4> EK, DK; }; } diff --git a/src/block/rc2/rc2.cpp b/src/block/rc2/rc2.cpp index b5e4a7d50..3114c6055 100644 --- a/src/block/rc2/rc2.cpp +++ b/src/block/rc2/rc2.cpp @@ -124,7 +124,7 @@ void RC2::key_schedule(const byte key[], u32bit length) 0xC5, 0xF3, 0xDB, 0x47, 0xE5, 0xA5, 0x9C, 0x77, 0x0A, 0xA6, 0x20, 0x68, 0xFE, 0x7F, 0xC1, 0xAD }; - SecureBuffer<byte, 128> L; + SecureVector<byte, 128> L; L.copy(key, length); for(u32bit j = length; j != 128; ++j) diff --git a/src/block/rc2/rc2.h b/src/block/rc2/rc2.h index c6e4946f9..dd0295572 100644 --- a/src/block/rc2/rc2.h +++ b/src/block/rc2/rc2.h @@ -31,7 +31,7 @@ class BOTAN_DLL RC2 : public BlockCipher private: void key_schedule(const byte[], u32bit); - SecureBuffer<u16bit, 64> K; + SecureVector<u16bit, 64> K; }; } diff --git a/src/block/rc5/rc5.cpp b/src/block/rc5/rc5.cpp index 1b71de85a..6c712db9a 100644 --- a/src/block/rc5/rc5.cpp +++ b/src/block/rc5/rc5.cpp @@ -82,7 +82,7 @@ void RC5::key_schedule(const byte key[], u32bit length) for(u32bit j = 1; j != S.size(); ++j) S[j] = S[j-1] + 0x9E3779B9; - SecureBuffer<u32bit, 8> K; + SecureVector<u32bit, 8> K; for(s32bit j = length-1; j >= 0; --j) K[j/4] = (K[j/4] << 8) + key[j]; for(u32bit j = 0, A = 0, B = 0; j != MIX_ROUNDS; ++j) diff --git a/src/block/rc6/rc6.cpp b/src/block/rc6/rc6.cpp index 8bda62259..ff846f006 100644 --- a/src/block/rc6/rc6.cpp +++ b/src/block/rc6/rc6.cpp @@ -119,7 +119,7 @@ void RC6::key_schedule(const byte key[], u32bit length) for(u32bit j = 1; j != S.size(); ++j) S[j] = S[j-1] + 0x9E3779B9; - SecureBuffer<u32bit, 8> K; + SecureVector<u32bit, 8> K; for(s32bit j = length-1; j >= 0; --j) K[j/4] = (K[j/4] << 8) + key[j]; for(u32bit j = 0, A = 0, B = 0; j != MIX_ROUNDS; ++j) diff --git a/src/block/rc6/rc6.h b/src/block/rc6/rc6.h index 6cd0f54db..cc1534ee2 100644 --- a/src/block/rc6/rc6.h +++ b/src/block/rc6/rc6.h @@ -29,7 +29,7 @@ class BOTAN_DLL RC6 : public BlockCipher private: void key_schedule(const byte[], u32bit); - SecureBuffer<u32bit, 44> S; + SecureVector<u32bit, 44> S; }; } diff --git a/src/block/safer/safer_sk.cpp b/src/block/safer/safer_sk.cpp index fcbe84c8b..84ad9523b 100644 --- a/src/block/safer/safer_sk.cpp +++ b/src/block/safer/safer_sk.cpp @@ -91,7 +91,7 @@ void SAFER_SK::decrypt_n(const byte in[], byte out[], u32bit blocks) const */ void SAFER_SK::key_schedule(const byte key[], u32bit) { - SecureBuffer<byte, 18> KB; + SecureVector<byte, 18> KB; for(u32bit j = 0; j != 8; ++j) { diff --git a/src/block/seed/seed.cpp b/src/block/seed/seed.cpp index 378be16e4..651233bdb 100644 --- a/src/block/seed/seed.cpp +++ b/src/block/seed/seed.cpp @@ -111,7 +111,7 @@ void SEED::key_schedule(const byte key[], u32bit) 0x779B99E3, 0xEF3733C6, 0xDE6E678D, 0xBCDCCF1B }; - SecureBuffer<u32bit, 4> WK; + SecureVector<u32bit, 4> WK; for(u32bit j = 0; j != 4; ++j) WK[j] = load_be<u32bit>(key, j); diff --git a/src/block/seed/seed.h b/src/block/seed/seed.h index 5a4b44057..e56b77dbb 100644 --- a/src/block/seed/seed.h +++ b/src/block/seed/seed.h @@ -37,7 +37,7 @@ class BOTAN_DLL SEED : public BlockCipher static const u32bit S0[256], S1[256], S2[256], S3[256]; }; - SecureBuffer<u32bit, 32> K; + SecureVector<u32bit, 32> K; }; } diff --git a/src/block/serpent/serpent.cpp b/src/block/serpent/serpent.cpp index e16afc89c..b93326e58 100644 --- a/src/block/serpent/serpent.cpp +++ b/src/block/serpent/serpent.cpp @@ -355,7 +355,7 @@ void Serpent::key_schedule(const byte key[], u32bit length) { const u32bit PHI = 0x9E3779B9; - SecureBuffer<u32bit, 140> W; + SecureVector<u32bit, 140> W; for(u32bit j = 0; j != length / 4; ++j) W[j] = load_le<u32bit>(key, j); diff --git a/src/block/serpent/serpent.h b/src/block/serpent/serpent.h index 4fa7451b9..37ce10c7b 100644 --- a/src/block/serpent/serpent.h +++ b/src/block/serpent/serpent.h @@ -28,7 +28,7 @@ class BOTAN_DLL Serpent : public BlockCipher protected: void key_schedule(const byte[], u32bit); - SecureBuffer<u32bit, 132> round_key; + SecureVector<u32bit, 132> round_key; }; } diff --git a/src/block/serpent_ia32/serp_ia32.cpp b/src/block/serpent_ia32/serp_ia32.cpp index 721584b18..ff454ab4c 100644 --- a/src/block/serpent_ia32/serp_ia32.cpp +++ b/src/block/serpent_ia32/serp_ia32.cpp @@ -49,7 +49,7 @@ void Serpent_IA32::decrypt_n(const byte in[], byte out[], u32bit blocks) const */ void Serpent_IA32::key_schedule(const byte key[], u32bit length) { - SecureBuffer<u32bit, 140> W; + SecureVector<u32bit, 140> W; for(u32bit j = 0; j != length / 4; ++j) W[j] = load_le<u32bit>(key, j); W[length / 4] |= u32bit(1) << ((length%4)*8); diff --git a/src/block/skipjack/skipjack.h b/src/block/skipjack/skipjack.h index b701e2091..d481aee08 100644 --- a/src/block/skipjack/skipjack.h +++ b/src/block/skipjack/skipjack.h @@ -29,7 +29,7 @@ class BOTAN_DLL Skipjack : public BlockCipher private: void key_schedule(const byte[], u32bit); - SecureBuffer<byte, 2560> FTAB; + SecureVector<byte, 2560> FTAB; }; } diff --git a/src/block/square/square.cpp b/src/block/square/square.cpp index 892568655..adcf18611 100644 --- a/src/block/square/square.cpp +++ b/src/block/square/square.cpp @@ -140,7 +140,7 @@ void Square::decrypt_n(const byte in[], byte out[], u32bit blocks) const */ void Square::key_schedule(const byte key[], u32bit) { - SecureBuffer<u32bit, 36> XEK, XDK; + SecureVector<u32bit, 36> XEK, XDK; for(u32bit i = 0; i != 4; ++i) XEK[i] = load_be<u32bit>(key, i); diff --git a/src/block/square/square.h b/src/block/square/square.h index 088122181..8e1f7f815 100644 --- a/src/block/square/square.h +++ b/src/block/square/square.h @@ -45,8 +45,8 @@ class BOTAN_DLL Square : public BlockCipher static const u32bit TD2[256]; static const u32bit TD3[256]; - SecureBuffer<u32bit, 28> EK, DK; - SecureBuffer<byte, 32> ME, MD; + SecureVector<u32bit, 28> EK, DK; + SecureVector<byte, 32> ME, MD; }; } diff --git a/src/block/tea/tea.h b/src/block/tea/tea.h index c19f272a6..152c9a905 100644 --- a/src/block/tea/tea.h +++ b/src/block/tea/tea.h @@ -28,7 +28,7 @@ class BOTAN_DLL TEA : public BlockCipher TEA() : BlockCipher(8, 16) {} private: void key_schedule(const byte[], u32bit); - SecureBuffer<u32bit, 4> K; + SecureVector<u32bit, 4> K; }; } diff --git a/src/block/twofish/twofish.cpp b/src/block/twofish/twofish.cpp index 3136837aa..a183821b2 100644 --- a/src/block/twofish/twofish.cpp +++ b/src/block/twofish/twofish.cpp @@ -118,7 +118,7 @@ void Twofish::decrypt_n(const byte in[], byte out[], u32bit blocks) const */ void Twofish::key_schedule(const byte key[], u32bit length) { - SecureBuffer<byte, 16> S; + SecureVector<byte, 16> S; for(u32bit j = 0; j != length; ++j) rs_mul(S + 4*(j/8), key[j], j); diff --git a/src/block/twofish/twofish.h b/src/block/twofish/twofish.h index 71a1e8781..7600abca8 100644 --- a/src/block/twofish/twofish.h +++ b/src/block/twofish/twofish.h @@ -41,8 +41,8 @@ class BOTAN_DLL Twofish : public BlockCipher static const byte EXP_TO_POLY[255]; static const byte POLY_TO_EXP[255]; - SecureBuffer<u32bit, 256> SBox0, SBox1, SBox2, SBox3; - SecureBuffer<u32bit, 40> round_key; + SecureVector<u32bit, 256> SBox0, SBox1, SBox2, SBox3; + SecureVector<u32bit, 40> round_key; }; } diff --git a/src/block/xtea/xtea.cpp b/src/block/xtea/xtea.cpp index fc14c0a57..bb1a30374 100644 --- a/src/block/xtea/xtea.cpp +++ b/src/block/xtea/xtea.cpp @@ -121,7 +121,7 @@ void XTEA::decrypt_n(const byte in[], byte out[], u32bit blocks) const */ void XTEA::key_schedule(const byte key[], u32bit) { - SecureBuffer<u32bit, 4> UK; + SecureVector<u32bit, 4> UK; for(u32bit i = 0; i != 4; ++i) UK[i] = load_be<u32bit>(key, i); diff --git a/src/block/xtea/xtea.h b/src/block/xtea/xtea.h index 9982d0712..940992dfa 100644 --- a/src/block/xtea/xtea.h +++ b/src/block/xtea/xtea.h @@ -28,7 +28,7 @@ class BOTAN_DLL XTEA : public BlockCipher XTEA() : BlockCipher(8, 16) {} protected: void key_schedule(const byte[], u32bit); - SecureBuffer<u32bit, 64> EK; + SecureVector<u32bit, 64> EK; }; } diff --git a/src/filters/base64/base64.cpp b/src/filters/base64/base64.cpp index 9110dc57e..e342f7109 100644 --- a/src/filters/base64/base64.cpp +++ b/src/filters/base64/base64.cpp @@ -107,7 +107,7 @@ void Base64_Encoder::end_msg() if(left_over) { - SecureBuffer<byte, 3> remainder(in + start_of_last_block, left_over); + SecureVector<byte, 3> remainder(in + start_of_last_block, left_over); encode(remainder, out); @@ -217,7 +217,7 @@ void Base64_Decoder::end_msg() if(left_over) { - SecureBuffer<byte, 4> remainder(in + start_of_last_block, left_over); + SecureVector<byte, 4> remainder(in + start_of_last_block, left_over); decode(remainder, out); send(out, ((left_over == 1) ? (1) : (left_over - 1))); } diff --git a/src/filters/secqueue.cpp b/src/filters/secqueue.cpp index f63ef898c..c8d1c5fbf 100644 --- a/src/filters/secqueue.cpp +++ b/src/filters/secqueue.cpp @@ -44,7 +44,7 @@ class SecureQueueNode private: friend class SecureQueue; SecureQueueNode* next; - SecureBuffer<byte, DEFAULT_BUFFERSIZE> buffer; + SecureVector<byte, DEFAULT_BUFFERSIZE> buffer; u32bit start, end; }; diff --git a/src/hash/bmw/bmw_512.h b/src/hash/bmw/bmw_512.h index 8130a88e4..c1c5238bd 100644 --- a/src/hash/bmw/bmw_512.h +++ b/src/hash/bmw/bmw_512.h @@ -23,8 +23,8 @@ class BOTAN_DLL BMW_512 : public MDx_HashFunction void compress_n(const byte input[], u32bit blocks); void copy_out(byte output[]); - SecureBuffer<u64bit, 16> H, M; - SecureBuffer<u64bit, 32> Q; + SecureVector<u64bit, 16> H, M; + SecureVector<u64bit, 32> Q; }; } diff --git a/src/hash/fork256/fork256.h b/src/hash/fork256/fork256.h index f535370e6..ed945b9d8 100644 --- a/src/hash/fork256/fork256.h +++ b/src/hash/fork256/fork256.h @@ -26,8 +26,8 @@ class BOTAN_DLL FORK_256 : public MDx_HashFunction void compress_n(const byte[], u32bit blocks); void copy_out(byte[]); - SecureBuffer<u32bit, 8> digest; - SecureBuffer<u32bit, 16> M; + SecureVector<u32bit, 8> digest; + SecureVector<u32bit, 16> M; }; } diff --git a/src/hash/gost_3411/gost_3411.cpp b/src/hash/gost_3411/gost_3411.cpp index 244a3fddf..f09b0fc60 100644 --- a/src/hash/gost_3411/gost_3411.cpp +++ b/src/hash/gost_3411/gost_3411.cpp @@ -223,11 +223,11 @@ void GOST_34_11::final_result(byte out[]) compress_n(buffer, 1); } - SecureBuffer<byte, 32> length_buf; + SecureVector<byte, 32> length_buf; const u64bit bit_count = count * 8; store_le(bit_count, length_buf); - SecureBuffer<byte, 32> sum_buf(sum); + SecureVector<byte, 32> sum_buf(sum); compress_n(length_buf, 1); compress_n(sum_buf, 1); diff --git a/src/hash/gost_3411/gost_3411.h b/src/hash/gost_3411/gost_3411.h index 7b17bdc1f..d2bada7ab 100644 --- a/src/hash/gost_3411/gost_3411.h +++ b/src/hash/gost_3411/gost_3411.h @@ -31,9 +31,9 @@ class BOTAN_DLL GOST_34_11 : public HashFunction void final_result(byte[]); GOST_28147_89 cipher; - SecureBuffer<byte, 32> buffer; - SecureBuffer<byte, 32> sum; - SecureBuffer<byte, 32> hash; + SecureVector<byte, 32> buffer; + SecureVector<byte, 32> sum; + SecureVector<byte, 32> hash; u64bit count; u32bit position; }; diff --git a/src/hash/has160/has160.h b/src/hash/has160/has160.h index cae66c93a..210145484 100644 --- a/src/hash/has160/has160.h +++ b/src/hash/has160/has160.h @@ -26,8 +26,8 @@ class BOTAN_DLL HAS_160 : public MDx_HashFunction void compress_n(const byte[], u32bit blocks); void copy_out(byte[]); - SecureBuffer<u32bit, 20> X; - SecureBuffer<u32bit, 5> digest; + SecureVector<u32bit, 20> X; + SecureVector<u32bit, 5> digest; }; } diff --git a/src/hash/md2/md2.h b/src/hash/md2/md2.h index 0a7125759..df056dc12 100644 --- a/src/hash/md2/md2.h +++ b/src/hash/md2/md2.h @@ -27,8 +27,8 @@ class BOTAN_DLL MD2 : public HashFunction void hash(const byte[]); void final_result(byte[]); - SecureBuffer<byte, 48> X; - SecureBuffer<byte, 16> checksum, buffer; + SecureVector<byte, 48> X; + SecureVector<byte, 16> checksum, buffer; u32bit position; }; diff --git a/src/hash/md4/md4.h b/src/hash/md4/md4.h index 0bff5a4ce..843727f6d 100644 --- a/src/hash/md4/md4.h +++ b/src/hash/md4/md4.h @@ -27,8 +27,8 @@ class BOTAN_DLL MD4 : public MDx_HashFunction void hash_old(const byte[]); void copy_out(byte[]); - SecureBuffer<u32bit, 16> M; - SecureBuffer<u32bit, 4> digest; + SecureVector<u32bit, 16> M; + SecureVector<u32bit, 4> digest; }; } diff --git a/src/hash/md5/md5.h b/src/hash/md5/md5.h index 456a02c28..d1f294a87 100644 --- a/src/hash/md5/md5.h +++ b/src/hash/md5/md5.h @@ -26,8 +26,8 @@ class BOTAN_DLL MD5 : public MDx_HashFunction void compress_n(const byte[], u32bit blocks); void copy_out(byte[]); - SecureBuffer<u32bit, 16> M; - SecureBuffer<u32bit, 4> digest; + SecureVector<u32bit, 16> M; + SecureVector<u32bit, 4> digest; }; } diff --git a/src/hash/rmd128/rmd128.h b/src/hash/rmd128/rmd128.h index d9cb4ebb4..9ae43483c 100644 --- a/src/hash/rmd128/rmd128.h +++ b/src/hash/rmd128/rmd128.h @@ -26,8 +26,8 @@ class BOTAN_DLL RIPEMD_128 : public MDx_HashFunction void compress_n(const byte[], u32bit blocks); void copy_out(byte[]); - SecureBuffer<u32bit, 16> M; - SecureBuffer<u32bit, 4> digest; + SecureVector<u32bit, 16> M; + SecureVector<u32bit, 4> digest; }; } diff --git a/src/hash/rmd160/rmd160.h b/src/hash/rmd160/rmd160.h index aee007b98..399d5a7c3 100644 --- a/src/hash/rmd160/rmd160.h +++ b/src/hash/rmd160/rmd160.h @@ -26,8 +26,8 @@ class BOTAN_DLL RIPEMD_160 : public MDx_HashFunction void compress_n(const byte[], u32bit blocks); void copy_out(byte[]); - SecureBuffer<u32bit, 16> M; - SecureBuffer<u32bit, 5> digest; + SecureVector<u32bit, 16> M; + SecureVector<u32bit, 5> digest; }; } diff --git a/src/hash/sha1/sha160.h b/src/hash/sha1/sha160.h index 142c6bf17..cb7e63821 100644 --- a/src/hash/sha1/sha160.h +++ b/src/hash/sha1/sha160.h @@ -29,7 +29,7 @@ class BOTAN_DLL SHA_160 : public MDx_HashFunction void compress_n(const byte[], u32bit blocks); void copy_out(byte[]); - SecureBuffer<u32bit, 5> digest; + SecureVector<u32bit, 5> digest; SecureVector<u32bit> W; }; diff --git a/src/hash/sha2/sha2_32.h b/src/hash/sha2/sha2_32.h index 313eec676..e157fd657 100644 --- a/src/hash/sha2/sha2_32.h +++ b/src/hash/sha2/sha2_32.h @@ -23,8 +23,8 @@ class BOTAN_DLL SHA_224_256_BASE : public MDx_HashFunction SHA_224_256_BASE(u32bit out) : MDx_HashFunction(out, 64, true, true) { clear(); } - SecureBuffer<u32bit, 64> W; - SecureBuffer<u32bit, 8> digest; + SecureVector<u32bit, 64> W; + SecureVector<u32bit, 8> digest; private: void compress_n(const byte[], u32bit blocks); void copy_out(byte[]); diff --git a/src/hash/sha2/sha2_64.h b/src/hash/sha2/sha2_64.h index 8e4d171f8..ed261b1c2 100644 --- a/src/hash/sha2/sha2_64.h +++ b/src/hash/sha2/sha2_64.h @@ -23,12 +23,12 @@ class BOTAN_DLL SHA_384_512_BASE : public MDx_HashFunction SHA_384_512_BASE(u32bit out) : MDx_HashFunction(out, 128, true, true, 16) {} - SecureBuffer<u64bit, 8> digest; + SecureVector<u64bit, 8> digest; private: void compress_n(const byte[], u32bit blocks); void copy_out(byte[]); - SecureBuffer<u64bit, 80> W; + SecureVector<u64bit, 80> W; }; /* diff --git a/src/hash/skein/skein_512.cpp b/src/hash/skein/skein_512.cpp index 869257567..42fc4ba37 100644 --- a/src/hash/skein/skein_512.cpp +++ b/src/hash/skein/skein_512.cpp @@ -234,7 +234,7 @@ void Skein_512::final_result(byte out[]) u32bit out_bytes = output_bits / 8; - SecureBuffer<u64bit, 9> H_out; + SecureVector<u64bit, 9> H_out; while(out_bytes) { diff --git a/src/hash/skein/skein_512.h b/src/hash/skein/skein_512.h index db8d3c8b7..222db5d68 100644 --- a/src/hash/skein/skein_512.h +++ b/src/hash/skein/skein_512.h @@ -29,10 +29,10 @@ class BOTAN_DLL Skein_512 : public HashFunction std::string personalization; u32bit output_bits; - SecureBuffer<u64bit, 9> H; - SecureBuffer<u64bit, 3> T; + SecureVector<u64bit, 9> H; + SecureVector<u64bit, 3> T; - SecureBuffer<byte, 64> buffer; + SecureVector<byte, 64> buffer; u32bit buf_pos; }; diff --git a/src/hash/tiger/tiger.h b/src/hash/tiger/tiger.h index 20dcf99ff..918e2de3c 100644 --- a/src/hash/tiger/tiger.h +++ b/src/hash/tiger/tiger.h @@ -33,8 +33,8 @@ class BOTAN_DLL Tiger : public MDx_HashFunction static const u64bit SBOX3[256]; static const u64bit SBOX4[256]; - SecureBuffer<u64bit, 8> X; - SecureBuffer<u64bit, 3> digest; + SecureVector<u64bit, 8> X; + SecureVector<u64bit, 3> digest; const u32bit PASS; }; diff --git a/src/hash/whirlpool/whrlpool.h b/src/hash/whirlpool/whrlpool.h index 34b4d2302..4711fafa3 100644 --- a/src/hash/whirlpool/whrlpool.h +++ b/src/hash/whirlpool/whrlpool.h @@ -34,7 +34,7 @@ class BOTAN_DLL Whirlpool : public MDx_HashFunction static const u64bit C5[256]; static const u64bit C6[256]; static const u64bit C7[256]; - SecureBuffer<u64bit, 8> M, digest; + SecureVector<u64bit, 8> M, digest; }; } diff --git a/src/libstate/libstate.cpp b/src/libstate/libstate.cpp index 943a7c2e6..e37617c94 100644 --- a/src/libstate/libstate.cpp +++ b/src/libstate/libstate.cpp @@ -237,36 +237,33 @@ void Library_State::initialize() load_default_config(); - std::vector<Engine*> engines = { + m_algorithm_factory = new Algorithm_Factory(*mutex_factory); #if defined(BOTAN_HAS_ENGINE_GNU_MP) - new GMP_Engine, + algorithm_factory().add_engine(new GMP_Engine); #endif #if defined(BOTAN_HAS_ENGINE_OPENSSL) - new OpenSSL_Engine, + algorithm_factory().add_engine(new OpenSSL_Engine); #endif #if defined(BOTAN_HAS_ENGINE_AES_ISA) - new AES_ISA_Engine, + algorithm_factory().add_engine(new AES_ISA_Engine); #endif #if defined(BOTAN_HAS_ENGINE_SIMD) - new SIMD_Engine, + algorithm_factory().add_engine(new SIMD_Engine); #endif #if defined(BOTAN_HAS_ENGINE_AMD64_ASSEMBLER) - new AMD64_Assembler_Engine, + algorithm_factory().add_engine(new AMD64_Assembler_Engine); #endif #if defined(BOTAN_HAS_ENGINE_IA32_ASSEMBLER) - new IA32_Assembler_Engine, + algorithm_factory().add_engine(new IA32_Assembler_Engine); #endif - new Default_Engine - }; - - m_algorithm_factory = new Algorithm_Factory(engines); + algorithm_factory().add_engine(new Default_Engine); #if defined(BOTAN_HAS_SELFTESTS) confirm_startup_self_tests(algorithm_factory()); @@ -280,6 +277,8 @@ Library_State::Library_State() { cached_default_allocator = 0; m_algorithm_factory = 0; + + global_rng_ptr = 0; } /* @@ -290,6 +289,10 @@ Library_State::~Library_State() delete m_algorithm_factory; m_algorithm_factory = 0; + delete global_rng_ptr; + global_rng_ptr = 0; + + cached_default_allocator = 0; for(u32bit j = 0; j != allocators.size(); ++j) diff --git a/src/mac/x919_mac/x919_mac.h b/src/mac/x919_mac/x919_mac.h index a4690fdcd..abd149ecd 100644 --- a/src/mac/x919_mac/x919_mac.h +++ b/src/mac/x919_mac/x919_mac.h @@ -32,7 +32,7 @@ class BOTAN_DLL ANSI_X919_MAC : public MessageAuthenticationCode BlockCipher* e; BlockCipher* d; - SecureBuffer<byte, 8> state; + SecureVector<byte, 8> state; u32bit position; }; diff --git a/src/rng/auto_rng/auto_rng.h b/src/rng/auto_rng/auto_rng.h index 9a93fee8f..90f342a50 100644 --- a/src/rng/auto_rng/auto_rng.h +++ b/src/rng/auto_rng/auto_rng.h @@ -35,7 +35,6 @@ class BOTAN_DLL AutoSeeded_RNG : public RandomNumberGenerator { rng->add_entropy(in, len); } AutoSeeded_RNG() { rng = &global_state().global_rng(); } - ~AutoSeeded_RNG() { delete rng; } private: RandomNumberGenerator* rng; }; diff --git a/src/ssl/c_kex.cpp b/src/ssl/c_kex.cpp index 9e59beefc..e09e18ce1 100644 --- a/src/ssl/c_kex.cpp +++ b/src/ssl/c_kex.cpp @@ -6,6 +6,7 @@ */ #include <botan/tls_messages.h> +#include <botan/internal/tls_reader.h> #include <botan/pubkey.h> #include <botan/dh.h> #include <botan/rsa.h> @@ -99,14 +100,8 @@ void Client_Key_Exchange::deserialize(const MemoryRegion<byte>& buf) { if(include_length) { - if(buf.size() < 2) - throw Decoding_Error("Client_Key_Exchange: Packet corrupted"); - - u32bit size = make_u16bit(buf[0], buf[1]); - if(size + 2 != buf.size()) - throw Decoding_Error("Client_Key_Exchange: Packet corrupted"); - - key_material.set(buf + 2, size); + TLS_Data_Reader reader(buf); + key_material = reader.get_range<byte>(2, 0, 65535); } else key_material = buf; diff --git a/src/ssl/cert_ver.cpp b/src/ssl/cert_ver.cpp index 0bf6c85be..3edf4266d 100644 --- a/src/ssl/cert_ver.cpp +++ b/src/ssl/cert_ver.cpp @@ -6,6 +6,7 @@ */ #include <botan/tls_messages.h> +#include <botan/internal/tls_reader.h> #include <botan/pubkey.h> #include <botan/rsa.h> #include <botan/dsa.h> @@ -62,14 +63,8 @@ SecureVector<byte> Certificate_Verify::serialize() const */ void Certificate_Verify::deserialize(const MemoryRegion<byte>& buf) { - if(buf.size() < 2) - throw Decoding_Error("Certificate_Verify: Corrupted packet"); - - u32bit sig_len = make_u16bit(buf[0], buf[1]); - if(buf.size() != 2 + sig_len) - throw Decoding_Error("Certificate_Verify: Corrupted packet"); - - signature.set(buf + 2, sig_len); + TLS_Data_Reader reader(buf); + signature = reader.get_range<byte>(2, 0, 65535); } /** diff --git a/src/ssl/finished.cpp b/src/ssl/finished.cpp index edbd4a3fe..b0f6abd25 100644 --- a/src/ssl/finished.cpp +++ b/src/ssl/finished.cpp @@ -72,7 +72,7 @@ SecureVector<byte> Finished::compute_verify(const MemoryRegion<byte>& secret, return hash.final_ssl3(secret); } - else if(version == TLS_V10) + else if(version == TLS_V10 || version == TLS_V11) { const byte TLS_CLIENT_LABEL[] = { 0x63, 0x6C, 0x69, 0x65, 0x6E, 0x74, 0x20, 0x66, 0x69, 0x6E, 0x69, diff --git a/src/ssl/hello.cpp b/src/ssl/hello.cpp index 53f680fba..a23d51c24 100644 --- a/src/ssl/hello.cpp +++ b/src/ssl/hello.cpp @@ -1,12 +1,12 @@ /** * TLS Hello Messages -* (C) 2004-2006 Jack Lloyd +* (C) 2004-2010 Jack Lloyd * * Released under the terms of the Botan license */ #include <botan/tls_messages.h> -#include <botan/loadstor.h> +#include <botan/internal/tls_reader.h> namespace Botan { @@ -93,15 +93,15 @@ SecureVector<byte> Client_Hello::serialize() const buf.append(get_byte(0, suites_size)); buf.append(get_byte(1, suites_size)); - for(u32bit j = 0; j != suites.size(); j++) + for(u32bit i = 0; i != suites.size(); i++) { - buf.append(get_byte(0, suites[j])); - buf.append(get_byte(1, suites[j])); + buf.append(get_byte(0, suites[i])); + buf.append(get_byte(1, suites[i])); } buf.append(static_cast<byte>(comp_algos.size())); - for(u32bit j = 0; j != comp_algos.size(); j++) - buf.append(comp_algos[j]); + for(u32bit i = 0; i != comp_algos.size(); i++) + buf.append(comp_algos[i]); return buf; } @@ -117,38 +117,61 @@ void Client_Hello::deserialize(const MemoryRegion<byte>& buf) if(buf.size() < 41) throw Decoding_Error("Client_Hello: Packet corrupted"); - c_version = static_cast<Version_Code>(make_u16bit(buf[0], buf[1])); - if(c_version != SSL_V3 && c_version != TLS_V10) - throw TLS_Exception(PROTOCOL_VERSION, "Client_Hello: Bad version code"); + TLS_Data_Reader reader(buf); - c_random.set(buf + 2, 32); + c_version = static_cast<Version_Code>(reader.get_u16bit()); + c_random = reader.get_fixed<byte>(32); - u32bit session_id_len = buf[34]; - if(session_id_len > 32 || session_id_len + 41 > buf.size()) - throw Decoding_Error("Client_Hello: Packet corrupted"); - sess_id.copy(buf + 35, session_id_len); + sess_id = reader.get_range<byte>(1, 0, 32); - u32bit offset = 2+32+1+session_id_len; + suites = reader.get_range_vector<u16bit>(2, 1, 32767); - u16bit suites_size = make_u16bit(buf[offset], buf[offset+1]); - offset += 2; - if(suites_size % 2 == 1 || offset + suites_size + 2 > buf.size()) - throw Decoding_Error("Client_Hello: Packet corrupted"); + comp_algos = reader.get_range_vector<byte>(1, 1, 255); - for(u32bit j = 0; j != suites_size; j += 2) + if(reader.has_remaining()) { - u16bit suite = make_u16bit(buf[offset+j], buf[offset+j+1]); - suites.push_back(suite); + const u16bit all_extn_size = reader.get_u16bit(); + + if(reader.remaining_bytes() != all_extn_size) + throw Decoding_Error("Client_Hello: Bad extension size"); + + while(reader.has_remaining()) + { + const u16bit extension_code = reader.get_u16bit(); + const u16bit extension_size = reader.get_u16bit(); + + if(extension_code == TLSEXT_SERVER_NAME_INDICATION) + { + u16bit name_bytes = reader.get_u16bit(); + + while(name_bytes) + { + byte name_type = reader.get_byte(); + name_bytes--; + + if(name_type == 0) // DNS + { + std::vector<byte> name = + reader.get_range_vector<byte>(2, 1, 65535); + + requested_hostname.assign((const char*)&name[0], + name.size()); + + name_bytes -= (2 + name.size()); + } + else + { + reader.discard_next(name_bytes); + name_bytes = 0; + } + } + } + else + { + reader.discard_next(extension_size); + } + } } - offset += suites_size; - - byte comp_algo_size = buf[offset]; - offset += 1; - if(offset + comp_algo_size > buf.size()) - throw Decoding_Error("Client_Hello: Packet corrupted"); - - for(u32bit j = 0; j != comp_algo_size; j++) - comp_algos.push_back(buf[offset+j]); } /** @@ -156,8 +179,8 @@ void Client_Hello::deserialize(const MemoryRegion<byte>& buf) */ bool Client_Hello::offered_suite(u16bit ciphersuite) const { - for(u32bit j = 0; j != suites.size(); j++) - if(suites[j] == ciphersuite) + for(u32bit i = 0; i != suites.size(); i++) + if(suites[i] == ciphersuite) return true; return false; } @@ -172,11 +195,15 @@ Server_Hello::Server_Hello(RandomNumberGenerator& rng, HandshakeHash& hash) { bool have_rsa = false, have_dsa = false; - for(u32bit j = 0; j != certs.size(); j++) + + for(u32bit i = 0; i != certs.size(); i++) { - Public_Key* key = certs[j].subject_public_key(); - if(key->algo_name() == "RSA") have_rsa = true; - if(key->algo_name() == "DSA") have_dsa = true; + Public_Key* key = certs[i].subject_public_key(); + if(key->algo_name() == "RSA") + have_rsa = true; + + if(key->algo_name() == "DSA") + have_dsa = true; } suite = policy->choose_suite(c_hello.ciphersuites(), have_rsa, have_dsa); @@ -218,23 +245,24 @@ void Server_Hello::deserialize(const MemoryRegion<byte>& buf) if(buf.size() < 38) throw Decoding_Error("Server_Hello: Packet corrupted"); - s_version = static_cast<Version_Code>(make_u16bit(buf[0], buf[1])); - if(s_version != SSL_V3 && s_version != TLS_V10) + TLS_Data_Reader reader(buf); + + s_version = static_cast<Version_Code>(reader.get_u16bit()); + + if(s_version != SSL_V3 && s_version != TLS_V10 && s_version != TLS_V11) + { throw TLS_Exception(PROTOCOL_VERSION, "Server_Hello: Unsupported server version"); + } - s_random.set(buf + 2, 32); + s_random = reader.get_fixed<byte>(32); - u32bit session_id_len = buf[2+32]; - if(session_id_len > 32 || session_id_len + 38 != buf.size()) - throw Decoding_Error("Server_Hello: Packet corrupted"); - sess_id.copy(buf + 2 + 32 + 1, session_id_len); + sess_id = reader.get_range<byte>(1, 0, 32); - suite = make_u16bit(buf[2+32+1+session_id_len], - buf[2+32+1+session_id_len+1]); - comp_algo = buf[2+32+1+session_id_len+2]; - } + suite = reader.get_u16bit(); + comp_algo = reader.get_byte(); + } /** * Create a new Server Hello Done message diff --git a/src/ssl/info.txt b/src/ssl/info.txt index 73e4207d8..1d28cf4f8 100644 --- a/src/ssl/info.txt +++ b/src/ssl/info.txt @@ -1 +1,40 @@ define SSL_TLS + +<header:public> +handshake_hash.h +socket.h +tls_alerts.h +tls_client.h +tls_connection.h +tls_exceptn.h +tls_magic.h +tls_messages.h +tls_policy.h +tls_record.h +tls_server.h +tls_session_key.h +tls_state.h +tls_suites.h +</header:public> + +<header:internal> +tls_reader.h +</header:internal> + +<source> +c_kex.cpp +cert_req.cpp +cert_ver.cpp +finished.cpp +handshake_hash.cpp +handshake_state.cpp +hello.cpp +rec_read.cpp +rec_wri.cpp +s_kex.cpp +tls_client.cpp +tls_policy.cpp +tls_server.cpp +tls_session_key.cpp +tls_suites.cpp +</source> diff --git a/src/ssl/rec_read.cpp b/src/ssl/rec_read.cpp index 95059dbf2..8f8e5dc1e 100644 --- a/src/ssl/rec_read.cpp +++ b/src/ssl/rec_read.cpp @@ -1,6 +1,6 @@ /** -* TLS Record Reading -* (C) 2004-2006 Jack Lloyd +* TLS Record Reading +* (C) 2004-2010 Jack Lloyd * * Released under the terms of the Botan license */ @@ -13,23 +13,15 @@ namespace Botan { /** -* Record_Reader Constructor -*/ -Record_Reader::Record_Reader(Socket& sock) : socket(sock) - { - reset(); - } - -/** * Reset the state */ void Record_Reader::reset() { - compress.reset(); cipher.reset(); mac.reset(); - do_compress = false; - mac_size = pad_amount = 0; + mac_size = 0; + block_size = 0; + iv_size = 0; major = minor = 0; seq_no = 0; } @@ -39,7 +31,7 @@ void Record_Reader::reset() */ void Record_Reader::set_version(Version_Code version) { - if(version != SSL_V3 && version != TLS_V10) + if(version != SSL_V3 && version != TLS_V10 && version != TLS_V11) throw Invalid_Argument("Record_Reader: Invalid protocol version"); major = (version >> 8) & 0xFF; @@ -47,15 +39,6 @@ void Record_Reader::set_version(Version_Code version) } /** -* Set the compression algorithm -*/ -void Record_Reader::set_compressor(Filter* compressor) - { - compress.append(compressor); - do_compress = true; - } - -/** * Set the keys for reading */ void Record_Reader::set_keys(const CipherSuite& suite, const SessionKeys& keys, @@ -89,12 +72,18 @@ void Record_Reader::set_keys(const CipherSuite& suite, const SessionKeys& keys, cipher_algo + "/CBC/NoPadding", cipher_key, iv, DECRYPTION) ); - pad_amount = block_size_of(cipher_algo); + block_size = block_size_of(cipher_algo); + + if(major == 3 && minor >= 2) + iv_size = block_size; + else + iv_size = 0; } else if(have_stream_cipher(cipher_algo)) { cipher.append(get_cipher(cipher_algo, cipher_key, DECRYPTION)); - pad_amount = 0; + block_size = 0; + iv_size = 0; } else throw Invalid_Argument("Record_Reader: Unknown cipher " + cipher_algo); @@ -112,75 +101,102 @@ void Record_Reader::set_keys(const CipherSuite& suite, const SessionKeys& keys, throw Invalid_Argument("Record_Reader: Unknown hash " + mac_algo); } +void Record_Reader::add_input(const byte input[], u32bit input_size) + { + input_queue.write(input, input_size); + } + /** * Retrieve the next record */ -SecureVector<byte> Record_Reader::get_record(byte& msg_type) +u32bit Record_Reader::get_record(byte& msg_type, + MemoryRegion<byte>& output) { byte header[5] = { 0 }; - u32bit got = socket.read(header, sizeof(header)); + const u32bit have_in_queue = input_queue.size(); - if(got == 0) - { - msg_type = CONNECTION_CLOSED; - return SecureVector<byte>(); - } - else if(got != sizeof(header)) - throw Decoding_Error("Record_Reader: Record truncated"); + if(have_in_queue < sizeof(header)) + return (sizeof(header) - have_in_queue); - msg_type = header[0]; + /* + * We peek first to make sure we have the full record + */ + input_queue.peek(header, sizeof(header)); - const u16bit version = make_u16bit(header[1], header[2]); + const u16bit version = make_u16bit(header[1], header[2]); + const u16bit record_len = make_u16bit(header[3], header[4]); if(major && (header[1] != major || header[2] != minor)) throw TLS_Exception(PROTOCOL_VERSION, "Record_Reader: Got unexpected version"); - SecureVector<byte> buffer(make_u16bit(header[3], header[4])); - if(socket.read(buffer, buffer.size()) != buffer.size()) - throw Decoding_Error("Record_Reader: Record truncated"); + // If insufficient data, return without doing anything + if(have_in_queue < (sizeof(header) + record_len)) + return (sizeof(header) + record_len - have_in_queue); + + SecureVector<byte> buffer(record_len); + input_queue.read(header, sizeof(header)); // pull off the header + input_queue.read(buffer, buffer.size()); + + /* + * We are handshaking, no crypto to do so return as-is + * TODO: Check msg_type to confirm a handshake? + */ if(mac_size == 0) - return buffer; + { + msg_type = header[0]; + output = buffer; + return 0; // got a full record + } + + // Otherwise, decrypt, check MAC, return plaintext cipher.process_msg(buffer); SecureVector<byte> plaintext = cipher.read_all(Pipe::LAST_MESSAGE); u32bit pad_size = 0; - if(pad_amount) + + if(block_size) { byte pad_value = plaintext[plaintext.size()-1]; pad_size = pad_value + 1; + /* + * Check the padding; if it is wrong, then say we have 0 bytes of + * padding, which should ensure that the MAC check below does not + * suceed. This hides a timing channel. + * + * This particular countermeasure is recommended in the TLS 1.2 + * spec (RFC 5246) in section 6.2.3.2 + */ if(version == SSL_V3) { - if(pad_value > pad_amount) - throw TLS_Exception(BAD_RECORD_MAC, - "Record_Reader: Bad padding"); + if(pad_value > block_size) + pad_size = 0; } else { for(u32bit j = 0; j != pad_size; j++) if(plaintext[plaintext.size()-j-1] != pad_value) - throw TLS_Exception(BAD_RECORD_MAC, - "Record_Reader: Bad padding"); + pad_size = 0; } } - if(plaintext.size() < mac_size + pad_size) + if(plaintext.size() < mac_size + pad_size + iv_size) throw Decoding_Error("Record_Reader: Record truncated"); const u32bit mac_offset = plaintext.size() - (mac_size + pad_size); SecureVector<byte> recieved_mac(plaintext.begin() + mac_offset, mac_size); - const u16bit plain_length = plaintext.size() - (mac_size + pad_size); + const u16bit plain_length = plaintext.size() - (mac_size + pad_size + iv_size); mac.start_msg(); for(u32bit j = 0; j != 8; j++) mac.write(get_byte(j, seq_no)); - mac.write(msg_type); + mac.write(header[0]); // msg_type if(version != SSL_V3) for(u32bit j = 0; j != 2; j++) @@ -188,7 +204,7 @@ SecureVector<byte> Record_Reader::get_record(byte& msg_type) for(u32bit j = 0; j != 2; j++) mac.write(get_byte(j, plain_length)); - mac.write(plaintext, plain_length); + mac.write(&plaintext[iv_size], plain_length); mac.end_msg(); ++seq_no; @@ -198,7 +214,9 @@ SecureVector<byte> Record_Reader::get_record(byte& msg_type) if(recieved_mac != computed_mac) throw TLS_Exception(BAD_RECORD_MAC, "Record_Reader: MAC failure"); - return SecureVector<byte>(plaintext, mac_offset); + msg_type = header[0]; + output.set(&plaintext[iv_size], plain_length); + return 0; } } diff --git a/src/ssl/rec_wri.cpp b/src/ssl/rec_wri.cpp index 842b2698c..f8079c235 100644 --- a/src/ssl/rec_wri.cpp +++ b/src/ssl/rec_wri.cpp @@ -1,6 +1,6 @@ /** -* TLS Record Writing -* (C) 2004-2006 Jack Lloyd +* TLS Record Writing +* (C) 2004-2010 Jack Lloyd * * Released under the terms of the Botan license */ @@ -9,6 +9,7 @@ #include <botan/handshake_hash.h> #include <botan/lookup.h> #include <botan/loadstor.h> +#include <botan/libstate.h> namespace Botan { @@ -26,13 +27,17 @@ Record_Writer::Record_Writer(Socket& sock) : */ void Record_Writer::reset() { - compress.reset(); cipher.reset(); mac.reset(); + buffer.clear(); - do_compress = false; + buf_pos = 0; + major = minor = buf_type = 0; - pad_amount = mac_size = buf_pos = 0; + block_size = 0; + mac_size = 0; + iv_size = 0; + seq_no = 0; } @@ -41,7 +46,7 @@ void Record_Writer::reset() */ void Record_Writer::set_version(Version_Code version) { - if(version != SSL_V3 && version != TLS_V10) + if(version != SSL_V3 && version != TLS_V10 && version != TLS_V11) throw Invalid_Argument("Record_Writer: Invalid protocol version"); major = (version >> 8) & 0xFF; @@ -49,15 +54,6 @@ void Record_Writer::set_version(Version_Code version) } /** -* Set the compression algorithm -*/ -void Record_Writer::set_compressor(Filter* compressor) - { - throw TLS_Exception(INTERNAL_ERROR, "Compression not implemented (FIXME)"); - compress.append(compressor); - } - -/** * Set the keys for writing */ void Record_Writer::set_keys(const CipherSuite& suite, const SessionKeys& keys, @@ -91,12 +87,18 @@ void Record_Writer::set_keys(const CipherSuite& suite, const SessionKeys& keys, cipher_algo + "/CBC/NoPadding", cipher_key, iv, ENCRYPTION) ); - pad_amount = block_size_of(cipher_algo); + block_size = block_size_of(cipher_algo); + + if(major == 3 && minor >= 2) + iv_size = block_size; + else + iv_size = 0; } else if(have_stream_cipher(cipher_algo)) { cipher.append(get_cipher(cipher_algo, cipher_key, ENCRYPTION)); - pad_amount = 0; + block_size = 0; + iv_size = 0; } else throw Invalid_Argument("Record_Writer: Unknown cipher " + cipher_algo); @@ -203,15 +205,30 @@ void Record_Writer::send_record(byte type, const byte buf[], u32bit length) mac.write(buf, length); mac.end_msg(); + // TODO: This could all use a single buffer + SecureVector<byte> buf_mac = mac.read_all(Pipe::LAST_MESSAGE); cipher.start_msg(); + + if(iv_size) + { + RandomNumberGenerator& rng = global_state().global_rng(); + + SecureVector<byte> random_iv(iv_size); + + rng.randomize(&random_iv[0], random_iv.size()); + + cipher.write(random_iv); + } + cipher.write(buf, length); cipher.write(buf_mac); - if(pad_amount) + + if(block_size) { u32bit pad_val = - (pad_amount - (1 + length + buf_mac.size())) % pad_amount; + (block_size - (1 + length + buf_mac.size())) % block_size; for(u32bit j = 0; j != pad_val + 1; j++) cipher.write(pad_val); @@ -240,7 +257,6 @@ void Record_Writer::send_record(byte type, byte major, byte minor, for(u32bit j = 0; j != 2; j++) header[j+3] = get_byte<u16bit>(j, length); - // FIXME: tradoff of TCP/syscall overhead vs copy overhead socket.write(header, 5); socket.write(out, length); } diff --git a/src/ssl/s_kex.cpp b/src/ssl/s_kex.cpp index 3223adc5b..9b8a3171d 100644 --- a/src/ssl/s_kex.cpp +++ b/src/ssl/s_kex.cpp @@ -51,7 +51,7 @@ Server_Key_Exchange::Server_Key_Exchange(RandomNumberGenerator& rng, padding = "EMSA3(TLS.Digest.0)"; else if(priv_key->algo_name() == "DSA") { - padding == "EMSA1(SHA-1)"; + padding = "EMSA1(SHA-1)"; format = DER_SEQUENCE; } else diff --git a/src/ssl/socket.h b/src/ssl/socket.h index 3d893ea77..62ceed028 100644 --- a/src/ssl/socket.h +++ b/src/ssl/socket.h @@ -19,11 +19,8 @@ namespace Botan { class BOTAN_DLL Socket { public: - virtual u32bit read(byte[], u32bit) = 0; - virtual void write(const byte[], u32bit) = 0; - - u32bit read(byte& x) { return read(&x, 1); } - void write(byte x) { write(&x, 1); } + virtual size_t read(byte[], size_t) = 0; + virtual void write(const byte[], size_t) = 0; virtual std::string peer_id() const = 0; diff --git a/src/ssl/tls_client.cpp b/src/ssl/tls_client.cpp index ce33573f5..fbad1f838 100644 --- a/src/ssl/tls_client.cpp +++ b/src/ssl/tls_client.cpp @@ -1,6 +1,6 @@ /** -* TLS Client -* (C) 2004-2006 Jack Lloyd +* TLS Client +* (C) 2004-2010 Jack Lloyd * * Released under the terms of the Botan license */ @@ -83,7 +83,7 @@ void client_check_state(Handshake_Type new_msg, Handshake_State* state) */ TLS_Client::TLS_Client(RandomNumberGenerator& r, Socket& sock, const TLS_Policy* pol) : - rng(r), writer(sock), reader(sock), policy(pol ? pol : new TLS_Policy) + rng(r), peer(sock), writer(sock), policy(pol ? pol : new TLS_Policy) { peer_id = sock.peer_id(); @@ -96,7 +96,7 @@ TLS_Client::TLS_Client(RandomNumberGenerator& r, TLS_Client::TLS_Client(RandomNumberGenerator& r, Socket& sock, const X509_Certificate& cert, const Private_Key& key, const TLS_Policy* pol) : - rng(r), writer(sock), reader(sock), policy(pol ? pol : new TLS_Policy) + rng(r), peer(sock), writer(sock), policy(pol ? pol : new TLS_Policy) { peer_id = sock.peer_id(); @@ -243,8 +243,26 @@ void TLS_Client::close(Alert_Level level, Alert_Type alert_code) */ void TLS_Client::state_machine() { - byte rec_type; - SecureVector<byte> record = reader.get_record(rec_type); + byte rec_type = CONNECTION_CLOSED; + SecureVector<byte> record(1024); + + u32bit bytes_needed = reader.get_record(rec_type, record); + + while(bytes_needed) + { + u32bit to_get = std::min<u32bit>(record.size(), bytes_needed); + u32bit got = peer.read(&record[0], to_get); + + if(got == 0) + { + rec_type = CONNECTION_CLOSED; + break; + } + + reader.add_input(&record[0], got); + + bytes_needed = reader.get_record(rec_type, record); + } if(rec_type == CONNECTION_CLOSED) { @@ -562,7 +580,7 @@ void TLS_Client::do_handshake() if(active && !state) break; if(!active && !state) - throw TLS_Exception(HANDSHAKE_FAILURE, "TLS_Client: Handshake failed"); + throw TLS_Exception(HANDSHAKE_FAILURE, "TLS_Client: Handshake failed (do_handshake)"); state_machine(); } diff --git a/src/ssl/tls_client.h b/src/ssl/tls_client.h index 896decdf9..2439a58f0 100644 --- a/src/ssl/tls_client.h +++ b/src/ssl/tls_client.h @@ -60,6 +60,8 @@ class BOTAN_DLL TLS_Client : public TLS_Connection RandomNumberGenerator& rng; + Socket& peer; + Record_Writer writer; Record_Reader reader; const TLS_Policy* policy; diff --git a/src/ssl/tls_magic.h b/src/ssl/tls_magic.h index 41fb756e9..a6ca1f8d6 100644 --- a/src/ssl/tls_magic.h +++ b/src/ssl/tls_magic.h @@ -115,6 +115,17 @@ enum Compression_Algo { NO_COMPRESSION = 0x00 }; +enum TLS_Handshake_Extension_Type { + TLSEXT_SERVER_NAME_INDICATION = 0, + TLSEXT_MAX_FRAGMENT_LENGTH = 1, + TLSEXT_CLIENT_CERT_URL = 2, + TLSEXT_TRUSTED_CA_KEYS = 3, + TLSEXT_TRUNCATED_HMAC = 4, + + TLSEXT_CERTIFICATE_TYPES = 9, + TLSEXT_SESSION_TICKET = 35, +}; + } #endif diff --git a/src/ssl/tls_messages.h b/src/ssl/tls_messages.h index 4b512a963..1f72c05f7 100644 --- a/src/ssl/tls_messages.h +++ b/src/ssl/tls_messages.h @@ -49,6 +49,8 @@ class BOTAN_DLL Client_Hello : public HandshakeMessage SecureVector<byte> random() const { return c_random; } + std::string hostname() const { return requested_hostname; } + bool offered_suite(u16bit) const; Client_Hello(RandomNumberGenerator& rng, @@ -63,6 +65,7 @@ class BOTAN_DLL Client_Hello : public HandshakeMessage SecureVector<byte> sess_id, c_random; std::vector<u16bit> suites; std::vector<byte> comp_algos; + std::string requested_hostname; }; /** diff --git a/src/ssl/tls_policy.h b/src/ssl/tls_policy.h index 98297181c..75d6d7663 100644 --- a/src/ssl/tls_policy.h +++ b/src/ssl/tls_policy.h @@ -40,7 +40,7 @@ class BOTAN_DLL TLS_Policy virtual u32bit rsa_export_keysize() const { return 512; } virtual Version_Code min_version() const { return SSL_V3; } - virtual Version_Code pref_version() const { return TLS_V10; } + virtual Version_Code pref_version() const { return TLS_V11; } virtual bool check_cert(const std::vector<X509_Certificate>&, const std::string&) const; diff --git a/src/ssl/tls_reader.h b/src/ssl/tls_reader.h new file mode 100644 index 000000000..ff3e63ae8 --- /dev/null +++ b/src/ssl/tls_reader.h @@ -0,0 +1,140 @@ +/* +* TLS Data Reader +* (C) 2010 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#ifndef BOTAN_TLS_READER_H__ +#define BOTAN_TLS_READER_H__ + +#include <botan/secmem.h> +#include <botan/loadstor.h> + +namespace Botan { + +class TLS_Data_Reader + { + public: + TLS_Data_Reader(const MemoryRegion<byte>& buf_in) : + buf(buf_in), offset(0) {} + + u32bit remaining_bytes() const + { + return buf.size() - offset; + } + + bool has_remaining() const + { + return (remaining_bytes() > 0); + } + + void discard_next(u32bit bytes) + { + assert_at_least(bytes); + offset += bytes; + } + + u16bit get_u16bit() + { + assert_at_least(2); + u16bit result = make_u16bit(buf[offset], buf[offset+1]); + offset += 2; + return result; + } + + byte get_byte() + { + assert_at_least(1); + byte result = buf[offset]; + offset += 1; + return result; + } + + template<typename T, typename Container> + Container get_elem(u32bit num_elems) + { + assert_at_least(num_elems * sizeof(T)); + + Container result(num_elems); + + for(u32bit i = 0; i != num_elems; ++i) + result[i] = load_be<T>(&buf[offset], i); + + offset += num_elems * sizeof(T); + + return result; + } + + template<typename T> + SecureVector<T> get_range(u32bit len_bytes, + u32bit min_elems, + u32bit max_elems) + { + const u32bit num_elems = + get_num_elems(len_bytes, sizeof(T), min_elems, max_elems); + + return get_elem<T, SecureVector<T> >(num_elems); + } + + template<typename T> + std::vector<T> get_range_vector(u32bit len_bytes, + u32bit min_elems, + u32bit max_elems) + { + const u32bit num_elems = + get_num_elems(len_bytes, sizeof(T), min_elems, max_elems); + + return get_elem<T, std::vector<T> >(num_elems); + } + + template<typename T> + SecureVector<T> get_fixed(u32bit size) + { + return get_elem<T, SecureVector<T> >(size); + } + + private: + u32bit get_length_field(u32bit len_bytes) + { + assert_at_least(len_bytes); + + if(len_bytes == 1) + return get_byte(); + else if(len_bytes == 2) + return get_u16bit(); + + throw Decoding_Error("TLS_Data_Reader: Bad length size"); + } + + u32bit get_num_elems(u32bit len_bytes, + u32bit T_size, + u32bit min_elems, + u32bit max_elems) + { + const u32bit byte_length = get_length_field(len_bytes); + + if(byte_length % T_size != 0) + throw Decoding_Error("TLS_Data_Reader: Size isn't multiple of T"); + + const u32bit num_elems = byte_length / T_size; + + if(num_elems < min_elems || num_elems > max_elems) + throw Decoding_Error("TLS_Data_Reader: Range outside paramaters"); + + return num_elems; + } + + void assert_at_least(u32bit n) const + { + if(buf.size() - offset < n) + throw Decoding_Error("TLS_Data_Reader: Corrupt packet"); + } + + const MemoryRegion<byte>& buf; + u32bit offset; + }; + +} + +#endif diff --git a/src/ssl/tls_record.h b/src/ssl/tls_record.h index 3bec2e8ef..2058933d0 100644 --- a/src/ssl/tls_record.h +++ b/src/ssl/tls_record.h @@ -1,6 +1,6 @@ /** -* TLS Record Handling -* (C) 2004-2006 Jack Lloyd +* TLS Record Handling +* (C) 2004-2010 Jack Lloyd * * Released under the terms of the Botan license */ @@ -12,6 +12,7 @@ #include <botan/socket.h> #include <botan/tls_suites.h> #include <botan/pipe.h> +#include <botan/secqueue.h> #include <vector> namespace Botan { @@ -29,24 +30,26 @@ class BOTAN_DLL Record_Writer void alert(Alert_Level, Alert_Type); void set_keys(const CipherSuite&, const SessionKeys&, Connection_Side); - void set_compressor(Filter*); void set_version(Version_Code); void reset(); - Record_Writer(Socket&); + Record_Writer(Socket& socket); + private: void send_record(byte, const byte[], u32bit); void send_record(byte, byte, byte, const byte[], u32bit); Socket& socket; - Pipe compress, cipher, mac; + Pipe cipher, mac; SecureVector<byte> buffer; - u32bit pad_amount, mac_size, buf_pos; + u32bit buf_pos; + + u32bit block_size, mac_size, iv_size; + u64bit seq_no; byte major, minor, buf_type; - bool do_compress; }; /** @@ -55,23 +58,34 @@ class BOTAN_DLL Record_Writer class BOTAN_DLL Record_Reader { public: - SecureVector<byte> get_record(byte&); + void add_input(const byte input[], u32bit input_size); - void set_keys(const CipherSuite&, const SessionKeys&, Connection_Side); - void set_compressor(Filter*); + /** + * @param msg_type (output variable) + * @param buffer (output variable) + * @return Number of bytes still needed (minimum), or 0 if success + */ + u32bit get_record(byte& msg_type, + MemoryRegion<byte>& buffer); - void set_version(Version_Code); + SecureVector<byte> get_record(byte& msg_type); + + void set_keys(const CipherSuite& suite, + const SessionKeys& keys, + Connection_Side side); + + void set_version(Version_Code version); void reset(); - Record_Reader(Socket&); + Record_Reader() { reset(); } private: - Socket& socket; - Pipe compress, cipher, mac; - u32bit pad_amount, mac_size; + SecureQueue input_queue; + + Pipe cipher, mac; + u32bit block_size, mac_size, iv_size; u64bit seq_no; byte major, minor; - bool do_compress; }; } diff --git a/src/ssl/tls_server.cpp b/src/ssl/tls_server.cpp index 37d9dbcd1..47902a71c 100644 --- a/src/ssl/tls_server.cpp +++ b/src/ssl/tls_server.cpp @@ -25,9 +25,9 @@ Version_Code choose_version(Version_Code client, Version_Code minimum) throw TLS_Exception(PROTOCOL_VERSION, "Client version is unacceptable by policy"); - if(client == SSL_V3 || client == TLS_V10) + if(client == SSL_V3 || client == TLS_V10 || client == TLS_V11) return client; - return TLS_V10; + return TLS_V11; } // FIXME: checks are wrong for session reuse (add a flag for that) @@ -88,7 +88,8 @@ void server_check_state(Handshake_Type new_msg, Handshake_State* state) TLS_Server::TLS_Server(RandomNumberGenerator& r, Socket& sock, const X509_Certificate& cert, const Private_Key& key, const TLS_Policy* pol) : - rng(r), writer(sock), reader(sock), policy(pol ? pol : new TLS_Policy) + rng(r), peer(sock), + writer(sock), policy(pol ? pol : new TLS_Policy) { peer_id = sock.peer_id(); @@ -112,7 +113,8 @@ TLS_Server::TLS_Server(RandomNumberGenerator& r, } writer.alert(FATAL, HANDSHAKE_FAILURE); - throw Stream_IO_Error("TLS_Server: Handshake failed"); + throw Stream_IO_Error(std::string("TLS_Server: Handshake failed: ") + + e.what()); } } @@ -207,8 +209,26 @@ void TLS_Server::close(Alert_Level level, Alert_Type alert_code) */ void TLS_Server::state_machine() { - byte rec_type; - SecureVector<byte> record = reader.get_record(rec_type); + byte rec_type = CONNECTION_CLOSED; + SecureVector<byte> record(1024); + + u32bit bytes_needed = reader.get_record(rec_type, record); + + while(bytes_needed) + { + u32bit to_get = std::min<u32bit>(record.size(), bytes_needed); + u32bit got = peer.read(&record[0], to_get); + + if(got == 0) + { + rec_type = CONNECTION_CLOSED; + break; + } + + reader.add_input(&record[0], got); + + bytes_needed = reader.get_record(rec_type, record); + } if(rec_type == CONNECTION_CLOSED) { @@ -250,7 +270,11 @@ void TLS_Server::read_handshake(byte rec_type, const MemoryRegion<byte>& rec_buf) { if(rec_type == HANDSHAKE) + { + if(!state) + state = new Handshake_State; state->queue.write(rec_buf, rec_buf.size()); + } while(true) { @@ -301,14 +325,6 @@ void TLS_Server::read_handshake(byte rec_type, void TLS_Server::process_handshake_msg(Handshake_Type type, const MemoryRegion<byte>& contents) { - if(type == CLIENT_HELLO) - { - if(state == 0) - state = new Handshake_State(); - else - return; - } - if(state == 0) throw Unexpected_Message("Unexpected handshake message"); @@ -327,6 +343,8 @@ void TLS_Server::process_handshake_msg(Handshake_Type type, state->client_hello = new Client_Hello(contents); + client_requested_hostname = state->client_hello->hostname(); + state->version = choose_version(state->client_hello->version(), policy->min_version()); diff --git a/src/ssl/tls_server.h b/src/ssl/tls_server.h index 683c3413a..5cf830a64 100644 --- a/src/ssl/tls_server.h +++ b/src/ssl/tls_server.h @@ -26,6 +26,9 @@ class BOTAN_DLL TLS_Server : public TLS_Connection std::vector<X509_Certificate> peer_cert_chain() const; + std::string requested_hostname() const + { return client_requested_hostname; } + void close(); bool is_closed() const; @@ -49,6 +52,8 @@ class BOTAN_DLL TLS_Server : public TLS_Connection RandomNumberGenerator& rng; + Socket& peer; + Record_Writer writer; Record_Reader reader; const TLS_Policy* policy; @@ -61,6 +66,7 @@ class BOTAN_DLL TLS_Server : public TLS_Connection SecureVector<byte> session_id; SecureQueue read_buf; std::string peer_id; + std::string client_requested_hostname; bool active; }; diff --git a/src/ssl/tls_session_key.cpp b/src/ssl/tls_session_key.cpp index 83c06ba07..13575adac 100644 --- a/src/ssl/tls_session_key.cpp +++ b/src/ssl/tls_session_key.cpp @@ -131,7 +131,7 @@ SessionKeys::SessionKeys(const CipherSuite& suite, Version_Code version, const MemoryRegion<byte>& c_random, const MemoryRegion<byte>& s_random) { - if(version != SSL_V3 && version != TLS_V10) + if(version != SSL_V3 && version != TLS_V10 && version != TLS_V11) throw Invalid_Argument("SessionKeys: Unknown version code"); const u32bit mac_keylen = output_length_of(suite.mac_algo()); diff --git a/src/ssl/unix_socket/unx_sock.cpp b/src/ssl/unix_socket/unx_sock.cpp index 0552a33b6..f9d9629fb 100644 --- a/src/ssl/unix_socket/unx_sock.cpp +++ b/src/ssl/unix_socket/unx_sock.cpp @@ -64,12 +64,12 @@ Unix_Socket::Unix_Socket(int fd, const std::string& peer_id) /** * Read from a Unix socket */ -u32bit Unix_Socket::read(byte buf[], u32bit length) +size_t Unix_Socket::read(byte buf[], size_t length) { if(sockfd == -1) throw Stream_IO_Error("Unix_Socket::read: Socket not connected"); - u32bit got = 0; + size_t got = 0; while(length) { @@ -95,12 +95,12 @@ u32bit Unix_Socket::read(byte buf[], u32bit length) /** * Write to a Unix socket */ -void Unix_Socket::write(const byte buf[], u32bit length) +void Unix_Socket::write(const byte buf[], size_t length) { if(sockfd == -1) throw Stream_IO_Error("Unix_Socket::write: Socket not connected"); - u32bit offset = 0; + size_t offset = 0; while(length) { ssize_t sent = ::send(sockfd, buf + offset, length, MSG_NOSIGNAL); diff --git a/src/ssl/unix_socket/unx_sock.h b/src/ssl/unix_socket/unx_sock.h index c1ff53ae3..58c7ada69 100644 --- a/src/ssl/unix_socket/unx_sock.h +++ b/src/ssl/unix_socket/unx_sock.h @@ -28,8 +28,8 @@ namespace Botan { class BOTAN_DLL Unix_Socket : public Socket { public: - u32bit read(byte[], u32bit); - void write(const byte[], u32bit); + size_t read(byte[], size_t); + void write(const byte[], size_t); std::string peer_id() const; diff --git a/src/stream/arc4/arc4.h b/src/stream/arc4/arc4.h index ae37cb165..07633f9ef 100644 --- a/src/stream/arc4/arc4.h +++ b/src/stream/arc4/arc4.h @@ -34,8 +34,8 @@ class BOTAN_DLL ARC4 : public StreamCipher const u32bit SKIP; - SecureBuffer<byte, DEFAULT_BUFFERSIZE> buffer; - SecureBuffer<u32bit, 256> state; + SecureVector<byte, DEFAULT_BUFFERSIZE> buffer; + SecureVector<u32bit, 256> state; u32bit X, Y, position; }; diff --git a/src/stream/salsa20/salsa20.h b/src/stream/salsa20/salsa20.h index af7ddd145..67fe54dda 100644 --- a/src/stream/salsa20/salsa20.h +++ b/src/stream/salsa20/salsa20.h @@ -34,8 +34,8 @@ class BOTAN_DLL Salsa20 : public StreamCipher private: void key_schedule(const byte key[], u32bit key_len); - SecureBuffer<u32bit, 16> state; - SecureBuffer<byte, 64> buffer; + SecureVector<u32bit, 16> state; + SecureVector<byte, 64> buffer; u32bit position; }; diff --git a/src/stream/turing/turing.h b/src/stream/turing/turing.h index 7291647ea..19d151fca 100644 --- a/src/stream/turing/turing.h +++ b/src/stream/turing/turing.h @@ -37,10 +37,10 @@ class BOTAN_DLL Turing : public StreamCipher static const u32bit Q_BOX[256]; static const byte SBOX[256]; - SecureBuffer<u32bit, 256> S0, S1, S2, S3; - SecureBuffer<u32bit, 17> R; + SecureVector<u32bit, 256> S0, S1, S2, S3; + SecureVector<u32bit, 17> R; SecureVector<u32bit> K; - SecureBuffer<byte, 340> buffer; + SecureVector<byte, 340> buffer; u32bit position; }; diff --git a/src/stream/wid_wake/wid_wake.h b/src/stream/wid_wake/wid_wake.h index 23e1eacab..1c52e8ba1 100644 --- a/src/stream/wid_wake/wid_wake.h +++ b/src/stream/wid_wake/wid_wake.h @@ -33,10 +33,10 @@ class BOTAN_DLL WiderWake_41_BE : public StreamCipher void generate(u32bit); - SecureBuffer<byte, DEFAULT_BUFFERSIZE> buffer; - SecureBuffer<u32bit, 256> T; - SecureBuffer<u32bit, 5> state; - SecureBuffer<u32bit, 4> t_key; + SecureVector<byte, DEFAULT_BUFFERSIZE> buffer; + SecureVector<u32bit, 256> T; + SecureVector<u32bit, 5> state; + SecureVector<u32bit, 4> t_key; u32bit position; }; |