diff options
Diffstat (limited to 'src')
37 files changed, 600 insertions, 299 deletions
diff --git a/src/alloc/secmem.h b/src/alloc/secmem.h index 13d2bfdce..f14e2a9db 100644 --- a/src/alloc/secmem.h +++ b/src/alloc/secmem.h @@ -162,6 +162,16 @@ class MemoryRegion { append(other.begin(), other.size()); } /** + * Truncate the buffer to at most n elements + * @param n the length of the resulting buffer + */ + void truncate(u32bit n) + { + if(n < used) + used = n; + } + + /** * Zeroise the bytes of this buffer. The length remains unchanged. */ void clear() { clear_mem(buf, allocated); } diff --git a/src/block/aes/aes.cpp b/src/block/aes/aes.cpp index bf9a4198b..8783f13a0 100644 --- a/src/block/aes/aes.cpp +++ b/src/block/aes/aes.cpp @@ -426,15 +426,33 @@ void AES::encrypt_n(const byte in[], byte out[], u32bit blocks) const u32bit T2 = load_be<u32bit>(in, 2) ^ EK[2]; u32bit T3 = load_be<u32bit>(in, 3) ^ EK[3]; - u32bit B0, B1, B2, B3; - B0 = TE0[get_byte(0, T0)] ^ TE1[get_byte(1, T1)] ^ - TE2[get_byte(2, T2)] ^ TE3[get_byte(3, T3)] ^ EK[4]; - B1 = TE0[get_byte(0, T1)] ^ TE1[get_byte(1, T2)] ^ - TE2[get_byte(2, T3)] ^ TE3[get_byte(3, T0)] ^ EK[5]; - B2 = TE0[get_byte(0, T2)] ^ TE1[get_byte(1, T3)] ^ - TE2[get_byte(2, T0)] ^ TE3[get_byte(3, T1)] ^ EK[6]; - B3 = TE0[get_byte(0, T3)] ^ TE1[get_byte(1, T0)] ^ - TE2[get_byte(2, T1)] ^ TE3[get_byte(3, T2)] ^ EK[7]; + /* Use only the first 256 entries of the TE table and do the + * rotations directly in the code. This reduces the number of + * cache lines potentially used in the first round from 64 to 16 + * (assuming a typical 64 byte cache line), which makes timing + * attacks a little harder; the first round is particularly + * vulnerable. + */ + + u32bit B0 = TE[get_byte(0, T0)] ^ + rotate_right(TE[get_byte(1, T1)], 8) ^ + rotate_right(TE[get_byte(2, T2)], 16) ^ + rotate_right(TE[get_byte(3, T3)], 24) ^ EK[4]; + + u32bit B1 = TE[get_byte(0, T1)] ^ + rotate_right(TE[get_byte(1, T2)], 8) ^ + rotate_right(TE[get_byte(2, T3)], 16) ^ + rotate_right(TE[get_byte(3, T0)], 24) ^ EK[5]; + + u32bit B2 = TE[get_byte(0, T2)] ^ + rotate_right(TE[get_byte(1, T3)], 8) ^ + rotate_right(TE[get_byte(2, T0)], 16) ^ + rotate_right(TE[get_byte(3, T1)], 24) ^ EK[6]; + + u32bit B3 = TE[get_byte(0, T3)] ^ + rotate_right(TE[get_byte(1, T0)], 8) ^ + rotate_right(TE[get_byte(2, T1)], 16) ^ + rotate_right(TE[get_byte(3, T2)], 24) ^ EK[7]; for(u32bit j = 2; j != ROUNDS; j += 2) { @@ -468,10 +486,14 @@ void AES::encrypt_n(const byte in[], byte out[], u32bit blocks) const } /* - Joseph Bonneau and Ilya Mironov's paper - <a href = "http://icme2007.org/users/mironov/papers/aes-timing.pdf"> - Cache-Collision Timing Attacks Against AES</a> describes an attack - that can recover AES keys with as few as 2<sup>13</sup> samples. + Joseph Bonneau and Ilya Mironov's paper "Cache-Collision Timing + Attacks Against AES" describes an attack that can recover AES + keys with as few as 2**13 samples. + + http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.88.4753 + + They recommend using a byte-wide table, which still allows an attack + but increases the samples required from 2**13 to 2**25: """In addition to OpenSSL v. 0.9.8.(a), which was used in our experiments, the AES implementations of Crypto++ 5.2.1 and @@ -481,6 +503,7 @@ void AES::encrypt_n(const byte in[], byte out[], u32bit blocks) const use a smaller byte-wide final table which lessens the effectiveness of the attacks.""" */ + out[ 0] = SE[get_byte(0, B0)] ^ ME[0]; out[ 1] = SE[get_byte(1, B1)] ^ ME[1]; out[ 2] = SE[get_byte(2, B2)] ^ ME[2]; @@ -520,15 +543,25 @@ void AES::decrypt_n(const byte in[], byte out[], u32bit blocks) const u32bit T2 = load_be<u32bit>(in, 2) ^ DK[2]; u32bit T3 = load_be<u32bit>(in, 3) ^ DK[3]; - u32bit B0, B1, B2, B3; - B0 = TD0[get_byte(0, T0)] ^ TD1[get_byte(1, T3)] ^ - TD2[get_byte(2, T2)] ^ TD3[get_byte(3, T1)] ^ DK[4]; - B1 = TD0[get_byte(0, T1)] ^ TD1[get_byte(1, T0)] ^ - TD2[get_byte(2, T3)] ^ TD3[get_byte(3, T2)] ^ DK[5]; - B2 = TD0[get_byte(0, T2)] ^ TD1[get_byte(1, T1)] ^ - TD2[get_byte(2, T0)] ^ TD3[get_byte(3, T3)] ^ DK[6]; - B3 = TD0[get_byte(0, T3)] ^ TD1[get_byte(1, T2)] ^ - TD2[get_byte(2, T1)] ^ TD3[get_byte(3, T0)] ^ DK[7]; + u32bit B0 = TD[get_byte(0, T0)] ^ + rotate_right(TD[get_byte(1, T3)], 8) ^ + rotate_right(TD[get_byte(2, T2)], 16) ^ + rotate_right(TD[get_byte(3, T1)], 24) ^ DK[4]; + + u32bit B1 = TD[get_byte(0, T1)] ^ + rotate_right(TD[get_byte(1, T0)], 8) ^ + rotate_right(TD[get_byte(2, T3)], 16) ^ + rotate_right(TD[get_byte(3, T2)], 24) ^ DK[5]; + + u32bit B2 = TD[get_byte(0, T2)] ^ + rotate_right(TD[get_byte(1, T1)], 8) ^ + rotate_right(TD[get_byte(2, T0)], 16) ^ + rotate_right(TD[get_byte(3, T3)], 24) ^ DK[6]; + + u32bit B3 = TD[get_byte(0, T3)] ^ + rotate_right(TD[get_byte(1, T2)], 8) ^ + rotate_right(TD[get_byte(2, T1)], 16) ^ + rotate_right(TD[get_byte(3, T0)], 24) ^ DK[7]; for(u32bit j = 2; j != ROUNDS; j += 2) { diff --git a/src/build-data/arch/ia32.txt b/src/build-data/arch/ia32.txt index d9b09746d..c2d4d1769 100644 --- a/src/build-data/arch/ia32.txt +++ b/src/build-data/arch/ia32.txt @@ -61,4 +61,5 @@ intelcput2700 -> prescott <isa_extn> sse2:pentium4,prescott,pentium-m,atom ssse3:atom +movbe:atom </isa_extn> diff --git a/src/build-data/cc/gcc.txt b/src/build-data/cc/gcc.txt index ed8a2abe6..6eeb837ed 100644 --- a/src/build-data/cc/gcc.txt +++ b/src/build-data/cc/gcc.txt @@ -45,6 +45,7 @@ ppc601 -> "-mpowerpc -mcpu=601" # Until GCC gets -march support for these models nehalem -> "-march=core2 -msse4.1 -msse4.2" westmere -> "-march=core2 -maes -msse4.1 -msse4.2" +atom -> "-march=i686 -msse2 -mssse3" cellppu -> "" alpha-ev68 -> "-mcpu=ev6" alpha-ev7 -> "-mcpu=ev6" diff --git a/src/build-data/os/windows.txt b/src/build-data/os/windows.txt index 2d435535c..30a6b77f8 100644 --- a/src/build-data/os/windows.txt +++ b/src/build-data/os/windows.txt @@ -12,6 +12,7 @@ install_cmd_exec "copy" <target_features> gmtime_s +loadlibrary win32_get_systemtime win32_query_perf_counter win32_virtual_lock diff --git a/src/codec/hex/hex.cpp b/src/codec/hex/hex.cpp new file mode 100644 index 000000000..70e819906 --- /dev/null +++ b/src/codec/hex/hex.cpp @@ -0,0 +1,180 @@ +/* +* Hex Encoding and Decoding +* (C) 2010 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/hex.h> +#include <botan/mem_ops.h> +#include <stdexcept> + +namespace Botan { + +void hex_encode(char output[], + const byte input[], + u32bit input_length, + bool uppercase) + { + static const byte BIN_TO_HEX_UPPER[16] = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'A', 'B', 'C', 'D', 'E', 'F' }; + + static const byte BIN_TO_HEX_LOWER[16] = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'a', 'b', 'c', 'd', 'e', 'f' }; + + const byte* tbl = uppercase ? BIN_TO_HEX_UPPER : BIN_TO_HEX_LOWER; + + for(u32bit i = 0; i != input_length; ++i) + { + byte x = input[i]; + output[2*i ] = tbl[(x >> 4) & 0x0F]; + output[2*i+1] = tbl[(x ) & 0x0F]; + } + } + +std::string hex_encode(const byte input[], + u32bit input_length, + bool uppercase) + { + std::string output(2 * input_length, 0); + hex_encode(&output[0], input, input_length, uppercase); + return output; + } + +u32bit hex_decode(byte output[], + const char input[], + u32bit input_length, + u32bit& input_consumed, + bool ignore_ws) + { + /* + * Mapping of hex characters to either their binary equivalent + * or to an error code. + * If valid hex (0-9 A-F a-f), the value. + * If whitespace, then 0x80 + * Otherwise 0xFF + * Warning: this table assumes ASCII character encodings + */ + + static const byte HEX_TO_BIN[256] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, + 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, + 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0A, 0x0B, 0x0C, + 0x0D, 0x0E, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + + byte* out_ptr = output; + bool top_nibble = true; + + clear_mem(output, input_length / 2); + + for(u32bit i = 0; i != input_length; ++i) + { + const byte bin = HEX_TO_BIN[(byte)input[i]]; + + if(bin >= 0x10) + { + if(bin == 0x80 && ignore_ws) + continue; + + std::string bad_char(1, input[i]); + if(bad_char == "\t") + bad_char = "\\t"; + else if(bad_char == "\n") + bad_char = "\\n"; + + throw std::invalid_argument( + std::string("hex_decode: invalid hex character '") + + bad_char + "'"); + } + + *out_ptr |= bin << (top_nibble*4); + + top_nibble = !top_nibble; + if(top_nibble) + ++out_ptr; + } + + input_consumed = input_length; + u32bit written = (out_ptr - output); + + /* + * We only got half of a byte at the end; zap the half-written + * output and mark it as unread + */ + if(!top_nibble) + { + *out_ptr = 0; + input_consumed -= 1; + } + + return written; + } + +u32bit hex_decode(byte output[], + const char input[], + u32bit input_length, + bool ignore_ws) + { + u32bit consumed = 0; + u32bit written = hex_decode(output, input, input_length, + consumed, ignore_ws); + + if(consumed != input_length) + throw std::invalid_argument("hex_decode: input did not have full bytes"); + + return written; + } + +u32bit hex_decode(byte output[], + const std::string& input, + bool ignore_ws) + { + return hex_decode(output, &input[0], input.length(), ignore_ws); + } + +SecureVector<byte> hex_decode(const char input[], + u32bit input_length, + bool ignore_ws) + { + SecureVector<byte> bin(input_length / 2); + + u32bit written = hex_decode(&bin[0], + input, + input_length, + ignore_ws); + + bin.truncate(written); + return bin; + } + +SecureVector<byte> hex_decode(const std::string& input, + bool ignore_ws) + { + return hex_decode(&input[0], input.size(), ignore_ws); + } + +} diff --git a/src/codec/hex/hex.h b/src/codec/hex/hex.h new file mode 100644 index 000000000..91a743b45 --- /dev/null +++ b/src/codec/hex/hex.h @@ -0,0 +1,108 @@ +/* +* Hex Encoding and Decoding +* (C) 2010 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_HEX_CODEC_H__ +#define BOTAN_HEX_CODEC_H__ + +#include <botan/secmem.h> +#include <string> + +namespace Botan { + +/** +* Perform hex encoding +* @param output an array of at least input_length*2 bytes +* @param input is some binary data +* @param input_length length of input in bytes +* @param uppercase should output be upper or lower case? +*/ +void BOTAN_DLL hex_encode(char output[], + const byte input[], + u32bit input_length, + bool uppercase = true); + +/** +* Perform hex encoding +* @param input some input +* @param input_length length of input in bytes +* @param uppercase should output be upper or lower case? +* @return hexadecimal representation of input +*/ +std::string BOTAN_DLL hex_encode(const byte input[], + u32bit input_length, + bool uppercase = true); + +/** +* Perform hex decoding +* @param output an array of at least input_length/2 bytes +* @param input some hex input +* @param input_length length of input in bytes +* @param input_consumed is an output parameter which says how many +* bytes of input were actually consumed. If less than +* input_length, then the range input[consumed:length] +* should be passed in later along with more input. +* @param ignore_ws ignore whitespace on input; if false, throw an + exception if whitespace is encountered +* @return number of bytes written to output +*/ +u32bit BOTAN_DLL hex_decode(byte output[], + const char input[], + u32bit input_length, + u32bit& input_consumed, + bool ignore_ws = true); + +/** +* Perform hex decoding +* @param output an array of at least input_length/2 bytes +* @param input some hex input +* @param input_length length of input in bytes +* @param ignore_ws ignore whitespace on input; if false, throw an + exception if whitespace is encountered +* @return number of bytes written to output +*/ +u32bit BOTAN_DLL hex_decode(byte output[], + const char input[], + u32bit input_length, + bool ignore_ws = true); + +/** +* Perform hex decoding +* @param output an array of at least input_length/2 bytes +* @param input some hex input +* @param ignore_ws ignore whitespace on input; if false, throw an + exception if whitespace is encountered +* @return number of bytes written to output +*/ +u32bit BOTAN_DLL hex_decode(byte output[], + const std::string& input, + bool ignore_ws = true); + +/** +* Perform hex decoding +* @param input some hex input +* @param input_length the length of input in bytes +* @param ignore_ws ignore whitespace on input; if false, throw an + exception if whitespace is encountered +* @return decoded hex output +*/ +SecureVector<byte> BOTAN_DLL hex_decode(const char input[], + u32bit input_length, + bool ignore_ws = true); + +/** +* Perform hex decoding +* @param input some hex input +* @param ignore_ws ignore whitespace on input; if false, throw an + exception if whitespace is encountered +* @return decoded hex output +*/ +SecureVector<byte> BOTAN_DLL hex_decode(const std::string& input, + bool ignore_ws = true); + +} + +#endif diff --git a/src/codec/hex/info.txt b/src/codec/hex/info.txt new file mode 100644 index 000000000..c9eb8fb73 --- /dev/null +++ b/src/codec/hex/info.txt @@ -0,0 +1 @@ +define HEX_CODEC diff --git a/src/constructs/passhash/passhash9.cpp b/src/constructs/passhash/passhash9.cpp index 920aafc4c..6618f36fa 100644 --- a/src/constructs/passhash/passhash9.cpp +++ b/src/constructs/passhash/passhash9.cpp @@ -23,6 +23,8 @@ const u32bit ALGID_BYTES = 1; const u32bit SALT_BYTES = 12; // 96 bits of salt const u32bit PASSHASH9_PBKDF_OUTPUT_LEN = 24; // 192 bits output +const byte PASSHASH9_DEFAULT_ALGO = 0; // HMAC(SHA-1) + const u32bit WORK_FACTOR_SCALE = 10000; MessageAuthenticationCode* get_pbkdf_prf(byte alg_id) @@ -33,34 +35,37 @@ MessageAuthenticationCode* get_pbkdf_prf(byte alg_id) { if(alg_id == 0) return af.make_mac("HMAC(SHA-1)"); + else if(alg_id == 1) + return af.make_mac("HMAC(SHA-256)"); + else if(alg_id == 2) + return af.make_mac("CMAC(Blowfish)"); } catch(Algorithm_Not_Found) {} return 0; } -std::pair<byte, MessageAuthenticationCode*> choose_pbkdf_prf() - { - for(byte alg_id = 0; alg_id != 255; ++alg_id) - { - MessageAuthenticationCode* prf = get_pbkdf_prf(alg_id); - if(prf) - return std::make_pair(alg_id, prf); - } +} - throw Internal_Error("Passhash9: No PRF available"); +std::string generate_passhash9(const std::string& pass, + RandomNumberGenerator& rng, + u16bit work_factor) + { + return generate_passhash9(pass, PASSHASH9_DEFAULT_ALGO, rng, work_factor); } -} - std::string generate_passhash9(const std::string& pass, + byte alg_id, RandomNumberGenerator& rng, u16bit work_factor) { - std::pair<byte, MessageAuthenticationCode*> prf = choose_pbkdf_prf(); - byte alg_id = prf.first; + MessageAuthenticationCode* prf = get_pbkdf_prf(alg_id); + + if(!prf) + throw Invalid_Argument("Passhash9: Algorithm id " + to_string(alg_id) + + " is not defined"); - PKCS5_PBKDF2 kdf(prf.second); // takes ownership of pointer + PKCS5_PBKDF2 kdf(prf); // takes ownership of pointer SecureVector<byte> salt(SALT_BYTES); rng.randomize(&salt[0], salt.size()); diff --git a/src/constructs/passhash/passhash9.h b/src/constructs/passhash/passhash9.h index 8900d55d3..92cc391dc 100644 --- a/src/constructs/passhash/passhash9.h +++ b/src/constructs/passhash/passhash9.h @@ -23,6 +23,22 @@ std::string BOTAN_DLL generate_passhash9(const std::string& password, u16bit work_factor = 10); /** +* Create a password hash using PBKDF2 +* @param password the password +* @param alg_id specifies which PRF to use with PBKDF2 +* 0 is HMAC(SHA-1) +* 1 is HMAC(SHA-256) +* 2 is CMAC(Blowfish) +* all other values are currently undefined +* @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, + byte alg_id, + 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 diff --git a/src/constructs/tss/tss.cpp b/src/constructs/tss/tss.cpp index 101640f96..daad9f6bf 100644 --- a/src/constructs/tss/tss.cpp +++ b/src/constructs/tss/tss.cpp @@ -106,9 +106,7 @@ HashFunction* get_rtss_hash_by_id(byte id) RTSS_Share::RTSS_Share(const std::string& hex_input) { - Pipe pipe(new Hex_Decoder); - pipe.process_msg(hex_input); - contents = pipe.read_all(); + contents = hex_decode(hex_input); } byte RTSS_Share::share_id() const @@ -121,9 +119,7 @@ byte RTSS_Share::share_id() const std::string RTSS_Share::to_string() const { - Pipe pipe(new Hex_Encoder); - pipe.process_msg(contents); - return pipe.read_all_as_string(); + return hex_encode(&contents[0], contents.size()); } std::vector<RTSS_Share> diff --git a/src/filters/data_snk.cpp b/src/filters/data_snk.cpp index f8ee9f86e..d61fcc61f 100644 --- a/src/filters/data_snk.cpp +++ b/src/filters/data_snk.cpp @@ -17,8 +17,8 @@ namespace Botan { */ void DataSink_Stream::write(const byte out[], u32bit length) { - sink->write(reinterpret_cast<const char*>(out), length); - if(!sink->good()) + sink.write(reinterpret_cast<const char*>(out), length); + if(!sink.good()) throw Stream_IO_Error("DataSink_Stream: Failure writing to " + identifier); } @@ -28,9 +28,10 @@ void DataSink_Stream::write(const byte out[], u32bit length) */ DataSink_Stream::DataSink_Stream(std::ostream& out, const std::string& name) : - identifier(name != "" ? name : "<std::ostream>"), owner(false) + identifier(name), + sink_p(0), + sink(out) { - sink = &out; } /* @@ -38,15 +39,17 @@ DataSink_Stream::DataSink_Stream(std::ostream& out, */ DataSink_Stream::DataSink_Stream(const std::string& path, bool use_binary) : - identifier(path), owner(true) + identifier(path), + sink_p(use_binary ? + new std::ofstream(path.c_str(), std::ios::binary) : + new std::ofstream(path.c_str())), + sink(*sink_p) { - if(use_binary) - sink = new std::ofstream(path.c_str(), std::ios::binary); - else - sink = new std::ofstream(path.c_str()); - - if(!sink->good()) + if(!sink.good()) + { + delete sink_p; throw Stream_IO_Error("DataSink_Stream: Failure opening " + path); + } } /* @@ -54,9 +57,7 @@ DataSink_Stream::DataSink_Stream(const std::string& path, */ DataSink_Stream::~DataSink_Stream() { - if(owner) - delete sink; - sink = 0; + delete sink_p; } } diff --git a/src/filters/data_snk.h b/src/filters/data_snk.h index 8d7fac3e1..b6f44db7f 100644 --- a/src/filters/data_snk.h +++ b/src/filters/data_snk.h @@ -43,7 +43,7 @@ class BOTAN_DLL DataSink_Stream : public DataSink * @param name identifier */ DataSink_Stream(std::ostream& stream, - const std::string& name = ""); + const std::string& name = "<std::ostream>"); /** * Construct a DataSink_Stream from a stream. @@ -57,9 +57,9 @@ class BOTAN_DLL DataSink_Stream : public DataSink ~DataSink_Stream(); private: const std::string identifier; - const bool owner; - std::ostream* sink; + std::ostream* sink_p; + std::ostream& sink; }; } diff --git a/src/filters/data_src.cpp b/src/filters/data_src.cpp index e6387c4ba..522ce09d0 100644 --- a/src/filters/data_src.cpp +++ b/src/filters/data_src.cpp @@ -8,7 +8,6 @@ #include <botan/data_src.h> #include <botan/exceptn.h> - #include <fstream> #include <algorithm> @@ -107,11 +106,11 @@ DataSource_Memory::DataSource_Memory(const std::string& in) */ u32bit DataSource_Stream::read(byte out[], u32bit length) { - source->read(reinterpret_cast<char*>(out), length); - if(source->bad()) + source.read(reinterpret_cast<char*>(out), length); + if(source.bad()) throw Stream_IO_Error("DataSource_Stream::read: Source failure"); - u32bit got = source->gcount(); + u32bit got = source.gcount(); total_read += got; return got; } @@ -129,23 +128,23 @@ u32bit DataSource_Stream::peek(byte out[], u32bit length, u32bit offset) const if(offset) { SecureVector<byte> buf(offset); - source->read(reinterpret_cast<char*>(buf.begin()), buf.size()); - if(source->bad()) + source.read(reinterpret_cast<char*>(buf.begin()), buf.size()); + if(source.bad()) throw Stream_IO_Error("DataSource_Stream::peek: Source failure"); - got = source->gcount(); + got = source.gcount(); } if(got == offset) { - source->read(reinterpret_cast<char*>(out), length); - if(source->bad()) + source.read(reinterpret_cast<char*>(out), length); + if(source.bad()) throw Stream_IO_Error("DataSource_Stream::peek: Source failure"); - got = source->gcount(); + got = source.gcount(); } - if(source->eof()) - source->clear(); - source->seekg(total_read, std::ios::beg); + if(source.eof()) + source.clear(); + source.seekg(total_read, std::ios::beg); return got; } @@ -155,7 +154,7 @@ u32bit DataSource_Stream::peek(byte out[], u32bit length, u32bit offset) const */ bool DataSource_Stream::end_of_data() const { - return (!source->good()); + return (!source.good()); } /* @@ -171,15 +170,17 @@ std::string DataSource_Stream::id() const */ DataSource_Stream::DataSource_Stream(const std::string& path, bool use_binary) : - identifier(path), owner(true) + identifier(path), + source_p(use_binary ? + new std::ifstream(path.c_str()) : + new std::ifstream(path.c_str(), std::ios::binary)), + source(*source_p) { - if(use_binary) - source = new std::ifstream(path.c_str(), std::ios::binary); - else - source = new std::ifstream(path.c_str()); - - if(!source->good()) + if(!source.good()) + { + delete source_p; throw Stream_IO_Error("DataSource: Failure opening file " + path); + } total_read = 0; } @@ -189,9 +190,10 @@ DataSource_Stream::DataSource_Stream(const std::string& path, */ DataSource_Stream::DataSource_Stream(std::istream& in, const std::string& name) : - identifier(name), owner(false) + identifier(name), + source_p(0), + source(in) { - source = ∈ total_read = 0; } @@ -200,8 +202,7 @@ DataSource_Stream::DataSource_Stream(std::istream& in, */ DataSource_Stream::~DataSource_Stream() { - if(owner) - delete source; + delete source_p; } } diff --git a/src/filters/data_src.h b/src/filters/data_src.h index 016402b61..823b4a013 100644 --- a/src/filters/data_src.h +++ b/src/filters/data_src.h @@ -129,7 +129,8 @@ class BOTAN_DLL DataSource_Stream : public DataSource bool end_of_data() const; std::string id() const; - DataSource_Stream(std::istream&, const std::string& id = ""); + DataSource_Stream(std::istream&, + const std::string& id = "<std::istream>"); /** * Construct a Stream-Based DataSource from file @@ -141,9 +142,9 @@ class BOTAN_DLL DataSource_Stream : public DataSource ~DataSource_Stream(); private: const std::string identifier; - const bool owner; - std::istream* source; + std::istream* source_p; + std::istream& source; u32bit total_read; }; diff --git a/src/filters/filters.h b/src/filters/filters.h index e2c7cb5ec..51b4f00fe 100644 --- a/src/filters/filters.h +++ b/src/filters/filters.h @@ -24,8 +24,8 @@ #include <botan/base64.h> #endif -#if defined(BOTAN_HAS_HEX_CODEC) - #include <botan/hex.h> +#if defined(BOTAN_HAS_HEX_FILTER) + #include <botan/hex_filt.h> #endif namespace Botan { diff --git a/src/filters/hex/hex_char.cpp b/src/filters/hex/hex_char.cpp deleted file mode 100644 index c28efc5f7..000000000 --- a/src/filters/hex/hex_char.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/* -* Hex Character Table -* (C) 1999-2008 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/hex.h> - -namespace Botan { - -/* -* Hex Encoder Lookup Tables -*/ -const byte Hex_Encoder::BIN_TO_HEX_UPPER[16] = { -0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, -0x44, 0x45, 0x46 }; - -const byte Hex_Encoder::BIN_TO_HEX_LOWER[16] = { -0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63, -0x64, 0x65, 0x66 }; - -/* -* Hex Decoder Lookup Table -*/ -const byte Hex_Decoder::HEX_TO_BIN[256] = { -0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x01, 0x02, 0x03, -0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x80, -0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 }; - -} diff --git a/src/filters/hex/hex.cpp b/src/filters/hex_filt/hex_filt.cpp index 430958ebd..0f3daa464 100644 --- a/src/filters/hex/hex.cpp +++ b/src/filters/hex_filt/hex_filt.cpp @@ -5,6 +5,7 @@ * Distributed under the terms of the Botan license */ +#include <botan/hex_filt.h> #include <botan/hex.h> #include <botan/parsing.h> #include <botan/charset.h> @@ -40,24 +41,13 @@ Hex_Encoder::Hex_Encoder(Case c) : casing(c), line_length(0) } /* -* Hex Encoding Operation -*/ -void Hex_Encoder::encode(byte in, byte out[2], Hex_Encoder::Case casing) - { - const byte* BIN_TO_HEX = ((casing == Uppercase) ? BIN_TO_HEX_UPPER : - BIN_TO_HEX_LOWER); - - out[0] = BIN_TO_HEX[((in >> 4) & 0x0F)]; - out[1] = BIN_TO_HEX[((in ) & 0x0F)]; - } - -/* * Encode and send a block */ void Hex_Encoder::encode_and_send(const byte block[], u32bit length) { - for(u32bit j = 0; j != length; ++j) - encode(block[j], out + 2*j, casing); + hex_encode(reinterpret_cast<char*>(&out[0]), + block, length, + casing == Uppercase); if(line_length == 0) send(out, 2*length); @@ -125,62 +115,35 @@ Hex_Decoder::Hex_Decoder(Decoder_Checking c) : checking(c) } /* -* Check if a character is a valid hex char -*/ -bool Hex_Decoder::is_valid(byte in) - { - return (HEX_TO_BIN[in] != 0x80); - } - -/* -* Handle processing an invalid character -*/ -void Hex_Decoder::handle_bad_char(byte c) - { - if(checking == NONE) - return; - - if((checking == IGNORE_WS) && Charset::is_space(c)) - return; - - throw Decoding_Error("Hex_Decoder: Invalid hex character: " + - std::to_string(c)); - } - -/* -* Hex Decoding Operation -*/ -byte Hex_Decoder::decode(const byte hex[2]) - { - return ((HEX_TO_BIN[hex[0]] << 4) | HEX_TO_BIN[hex[1]]); - } - -/* -* Decode and send a block -*/ -void Hex_Decoder::decode_and_send(const byte block[], u32bit length) - { - for(u32bit j = 0; j != length / 2; ++j) - out[j] = decode(block + 2*j); - send(out, length / 2); - } - -/* * Convert some data from hex format */ void Hex_Decoder::write(const byte input[], u32bit length) { - for(u32bit j = 0; j != length; ++j) + while(length) { - if(is_valid(input[j])) - in[position++] = input[j]; - else - handle_bad_char(input[j]); - if(position == in.size()) + u32bit to_copy = std::min(length, in.size() - position); + copy_mem(&in[position], input, to_copy); + position += to_copy; + + u32bit consumed = 0; + u32bit written = hex_decode(&out[0], + reinterpret_cast<const char*>(&in[0]), + position, + consumed, + checking != FULL_CHECK); + + send(out, written); + + if(consumed != position) { - decode_and_send(in, in.size()); - position = 0; + copy_mem(&in[0], &in[consumed], position - consumed); + position = position - consumed; } + else + position = 0; + + length -= to_copy; + input += to_copy; } } @@ -189,8 +152,21 @@ void Hex_Decoder::write(const byte input[], u32bit length) */ void Hex_Decoder::end_msg() { - decode_and_send(in, position); + u32bit consumed = 0; + u32bit written = hex_decode(&out[0], + reinterpret_cast<const char*>(&in[0]), + position, + consumed, + checking != FULL_CHECK); + + send(out, written); + + const bool not_full_bytes = consumed != position; + position = 0; + + if(not_full_bytes) + throw std::invalid_argument("Hex_Decoder: Input not full bytes"); } } diff --git a/src/filters/hex/hex.h b/src/filters/hex_filt/hex_filt.h index 6698a61be..88bf35de8 100644 --- a/src/filters/hex/hex.h +++ b/src/filters/hex_filt/hex_filt.h @@ -1,19 +1,20 @@ /* * Hex Encoder/Decoder -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ -#ifndef BOTAN_HEX_H__ -#define BOTAN_HEX_H__ +#ifndef BOTAN_HEX_FILTER_H__ +#define BOTAN_HEX_FILTER_H__ #include <botan/filter.h> namespace Botan { /** -* This class represents a hex encoder. It encodes byte arrays to hex strings. +* Converts arbitrary binary data to hex strings, optionally with +* newlines inserted */ class BOTAN_DLL Hex_Encoder : public Filter { @@ -23,11 +24,6 @@ class BOTAN_DLL Hex_Encoder : public Filter */ enum Case { Uppercase, Lowercase }; - /** - * Encode a single byte into two hex characters - */ - static void encode(byte in, byte out[2], Case the_case = Uppercase); - std::string name() const { return "Hex_Encoder"; } void write(const byte in[], u32bit length); @@ -50,8 +46,6 @@ class BOTAN_DLL Hex_Encoder : public Filter Case the_case = Uppercase); private: void encode_and_send(const byte[], u32bit); - static const byte BIN_TO_HEX_UPPER[16]; - static const byte BIN_TO_HEX_LOWER[16]; const Case casing; const u32bit line_length; @@ -60,25 +54,11 @@ class BOTAN_DLL Hex_Encoder : public Filter }; /** -* This class represents a hex decoder. It converts hex strings to byte arrays. +* Converts hex strings to bytes */ class BOTAN_DLL Hex_Decoder : public Filter { public: - /** - * Decode a pair of hex chars to a byte - * @param in an array of two hex chars - * @return byte formed by decoding in - */ - static byte decode(const byte in[2]); - - /** - * Check if this character is a valid hex input - * @param c a single character - * @return true iff c is a valid hex char - */ - static bool is_valid(byte c); - std::string name() const { return "Hex_Decoder"; } void write(const byte[], u32bit); @@ -91,10 +71,6 @@ class BOTAN_DLL Hex_Decoder : public Filter */ Hex_Decoder(Decoder_Checking checking = NONE); private: - void decode_and_send(const byte[], u32bit); - void handle_bad_char(byte); - static const byte HEX_TO_BIN[256]; - const Decoder_Checking checking; SecureVector<byte> in, out; u32bit position; diff --git a/src/filters/hex/info.txt b/src/filters/hex_filt/info.txt index 0a4205669..7f5f47fa1 100644 --- a/src/filters/hex/info.txt +++ b/src/filters/hex_filt/info.txt @@ -1,4 +1,4 @@ -define HEX_CODEC +define HEX_FILTER <requires> filters diff --git a/src/libstate/get_enc.cpp b/src/libstate/get_enc.cpp index a825a5d24..1176061c2 100644 --- a/src/libstate/get_enc.cpp +++ b/src/libstate/get_enc.cpp @@ -15,7 +15,6 @@ #if defined(BOTAN_HAS_PBKDF2) #include <botan/pbkdf2.h> - #include <botan/hmac.h> #endif #if defined(BOTAN_HAS_PGPS2K) @@ -96,7 +95,12 @@ PBKDF* get_pbkdf(const std::string& algo_spec) #if defined(BOTAN_HAS_PBKDF2) if(request.algo_name() == "PBKDF2" && request.arg_count() == 1) - return new PKCS5_PBKDF2(new HMAC(af.make_hash_function(request.arg(0)))); + { + if(const MessageAuthenticationCode* mac_proto = af.prototype_mac(request.arg(0))) + return new PKCS5_PBKDF2(mac_proto->clone()); + + return new PKCS5_PBKDF2(af.make_mac("HMAC(" + request.arg(0) + ")")); + } #endif #if defined(BOTAN_HAS_PGPS2K) diff --git a/src/mac/hmac/hmac.cpp b/src/mac/hmac/hmac.cpp index f69504c82..0d5c99702 100644 --- a/src/mac/hmac/hmac.cpp +++ b/src/mac/hmac/hmac.cpp @@ -86,7 +86,7 @@ MessageAuthenticationCode* HMAC::clone() const */ HMAC::HMAC(HashFunction* hash_in) : MessageAuthenticationCode(hash_in->OUTPUT_LENGTH, - 1, 2*hash_in->HASH_BLOCK_SIZE), + 0, 2*hash_in->HASH_BLOCK_SIZE), hash(hash_in) { if(hash->HASH_BLOCK_SIZE == 0) diff --git a/src/math/bigint/big_code.cpp b/src/math/bigint/big_code.cpp index 74701e532..a8272390d 100644 --- a/src/math/bigint/big_code.cpp +++ b/src/math/bigint/big_code.cpp @@ -1,6 +1,6 @@ /* * BigInt Encoding/Decoding -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -23,8 +23,9 @@ void BigInt::encode(byte output[], const BigInt& n, Base base) { SecureVector<byte> binary(n.encoded_size(Binary)); n.binary_encode(binary); - for(u32bit j = 0; j != binary.size(); ++j) - Hex_Encoder::encode(binary[j], output + 2*j); + + hex_encode(reinterpret_cast<char*>(output), + &binary[0], binary.size()); } else if(base == Octal) { @@ -103,22 +104,23 @@ BigInt BigInt::decode(const byte buf[], u32bit length, Base base) r.binary_decode(buf, length); else if(base == Hexadecimal) { - SecureVector<byte> hex; - for(u32bit j = 0; j != length; ++j) - if(Hex_Decoder::is_valid(buf[j])) - hex.append(buf[j]); - - u32bit offset = (hex.size() % 2); - SecureVector<byte> binary(hex.size() / 2 + offset); + SecureVector<byte> binary; - if(offset) + if(length % 2) { - byte temp[2] = { '0', hex[0] }; - binary[0] = Hex_Decoder::decode(temp); + // Handle lack of leading 0 + const char buf0_with_leading_0[2] = { '0', buf[0] }; + binary = hex_decode(buf0_with_leading_0, 2); + + binary.append(hex_decode(reinterpret_cast<const char*>(&buf[1]), + length - 1, + false)); + } + else + binary = hex_decode(reinterpret_cast<const char*>(buf), + length, false); - for(u32bit j = offset; j != binary.size(); ++j) - binary[j] = Hex_Decoder::decode(hex+2*j-offset); r.binary_decode(binary, binary.size()); } else if(base == Decimal || base == Octal) diff --git a/src/math/bigint/bigint.h b/src/math/bigint/bigint.h index 2b95bfc90..aa2e4347e 100644 --- a/src/math/bigint/bigint.h +++ b/src/math/bigint/bigint.h @@ -545,7 +545,11 @@ BOTAN_DLL std::istream& operator>>(std::istream&, BigInt&); namespace std { -inline void swap(Botan::BigInt& a, Botan::BigInt& b) { a.swap(b); } +template<> +inline void swap(Botan::BigInt& x, Botan::BigInt& y) + { + x.swap(y); + } } diff --git a/src/math/bigint/info.txt b/src/math/bigint/info.txt index 0511c2d8d..7892a6edf 100644 --- a/src/math/bigint/info.txt +++ b/src/math/bigint/info.txt @@ -30,7 +30,7 @@ mp_shift.cpp <requires> alloc hex -mp_amd64|mp_amd64_msvc|mp_asm64|mp_ia32|mp_ia32_msvc|mp_generic +mp_amd64|mp_msvc64|mp_asm64|mp_ia32|mp_ia32_msvc|mp_generic monty_generic mulop_generic rng diff --git a/src/math/bigint/mp_amd64_msvc/info.txt b/src/math/bigint/mp_msvc64/info.txt index 56ae05927..56ae05927 100644 --- a/src/math/bigint/mp_amd64_msvc/info.txt +++ b/src/math/bigint/mp_msvc64/info.txt diff --git a/src/math/bigint/mp_amd64_msvc/mp_asm.h b/src/math/bigint/mp_msvc64/mp_asm.h index 3acbe11bb..8e4535c35 100644 --- a/src/math/bigint/mp_amd64_msvc/mp_asm.h +++ b/src/math/bigint/mp_msvc64/mp_asm.h @@ -12,7 +12,7 @@ #include <intrin.h> #if (BOTAN_MP_WORD_BITS != 64) - #error The mp_amd64_msvc module requires that BOTAN_MP_WORD_BITS == 64 + #error The mp_msvc64 module requires that BOTAN_MP_WORD_BITS == 64 #endif #pragma intrinsic(_umul128) diff --git a/src/pbkdf/pbkdf.h b/src/pbkdf/pbkdf.h index 7262a4d9f..14615103f 100644 --- a/src/pbkdf/pbkdf.h +++ b/src/pbkdf/pbkdf.h @@ -38,11 +38,10 @@ class BOTAN_DLL PBKDF virtual void clear() {} /** - * Derive a key from a passphrase with this PBKDF object. It will use - * the salt value and number of iterations configured in this object. + * Derive a key from a passphrase * @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 a randomly chosen salt * @param salt_len length of salt in bytes * @param iterations the number of iterations to use (use 10K or more) */ diff --git a/src/pbkdf/pbkdf2/pbkdf2.cpp b/src/pbkdf/pbkdf2/pbkdf2.cpp index e88a5749a..6f6a514f8 100644 --- a/src/pbkdf/pbkdf2/pbkdf2.cpp +++ b/src/pbkdf/pbkdf2/pbkdf2.cpp @@ -22,11 +22,16 @@ OctetString PKCS5_PBKDF2::derive_key(u32bit key_len, if(iterations == 0) throw Invalid_Argument("PKCS#5 PBKDF2: Invalid iteration count"); - if(passphrase.length() == 0) - throw Invalid_Argument("PKCS#5 PBKDF2: Empty passphrase is invalid"); - - mac->set_key(reinterpret_cast<const byte*>(passphrase.data()), - passphrase.length()); + try + { + mac->set_key(reinterpret_cast<const byte*>(passphrase.data()), + passphrase.length()); + } + catch(Invalid_Key_Length) + { + throw Exception(name() + " cannot accept passphrases of length " + + to_string(passphrase.length())); + } SecureVector<byte> key(key_len); diff --git a/src/pbkdf/pbkdf2/pbkdf2.h b/src/pbkdf/pbkdf2/pbkdf2.h index 2b25a7b1d..8b50b4a67 100644 --- a/src/pbkdf/pbkdf2/pbkdf2.h +++ b/src/pbkdf/pbkdf2/pbkdf2.h @@ -36,9 +36,9 @@ class BOTAN_DLL PKCS5_PBKDF2 : public PBKDF /** * Create a PKCS #5 instance using the specified message auth code - * @param mac the MAC to use + * @param mac_fn the MAC to use */ - PKCS5_PBKDF2(MessageAuthenticationCode* m) : mac(m) {} + PKCS5_PBKDF2(MessageAuthenticationCode* mac_fn) : mac(mac_fn) {} /** * Destructor diff --git a/src/ssl/info.txt b/src/ssl/info.txt index 1d28cf4f8..f0867b3f1 100644 --- a/src/ssl/info.txt +++ b/src/ssl/info.txt @@ -38,3 +38,23 @@ tls_server.cpp tls_session_key.cpp tls_suites.cpp </source> + +<requires> +alloc +asn1 +bigint +dh +dl_group +dsa +filters +libstate +md5 +pubkey +rng +rsa +sha1 +ssl_prf +sym_algo +tls_prf +x509 +</requires> diff --git a/src/sym_algo/symkey.cpp b/src/sym_algo/symkey.cpp index 97bd08819..bf2b705d3 100644 --- a/src/sym_algo/symkey.cpp +++ b/src/sym_algo/symkey.cpp @@ -29,16 +29,11 @@ OctetString::OctetString(RandomNumberGenerator& rng, */ void OctetString::change(const std::string& hex_string) { - SecureVector<byte> hex; - for(u32bit j = 0; j != hex_string.length(); ++j) - if(Hex_Decoder::is_valid(hex_string[j])) - hex.append(hex_string[j]); - - if(hex.size() % 2 != 0) - throw Invalid_Argument("OctetString: hex string must encode full bytes"); - bits.resize(hex.size() / 2); - for(u32bit j = 0; j != bits.size(); ++j) - bits[j] = Hex_Decoder::decode(hex.begin() + 2*j); + SecureVector<byte> decoded(hex_string.length() / 2); + + u32bit written = hex_decode(&decoded[0], hex_string); + + bits.set(&decoded[0], written); } /* @@ -88,9 +83,7 @@ void OctetString::set_odd_parity() */ std::string OctetString::as_string() const { - Pipe pipe(new Hex_Encoder); - pipe.process_msg(bits); - return pipe.read_all_as_string(); + return hex_encode(&bits[0], bits.size()); } /* diff --git a/src/utils/datastor/datastor.cpp b/src/utils/datastor/datastor.cpp index 85b0f22ba..363136c69 100644 --- a/src/utils/datastor/datastor.cpp +++ b/src/utils/datastor/datastor.cpp @@ -8,8 +8,8 @@ #include <botan/datastor.h> #include <botan/exceptn.h> #include <botan/parsing.h> +#include <botan/hex.h> #include <botan/internal/stl_util.h> -#include <botan/filters.h> namespace Botan { @@ -79,19 +79,14 @@ Data_Store::get1_memvec(const std::string& key) const { std::vector<std::string> vals = get(key); + if(vals.empty()) + return MemoryVector<byte>(); + if(vals.size() > 1) throw Invalid_State("Data_Store::get1_memvec: Multiple values for " + key); - if(vals.empty()) - return MemoryVector<byte>(); - - Pipe pipe(new Hex_Decoder(FULL_CHECK)); - pipe.start_msg(); - if(vals.size()) - pipe.write(vals[0]); - pipe.end_msg(); - return pipe.read_all(); + return hex_decode(vals[0]); } /* @@ -132,9 +127,7 @@ void Data_Store::add(const std::string& key, u32bit val) */ void Data_Store::add(const std::string& key, const MemoryRegion<byte>& val) { - Pipe pipe(new Hex_Encoder); - pipe.process_msg(val); - add(key, pipe.read_all_as_string()); + add(key, hex_encode(&val[0], val.size())); } /* diff --git a/src/utils/datastor/info.txt b/src/utils/datastor/info.txt index 93e938d78..b91fe5082 100644 --- a/src/utils/datastor/info.txt +++ b/src/utils/datastor/info.txt @@ -1,4 +1,3 @@ <requires> alloc -filters </requires> diff --git a/src/utils/dyn_load/dyn_load.cpp b/src/utils/dyn_load/dyn_load.cpp index 6d359bc01..5f3814778 100644 --- a/src/utils/dyn_load/dyn_load.cpp +++ b/src/utils/dyn_load/dyn_load.cpp @@ -11,10 +11,23 @@ #if defined(BOTAN_TARGET_OS_HAS_DLOPEN) #include <dlfcn.h> +#elif defined(BOTAN_TARGET_OS_HAS_LOADLIBRARY) + #include <windows.h> #endif namespace Botan { +namespace { + +void raise_runtime_loader_exception(const std::string& lib_name, + const char* msg) + { + throw std::runtime_error("Failed to load " + lib_name + ": " + + (msg ? msg : "Unknown error")); + } + +} + Dynamically_Loaded_Library::Dynamically_Loaded_Library( const std::string& library) : lib_name(library), lib(0) @@ -23,22 +36,25 @@ Dynamically_Loaded_Library::Dynamically_Loaded_Library( lib = ::dlopen(lib_name.c_str(), RTLD_LAZY); if(!lib) - { - const char* dl_err = dlerror(); - if(!dl_err) - dl_err = "Unknown error"; - - throw std::runtime_error("Failed to load engine " + lib_name + ": " + - dl_err); - } + raise_runtime_loader_exception(lib_name, dlerror()); + +#elif defined(BOTAN_TARGET_OS_HAS_LOADLIBRARY) + lib = ::LoadLibrary(lib_name.c_str()); + + if(!lib) + raise_runtime_loader_exception(lib_name, "LoadLibrary failed"); #endif + if(!lib) + raise_runtime_loader_exception(lib_name, "Dynamic load not supported"); } Dynamically_Loaded_Library::~Dynamically_Loaded_Library() { #if defined(BOTAN_TARGET_OS_HAS_DLOPEN) ::dlclose(lib); +#elif defined(BOTAN_TARGET_OS_HAS_LOADLIBRARY) + ::FreeLibrary(lib); #endif } @@ -48,6 +64,8 @@ void* Dynamically_Loaded_Library::resolve_symbol(const std::string& symbol) #if defined(BOTAN_TARGET_OS_HAS_DLOPEN) addr = ::dlsym(lib, symbol.c_str()); +#elif defined(BOTAN_TARGET_OS_HAS_LOADLIBRARY) + addr = ::GetProcAddress(lib, symbol.c_str()); #endif if(!addr) diff --git a/src/utils/dyn_load/dyn_load.h b/src/utils/dyn_load/dyn_load.h index 56277d3e4..c8fb31cf0 100644 --- a/src/utils/dyn_load/dyn_load.h +++ b/src/utils/dyn_load/dyn_load.h @@ -18,6 +18,11 @@ class Dynamically_Loaded_Library /** * Load a DLL (or fail with an exception) * @param lib_name name or path to a library + * + * If you don't use a full path, the search order will be defined + * by whatever the system linker does by default. Always using fully + * qualified pathnames can help prevent code injection attacks (eg + * via manipulation of LD_LIBRARY_PATH on Linux) */ Dynamically_Loaded_Library(const std::string& lib_name); diff --git a/src/wrap/perl-xs/Botan.xs b/src/wrap/perl-xs/Botan.xs index ded129d2e..5268a96d1 100644 --- a/src/wrap/perl-xs/Botan.xs +++ b/src/wrap/perl-xs/Botan.xs @@ -14,7 +14,7 @@ extern "C" { #include <botan/asn1_oid.h> #include <botan/base64.h> #include <botan/basefilt.h> -#include <botan/hex.h> +#include <botan/hex_filt.h> #include <botan/init.h> #include <botan/oids.h> #include <botan/x509cert.h> |