aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/alloc/secmem.h10
-rw-r--r--src/block/aes/aes.cpp77
-rw-r--r--src/build-data/arch/ia32.txt1
-rw-r--r--src/build-data/cc/gcc.txt1
-rw-r--r--src/build-data/os/windows.txt1
-rw-r--r--src/codec/hex/hex.cpp180
-rw-r--r--src/codec/hex/hex.h108
-rw-r--r--src/codec/hex/info.txt1
-rw-r--r--src/constructs/passhash/passhash9.cpp33
-rw-r--r--src/constructs/passhash/passhash9.h16
-rw-r--r--src/constructs/tss/tss.cpp8
-rw-r--r--src/filters/data_snk.cpp29
-rw-r--r--src/filters/data_snk.h6
-rw-r--r--src/filters/data_src.cpp51
-rw-r--r--src/filters/data_src.h7
-rw-r--r--src/filters/filters.h4
-rw-r--r--src/filters/hex/hex_char.cpp48
-rw-r--r--src/filters/hex_filt/hex_filt.cpp (renamed from src/filters/hex/hex.cpp)104
-rw-r--r--src/filters/hex_filt/hex_filt.h (renamed from src/filters/hex/hex.h)36
-rw-r--r--src/filters/hex_filt/info.txt (renamed from src/filters/hex/info.txt)2
-rw-r--r--src/libstate/get_enc.cpp8
-rw-r--r--src/mac/hmac/hmac.cpp2
-rw-r--r--src/math/bigint/big_code.cpp32
-rw-r--r--src/math/bigint/bigint.h6
-rw-r--r--src/math/bigint/info.txt2
-rw-r--r--src/math/bigint/mp_msvc64/info.txt (renamed from src/math/bigint/mp_amd64_msvc/info.txt)0
-rw-r--r--src/math/bigint/mp_msvc64/mp_asm.h (renamed from src/math/bigint/mp_amd64_msvc/mp_asm.h)2
-rw-r--r--src/pbkdf/pbkdf.h5
-rw-r--r--src/pbkdf/pbkdf2/pbkdf2.cpp15
-rw-r--r--src/pbkdf/pbkdf2/pbkdf2.h4
-rw-r--r--src/ssl/info.txt20
-rw-r--r--src/sym_algo/symkey.cpp19
-rw-r--r--src/utils/datastor/datastor.cpp19
-rw-r--r--src/utils/datastor/info.txt1
-rw-r--r--src/utils/dyn_load/dyn_load.cpp34
-rw-r--r--src/utils/dyn_load/dyn_load.h5
-rw-r--r--src/wrap/perl-xs/Botan.xs2
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 = &in;
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>