diff options
54 files changed, 1006 insertions, 509 deletions
diff --git a/checks/bench.cpp b/checks/bench.cpp index e733c75ec..df346ec75 100644 --- a/checks/bench.cpp +++ b/checks/bench.cpp @@ -147,7 +147,7 @@ void report_results(const std::string& algo, std::cout << " [" << i->second << "] " << std::fixed << std::setprecision(2) << i->first; } - std::cout << "\n"; + std::cout << std::endl; } } diff --git a/checks/check.cpp b/checks/check.cpp index 8b31f354d..975315608 100644 --- a/checks/check.cpp +++ b/checks/check.cpp @@ -123,7 +123,7 @@ int main(int argc, char* argv[]) opts.is_set("benchmark") || opts.is_set("bench-type")) { - double seconds = 2; + double seconds = 5; if(opts.is_set("seconds")) { diff --git a/checks/misc.cpp b/checks/misc.cpp index 198671451..a49778dc6 100644 --- a/checks/misc.cpp +++ b/checks/misc.cpp @@ -43,7 +43,7 @@ SecureVector<byte> decode_hex(const std::string& in) pipe.process_msg(in); result = pipe.read_all(); } - catch(std::exception& e) + catch(std::exception) { result.destroy(); } diff --git a/checks/validate.dat b/checks/validate.dat index ff2ed2f4b..9d319eaf3 100644 --- a/checks/validate.dat +++ b/checks/validate.dat @@ -4799,6 +4799,12 @@ D5D5D5D5D5D5D5D5:75F7C7005EA47839:D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5 0000000000000000:AA553A5DEC50E4A4:00000000000000040000000000000000 0000000000000001:0013FFF500120009:00000000000000000000000000000000 +000000010002000301020304050607080019324B647D96AFF5202D5B9C671B08\ +FAE6D2BEAA96826E0A141E28323C4650050A0F14191E2328050A0F14191E2328:\ +11FBED2B01986DE5540E5FEA18C2F8B19F0A0AB6E10CED78CF18FD7355E2C5C5\ +85DF52005608193D2F7DE750212FB7347B7314925DE59C097B7314925DE59C09:\ +00010002000300040005000600070008 + # Test vectors taken from ARIB STD-T63-35.203 V6.0.0 [KASUMI] EA024714AD5C4D84:DF1F9B251C0BF45F:2BD6459F82C5B300952C49104881FF48 @@ -23023,6 +23029,17 @@ AAE1BA501274C49A7A7EC67D7577114B7707DAB9D066AF086C09E7DD4116CEA6\ EE25DA9A65EF05A31ED0BDF56D525EC8968D1D01AF7165C5AEAC76BD367A575A:\ 00000000000000000000000000000000 +[IDEA/ECB/NoPadding] +000000010002000301020304050607080019324B647D96AFF5202D5B9C671B08\ +FAE6D2BEAA96826E0A141E28323C4650050A0F14191E2328050A0F14191E2328\ +000000010002000301020304050607080019324B647D96AFF5202D5B9C671B08\ +FAE6D2BEAA96826E0A141E28323C4650050A0F14191E2328050A0F14191E2328:\ +11FBED2B01986DE5540E5FEA18C2F8B19F0A0AB6E10CED78CF18FD7355E2C5C5\ +85DF52005608193D2F7DE750212FB7347B7314925DE59C097B7314925DE59C09\ +11FBED2B01986DE5540E5FEA18C2F8B19F0A0AB6E10CED78CF18FD7355E2C5C5\ +85DF52005608193D2F7DE750212FB7347B7314925DE59C097B7314925DE59C09:\ +00010002000300040005000600070008 + [DES/ECB/NoPadding] 059B5E0851CF143A:86A560F10EC6D85B:0113B970FD34F2CE 4E6F772069732074:3FA40E8A984D4815:0123456789ABCDEF diff --git a/configure.py b/configure.py index 5298f7eb3..97e591b5d 100755 --- a/configure.py +++ b/configure.py @@ -121,6 +121,13 @@ class BuildConfigurationInformation(object): Handle command line options """ def process_command_line(args): + + # This is just an implementation of Optik's append_const action, + # but that is not available in Python 2.4's optparse, so use a + # callback instead + def optparse_append_const(option, opt, value, parser, dest, arg): + parser.values.__dict__[dest].append(arg) + parser = OptionParser( formatter = IndentedHelpFormatter(max_help_position = 50), version = BuildConfigurationInformation.version_string) @@ -145,10 +152,34 @@ def process_command_line(args): dest='unaligned_mem', action='store_false', help=SUPPRESS_HELP) - target_group.add_option('--with-isa-extension', metavar='ISALIST', - dest='with_isa_extns', + target_group.add_option('--enable-isa', metavar='ISALIST', + dest='enable_isa_extns', + action='append', default=[], + help='enable ISA extensions') + + target_group.add_option('--disable-isa', metavar='ISALIST', + dest='disable_isa_extns', action='append', default=[], - help='enable ISA extensions (sse2, altivec)') + help=SUPPRESS_HELP) + + for isa_extn in ['sse2', 'ssse3', 'altivec', 'aes_ni']: + target_group.add_option('--enable-%s' % (isa_extn), + action='callback', + help=SUPPRESS_HELP, + callback=optparse_append_const, + callback_kwargs = { + 'dest': 'enable_isa_extns', + 'arg': isa_extn } + ) + + target_group.add_option('--disable-%s' % (isa_extn), + action='callback', + help=SUPPRESS_HELP, + callback=optparse_append_const, + callback_kwargs = { + 'dest': 'disable_isa_extns', + 'arg': isa_extn } + ) build_group = OptionGroup(parser, 'Build options') @@ -208,25 +239,18 @@ def process_command_line(args): for mod in ['openssl', 'gnump', 'bzip2', 'zlib']: - # This is just an implementation of Optik's append_const action, - # but that is not available in Python 2.4's optparse, so use a - # callback instead - - def optparse_callback(option, opt, value, parser, dest, mod): - parser.values.__dict__[dest].append(mod) - mods_group.add_option('--with-%s' % (mod), action='callback', - callback=optparse_callback, + callback=optparse_append_const, callback_kwargs = { - 'dest': 'enabled_modules', 'mod': mod } + 'dest': 'enabled_modules', 'arg': mod } ) mods_group.add_option('--without-%s' % (mod), help=SUPPRESS_HELP, action='callback', - callback=optparse_callback, + callback=optparse_append_const, callback_kwargs = { - 'dest': 'disabled_modules', 'mod': mod } + 'dest': 'disabled_modules', 'arg': mod } ) install_group = OptionGroup(parser, 'Installation options') @@ -284,7 +308,8 @@ def process_command_line(args): options.enabled_modules = parse_multiple_enable(options.enabled_modules) options.disabled_modules = parse_multiple_enable(options.disabled_modules) - options.with_isa_extns = parse_multiple_enable(options.with_isa_extns) + options.enable_isa_extns = parse_multiple_enable(options.enable_isa_extns) + options.disable_isa_extns = parse_multiple_enable(options.disable_isa_extns) return options @@ -443,9 +468,14 @@ class ModuleInfo(object): return False if self.need_isa != None: - cpu_isa = archinfo.isa_extensions_in(cpu_name) - if self.need_isa not in cpu_isa: - return self.need_isa in options.with_isa_extns + if self.need_isa in options.disable_isa_extns: + return False # explicitly disabled + + if self.need_isa in options.enable_isa_extns: + return True # explicitly enabled + + # Default to whatever the CPU is supposed to support + return self.need_isa in archinfo.isa_extensions_in(cpu_name) return True @@ -532,12 +562,16 @@ class ArchInfo(object): if self.basename != options.cpu: macros.append('TARGET_CPU_IS_%s' % (form_cpu_macro(options.cpu))) - isa_extensions = sorted(set( - flatten([self.isa_extensions_in(options.cpu), - options.with_isa_extns]))) + enabled_isas = set(flatten( + [self.isa_extensions_in(options.cpu), + options.enable_isa_extns])) + + disabled_isas = set(options.disable_isa_extns) + + isa_extensions = sorted(enabled_isas - disabled_isas) - for simd in isa_extensions: - macros.append('TARGET_CPU_HAS_%s' % (simd.upper())) + for isa in isa_extensions: + macros.append('TARGET_CPU_HAS_%s' % (isa.upper())) endian = options.with_endian or self.endian diff --git a/doc/log.txt b/doc/log.txt index 6334ee995..c150e6f66 100644 --- a/doc/log.txt +++ b/doc/log.txt @@ -1,5 +1,8 @@ * 1.9.4-dev, ????-??-?? + - Add SSE2 implementation of IDEA + - Add support for Win32 high resolution system timers + - Remove Timer class entirely - New option --gen-amalgamation for creating a SQLite-style amalgamation - Many headers are now explicitly internal-use-only and are not installed - Greatly improve the Win32 installer diff --git a/src/block/idea/idea.cpp b/src/block/idea/idea.cpp index fb5fe83f1..15ff7c0ec 100644 --- a/src/block/idea/idea.cpp +++ b/src/block/idea/idea.cpp @@ -55,13 +55,13 @@ u16bit mul_inv(u16bit x) return (1 - t0); } -} - -/* -* IDEA Encryption +/** +* IDEA is involutional, depending only on the key schedule */ -void IDEA::encrypt_n(const byte in[], byte out[], u32bit blocks) const +void idea_op(const byte in[], byte out[], u32bit blocks, const u16bit K[52]) { + const u32bit BLOCK_SIZE = 8; + for(u32bit i = 0; i != blocks; ++i) { u16bit X1 = load_be<u16bit>(in, 0); @@ -71,16 +71,16 @@ void IDEA::encrypt_n(const byte in[], byte out[], u32bit blocks) const for(u32bit j = 0; j != 8; ++j) { - X1 = mul(X1, EK[6*j+0]); - X2 += EK[6*j+1]; - X3 += EK[6*j+2]; - X4 = mul(X4, EK[6*j+3]); + X1 = mul(X1, K[6*j+0]); + X2 += K[6*j+1]; + X3 += K[6*j+2]; + X4 = mul(X4, K[6*j+3]); u16bit T0 = X3; - X3 = mul(X3 ^ X1, EK[6*j+4]); + X3 = mul(X3 ^ X1, K[6*j+4]); u16bit T1 = X2; - X2 = mul((X2 ^ X4) + X3, EK[6*j+5]); + X2 = mul((X2 ^ X4) + X3, K[6*j+5]); X3 += X2; X1 ^= X2; @@ -89,10 +89,10 @@ void IDEA::encrypt_n(const byte in[], byte out[], u32bit blocks) const X3 ^= T1; } - X1 = mul(X1, EK[48]); - X2 += EK[50]; - X3 += EK[49]; - X4 = mul(X4, EK[51]); + X1 = mul(X1, K[48]); + X2 += K[50]; + X3 += K[49]; + X4 = mul(X4, K[51]); store_be(out, X1, X3, X2, X4); @@ -101,48 +101,22 @@ void IDEA::encrypt_n(const byte in[], byte out[], u32bit blocks) const } } +} + +/* +* IDEA Encryption +*/ +void IDEA::encrypt_n(const byte in[], byte out[], u32bit blocks) const + { + idea_op(in, out, blocks, EK); + } + /* * IDEA Decryption */ void IDEA::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - for(u32bit i = 0; i != blocks; ++i) - { - u16bit X1 = load_be<u16bit>(in, 0); - u16bit X2 = load_be<u16bit>(in, 1); - u16bit X3 = load_be<u16bit>(in, 2); - u16bit X4 = load_be<u16bit>(in, 3); - - for(u32bit j = 0; j != 8; ++j) - { - X1 = mul(X1, DK[6*j+0]); - X2 += DK[6*j+1]; - X3 += DK[6*j+2]; - X4 = mul(X4, DK[6*j+3]); - - u16bit T0 = X3; - X3 = mul(X3 ^ X1, DK[6*j+4]); - - u16bit T1 = X2; - X2 = mul((X2 ^ X4) + X3, DK[6*j+5]); - X3 += X2; - - X1 ^= X2; - X4 ^= X3; - X2 ^= T0; - X3 ^= T1; - } - - X1 = mul(X1, DK[48]); - X2 += DK[50]; - X3 += DK[49]; - X4 = mul(X4, DK[51]); - - store_be(out, X1, X3, X2, X4); - - in += BLOCK_SIZE; - out += BLOCK_SIZE; - } + idea_op(in, out, blocks, DK); } /* diff --git a/src/block/idea/idea.h b/src/block/idea/idea.h index c1a79f423..89ec117e3 100644 --- a/src/block/idea/idea.h +++ b/src/block/idea/idea.h @@ -26,7 +26,7 @@ class BOTAN_DLL IDEA : public BlockCipher BlockCipher* clone() const { return new IDEA; } IDEA() : BlockCipher(8, 16) {} - private: + protected: void key_schedule(const byte[], u32bit); SecureBuffer<u16bit, 52> EK, DK; }; diff --git a/src/block/idea_sse2/idea_sse2.cpp b/src/block/idea_sse2/idea_sse2.cpp new file mode 100644 index 000000000..c00d13ee9 --- /dev/null +++ b/src/block/idea_sse2/idea_sse2.cpp @@ -0,0 +1,227 @@ +/* +* IDEA in SSE2 +* (C) 2009 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/idea_sse2.h> +#include <botan/loadstor.h> +#include <emmintrin.h> + +namespace Botan { + +namespace { + +inline __m128i mul(__m128i X, u16bit K_16) + { + const __m128i zeros = _mm_set1_epi16(0); + const __m128i ones = _mm_set1_epi16(1); + const __m128i high_bit = _mm_set1_epi16(0x8000); + + const __m128i K = _mm_set1_epi16(K_16); + + const __m128i X_is_zero = _mm_cmpeq_epi16(X, zeros); + const __m128i K_is_zero = _mm_cmpeq_epi16(K, zeros); + + const __m128i mul_lo = _mm_mullo_epi16(X, K); + const __m128i mul_hi = _mm_mulhi_epu16(X, K); + + __m128i T = _mm_sub_epi16(mul_lo, mul_hi); + + // Unsigned compare; cmp = 1 if mul_lo < mul_hi else 0 + const __m128i cmp = _mm_srli_epi16(_mm_cmpgt_epi16( + _mm_add_epi16(mul_hi, high_bit), + _mm_add_epi16(mul_lo, high_bit)), + 15); + + T = _mm_add_epi16(T, cmp); + + /* Selection: if X[i] is zero then assign 1-K + if K is zero then assign 1-X[i] + + Could if() off value of K_16 for the second, but this gives a + constant time implementation which is a nice bonus. + */ + + T = _mm_or_si128( + _mm_andnot_si128(X_is_zero, T), + _mm_and_si128(_mm_sub_epi16(ones, K), X_is_zero)); + + T = _mm_or_si128( + _mm_andnot_si128(K_is_zero, T), + _mm_and_si128(_mm_sub_epi16(ones, X), K_is_zero)); + + return T; + } + +/* +* 4x8 matrix transpose +* +* FIXME: why do I need the extra set of unpack_epi32 here? Inverse in +* transpose_out doesn't need it. Something with the shuffle? Removing +* that extra unpack could easily save 3-4 cycles per block, and would +* also help a lot with register pressure on 32-bit x86 +*/ +void transpose_in(__m128i& B0, __m128i& B1, __m128i& B2, __m128i& B3) + { + __m128i T0 = _mm_unpackhi_epi32(B0, B1); + __m128i T1 = _mm_unpacklo_epi32(B0, B1); + __m128i T2 = _mm_unpackhi_epi32(B2, B3); + __m128i T3 = _mm_unpacklo_epi32(B2, B3); + + __m128i T4 = _mm_unpacklo_epi32(T0, T1); + __m128i T5 = _mm_unpackhi_epi32(T0, T1); + __m128i T6 = _mm_unpacklo_epi32(T2, T3); + __m128i T7 = _mm_unpackhi_epi32(T2, T3); + + T0 = _mm_shufflehi_epi16(T4, _MM_SHUFFLE(1, 3, 0, 2)); + T1 = _mm_shufflehi_epi16(T5, _MM_SHUFFLE(1, 3, 0, 2)); + T2 = _mm_shufflehi_epi16(T6, _MM_SHUFFLE(1, 3, 0, 2)); + T3 = _mm_shufflehi_epi16(T7, _MM_SHUFFLE(1, 3, 0, 2)); + + T0 = _mm_shufflelo_epi16(T0, _MM_SHUFFLE(1, 3, 0, 2)); + T1 = _mm_shufflelo_epi16(T1, _MM_SHUFFLE(1, 3, 0, 2)); + T2 = _mm_shufflelo_epi16(T2, _MM_SHUFFLE(1, 3, 0, 2)); + T3 = _mm_shufflelo_epi16(T3, _MM_SHUFFLE(1, 3, 0, 2)); + + T0 = _mm_shuffle_epi32(T0, _MM_SHUFFLE(3, 1, 2, 0)); + T1 = _mm_shuffle_epi32(T1, _MM_SHUFFLE(3, 1, 2, 0)); + T2 = _mm_shuffle_epi32(T2, _MM_SHUFFLE(3, 1, 2, 0)); + T3 = _mm_shuffle_epi32(T3, _MM_SHUFFLE(3, 1, 2, 0)); + + B0 = _mm_unpacklo_epi64(T0, T2); + B1 = _mm_unpackhi_epi64(T0, T2); + B2 = _mm_unpacklo_epi64(T1, T3); + B3 = _mm_unpackhi_epi64(T1, T3); + } + +/* +* 4x8 matrix transpose (reverse) +*/ +void transpose_out(__m128i& B0, __m128i& B1, __m128i& B2, __m128i& B3) + { + __m128i T0 = _mm_unpacklo_epi64(B0, B1); + __m128i T1 = _mm_unpacklo_epi64(B2, B3); + __m128i T2 = _mm_unpackhi_epi64(B0, B1); + __m128i T3 = _mm_unpackhi_epi64(B2, B3); + + T0 = _mm_shuffle_epi32(T0, _MM_SHUFFLE(3, 1, 2, 0)); + T1 = _mm_shuffle_epi32(T1, _MM_SHUFFLE(3, 1, 2, 0)); + T2 = _mm_shuffle_epi32(T2, _MM_SHUFFLE(3, 1, 2, 0)); + T3 = _mm_shuffle_epi32(T3, _MM_SHUFFLE(3, 1, 2, 0)); + + T0 = _mm_shufflehi_epi16(T0, _MM_SHUFFLE(3, 1, 2, 0)); + T1 = _mm_shufflehi_epi16(T1, _MM_SHUFFLE(3, 1, 2, 0)); + T2 = _mm_shufflehi_epi16(T2, _MM_SHUFFLE(3, 1, 2, 0)); + T3 = _mm_shufflehi_epi16(T3, _MM_SHUFFLE(3, 1, 2, 0)); + + T0 = _mm_shufflelo_epi16(T0, _MM_SHUFFLE(3, 1, 2, 0)); + T1 = _mm_shufflelo_epi16(T1, _MM_SHUFFLE(3, 1, 2, 0)); + T2 = _mm_shufflelo_epi16(T2, _MM_SHUFFLE(3, 1, 2, 0)); + T3 = _mm_shufflelo_epi16(T3, _MM_SHUFFLE(3, 1, 2, 0)); + + B0 = _mm_unpacklo_epi32(T0, T1); + B1 = _mm_unpackhi_epi32(T0, T1); + B2 = _mm_unpacklo_epi32(T2, T3); + B3 = _mm_unpackhi_epi32(T2, T3); + } + +/* +* IDEA encryption/decryption in SSE2 +*/ +void idea_op_8(const byte in[64], byte out[64], const u16bit EK[52]) + { + __m128i B0 = _mm_loadu_si128((const __m128i*)in); + __m128i B1 = _mm_loadu_si128((const __m128i*)in + 1); + __m128i B2 = _mm_loadu_si128((const __m128i*)in + 2); + __m128i B3 = _mm_loadu_si128((const __m128i*)in + 3); + + transpose_in(B0, B1, B2, B3); + + // byte swap + B0 = _mm_or_si128(_mm_slli_epi16(B0, 8), _mm_srli_epi16(B0, 8)); + B1 = _mm_or_si128(_mm_slli_epi16(B1, 8), _mm_srli_epi16(B1, 8)); + B2 = _mm_or_si128(_mm_slli_epi16(B2, 8), _mm_srli_epi16(B2, 8)); + B3 = _mm_or_si128(_mm_slli_epi16(B3, 8), _mm_srli_epi16(B3, 8)); + + for(u32bit i = 0; i != 8; ++i) + { + B0 = mul(B0, EK[6*i+0]); + B1 = _mm_add_epi16(B1, _mm_set1_epi16(EK[6*i+1])); + B2 = _mm_add_epi16(B2, _mm_set1_epi16(EK[6*i+2])); + B3 = mul(B3, EK[6*i+3]); + + __m128i T0 = B2; + + B2 = _mm_xor_si128(B2, B0); + B2 = mul(B2, EK[6*i+4]); + + __m128i T1 = B1; + + B1 = _mm_xor_si128(B1, B3); + B1 = _mm_add_epi16(B1, B2); + B1 = mul(B1, EK[6*i+5]); + + B2 = _mm_add_epi16(B2, B1); + + B0 = _mm_xor_si128(B0, B1); + B1 = _mm_xor_si128(B1, T0); + B3 = _mm_xor_si128(B3, B2); + B2 = _mm_xor_si128(B2, T1); + } + + B0 = mul(B0, EK[48]); + B1 = _mm_add_epi16(B1, _mm_set1_epi16(EK[50])); + B2 = _mm_add_epi16(B2, _mm_set1_epi16(EK[49])); + B3 = mul(B3, EK[51]); + + // byte swap + B0 = _mm_or_si128(_mm_slli_epi16(B0, 8), _mm_srli_epi16(B0, 8)); + B1 = _mm_or_si128(_mm_slli_epi16(B1, 8), _mm_srli_epi16(B1, 8)); + B2 = _mm_or_si128(_mm_slli_epi16(B2, 8), _mm_srli_epi16(B2, 8)); + B3 = _mm_or_si128(_mm_slli_epi16(B3, 8), _mm_srli_epi16(B3, 8)); + + transpose_out(B0, B2, B1, B3); + + _mm_storeu_si128((__m128i*)out, B0); + _mm_storeu_si128((__m128i*)out + 1, B2); + _mm_storeu_si128((__m128i*)out + 2, B1); + _mm_storeu_si128((__m128i*)out + 3, B3); + } + +} + +/* +* IDEA Encryption +*/ +void IDEA_SSE2::encrypt_n(const byte in[], byte out[], u32bit blocks) const + { + while(blocks >= 8) + { + idea_op_8(in, out, this->EK); + in += 8 * BLOCK_SIZE; + out += 8 * BLOCK_SIZE; + blocks -= 8; + } + + IDEA::encrypt_n(in, out, blocks); + } + +/* +* IDEA Decryption +*/ +void IDEA_SSE2::decrypt_n(const byte in[], byte out[], u32bit blocks) const + { + while(blocks >= 8) + { + idea_op_8(in, out, this->DK); + in += 8 * BLOCK_SIZE; + out += 8 * BLOCK_SIZE; + blocks -= 8; + } + + IDEA::decrypt_n(in, out, blocks); + } + +} diff --git a/src/block/idea_sse2/idea_sse2.h b/src/block/idea_sse2/idea_sse2.h new file mode 100644 index 000000000..167c981f8 --- /dev/null +++ b/src/block/idea_sse2/idea_sse2.h @@ -0,0 +1,29 @@ +/* +* IDEA in SSE2 +* (C) 2009 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_IDEA_SSE2_H__ +#define BOTAN_IDEA_SSE2_H__ + +#include <botan/idea.h> + +namespace Botan { + +/* +* IDEA in SSE2 +*/ +class BOTAN_DLL IDEA_SSE2 : public IDEA + { + public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + + BlockCipher* clone() const { return new IDEA_SSE2; } + }; + +} + +#endif diff --git a/src/block/idea_sse2/info.txt b/src/block/idea_sse2/info.txt new file mode 100644 index 000000000..fe09d3ee5 --- /dev/null +++ b/src/block/idea_sse2/info.txt @@ -0,0 +1,7 @@ +define IDEA_SSE2 + +need_isa sse2 + +<requires> +idea +</requires> diff --git a/src/build-data/buildh.in b/src/build-data/buildh.in index 9d7012a73..7588dc99b 100644 --- a/src/build-data/buildh.in +++ b/src/build-data/buildh.in @@ -30,8 +30,7 @@ #define BOTAN_PARALLEL_BLOCKS_ECB 8 #define BOTAN_PARALLEL_BLOCKS_CBC 8 #define BOTAN_PARALLEL_BLOCKS_CFB 8 -#define BOTAN_PARALLEL_BLOCKS_CTR 8 -#define BOTAN_PARALLEL_BLOCKS_EAX 8 +#define BOTAN_PARALLEL_BLOCKS_CTR 16 #define BOTAN_PARALLEL_BLOCKS_XTS 8 /* PK key consistency checking toggles */ @@ -53,8 +52,19 @@ %{target_cpu_defines} +#if defined(BOTAN_TARGET_CPU_IS_LITTLE_ENDIAN) || \ + defined(BOTAN_TARGET_CPU_IS_BIG_ENDIAN) + #define BOTAN_TARGET_CPU_HAS_KNOWN_ENDIANNESS +#endif + %{target_compiler_defines} +#if defined(BOTAN_BUILD_COMPILER_IS_MSVC) + // 4250: inherits via dominance (diamond inheritence issue) + // 4251: needs DLL interface (STL DLL exports) + #pragma warning(disable: 4250 4251) +#endif + /* Module definitions */ %{module_defines} diff --git a/src/build-data/cc/msvc.txt b/src/build-data/cc/msvc.txt index 892e80c4b..36437e6a2 100644 --- a/src/build-data/cc/msvc.txt +++ b/src/build-data/cc/msvc.txt @@ -12,7 +12,7 @@ no_debug_flags "/O2" debug_flags "/Od /Zi /DDEBUG" check_opt_flags "/O2 /D_CONSOLE" lang_flags "/EHsc /GR" -warning_flags "" +warning_flags "/W3" shared_flags "/DBOTAN_DLL=__declspec(dllexport)" dll_import_flags "__declspec(dllimport)" diff --git a/src/build-data/innosetup.in b/src/build-data/innosetup.in index 228ab4e97..c3e0f1ebd 100644 --- a/src/build-data/innosetup.in +++ b/src/build-data/innosetup.in @@ -9,7 +9,7 @@ AppPublisherURL=http://botan.randombit.net/ AppVersion=%{version} VersionInfoCopyright=Copyright (C) 1999-2009 Jack Lloyd and others -VersionInfoVersion=%{version}.0 +VersionInfoVersion=%{version_major}.%{version_minor}.%{version_patch}.0 ; Require at least Windows 98 or 2000 MinVersion=4.1,5.0 diff --git a/src/build-data/os/linux.txt b/src/build-data/os/linux.txt index b3c227533..2f59fb9d1 100644 --- a/src/build-data/os/linux.txt +++ b/src/build-data/os/linux.txt @@ -4,6 +4,7 @@ os_type unix clock_gettime gettimeofday posix_mlock +gmtime_r </target_features> # Is this correct? diff --git a/src/build-data/os/mingw.txt b/src/build-data/os/mingw.txt index 2b7a16cf7..1b30e0b3a 100644 --- a/src/build-data/os/mingw.txt +++ b/src/build-data/os/mingw.txt @@ -19,3 +19,8 @@ install_cmd_exec "install -m 755" msys mingw32 </aliases> + +<target_features> +win32_virtual_lock +win32_get_systemtime +</target_features> diff --git a/src/build-data/os/windows.txt b/src/build-data/os/windows.txt index 59e3ec072..23838eb6d 100644 --- a/src/build-data/os/windows.txt +++ b/src/build-data/os/windows.txt @@ -11,8 +11,10 @@ install_cmd_data "copy" install_cmd_exec "copy" <target_features> -win32_virtual_lock +gmtime_s +win32_get_systemtime win32_query_perf_counter +win32_virtual_lock </target_features> <supports_shared> diff --git a/src/cert/x509/pkcs10.cpp b/src/cert/x509/pkcs10.cpp index 5645552a0..e78439757 100644 --- a/src/cert/x509/pkcs10.cpp +++ b/src/cert/x509/pkcs10.cpp @@ -186,7 +186,7 @@ std::vector<OID> PKCS10_Request::ex_constraints() const */ bool PKCS10_Request::is_CA() const { - return info.get1_u32bit("X509v3.BasicConstraints.is_ca"); + return (info.get1_u32bit("X509v3.BasicConstraints.is_ca") > 0); } /* diff --git a/src/cert/x509/x509_ext.cpp b/src/cert/x509/x509_ext.cpp index e88b5a268..9a03c9d23 100644 --- a/src/cert/x509/x509_ext.cpp +++ b/src/cert/x509/x509_ext.cpp @@ -471,8 +471,10 @@ class Policy_Information : public ASN1_Object */ MemoryVector<byte> Certificate_Policies::encode_inner() const { + // FIXME +#if 1 throw Exception("Certificate_Policies::encode_inner: Bugged"); - +#else std::vector<Policy_Information> policies; return DER_Encoder() @@ -480,6 +482,7 @@ MemoryVector<byte> Certificate_Policies::encode_inner() const .encode_list(policies) .end_cons() .get_contents(); +#endif } /* diff --git a/src/cert/x509/x509opt.cpp b/src/cert/x509/x509opt.cpp index 8d235ad5d..fda889224 100644 --- a/src/cert/x509/x509opt.cpp +++ b/src/cert/x509/x509opt.cpp @@ -78,7 +78,7 @@ void X509_Cert_Options::sanity_check() const * Initialize the certificate options */ X509_Cert_Options::X509_Cert_Options(const std::string& initial_opts, - u32bit expiration_time) + u32bit expiration_time_in_seconds) { is_CA = false; path_limit = 0; diff --git a/src/constructs/tss/tss.h b/src/constructs/tss/tss.h index 45d64d9cb..c8b0242d8 100644 --- a/src/constructs/tss/tss.h +++ b/src/constructs/tss/tss.h @@ -45,7 +45,7 @@ class BOTAN_DLL RTSS_Share byte share_id() const; u32bit size() const { return contents.size(); } - bool initialized() const { return contents.size(); } + bool initialized() const { return (contents.size() > 0); } private: SecureVector<byte> contents; }; diff --git a/src/engine/simd_engine/simd_engine.cpp b/src/engine/simd_engine/simd_engine.cpp index 892221f22..b8ebd6a80 100644 --- a/src/engine/simd_engine/simd_engine.cpp +++ b/src/engine/simd_engine/simd_engine.cpp @@ -17,6 +17,10 @@ #include <botan/xtea_simd.h> #endif +#if defined(BOTAN_HAS_IDEA_SSE2) + #include <botan/idea_sse2.h> +#endif + #if defined(BOTAN_HAS_SHA1_SSE2) #include <botan/sha1_sse2.h> #endif @@ -27,16 +31,18 @@ BlockCipher* SIMD_Engine::find_block_cipher(const SCAN_Name& request, Algorithm_Factory&) const { - if(!SIMD_32::enabled()) - return 0; +#if defined(BOTAN_HAS_IDEA_SSE2) + if(request.algo_name() == "IDEA" && CPUID::has_sse2()) + return new IDEA_SSE2; +#endif #if defined(BOTAN_HAS_SERPENT_SIMD) - if(request.algo_name() == "Serpent") + if(request.algo_name() == "Serpent" && SIMD_32::enabled()) return new Serpent_SIMD; #endif #if defined(BOTAN_HAS_XTEA_SIMD) - if(request.algo_name() == "XTEA") + if(request.algo_name() == "XTEA" && SIMD_32::enabled()) return new XTEA_SIMD; #endif diff --git a/src/entropy/beos_stats/es_beos.cpp b/src/entropy/beos_stats/es_beos.cpp index 18eca5511..148d38b9b 100644 --- a/src/entropy/beos_stats/es_beos.cpp +++ b/src/entropy/beos_stats/es_beos.cpp @@ -5,7 +5,7 @@ * Distributed under the terms of the Botan license */ -#include <botan/es_beos.h> +#include <botan/internal/es_beos.h> #include <kernel/OS.h> #include <kernel/image.h> diff --git a/src/entropy/cryptoapi_rng/es_capi.cpp b/src/entropy/cryptoapi_rng/es_capi.cpp index a70b52044..367166c62 100644 --- a/src/entropy/cryptoapi_rng/es_capi.cpp +++ b/src/entropy/cryptoapi_rng/es_capi.cpp @@ -5,7 +5,7 @@ * Distributed under the terms of the Botan license */ -#include <botan/es_capi.h> +#include <botan/internal/es_capi.h> #include <botan/parsing.h> #include <windows.h> #include <wincrypt.h> diff --git a/src/entropy/hres_timer/hres_timer.cpp b/src/entropy/hres_timer/hres_timer.cpp index 3e7c235ca..9f0a25c9b 100644 --- a/src/entropy/hres_timer/hres_timer.cpp +++ b/src/entropy/hres_timer/hres_timer.cpp @@ -25,7 +25,7 @@ void High_Resolution_Timestamp::poll(Entropy_Accumulator& accum) accum.add(tv.QuadPart, 0); #endif -#if defined(BOTAN_USE_GCC_INLINE_ASM) +#if BOTAN_USE_GCC_INLINE_ASM u64bit rtc = 0; diff --git a/src/entropy/win32_stats/es_win32.cpp b/src/entropy/win32_stats/es_win32.cpp index a8e9e40f5..e9f564fee 100644 --- a/src/entropy/win32_stats/es_win32.cpp +++ b/src/entropy/win32_stats/es_win32.cpp @@ -5,7 +5,7 @@ * Distributed under the terms of the Botan license */ -#include <botan/es_win32.h> +#include <botan/internal/es_win32.h> #include <windows.h> #include <tlhelp32.h> diff --git a/src/filters/modes/cbc/cbc.cpp b/src/filters/modes/cbc/cbc.cpp index a52f4b2e1..48ecdf509 100644 --- a/src/filters/modes/cbc/cbc.cpp +++ b/src/filters/modes/cbc/cbc.cpp @@ -16,11 +16,14 @@ namespace Botan { */ CBC_Encryption::CBC_Encryption(BlockCipher* ciph, BlockCipherModePaddingMethod* pad) : - BlockCipherMode(ciph, "CBC", ciph->BLOCK_SIZE), - padder(pad) + cipher(ciph), padder(pad) { - if(!padder->valid_blocksize(BLOCK_SIZE)) + if(!padder->valid_blocksize(cipher->BLOCK_SIZE)) throw Invalid_Block_Size(name(), padder->name()); + + buffer.resize(cipher->BLOCK_SIZE); + state.resize(cipher->BLOCK_SIZE); + position = 0; } /* @@ -30,31 +33,48 @@ CBC_Encryption::CBC_Encryption(BlockCipher* ciph, BlockCipherModePaddingMethod* pad, const SymmetricKey& key, const InitializationVector& iv) : - BlockCipherMode(ciph, "CBC", ciph->BLOCK_SIZE), - padder(pad) + cipher(ciph), padder(pad) { - if(!padder->valid_blocksize(BLOCK_SIZE)) + if(!padder->valid_blocksize(cipher->BLOCK_SIZE)) throw Invalid_Block_Size(name(), padder->name()); + + buffer.resize(cipher->BLOCK_SIZE); + state.resize(cipher->BLOCK_SIZE); + position = 0; + set_key(key); set_iv(iv); } /* +* Set the IV +*/ +void CBC_Encryption::set_iv(const InitializationVector& iv) + { + if(iv.length() != state.size()) + throw Invalid_IV_Length(name(), iv.length()); + + state = iv.bits_of(); + buffer.clear(); + position = 0; + } + +/* * Encrypt in CBC mode */ void CBC_Encryption::write(const byte input[], u32bit length) { while(length) { - u32bit xored = std::min(BLOCK_SIZE - position, length); + u32bit xored = std::min(cipher->BLOCK_SIZE - position, length); xor_buf(state + position, input, xored); input += xored; length -= xored; position += xored; - if(position == BLOCK_SIZE) + if(position == cipher->BLOCK_SIZE) { cipher->encrypt(state); - send(state, BLOCK_SIZE); + send(state, cipher->BLOCK_SIZE); position = 0; } } @@ -65,9 +85,9 @@ void CBC_Encryption::write(const byte input[], u32bit length) */ void CBC_Encryption::end_msg() { - SecureVector<byte> padding(BLOCK_SIZE); + SecureVector<byte> padding(cipher->BLOCK_SIZE); padder->pad(padding, padding.size(), position); - write(padding, padder->pad_bytes(BLOCK_SIZE, position)); + write(padding, padder->pad_bytes(cipher->BLOCK_SIZE, position)); if(position != 0) throw Exception(name() + ": Did not pad to full blocksize"); } @@ -77,7 +97,7 @@ void CBC_Encryption::end_msg() */ std::string CBC_Encryption::name() const { - return (cipher->name() + "/" + mode_name + "/" + padder->name()); + return (cipher->name() + "/CBC/" + padder->name()); } /* @@ -85,12 +105,15 @@ std::string CBC_Encryption::name() const */ CBC_Decryption::CBC_Decryption(BlockCipher* ciph, BlockCipherModePaddingMethod* pad) : - BlockCipherMode(ciph, "CBC", ciph->BLOCK_SIZE), - padder(pad) + cipher(ciph), padder(pad) { - if(!padder->valid_blocksize(BLOCK_SIZE)) + if(!padder->valid_blocksize(cipher->BLOCK_SIZE)) throw Invalid_Block_Size(name(), padder->name()); - temp.resize(BLOCK_SIZE); + + buffer.resize(cipher->BLOCK_SIZE); + state.resize(cipher->BLOCK_SIZE); + temp.resize(cipher->BLOCK_SIZE); + position = 0; } /* @@ -100,32 +123,50 @@ CBC_Decryption::CBC_Decryption(BlockCipher* ciph, BlockCipherModePaddingMethod* pad, const SymmetricKey& key, const InitializationVector& iv) : - BlockCipherMode(ciph, "CBC", ciph->BLOCK_SIZE), - padder(pad) + cipher(ciph), padder(pad) { - if(!padder->valid_blocksize(BLOCK_SIZE)) + if(!padder->valid_blocksize(cipher->BLOCK_SIZE)) throw Invalid_Block_Size(name(), padder->name()); - temp.resize(BLOCK_SIZE); + + buffer.resize(cipher->BLOCK_SIZE); + state.resize(cipher->BLOCK_SIZE); + temp.resize(cipher->BLOCK_SIZE); + position = 0; + set_key(key); set_iv(iv); } /* +* Set the IV +*/ +void CBC_Decryption::set_iv(const InitializationVector& iv) + { + if(iv.length() != state.size()) + throw Invalid_IV_Length(name(), iv.length()); + + state = iv.bits_of(); + buffer.clear(); + position = 0; + } + +/* * Decrypt in CBC mode */ void CBC_Decryption::write(const byte input[], u32bit length) { while(length) { - if(position == BLOCK_SIZE) + if(position == cipher->BLOCK_SIZE) { cipher->decrypt(buffer, temp); - xor_buf(temp, state, BLOCK_SIZE); - send(temp, BLOCK_SIZE); + xor_buf(temp, state, cipher->BLOCK_SIZE); + send(temp, cipher->BLOCK_SIZE); state = buffer; position = 0; } - u32bit added = std::min(BLOCK_SIZE - position, length); + + u32bit added = std::min(cipher->BLOCK_SIZE - position, length); buffer.copy(position, input, added); input += added; length -= added; @@ -138,11 +179,11 @@ void CBC_Decryption::write(const byte input[], u32bit length) */ void CBC_Decryption::end_msg() { - if(position != BLOCK_SIZE) + if(position != cipher->BLOCK_SIZE) throw Decoding_Error(name()); cipher->decrypt(buffer, temp); - xor_buf(temp, state, BLOCK_SIZE); - send(temp, padder->unpad(temp, BLOCK_SIZE)); + xor_buf(temp, state, cipher->BLOCK_SIZE); + send(temp, padder->unpad(temp, cipher->BLOCK_SIZE)); state = buffer; position = 0; } @@ -152,7 +193,7 @@ void CBC_Decryption::end_msg() */ std::string CBC_Decryption::name() const { - return (cipher->name() + "/" + mode_name + "/" + padder->name()); + return (cipher->name() + "/CBC/" + padder->name()); } } diff --git a/src/filters/modes/cbc/cbc.h b/src/filters/modes/cbc/cbc.h index a926ac180..91ab21ab6 100644 --- a/src/filters/modes/cbc/cbc.h +++ b/src/filters/modes/cbc/cbc.h @@ -8,7 +8,8 @@ #ifndef BOTAN_CBC_H__ #define BOTAN_CBC_H__ -#include <botan/modebase.h> +#include <botan/block_cipher.h> +#include <botan/key_filt.h> #include <botan/mode_pad.h> namespace Botan { @@ -16,38 +17,69 @@ namespace Botan { /* * CBC Encryption */ -class BOTAN_DLL CBC_Encryption : public BlockCipherMode +class BOTAN_DLL CBC_Encryption : public Keyed_Filter { public: - CBC_Encryption(BlockCipher*, BlockCipherModePaddingMethod*); - CBC_Encryption(BlockCipher*, BlockCipherModePaddingMethod*, - const SymmetricKey&, const InitializationVector&); + std::string name() const; + + void set_iv(const InitializationVector&); + + void set_key(const SymmetricKey& key) { cipher->set_key(key); } + + bool valid_keylength(u32bit key_len) const + { return cipher->valid_keylength(key_len); } + + CBC_Encryption(BlockCipher* cipher, + BlockCipherModePaddingMethod* padding); + + CBC_Encryption(BlockCipher* cipher, + BlockCipherModePaddingMethod* padding, + const SymmetricKey& key, + const InitializationVector& iv); ~CBC_Encryption() { delete padder; } private: - std::string name() const; void write(const byte[], u32bit); void end_msg(); + + BlockCipher* cipher; const BlockCipherModePaddingMethod* padder; + SecureVector<byte> buffer, state; + u32bit position; }; /* * CBC Decryption */ -class BOTAN_DLL CBC_Decryption : public BlockCipherMode +class BOTAN_DLL CBC_Decryption : public Keyed_Filter { public: - CBC_Decryption(BlockCipher*, BlockCipherModePaddingMethod*); - CBC_Decryption(BlockCipher*, BlockCipherModePaddingMethod*, - const SymmetricKey&, const InitializationVector&); + std::string name() const; + + void set_iv(const InitializationVector&); + + void set_key(const SymmetricKey& key) { cipher->set_key(key); } + + bool valid_keylength(u32bit key_len) const + { return cipher->valid_keylength(key_len); } + + CBC_Decryption(BlockCipher* cipher, + BlockCipherModePaddingMethod* padding); + + CBC_Decryption(BlockCipher* cipher, + BlockCipherModePaddingMethod* padding, + const SymmetricKey& key, + const InitializationVector& iv); ~CBC_Decryption() { delete padder; } private: - std::string name() const; void write(const byte[], u32bit); void end_msg(); + + BlockCipher* cipher; const BlockCipherModePaddingMethod* padder; - SecureVector<byte> temp; + SecureVector<byte> buffer, state, temp; + u32bit position; }; } diff --git a/src/filters/modes/cbc/info.txt b/src/filters/modes/cbc/info.txt index 92a39d674..229edfbf7 100644 --- a/src/filters/modes/cbc/info.txt +++ b/src/filters/modes/cbc/info.txt @@ -1,5 +1,6 @@ define CBC <requires> +block mode_pad </requires> diff --git a/src/filters/modes/cfb/cfb.cpp b/src/filters/modes/cfb/cfb.cpp index 5456bbe0f..e7737e673 100644 --- a/src/filters/modes/cfb/cfb.cpp +++ b/src/filters/modes/cfb/cfb.cpp @@ -12,30 +12,21 @@ namespace Botan { -namespace { - /* -* Check the feedback size +* CFB Encryption Constructor */ -void check_feedback(u32bit BLOCK_SIZE, u32bit FEEDBACK_SIZE, u32bit bits, - const std::string& name) +CFB_Encryption::CFB_Encryption(BlockCipher* ciph, u32bit fback_bits) { - if(FEEDBACK_SIZE == 0 || FEEDBACK_SIZE > BLOCK_SIZE || bits % 8 != 0) - throw Invalid_Argument(name + ": Invalid feedback size " + - std::to_string(bits)); - } + cipher = ciph; + feedback = fback_bits ? fback_bits / 8: cipher->BLOCK_SIZE; -} + buffer.resize(cipher->BLOCK_SIZE); + state.resize(cipher->BLOCK_SIZE); + position = 0; -/* -* CFB Encryption Constructor -*/ -CFB_Encryption::CFB_Encryption(BlockCipher* ciph, - u32bit fback_bits) : - BlockCipherMode(ciph, "CFB", ciph->BLOCK_SIZE, 1), - FEEDBACK_SIZE(fback_bits ? fback_bits / 8: BLOCK_SIZE) - { - check_feedback(BLOCK_SIZE, FEEDBACK_SIZE, fback_bits, name()); + if(feedback == 0 || fback_bits % 8 != 0 || feedback > cipher->BLOCK_SIZE) + throw Invalid_Argument("CFB_Encryption: Invalid feedback size " + + std::to_string(fback_bits)); } /* @@ -44,15 +35,35 @@ CFB_Encryption::CFB_Encryption(BlockCipher* ciph, CFB_Encryption::CFB_Encryption(BlockCipher* ciph, const SymmetricKey& key, const InitializationVector& iv, - u32bit fback_bits) : - BlockCipherMode(ciph, "CFB", ciph->BLOCK_SIZE, 1), - FEEDBACK_SIZE(fback_bits ? fback_bits / 8: BLOCK_SIZE) + u32bit fback_bits) { - check_feedback(BLOCK_SIZE, FEEDBACK_SIZE, fback_bits, name()); + cipher = ciph; + feedback = fback_bits ? fback_bits / 8: cipher->BLOCK_SIZE; + + buffer.resize(cipher->BLOCK_SIZE); + state.resize(cipher->BLOCK_SIZE); + position = 0; + + if(feedback == 0 || fback_bits % 8 != 0 || feedback > cipher->BLOCK_SIZE) + throw Invalid_Argument("CFB_Encryption: Invalid feedback size " + + std::to_string(fback_bits)); + set_key(key); set_iv(iv); } +void CFB_Encryption::set_iv(const InitializationVector& iv) + { + if(iv.length() != state.size()) + throw Invalid_IV_Length(name(), iv.length()); + + state = iv.bits_of(); + buffer.clear(); + position = 0; + + cipher->encrypt(state, buffer); + } + /* * Encrypt data in CFB mode */ @@ -60,38 +71,39 @@ void CFB_Encryption::write(const byte input[], u32bit length) { while(length) { - u32bit xored = std::min(FEEDBACK_SIZE - position, length); + u32bit xored = std::min(feedback - position, length); xor_buf(buffer + position, input, xored); send(buffer + position, xored); input += xored; length -= xored; position += xored; - if(position == FEEDBACK_SIZE) - feedback(); + + if(position == feedback) + { + for(u32bit j = 0; j != cipher->BLOCK_SIZE - feedback; ++j) + state[j] = state[j + feedback]; + state.copy(cipher->BLOCK_SIZE - feedback, buffer, feedback); + cipher->encrypt(state, buffer); + position = 0; + } } } /* -* Do the feedback +* CFB Decryption Constructor */ -void CFB_Encryption::feedback() +CFB_Decryption::CFB_Decryption(BlockCipher* ciph, u32bit fback_bits) { - for(u32bit j = 0; j != BLOCK_SIZE - FEEDBACK_SIZE; ++j) - state[j] = state[j + FEEDBACK_SIZE]; - state.copy(BLOCK_SIZE - FEEDBACK_SIZE, buffer, FEEDBACK_SIZE); - cipher->encrypt(state, buffer); + cipher = ciph; + feedback = fback_bits ? fback_bits / 8: cipher->BLOCK_SIZE; + + buffer.resize(cipher->BLOCK_SIZE); + state.resize(cipher->BLOCK_SIZE); position = 0; - } -/* -* CFB Decryption Constructor -*/ -CFB_Decryption::CFB_Decryption(BlockCipher* ciph, - u32bit fback_bits) : - BlockCipherMode(ciph, "CFB", ciph->BLOCK_SIZE, 1), - FEEDBACK_SIZE(fback_bits ? fback_bits / 8 : BLOCK_SIZE) - { - check_feedback(BLOCK_SIZE, FEEDBACK_SIZE, fback_bits, name()); + if(feedback == 0 || fback_bits % 8 != 0 || feedback > cipher->BLOCK_SIZE) + throw Invalid_Argument("CFB_Decryption: Invalid feedback size " + + to_string(fback_bits)); } /* @@ -100,15 +112,35 @@ CFB_Decryption::CFB_Decryption(BlockCipher* ciph, CFB_Decryption::CFB_Decryption(BlockCipher* ciph, const SymmetricKey& key, const InitializationVector& iv, - u32bit fback_bits) : - BlockCipherMode(ciph, "CFB", ciph->BLOCK_SIZE, 1), - FEEDBACK_SIZE(fback_bits ? fback_bits / 8 : BLOCK_SIZE) + u32bit fback_bits) { - check_feedback(BLOCK_SIZE, FEEDBACK_SIZE, fback_bits, name()); + cipher = ciph; + feedback = fback_bits ? fback_bits / 8: cipher->BLOCK_SIZE; + + buffer.resize(cipher->BLOCK_SIZE); + state.resize(cipher->BLOCK_SIZE); + position = 0; + + if(feedback == 0 || fback_bits % 8 != 0 || feedback > cipher->BLOCK_SIZE) + throw Invalid_Argument("CFB_Decryption: Invalid feedback size " + + to_string(fback_bits)); + set_key(key); set_iv(iv); } +void CFB_Decryption::set_iv(const InitializationVector& iv) + { + if(iv.length() != state.size()) + throw Invalid_IV_Length(name(), iv.length()); + + state = iv.bits_of(); + buffer.clear(); + position = 0; + + cipher->encrypt(state, buffer); + } + /* * Decrypt data in CFB mode */ @@ -116,28 +148,22 @@ void CFB_Decryption::write(const byte input[], u32bit length) { while(length) { - u32bit xored = std::min(FEEDBACK_SIZE - position, length); + u32bit xored = std::min(feedback - position, length); xor_buf(buffer + position, input, xored); send(buffer + position, xored); buffer.copy(position, input, xored); input += xored; length -= xored; position += xored; - if(position == FEEDBACK_SIZE) - feedback(); + if(position == feedback) + { + for(u32bit j = 0; j != cipher->BLOCK_SIZE - feedback; ++j) + state[j] = state[j + feedback]; + state.copy(cipher->BLOCK_SIZE - feedback, buffer, feedback); + cipher->encrypt(state, buffer); + position = 0; + } } } -/* -* Do the feedback -*/ -void CFB_Decryption::feedback() - { - for(u32bit j = 0; j != BLOCK_SIZE - FEEDBACK_SIZE; ++j) - state[j] = state[j + FEEDBACK_SIZE]; - state.copy(BLOCK_SIZE - FEEDBACK_SIZE, buffer, FEEDBACK_SIZE); - cipher->encrypt(state, buffer); - position = 0; - } - } diff --git a/src/filters/modes/cfb/cfb.h b/src/filters/modes/cfb/cfb.h index 7810c00e4..917125e46 100644 --- a/src/filters/modes/cfb/cfb.h +++ b/src/filters/modes/cfb/cfb.h @@ -8,38 +8,67 @@ #ifndef BOTAN_CFB_H__ #define BOTAN_CFB_H__ -#include <botan/modebase.h> +#include <botan/block_cipher.h> +#include <botan/key_filt.h> namespace Botan { /* * CFB Encryption */ -class BOTAN_DLL CFB_Encryption : public BlockCipherMode +class BOTAN_DLL CFB_Encryption : public Keyed_Filter { public: - CFB_Encryption(BlockCipher*, u32bit = 0); - CFB_Encryption(BlockCipher*, const SymmetricKey&, - const InitializationVector&, u32bit = 0); + std::string name() const { return cipher->name() + "/CFB"; } + + void set_iv(const InitializationVector&); + + void set_key(const SymmetricKey& key) { cipher->set_key(key); } + + bool valid_keylength(u32bit key_len) const + { return cipher->valid_keylength(key_len); } + + CFB_Encryption(BlockCipher* cipher, u32bit feedback = 0); + + CFB_Encryption(BlockCipher* cipher, + const SymmetricKey& key, + const InitializationVector& iv, + u32bit feedback = 0); private: void write(const byte[], u32bit); - void feedback(); - const u32bit FEEDBACK_SIZE; + + BlockCipher* cipher; + SecureVector<byte> buffer, state; + u32bit position, feedback; }; /* * CFB Decryption */ -class BOTAN_DLL CFB_Decryption : public BlockCipherMode +class BOTAN_DLL CFB_Decryption : public Keyed_Filter { public: - CFB_Decryption(BlockCipher*, u32bit = 0); - CFB_Decryption(BlockCipher*, const SymmetricKey&, - const InitializationVector&, u32bit = 0); + std::string name() const { return cipher->name() + "/CFB"; } + + void set_iv(const InitializationVector&); + + void set_key(const SymmetricKey& key) { cipher->set_key(key); } + + bool valid_keylength(u32bit key_len) const + { return cipher->valid_keylength(key_len); } + + CFB_Decryption(BlockCipher* cipher, u32bit feedback = 0); + + CFB_Decryption(BlockCipher* cipher, + const SymmetricKey& key, + const InitializationVector& iv, + u32bit feedback = 0); private: void write(const byte[], u32bit); - void feedback(); - const u32bit FEEDBACK_SIZE; + + BlockCipher* cipher; + SecureVector<byte> buffer, state; + u32bit position, feedback; }; } diff --git a/src/filters/modes/cfb/info.txt b/src/filters/modes/cfb/info.txt index 230899a03..eb2cc69ba 100644 --- a/src/filters/modes/cfb/info.txt +++ b/src/filters/modes/cfb/info.txt @@ -1 +1,5 @@ define CFB + +<requires> +block +</requires> diff --git a/src/filters/modes/cts/cts.cpp b/src/filters/modes/cts/cts.cpp index 226a31898..3a15a1d68 100644 --- a/src/filters/modes/cts/cts.cpp +++ b/src/filters/modes/cts/cts.cpp @@ -12,13 +12,53 @@ namespace Botan { /* +* CTS Encryption Constructor +*/ +CTS_Encryption::CTS_Encryption(BlockCipher* ciph) : + cipher(ciph) + { + buffer.resize(2 * cipher->BLOCK_SIZE); + state.resize(cipher->BLOCK_SIZE); + position = 0; + } + +/* +* CTS Encryption Constructor +*/ +CTS_Encryption::CTS_Encryption(BlockCipher* ciph, + const SymmetricKey& key, + const InitializationVector& iv) : + cipher(ciph) + { + buffer.resize(2 * cipher->BLOCK_SIZE); + state.resize(cipher->BLOCK_SIZE); + position = 0; + + set_key(key); + set_iv(iv); + } + +/* +* Set the IV +*/ +void CTS_Encryption::set_iv(const InitializationVector& iv) + { + if(iv.length() != state.size()) + throw Invalid_IV_Length(name(), iv.length()); + + state = iv.bits_of(); + buffer.clear(); + position = 0; + } + +/* * Encrypt a block */ void CTS_Encryption::encrypt(const byte block[]) { - xor_buf(state, block, BLOCK_SIZE); + xor_buf(state, block, cipher->BLOCK_SIZE); cipher->encrypt(state); - send(state, BLOCK_SIZE); + send(state, cipher->BLOCK_SIZE); } /* @@ -26,7 +66,7 @@ void CTS_Encryption::encrypt(const byte block[]) */ void CTS_Encryption::write(const byte input[], u32bit length) { - u32bit copied = std::min(BUFFER_SIZE - position, length); + u32bit copied = std::min(buffer.size() - position, length); buffer.copy(position, input, copied); length -= copied; input += copied; @@ -35,21 +75,21 @@ void CTS_Encryption::write(const byte input[], u32bit length) if(length == 0) return; encrypt(buffer); - if(length > BLOCK_SIZE) + if(length > cipher->BLOCK_SIZE) { - encrypt(buffer + BLOCK_SIZE); - while(length > 2*BLOCK_SIZE) + encrypt(buffer + cipher->BLOCK_SIZE); + while(length > 2*cipher->BLOCK_SIZE) { encrypt(input); - length -= BLOCK_SIZE; - input += BLOCK_SIZE; + length -= cipher->BLOCK_SIZE; + input += cipher->BLOCK_SIZE; } position = 0; } else { - copy_mem(buffer.begin(), buffer + BLOCK_SIZE, BLOCK_SIZE); - position = BLOCK_SIZE; + copy_mem(buffer.begin(), buffer + cipher->BLOCK_SIZE, cipher->BLOCK_SIZE); + position = cipher->BLOCK_SIZE; } buffer.copy(position, input, length); position += length; @@ -60,14 +100,56 @@ void CTS_Encryption::write(const byte input[], u32bit length) */ void CTS_Encryption::end_msg() { - if(position < BLOCK_SIZE + 1) + if(position < cipher->BLOCK_SIZE + 1) throw Exception("CTS_Encryption: insufficient data to encrypt"); - xor_buf(state, buffer, BLOCK_SIZE); + xor_buf(state, buffer, cipher->BLOCK_SIZE); cipher->encrypt(state); SecureVector<byte> cn = state; - clear_mem(buffer + position, BUFFER_SIZE - position); - encrypt(buffer + BLOCK_SIZE); - send(cn, position - BLOCK_SIZE); + clear_mem(buffer + position, buffer.size() - position); + encrypt(buffer + cipher->BLOCK_SIZE); + send(cn, position - cipher->BLOCK_SIZE); + } + +/* +* CTS Decryption Constructor +*/ +CTS_Decryption::CTS_Decryption(BlockCipher* ciph) : + cipher(ciph) + { + buffer.resize(2 * cipher->BLOCK_SIZE); + state.resize(cipher->BLOCK_SIZE); + temp.resize(cipher->BLOCK_SIZE); + position = 0; + } + +/* +* CTS Decryption Constructor +*/ +CTS_Decryption::CTS_Decryption(BlockCipher* ciph, + const SymmetricKey& key, + const InitializationVector& iv) : + cipher(ciph) + { + buffer.resize(2 * cipher->BLOCK_SIZE); + state.resize(cipher->BLOCK_SIZE); + temp.resize(cipher->BLOCK_SIZE); + position = 0; + + set_key(key); + set_iv(iv); + } + +/* +* Set the IV +*/ +void CTS_Decryption::set_iv(const InitializationVector& iv) + { + if(iv.length() != state.size()) + throw Invalid_IV_Length(name(), iv.length()); + + state = iv.bits_of(); + buffer.clear(); + position = 0; } /* @@ -76,9 +158,9 @@ void CTS_Encryption::end_msg() void CTS_Decryption::decrypt(const byte block[]) { cipher->decrypt(block, temp); - xor_buf(temp, state, BLOCK_SIZE); - send(temp, BLOCK_SIZE); - state.copy(block, BLOCK_SIZE); + xor_buf(temp, state, cipher->BLOCK_SIZE); + send(temp, cipher->BLOCK_SIZE); + state.copy(block, cipher->BLOCK_SIZE); } /* @@ -86,7 +168,7 @@ void CTS_Decryption::decrypt(const byte block[]) */ void CTS_Decryption::write(const byte input[], u32bit length) { - u32bit copied = std::min(BUFFER_SIZE - position, length); + u32bit copied = std::min(buffer.size() - position, length); buffer.copy(position, input, copied); length -= copied; input += copied; @@ -95,21 +177,21 @@ void CTS_Decryption::write(const byte input[], u32bit length) if(length == 0) return; decrypt(buffer); - if(length > BLOCK_SIZE) + if(length > cipher->BLOCK_SIZE) { - decrypt(buffer + BLOCK_SIZE); - while(length > 2*BLOCK_SIZE) + decrypt(buffer + cipher->BLOCK_SIZE); + while(length > 2*cipher->BLOCK_SIZE) { decrypt(input); - length -= BLOCK_SIZE; - input += BLOCK_SIZE; + length -= cipher->BLOCK_SIZE; + input += cipher->BLOCK_SIZE; } position = 0; } else { - copy_mem(buffer.begin(), buffer + BLOCK_SIZE, BLOCK_SIZE); - position = BLOCK_SIZE; + copy_mem(buffer.begin(), buffer + cipher->BLOCK_SIZE, cipher->BLOCK_SIZE); + position = cipher->BLOCK_SIZE; } buffer.copy(position, input, length); position += length; @@ -121,14 +203,14 @@ void CTS_Decryption::write(const byte input[], u32bit length) void CTS_Decryption::end_msg() { cipher->decrypt(buffer, temp); - xor_buf(temp, buffer + BLOCK_SIZE, position - BLOCK_SIZE); + xor_buf(temp, buffer + cipher->BLOCK_SIZE, position - cipher->BLOCK_SIZE); SecureVector<byte> xn = temp; - copy_mem(buffer + position, xn + (position - BLOCK_SIZE), - BUFFER_SIZE - position); - cipher->decrypt(buffer + BLOCK_SIZE, temp); - xor_buf(temp, state, BLOCK_SIZE); - send(temp, BLOCK_SIZE); - send(xn, position - BLOCK_SIZE); + copy_mem(buffer + position, xn + (position - cipher->BLOCK_SIZE), + buffer.size() - position); + cipher->decrypt(buffer + cipher->BLOCK_SIZE, temp); + xor_buf(temp, state, cipher->BLOCK_SIZE); + send(temp, cipher->BLOCK_SIZE); + send(xn, position - cipher->BLOCK_SIZE); } } diff --git a/src/filters/modes/cts/cts.h b/src/filters/modes/cts/cts.h index 1a2cae44e..4a7513fa0 100644 --- a/src/filters/modes/cts/cts.h +++ b/src/filters/modes/cts/cts.h @@ -8,51 +8,69 @@ #ifndef BOTAN_CTS_H__ #define BOTAN_CTS_H__ -#include <botan/modebase.h> #include <botan/block_cipher.h> +#include <botan/key_filt.h> namespace Botan { /* * CTS Encryption */ -class BOTAN_DLL CTS_Encryption : public BlockCipherMode +class BOTAN_DLL CTS_Encryption : public Keyed_Filter { public: - CTS_Encryption(BlockCipher* ciph) : - BlockCipherMode(ciph, "CTS", ciph->BLOCK_SIZE, 0, 2) {} + std::string name() const { return cipher->name() + "/CTS"; } - CTS_Encryption(BlockCipher* ciph, + void set_iv(const InitializationVector&); + + void set_key(const SymmetricKey& key) { cipher->set_key(key); } + + bool valid_keylength(u32bit key_len) const + { return cipher->valid_keylength(key_len); } + + CTS_Encryption(BlockCipher* cipher); + + CTS_Encryption(BlockCipher* cipher, const SymmetricKey& key, - const InitializationVector& iv) : - BlockCipherMode(ciph, "CTS", ciph->BLOCK_SIZE, 0, 2) - { set_key(key); set_iv(iv); } + const InitializationVector& iv); private: void write(const byte[], u32bit); void end_msg(); void encrypt(const byte[]); + + BlockCipher* cipher; + SecureVector<byte> buffer, state; + u32bit position; }; /* * CTS Decryption */ -class BOTAN_DLL CTS_Decryption : public BlockCipherMode +class BOTAN_DLL CTS_Decryption : public Keyed_Filter { public: - CTS_Decryption(BlockCipher* ciph) : - BlockCipherMode(ciph, "CTS", ciph->BLOCK_SIZE, 0, 2) - { temp.resize(BLOCK_SIZE); } + std::string name() const { return cipher->name() + "/CTS"; } - CTS_Decryption(BlockCipher* ciph, + void set_iv(const InitializationVector&); + + void set_key(const SymmetricKey& key) { cipher->set_key(key); } + + bool valid_keylength(u32bit key_len) const + { return cipher->valid_keylength(key_len); } + + CTS_Decryption(BlockCipher* cipher); + + CTS_Decryption(BlockCipher* cipher, const SymmetricKey& key, - const InitializationVector& iv) : - BlockCipherMode(ciph, "CTS", ciph->BLOCK_SIZE, 0, 2) - { set_key(key); set_iv(iv); temp.resize(BLOCK_SIZE); } + const InitializationVector& iv); private: void write(const byte[], u32bit); void end_msg(); void decrypt(const byte[]); - SecureVector<byte> temp; + + BlockCipher* cipher; + SecureVector<byte> buffer, state, temp; + u32bit position; }; } diff --git a/src/filters/modes/cts/info.txt b/src/filters/modes/cts/info.txt index 237f8cd97..7b590c5cb 100644 --- a/src/filters/modes/cts/info.txt +++ b/src/filters/modes/cts/info.txt @@ -1 +1,5 @@ define CTS + +<requires> +block +</requires> diff --git a/src/filters/modes/eax/eax.cpp b/src/filters/modes/eax/eax.cpp index 1187d8461..ee3b9f8e7 100644 --- a/src/filters/modes/eax/eax.cpp +++ b/src/filters/modes/eax/eax.cpp @@ -7,8 +7,9 @@ #include <botan/eax.h> #include <botan/cmac.h> -#include <botan/internal/xor_buf.h> +#include <botan/ctr.h> #include <botan/parsing.h> +#include <botan/internal/xor_buf.h> #include <algorithm> namespace Botan { @@ -34,20 +35,17 @@ SecureVector<byte> eax_prf(byte tag, u32bit BLOCK_SIZE, /* * EAX_Base Constructor */ -EAX_Base::EAX_Base(BlockCipher* ciph, - u32bit tag_size) : - TAG_SIZE(tag_size ? tag_size / 8 : ciph->BLOCK_SIZE), - BLOCK_SIZE(ciph->BLOCK_SIZE) +EAX_Base::EAX_Base(BlockCipher* cipher, u32bit tag_size) : + BLOCK_SIZE(cipher->BLOCK_SIZE), + TAG_SIZE(tag_size ? tag_size / 8 : BLOCK_SIZE), + cipher_name(cipher->name()), + ctr_buf(DEFAULT_BUFFERSIZE) { - cipher = ciph; - mac = new CMAC(cipher->clone()); + cmac = new CMAC(cipher->clone()); + ctr = new CTR_BE(cipher); // takes ownership - if(tag_size % 8 != 0 || TAG_SIZE == 0 || TAG_SIZE > mac->OUTPUT_LENGTH) + if(tag_size % 8 != 0 || TAG_SIZE == 0 || TAG_SIZE > cmac->OUTPUT_LENGTH) throw Invalid_Argument(name() + ": Bad tag size " + std::to_string(tag_size)); - - state.resize(BLOCK_SIZE); - buffer.resize(BLOCK_SIZE); - position = 0; } /* @@ -55,9 +53,7 @@ EAX_Base::EAX_Base(BlockCipher* ciph, */ bool EAX_Base::valid_keylength(u32bit n) const { - if(!cipher->valid_keylength(n)) - return false; - if(!mac->valid_keylength(n)) + if(!ctr->valid_keylength(n)) return false; return true; } @@ -67,9 +63,14 @@ bool EAX_Base::valid_keylength(u32bit n) const */ void EAX_Base::set_key(const SymmetricKey& key) { - cipher->set_key(key); - mac->set_key(key); - header_mac = eax_prf(1, BLOCK_SIZE, mac, 0, 0); + /* + * These could share the key schedule, which is one nice part of EAX, + * but it's much easier to ignore that here... + */ + ctr->set_key(key); + cmac->set_key(key); + + header_mac = eax_prf(1, BLOCK_SIZE, cmac, 0, 0); } /* @@ -78,8 +79,8 @@ void EAX_Base::set_key(const SymmetricKey& key) void EAX_Base::start_msg() { for(u32bit j = 0; j != BLOCK_SIZE - 1; ++j) - mac->update(0); - mac->update(2); + cmac->update(0); + cmac->update(2); } /* @@ -87,9 +88,8 @@ void EAX_Base::start_msg() */ void EAX_Base::set_iv(const InitializationVector& iv) { - nonce_mac = eax_prf(0, BLOCK_SIZE, mac, iv.begin(), iv.length()); - state = nonce_mac; - cipher->encrypt(state, buffer); + nonce_mac = eax_prf(0, BLOCK_SIZE, cmac, iv.begin(), iv.length()); + ctr->set_iv(&nonce_mac[0], nonce_mac.size()); } /* @@ -97,7 +97,7 @@ void EAX_Base::set_iv(const InitializationVector& iv) */ void EAX_Base::set_header(const byte header[], u32bit length) { - header_mac = eax_prf(1, BLOCK_SIZE, mac, header, length); + header_mac = eax_prf(1, BLOCK_SIZE, cmac, header, length); } /* @@ -105,19 +105,7 @@ void EAX_Base::set_header(const byte header[], u32bit length) */ std::string EAX_Base::name() const { - return (cipher->name() + "/EAX"); - } - -/* -* Increment the counter and update the buffer -*/ -void EAX_Base::increment_counter() - { - for(s32bit j = BLOCK_SIZE - 1; j >= 0; --j) - if(++state[j]) - break; - cipher->encrypt(state, buffer); - position = 0; + return (cipher_name + "/EAX"); } /* @@ -125,32 +113,17 @@ void EAX_Base::increment_counter() */ void EAX_Encryption::write(const byte input[], u32bit length) { - u32bit copied = std::min(BLOCK_SIZE - position, length); - xor_buf(buffer + position, input, copied); - send(buffer + position, copied); - mac->update(buffer + position, copied); - input += copied; - length -= copied; - position += copied; - - if(position == BLOCK_SIZE) - increment_counter(); - - while(length >= BLOCK_SIZE) + while(length) { - xor_buf(buffer, input, BLOCK_SIZE); - send(buffer, BLOCK_SIZE); - mac->update(buffer, BLOCK_SIZE); + u32bit copied = std::min(length, ctr_buf.size()); - input += BLOCK_SIZE; - length -= BLOCK_SIZE; - increment_counter(); - } + ctr->cipher(input, ctr_buf, copied); + cmac->update(ctr_buf, copied); - xor_buf(buffer + position, input, length); - send(buffer + position, length); - mac->update(buffer + position, length); - position += length; + send(ctr_buf, copied); + input += copied; + length -= copied; + } } /* @@ -158,15 +131,11 @@ void EAX_Encryption::write(const byte input[], u32bit length) */ void EAX_Encryption::end_msg() { - SecureVector<byte> data_mac = mac->final(); + SecureVector<byte> data_mac = cmac->final(); xor_buf(data_mac, nonce_mac, data_mac.size()); xor_buf(data_mac, header_mac, data_mac.size()); send(data_mac, TAG_SIZE); - - state.clear(); - buffer.clear(); - position = 0; } } diff --git a/src/filters/modes/eax/eax.h b/src/filters/modes/eax/eax.h index f569f2ede..e45e29ba8 100644 --- a/src/filters/modes/eax/eax.h +++ b/src/filters/modes/eax/eax.h @@ -10,6 +10,7 @@ #include <botan/key_filt.h> #include <botan/block_cipher.h> +#include <botan/stream_cipher.h> #include <botan/mac.h> namespace Botan { @@ -27,17 +28,19 @@ class BOTAN_DLL EAX_Base : public Keyed_Filter bool valid_keylength(u32bit) const; - ~EAX_Base() { delete cipher; delete mac; } + ~EAX_Base() { delete ctr; delete cmac; } protected: EAX_Base(BlockCipher*, u32bit); void start_msg(); - void increment_counter(); - const u32bit TAG_SIZE, BLOCK_SIZE; - BlockCipher* cipher; - MessageAuthenticationCode* mac; - SecureVector<byte> nonce_mac, header_mac, state, buffer; - u32bit position; + const u32bit BLOCK_SIZE, TAG_SIZE; + std::string cipher_name; + + StreamCipher* ctr; + MessageAuthenticationCode* cmac; + + SecureVector<byte> nonce_mac, header_mac; + SecureVector<byte> ctr_buf; }; /* @@ -76,6 +79,7 @@ class BOTAN_DLL EAX_Decryption : public EAX_Base void write(const byte[], u32bit); void do_write(const byte[], u32bit); void end_msg(); + SecureVector<byte> queue; u32bit queue_start, queue_end; }; diff --git a/src/filters/modes/eax/eax_dec.cpp b/src/filters/modes/eax/eax_dec.cpp index 24b68f3b7..f41327ffc 100644 --- a/src/filters/modes/eax/eax_dec.cpp +++ b/src/filters/modes/eax/eax_dec.cpp @@ -52,7 +52,6 @@ void EAX_Decryption::write(const byte input[], u32bit length) length -= copied; queue_end += copied; - SecureVector<byte> block_buf(cipher->BLOCK_SIZE); while((queue_end - queue_start) > TAG_SIZE) { u32bit removed = (queue_end - queue_start) - TAG_SIZE; @@ -77,31 +76,20 @@ void EAX_Decryption::write(const byte input[], u32bit length) */ void EAX_Decryption::do_write(const byte input[], u32bit length) { - mac->update(input, length); - - u32bit copied = std::min(BLOCK_SIZE - position, length); - xor_buf(buffer + position, input, copied); - send(buffer + position, copied); - input += copied; - length -= copied; - position += copied; - - if(position == BLOCK_SIZE) - increment_counter(); - - while(length >= BLOCK_SIZE) + while(length) { - xor_buf(buffer, input, BLOCK_SIZE); - send(buffer, BLOCK_SIZE); - - input += BLOCK_SIZE; - length -= BLOCK_SIZE; - increment_counter(); + u32bit copied = std::min(length, ctr_buf.size()); + + /* + Process same block with cmac and ctr at the same time to + help cache locality. + */ + cmac->update(input, copied); + ctr->cipher(input, ctr_buf, copied); + send(ctr_buf, copied); + input += copied; + length -= copied; } - - xor_buf(buffer + position, input, length); - send(buffer + position, length); - position += length; } /* @@ -112,15 +100,12 @@ void EAX_Decryption::end_msg() if((queue_end - queue_start) != TAG_SIZE) throw Integrity_Failure(name() + ": Message authentication failure"); - SecureVector<byte> data_mac = mac->final(); + SecureVector<byte> data_mac = cmac->final(); for(u32bit j = 0; j != TAG_SIZE; ++j) if(queue[queue_start+j] != (data_mac[j] ^ nonce_mac[j] ^ header_mac[j])) throw Integrity_Failure(name() + ": Message authentication failure"); - state.clear(); - buffer.clear(); - position = 0; queue_start = queue_end = 0; } diff --git a/src/filters/modes/eax/info.txt b/src/filters/modes/eax/info.txt index 4c91318d6..09d92e724 100644 --- a/src/filters/modes/eax/info.txt +++ b/src/filters/modes/eax/info.txt @@ -1,5 +1,7 @@ define EAX <requires> +block cmac +ctr </requires> diff --git a/src/filters/modes/ecb/ecb.h b/src/filters/modes/ecb/ecb.h index ff9ea9635..2b3b3fe83 100644 --- a/src/filters/modes/ecb/ecb.h +++ b/src/filters/modes/ecb/ecb.h @@ -8,11 +8,9 @@ #ifndef BOTAN_ECB_H__ #define BOTAN_ECB_H__ -#include <botan/basefilt.h> #include <botan/block_cipher.h> #include <botan/mode_pad.h> - -#include <botan/modebase.h> +#include <botan/key_filt.h> namespace Botan { diff --git a/src/filters/modes/ecb/info.txt b/src/filters/modes/ecb/info.txt index a26930470..38a56040c 100644 --- a/src/filters/modes/ecb/info.txt +++ b/src/filters/modes/ecb/info.txt @@ -1,5 +1,6 @@ define ECB <requires> +block mode_pad </requires> diff --git a/src/filters/modes/info.txt b/src/filters/modes/info.txt deleted file mode 100644 index 6d27c9709..000000000 --- a/src/filters/modes/info.txt +++ /dev/null @@ -1,6 +0,0 @@ -define CIPHER_MODEBASE - -<requires> -block -filters -</requires> diff --git a/src/filters/modes/mode_pad/mode_pad.cpp b/src/filters/modes/mode_pad/mode_pad.cpp index 2204c28b5..94f84fa03 100644 --- a/src/filters/modes/mode_pad/mode_pad.cpp +++ b/src/filters/modes/mode_pad/mode_pad.cpp @@ -120,8 +120,7 @@ u32bit OneAndZeros_Padding::unpad(const byte block[], u32bit size) const */ bool OneAndZeros_Padding::valid_blocksize(u32bit size) const { - if(size) return true; - else return false; + return (size > 0); } } diff --git a/src/filters/modes/modebase.cpp b/src/filters/modes/modebase.cpp deleted file mode 100644 index 59ee55a8a..000000000 --- a/src/filters/modes/modebase.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* -* Block Cipher Mode -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/modebase.h> - -namespace Botan { - -/* -* Block Cipher Mode Constructor -*/ -BlockCipherMode::BlockCipherMode(BlockCipher* cipher_ptr, - const std::string& cipher_mode_name, - u32bit iv_size, u32bit iv_meth, - u32bit buf_mult) : - BLOCK_SIZE(cipher_ptr->BLOCK_SIZE), BUFFER_SIZE(buf_mult * BLOCK_SIZE), - IV_METHOD(iv_meth), mode_name(cipher_mode_name) - { - cipher = cipher_ptr; - buffer.resize(BUFFER_SIZE); - state.resize(iv_size); - position = 0; - } - -/* -* Return the name of this type -*/ -std::string BlockCipherMode::name() const - { - return (cipher->name() + "/" + mode_name); - } - -/* -* Set the IV -*/ -void BlockCipherMode::set_iv(const InitializationVector& new_iv) - { - if(new_iv.length() != state.size()) - throw Invalid_IV_Length(name(), new_iv.length()); - - state = new_iv.bits_of(); - buffer.clear(); - position = 0; - - if(IV_METHOD == 1) - cipher->encrypt(state, buffer); - else if(IV_METHOD == 2) - cipher->encrypt(state); - } - -} diff --git a/src/filters/modes/modebase.h b/src/filters/modes/modebase.h deleted file mode 100644 index 4a15524b6..000000000 --- a/src/filters/modes/modebase.h +++ /dev/null @@ -1,44 +0,0 @@ -/* -* Block Cipher Mode -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_MODEBASE_H__ -#define BOTAN_MODEBASE_H__ - -#include <botan/key_filt.h> -#include <botan/block_cipher.h> - -namespace Botan { - -/** -* This class represents an abstract block cipher mode -*/ -class BOTAN_DLL BlockCipherMode : public Keyed_Filter - { - public: - std::string name() const; - - void set_iv(const InitializationVector&); - void set_key(const SymmetricKey& key) { cipher->set_key(key); } - - bool valid_keylength(u32bit key_len) const - { return cipher->valid_keylength(key_len); } - - BlockCipherMode(BlockCipher*, const std::string&, - u32bit, u32bit = 0, u32bit = 1); - - virtual ~BlockCipherMode() { delete cipher; } - protected: - const u32bit BLOCK_SIZE, BUFFER_SIZE, IV_METHOD; - const std::string mode_name; - BlockCipher* cipher; - SecureVector<byte> buffer, state; - u32bit position; - }; - -} - -#endif diff --git a/src/filters/modes/xts/info.txt b/src/filters/modes/xts/info.txt index 9af3238f1..7327298f9 100644 --- a/src/filters/modes/xts/info.txt +++ b/src/filters/modes/xts/info.txt @@ -1 +1,5 @@ define XTS + +<requires> +block +</requires> diff --git a/src/hash/skein/skein_512.cpp b/src/hash/skein/skein_512.cpp index ab74faf42..869257567 100644 --- a/src/hash/skein/skein_512.cpp +++ b/src/hash/skein/skein_512.cpp @@ -27,11 +27,11 @@ enum type_code { SKEIN_OUTPUT = 63 }; -void ubi_512(u64bit H[9], u64bit T[], const byte msg[], u64bit msg_len) +void ubi_512(u64bit H[9], u64bit T[], const byte msg[], u32bit msg_len) { do { - const u64bit to_proc = std::min<u64bit>(msg_len, 64); + const u32bit to_proc = std::min<u32bit>(msg_len, 64); T[0] += to_proc; u64bit M[8] = { 0 }; diff --git a/src/libstate/lookup.cpp b/src/libstate/lookup.cpp index 3b49116f6..9016dbe6e 100644 --- a/src/libstate/lookup.cpp +++ b/src/libstate/lookup.cpp @@ -71,7 +71,7 @@ HashFunction* get_hash(const std::string& algo_spec) bool have_hash(const std::string& algo_spec) { Algorithm_Factory& af = global_state().algorithm_factory(); - return af.prototype_hash_function(algo_spec); + return (af.prototype_hash_function(algo_spec) != 0); } /** @@ -98,7 +98,7 @@ MessageAuthenticationCode* get_mac(const std::string& algo_spec) bool have_mac(const std::string& algo_spec) { Algorithm_Factory& af = global_state().algorithm_factory(); - return af.prototype_mac(algo_spec); + return (af.prototype_mac(algo_spec) != 0); } /** diff --git a/src/math/numbertheory/numthry.cpp b/src/math/numbertheory/numthry.cpp index 42e83fa4a..760250712 100644 --- a/src/math/numbertheory/numthry.cpp +++ b/src/math/numbertheory/numthry.cpp @@ -76,8 +76,6 @@ u32bit miller_rabin_test_iterations(u32bit bits, bool verify) */ u32bit low_zero_bits(const BigInt& n) { - if(n.is_negative() || n.is_zero()) return 0; - u32bit low_zero = 0; if(n.is_positive() && n.is_nonzero()) diff --git a/src/selftest/selftest.cpp b/src/selftest/selftest.cpp index 2f6bea4cd..d1fdd03b0 100644 --- a/src/selftest/selftest.cpp +++ b/src/selftest/selftest.cpp @@ -19,12 +19,14 @@ namespace { */ bool test_filter_kat(Filter* filter, const std::string& input, - const std::string& output) + const std::string& expected_output) { Pipe pipe(new Hex_Decoder, filter, new Hex_Encoder); pipe.process_msg(input); - return (output == pipe.read_all_as_string()); + std::string output = pipe.read_all_as_string(); + + return (output == expected_output); } } diff --git a/src/utils/bswap.h b/src/utils/bswap.h index 1a5349fd0..96ec4982a 100644 --- a/src/utils/bswap.h +++ b/src/utils/bswap.h @@ -12,6 +12,14 @@ #include <botan/types.h> #include <botan/rotate.h> +#if defined(BOTAN_TARGET_CPU_HAS_SSE2) + #include <emmintrin.h> +#endif + +#if defined(BOTAN_TARGET_CPU_HAS_SSSE3) + #include <tmmintrin.h> +#endif + namespace Botan { /* @@ -66,6 +74,48 @@ inline u64bit reverse_bytes(u64bit input) #endif } +template<typename T> +inline void bswap_4(T x[4]) + { + x[0] = reverse_bytes(x[0]); + x[1] = reverse_bytes(x[1]); + x[2] = reverse_bytes(x[2]); + x[3] = reverse_bytes(x[3]); + } + +#if defined(BOTAN_TARGET_CPU_HAS_SSSE3) + +template<> +inline void bswap_4(u32bit x[4]) + { + const __m128i bswap_mask = _mm_set_epi8( + 12, 13, 14, 15, + 8, 9, 10, 11, + 4, 5, 6, 7, + 0, 1, 2, 3); + + __m128i T = _mm_loadu_si128((const __m128i*)x); + T = _mm_shuffle_epi8(T, bswap_mask); + _mm_storeu_si128((__m128i*)x, T); + } + +#elif defined(BOTAN_TARGET_CPU_HAS_SSE2) + +template<> +inline void bswap_4(u32bit x[4]) + { + __m128i T = _mm_loadu_si128((const __m128i*)x); + + T = _mm_shufflehi_epi16(T, _MM_SHUFFLE(2, 3, 0, 1)); + T = _mm_shufflelo_epi16(T, _MM_SHUFFLE(2, 3, 0, 1)); + + T = _mm_or_si128(_mm_srli_epi16(T, 8), _mm_slli_epi16(T, 8)); + + _mm_storeu_si128((__m128i*)x, T); + } + +#endif + } #endif diff --git a/src/utils/loadstor.h b/src/utils/loadstor.h index 77a6e846c..bd2acc87d 100644 --- a/src/utils/loadstor.h +++ b/src/utils/loadstor.h @@ -42,7 +42,9 @@ namespace Botan { */ template<typename T> inline byte get_byte(u32bit byte_num, T input) { - return (input >> ((sizeof(T)-1-(byte_num&(sizeof(T)-1))) << 3)); + return static_cast<byte>( + input >> ((sizeof(T)-1-(byte_num&(sizeof(T)-1))) << 3) + ); } /* @@ -202,24 +204,22 @@ inline void load_le(T out[], const byte in[], u32bit count) { -#if defined(BOTAN_TARGET_CPU_IS_LITTLE_ENDIAN) +#if defined(BOTAN_TARGET_CPU_HAS_KNOWN_ENDIANNESS) std::memcpy(out, in, sizeof(T)*count); -#else + +#if defined(BOTAN_TARGET_CPU_IS_BIG_ENDIAN) const u32bit blocks = count - (count % 4); const u32bit left = count - blocks; for(u32bit i = 0; i != blocks; i += 4) - { - out[0] = load_le<T>(in, 0); - out[1] = load_le<T>(in, 1); - out[2] = load_le<T>(in, 2); - out[3] = load_le<T>(in, 3); - - out += 4; - in += 4*sizeof(T); - } + bswap_4(out + i); for(u32bit i = 0; i != left; ++i) + out[blocks+i] = reverse_bytes(out[blocks+i]); +#endif + +#else + for(u32bit i = 0; i != count; ++i) out[i] = load_le<T>(in, i); #endif } @@ -261,24 +261,22 @@ inline void load_be(T out[], const byte in[], u32bit count) { -#if defined(BOTAN_TARGET_CPU_IS_BIG_ENDIAN) +#if defined(BOTAN_TARGET_CPU_HAS_KNOWN_ENDIANNESS) std::memcpy(out, in, sizeof(T)*count); -#else + +#if defined(BOTAN_TARGET_CPU_IS_LITTLE_ENDIAN) const u32bit blocks = count - (count % 4); const u32bit left = count - blocks; for(u32bit i = 0; i != blocks; i += 4) - { - out[0] = load_be<T>(in, 0); - out[1] = load_be<T>(in, 1); - out[2] = load_be<T>(in, 2); - out[3] = load_be<T>(in, 3); - - out += 4; - in += 4*sizeof(T); - } + bswap_4(out + i); for(u32bit i = 0; i != left; ++i) + out[blocks+i] = reverse_bytes(out[blocks+i]); +#endif + +#else + for(u32bit i = 0; i != count; ++i) out[i] = load_be<T>(in, i); #endif } diff --git a/src/utils/time.cpp b/src/utils/time.cpp index 97804813d..db8055d9f 100644 --- a/src/utils/time.cpp +++ b/src/utils/time.cpp @@ -9,21 +9,25 @@ #include <botan/exceptn.h> #include <ctime> +#if defined(BOTAN_TARGET_OS_HAS_WIN32_GET_SYSTEMTIME) + #include <windows.h> +#endif + #if defined(BOTAN_TARGET_OS_HAS_GETTIMEOFDAY) #include <sys/time.h> #endif #if defined(BOTAN_TARGET_OS_HAS_CLOCK_GETTIME) -#ifndef _POSIX_C_SOURCE - #define _POSIX_C_SOURCE 199309 -#endif + #ifndef _POSIX_C_SOURCE + #define _POSIX_C_SOURCE 199309 + #endif -#include <time.h> + #include <time.h> -#ifndef CLOCK_REALTIME - #define CLOCK_REALTIME 0 -#endif + #ifndef CLOCK_REALTIME + #define CLOCK_REALTIME 0 + #endif #endif @@ -64,12 +68,34 @@ calendar_point calendar_value( { std::tm tm = do_gmtime(std::chrono::system_clock::to_time_t(time_point)); +<<<<<<< variant A + std::tm tm; + +#if defined(BOTAN_TARGET_OS_HAS_GMTIME_S) + gmtime_s(&tm, &time_val); // Windows +#elif defined(BOTAN_TARGET_OS_HAS_GMTIME_R) + gmtime_r(&time_val, &tm); // Unix/SUSv2 +#else + std::tm* tm_p = std::gmtime(&time_val); + if (tm_p == 0) + throw Encoding_Error("time_t_to_tm could not convert"); + tm = *tm_p; +#endif + + return tm; +>>>>>>> variant B return calendar_point(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); +####### Ancestor + std::tm* tm_p = std::gmtime(&time_val); + if (tm_p == 0) + throw Encoding_Error("time_t_to_tm could not convert"); + return (*tm_p); +======= end } u64bit get_nanoseconds_clock() @@ -84,6 +110,16 @@ u64bit get_nanoseconds_clock() ::gettimeofday(&tv, 0); return combine_timers(tv.tv_sec, tv.tv_usec, 1000000); +#elif defined(BOTAN_TARGET_OS_HAS_WIN32_GET_SYSTEMTIME) + + // Returns time since January 1, 1601 in 100-ns increments + ::FILETIME tv; + ::GetSystemTimeAsFileTime(&tv); + u64bit tstamp = (static_cast<u64bit>(tv.dwHighDateTime) << 32) | + tv.dwLowDateTime; + + return (tstamp * 100); // Scale to 1 nanosecond units + #else return combine_timers(std::time(0), std::clock(), CLOCKS_PER_SEC); diff --git a/src/utils/xor_buf.h b/src/utils/xor_buf.h index 39c4a493d..0d7d587c8 100644 --- a/src/utils/xor_buf.h +++ b/src/utils/xor_buf.h @@ -22,7 +22,7 @@ inline void xor_buf(byte out[], const byte in[], u32bit length) { while(length >= 8) { -#if BOTAN_UNALIGNED_MEMORY_ACCESS_OK +#if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK *reinterpret_cast<u64bit*>(out) ^= *reinterpret_cast<const u64bit*>(in); #else out[0] ^= in[0]; out[1] ^= in[1]; @@ -51,7 +51,7 @@ inline void xor_buf(byte out[], { while(length >= 8) { -#if BOTAN_UNALIGNED_MEMORY_ACCESS_OK +#if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK *reinterpret_cast<u64bit*>(out) = *reinterpret_cast<const u64bit*>(in) ^ *reinterpret_cast<const u64bit*>(in2); |