diff options
Diffstat (limited to 'src')
247 files changed, 7481 insertions, 2406 deletions
diff --git a/src/algo_factory/algo_cache.h b/src/algo_factory/algo_cache.h index 17ea9964a..08b25cd47 100644 --- a/src/algo_factory/algo_cache.h +++ b/src/algo_factory/algo_cache.h @@ -1,5 +1,8 @@ -/** +/* * An algorithm cache (used by Algorithm_Factory) +* (C) 2008-2009 Jack Lloyd +* +* Distributed under the terms of the Botan license */ #ifndef BOTAN_ALGORITHM_CACHE_TEMPLATE_H__ diff --git a/src/algo_factory/algo_factory.cpp b/src/algo_factory/algo_factory.cpp index 269c58c3b..3523b19d4 100644 --- a/src/algo_factory/algo_factory.cpp +++ b/src/algo_factory/algo_factory.cpp @@ -1,6 +1,6 @@ /* -Algorithm Factory -(C) 2008 Jack Lloyd +* Algorithm Factory +* (C) 2008 Jack Lloyd * * Distributed under the terms of the Botan license */ diff --git a/src/alloc/mem_pool/mem_pool.cpp b/src/alloc/mem_pool/mem_pool.cpp index 38e0c3285..dabf5e310 100644 --- a/src/alloc/mem_pool/mem_pool.cpp +++ b/src/alloc/mem_pool/mem_pool.cpp @@ -8,7 +8,7 @@ */ #include <botan/mem_pool.h> -#include <botan/util.h> +#include <botan/rounding.h> #include <botan/mem_ops.h> #include <algorithm> #include <exception> diff --git a/src/alloc/system_alloc/defalloc.cpp b/src/alloc/system_alloc/defalloc.cpp index 8791c74e4..b1b338d71 100644 --- a/src/alloc/system_alloc/defalloc.cpp +++ b/src/alloc/system_alloc/defalloc.cpp @@ -7,7 +7,7 @@ #include <botan/defalloc.h> #include <botan/libstate.h> -#include <botan/util.h> +#include <botan/mlock.h> #include <cstdlib> #include <cstring> diff --git a/src/aont/info.txt b/src/aont/info.txt new file mode 100644 index 000000000..a0387f358 --- /dev/null +++ b/src/aont/info.txt @@ -0,0 +1,17 @@ +realname "All or Nothing Transforms" + +define PACKAGE_TRANSFORM + +load_on auto + +<add> +package.cpp +package.h +</add> + +<requires> +block +ctr +rng +filters +</requires> diff --git a/src/aont/package.cpp b/src/aont/package.cpp new file mode 100644 index 000000000..6c6b56865 --- /dev/null +++ b/src/aont/package.cpp @@ -0,0 +1,128 @@ +/* +* Rivest's Package Tranform +* +* (C) 2009 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/package.h> +#include <botan/pipe.h> +#include <botan/ctr.h> +#include <botan/loadstor.h> +#include <botan/xor_buf.h> + +namespace Botan { + +namespace AllOrNothingTransform { + +void package(RandomNumberGenerator& rng, + BlockCipher* cipher, + const byte input[], u32bit input_len, + byte output[]) + { + if(!cipher->valid_keylength(cipher->BLOCK_SIZE)) + throw Invalid_Argument("AONT::package: Invalid cipher"); + + // The all-zero string which is used both as the CTR IV and as K0 + const std::string all_zeros(cipher->BLOCK_SIZE*2, '0'); + + SymmetricKey package_key(rng, cipher->BLOCK_SIZE); + + // takes ownership of cipher object + Keyed_Filter* ctr_mode = new CTR_BE(cipher, + package_key, + InitializationVector(all_zeros)); + + Pipe pipe(ctr_mode); + + pipe.process_msg(input, input_len); + pipe.read(output, pipe.remaining()); + + // Set K0 (the all zero key) + cipher->set_key(SymmetricKey(all_zeros)); + + SecureVector<byte> buf(cipher->BLOCK_SIZE); + + const u32bit blocks = + (input_len + cipher->BLOCK_SIZE - 1) / cipher->BLOCK_SIZE; + + byte* final_block = output + input_len; + clear_mem(final_block, cipher->BLOCK_SIZE); + + // XOR the hash blocks into the final block + for(u32bit i = 0; i != blocks; ++i) + { + u32bit left = std::min<u32bit>(cipher->BLOCK_SIZE, + input_len - cipher->BLOCK_SIZE * i); + + buf.clear(); + copy_mem(&buf[0], output + cipher->BLOCK_SIZE * i, left); + + for(u32bit j = 0; j != 4; ++j) + buf[cipher->BLOCK_SIZE - 1 - j] ^= get_byte(3-j, i); + + cipher->encrypt(buf); + + xor_buf(final_block, buf, cipher->BLOCK_SIZE); + } + + // XOR the random package key into the final block + xor_buf(final_block, package_key.begin(), cipher->BLOCK_SIZE); + } + +void unpackage(BlockCipher* cipher, + const byte input[], u32bit input_len, + byte output[]) + { + if(!cipher->valid_keylength(cipher->BLOCK_SIZE)) + throw Invalid_Argument("AONT::unpackage: Invalid cipher"); + + if(input_len < cipher->BLOCK_SIZE) + throw Invalid_Argument("AONT::unpackage: Input too short"); + + // The all-zero string which is used both as the CTR IV and as K0 + const std::string all_zeros(cipher->BLOCK_SIZE*2, '0'); + + cipher->set_key(SymmetricKey(all_zeros)); + + SecureVector<byte> package_key(cipher->BLOCK_SIZE); + SecureVector<byte> buf(cipher->BLOCK_SIZE); + + // Copy the package key (masked with the block hashes) + copy_mem(&package_key[0], + input + (input_len - cipher->BLOCK_SIZE), + cipher->BLOCK_SIZE); + + const u32bit blocks = ((input_len - 1) / cipher->BLOCK_SIZE); + + // XOR the blocks into the package key bits + for(u32bit i = 0; i != blocks; ++i) + { + u32bit left = std::min<u32bit>(cipher->BLOCK_SIZE, + input_len - cipher->BLOCK_SIZE * (i+1)); + + buf.clear(); + copy_mem(&buf[0], input + cipher->BLOCK_SIZE * i, left); + + for(u32bit j = 0; j != 4; ++j) + buf[cipher->BLOCK_SIZE - 1 - j] ^= get_byte(3-j, i); + + cipher->encrypt(buf); + + xor_buf(&package_key[0], buf, cipher->BLOCK_SIZE); + } + + // takes ownership of cipher object + Pipe pipe(new CTR_BE(cipher, + SymmetricKey(package_key), + InitializationVector(all_zeros))); + + pipe.process_msg(input, input_len - cipher->BLOCK_SIZE); + + pipe.read(output, pipe.remaining()); + } + +} + +} diff --git a/src/aont/package.h b/src/aont/package.h new file mode 100644 index 000000000..35d2a23fc --- /dev/null +++ b/src/aont/package.h @@ -0,0 +1,45 @@ +/* +* Rivest's Package Tranform +* +* (C) 2009 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/block_cipher.h> +#include <botan/rng.h> + +namespace Botan { + +namespace AllOrNothingTransform { + +/** +* Rivest's Package Tranform +* @arg rng the random number generator to use +* @arg cipher the block cipher to use +* @arg input the input data buffer +* @arg input_len the length of the input data in bytes +* @arg output the output data buffer (must be at least +* input_len + cipher->BLOCK_SIZE bytes long) +*/ +void package(RandomNumberGenerator& rng, + BlockCipher* cipher, + const byte input[], u32bit input_len, + byte output[]); + +/** +* Rivest's Package Tranform (Inversion) +* @arg rng the random number generator to use +* @arg cipher the block cipher to use +* @arg input the input data buffer +* @arg input_len the length of the input data in bytes +* @arg output the output data buffer (must be at least +* input_len - cipher->BLOCK_SIZE bytes long) +*/ +void unpackage(BlockCipher* cipher, + const byte input[], u32bit input_len, + byte output[]); + +} + +} diff --git a/src/asn1/asn1_tm.cpp b/src/asn1/asn1_tm.cpp index f85ea128b..09bc4d347 100644 --- a/src/asn1/asn1_tm.cpp +++ b/src/asn1/asn1_tm.cpp @@ -10,28 +10,10 @@ #include <botan/ber_dec.h> #include <botan/charset.h> #include <botan/parsing.h> -#include <ctime> +#include <botan/timer.h> namespace Botan { -namespace { - -/* -* Convert a time_t to a struct tm -*/ -std::tm get_tm(u64bit timer) - { - std::time_t time_val = static_cast<std::time_t>(timer); - - std::tm* tm_p = std::gmtime(&time_val); - if(tm_p == 0) - throw Encoding_Error("X509_Time: gmtime could not encode " + - to_string(timer)); - return (*tm_p); - } - -} - /* * Create an X509_Time */ @@ -45,7 +27,7 @@ X509_Time::X509_Time(const std::string& time_str) */ X509_Time::X509_Time(u64bit timer) { - std::tm time_info = get_tm(timer); + std::tm time_info = time_t_to_tm(timer); year = time_info.tm_year + 1900; month = time_info.tm_mon + 1; diff --git a/src/benchmark/benchmark.cpp b/src/benchmark/benchmark.cpp index 01e3b94f3..6e61baa59 100644 --- a/src/benchmark/benchmark.cpp +++ b/src/benchmark/benchmark.cpp @@ -11,7 +11,6 @@ #include <botan/stream_cipher.h> #include <botan/hash.h> #include <botan/mac.h> -#include <botan/util.h> #include <memory> namespace Botan { @@ -55,10 +54,11 @@ bench_block_cipher(BlockCipher* block_cipher, const u32bit in_blocks = buf_len / block_cipher->BLOCK_SIZE; + block_cipher->set_key(buf, block_cipher->MAXIMUM_KEYLENGTH); + while(nanoseconds_used < nanoseconds_max) { - for(u32bit i = 0; i != in_blocks; ++i) - block_cipher->encrypt(buf + block_cipher->BLOCK_SIZE * i); + block_cipher->encrypt_n(buf, buf, in_blocks); ++reps; nanoseconds_used = timer.clock() - start; @@ -81,6 +81,8 @@ bench_stream_cipher(StreamCipher* stream_cipher, u64bit nanoseconds_used = 0; u64bit reps = 0; + stream_cipher->set_key(buf, stream_cipher->MAXIMUM_KEYLENGTH); + while(nanoseconds_used < nanoseconds_max) { stream_cipher->encrypt(buf, buf_len); diff --git a/src/block/aes/aes.cpp b/src/block/aes/aes.cpp index 9072b507b..34698ae7f 100644 --- a/src/block/aes/aes.cpp +++ b/src/block/aes/aes.cpp @@ -1,6 +1,6 @@ /** * AES -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -13,163 +13,175 @@ namespace Botan { /** * AES Encryption */ -void AES::enc(const byte in[], byte out[]) const +void AES::encrypt_n(const byte in[], byte out[], u32bit blocks) const { const u32bit* TE0 = TE; const u32bit* TE1 = TE + 256; const u32bit* TE2 = TE + 512; const u32bit* TE3 = TE + 768; - u32bit T0 = load_be<u32bit>(in, 0) ^ EK[0]; - u32bit T1 = load_be<u32bit>(in, 1) ^ EK[1]; - 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]; - - for(u32bit j = 2; j != ROUNDS; j += 2) + for(u32bit i = 0; i != blocks; ++i) { - const u32bit K0 = EK[4*j]; - const u32bit K1 = EK[4*j+1]; - const u32bit K2 = EK[4*j+2]; - const u32bit K3 = EK[4*j+3]; - - T0 = TE0[get_byte(0, B0)] ^ TE1[get_byte(1, B1)] ^ - TE2[get_byte(2, B2)] ^ TE3[get_byte(3, B3)] ^ K0; - T1 = TE0[get_byte(0, B1)] ^ TE1[get_byte(1, B2)] ^ - TE2[get_byte(2, B3)] ^ TE3[get_byte(3, B0)] ^ K1; - T2 = TE0[get_byte(0, B2)] ^ TE1[get_byte(1, B3)] ^ - TE2[get_byte(2, B0)] ^ TE3[get_byte(3, B1)] ^ K2; - T3 = TE0[get_byte(0, B3)] ^ TE1[get_byte(1, B0)] ^ - TE2[get_byte(2, B1)] ^ TE3[get_byte(3, B2)] ^ K3; - - const u32bit K4 = EK[4*(j+1)+0]; - const u32bit K5 = EK[4*(j+1)+1]; - const u32bit K6 = EK[4*(j+1)+2]; - const u32bit K7 = EK[4*(j+1)+3]; + u32bit T0 = load_be<u32bit>(in, 0) ^ EK[0]; + u32bit T1 = load_be<u32bit>(in, 1) ^ EK[1]; + 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)] ^ K4; + 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)] ^ K5; + 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)] ^ K6; + 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)] ^ K7; - } + TE2[get_byte(2, T1)] ^ TE3[get_byte(3, T2)] ^ EK[7]; + + for(u32bit j = 2; j != ROUNDS; j += 2) + { + const u32bit K0 = EK[4*j]; + const u32bit K1 = EK[4*j+1]; + const u32bit K2 = EK[4*j+2]; + const u32bit K3 = EK[4*j+3]; + + T0 = TE0[get_byte(0, B0)] ^ TE1[get_byte(1, B1)] ^ + TE2[get_byte(2, B2)] ^ TE3[get_byte(3, B3)] ^ K0; + T1 = TE0[get_byte(0, B1)] ^ TE1[get_byte(1, B2)] ^ + TE2[get_byte(2, B3)] ^ TE3[get_byte(3, B0)] ^ K1; + T2 = TE0[get_byte(0, B2)] ^ TE1[get_byte(1, B3)] ^ + TE2[get_byte(2, B0)] ^ TE3[get_byte(3, B1)] ^ K2; + T3 = TE0[get_byte(0, B3)] ^ TE1[get_byte(1, B0)] ^ + TE2[get_byte(2, B1)] ^ TE3[get_byte(3, B2)] ^ K3; + + const u32bit K4 = EK[4*(j+1)+0]; + const u32bit K5 = EK[4*(j+1)+1]; + const u32bit K6 = EK[4*(j+1)+2]; + const u32bit K7 = EK[4*(j+1)+3]; - /* - 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. - - """In addition to OpenSSL v. 0.9.8.(a), which was used in our - experiments, the AES implementations of Crypto++ 5.2.1 and - LibTomCrypt 1.09 use the original Rijndael C implementation with - very few changes and are highly vulnerable. The AES implementations - in libgcrypt v. 1.2.2 and Botan v. 1.4.2 are also vulnerable, but - 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]; - out[ 3] = SE[get_byte(3, B3)] ^ ME[3]; - out[ 4] = SE[get_byte(0, B1)] ^ ME[4]; - out[ 5] = SE[get_byte(1, B2)] ^ ME[5]; - out[ 6] = SE[get_byte(2, B3)] ^ ME[6]; - out[ 7] = SE[get_byte(3, B0)] ^ ME[7]; - out[ 8] = SE[get_byte(0, B2)] ^ ME[8]; - out[ 9] = SE[get_byte(1, B3)] ^ ME[9]; - out[10] = SE[get_byte(2, B0)] ^ ME[10]; - out[11] = SE[get_byte(3, B1)] ^ ME[11]; - out[12] = SE[get_byte(0, B3)] ^ ME[12]; - out[13] = SE[get_byte(1, B0)] ^ ME[13]; - out[14] = SE[get_byte(2, B1)] ^ ME[14]; - out[15] = SE[get_byte(3, B2)] ^ ME[15]; + B0 = TE0[get_byte(0, T0)] ^ TE1[get_byte(1, T1)] ^ + TE2[get_byte(2, T2)] ^ TE3[get_byte(3, T3)] ^ K4; + B1 = TE0[get_byte(0, T1)] ^ TE1[get_byte(1, T2)] ^ + TE2[get_byte(2, T3)] ^ TE3[get_byte(3, T0)] ^ K5; + B2 = TE0[get_byte(0, T2)] ^ TE1[get_byte(1, T3)] ^ + TE2[get_byte(2, T0)] ^ TE3[get_byte(3, T1)] ^ K6; + B3 = TE0[get_byte(0, T3)] ^ TE1[get_byte(1, T0)] ^ + TE2[get_byte(2, T1)] ^ TE3[get_byte(3, T2)] ^ K7; + } + + /* + 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. + + """In addition to OpenSSL v. 0.9.8.(a), which was used in our + experiments, the AES implementations of Crypto++ 5.2.1 and + LibTomCrypt 1.09 use the original Rijndael C implementation with + very few changes and are highly vulnerable. The AES implementations + in libgcrypt v. 1.2.2 and Botan v. 1.4.2 are also vulnerable, but + 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]; + out[ 3] = SE[get_byte(3, B3)] ^ ME[3]; + out[ 4] = SE[get_byte(0, B1)] ^ ME[4]; + out[ 5] = SE[get_byte(1, B2)] ^ ME[5]; + out[ 6] = SE[get_byte(2, B3)] ^ ME[6]; + out[ 7] = SE[get_byte(3, B0)] ^ ME[7]; + out[ 8] = SE[get_byte(0, B2)] ^ ME[8]; + out[ 9] = SE[get_byte(1, B3)] ^ ME[9]; + out[10] = SE[get_byte(2, B0)] ^ ME[10]; + out[11] = SE[get_byte(3, B1)] ^ ME[11]; + out[12] = SE[get_byte(0, B3)] ^ ME[12]; + out[13] = SE[get_byte(1, B0)] ^ ME[13]; + out[14] = SE[get_byte(2, B1)] ^ ME[14]; + out[15] = SE[get_byte(3, B2)] ^ ME[15]; + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /** * AES Decryption */ -void AES::dec(const byte in[], byte out[]) const +void AES::decrypt_n(const byte in[], byte out[], u32bit blocks) const { const u32bit* TD0 = TD; const u32bit* TD1 = TD + 256; const u32bit* TD2 = TD + 512; const u32bit* TD3 = TD + 768; - u32bit T0 = load_be<u32bit>(in, 0) ^ DK[0]; - u32bit T1 = load_be<u32bit>(in, 1) ^ DK[1]; - 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]; - - for(u32bit j = 2; j != ROUNDS; j += 2) + for(u32bit i = 0; i != blocks; ++i) { - const u32bit K0 = DK[4*j+0]; - const u32bit K1 = DK[4*j+1]; - const u32bit K2 = DK[4*j+2]; - const u32bit K3 = DK[4*j+3]; - - T0 = TD0[get_byte(0, B0)] ^ TD1[get_byte(1, B3)] ^ - TD2[get_byte(2, B2)] ^ TD3[get_byte(3, B1)] ^ K0; - T1 = TD0[get_byte(0, B1)] ^ TD1[get_byte(1, B0)] ^ - TD2[get_byte(2, B3)] ^ TD3[get_byte(3, B2)] ^ K1; - T2 = TD0[get_byte(0, B2)] ^ TD1[get_byte(1, B1)] ^ - TD2[get_byte(2, B0)] ^ TD3[get_byte(3, B3)] ^ K2; - T3 = TD0[get_byte(0, B3)] ^ TD1[get_byte(1, B2)] ^ - TD2[get_byte(2, B1)] ^ TD3[get_byte(3, B0)] ^ K3; - - const u32bit K4 = DK[4*(j+1)+0]; - const u32bit K5 = DK[4*(j+1)+1]; - const u32bit K6 = DK[4*(j+1)+2]; - const u32bit K7 = DK[4*(j+1)+3]; + u32bit T0 = load_be<u32bit>(in, 0) ^ DK[0]; + u32bit T1 = load_be<u32bit>(in, 1) ^ DK[1]; + 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)] ^ K4; + 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)] ^ K5; + 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)] ^ K6; + 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)] ^ K7; - } + TD2[get_byte(2, T1)] ^ TD3[get_byte(3, T0)] ^ DK[7]; + + for(u32bit j = 2; j != ROUNDS; j += 2) + { + const u32bit K0 = DK[4*j+0]; + const u32bit K1 = DK[4*j+1]; + const u32bit K2 = DK[4*j+2]; + const u32bit K3 = DK[4*j+3]; + + T0 = TD0[get_byte(0, B0)] ^ TD1[get_byte(1, B3)] ^ + TD2[get_byte(2, B2)] ^ TD3[get_byte(3, B1)] ^ K0; + T1 = TD0[get_byte(0, B1)] ^ TD1[get_byte(1, B0)] ^ + TD2[get_byte(2, B3)] ^ TD3[get_byte(3, B2)] ^ K1; + T2 = TD0[get_byte(0, B2)] ^ TD1[get_byte(1, B1)] ^ + TD2[get_byte(2, B0)] ^ TD3[get_byte(3, B3)] ^ K2; + T3 = TD0[get_byte(0, B3)] ^ TD1[get_byte(1, B2)] ^ + TD2[get_byte(2, B1)] ^ TD3[get_byte(3, B0)] ^ K3; + + const u32bit K4 = DK[4*(j+1)+0]; + const u32bit K5 = DK[4*(j+1)+1]; + const u32bit K6 = DK[4*(j+1)+2]; + const u32bit K7 = DK[4*(j+1)+3]; - out[ 0] = SD[get_byte(0, B0)] ^ MD[0]; - out[ 1] = SD[get_byte(1, B3)] ^ MD[1]; - out[ 2] = SD[get_byte(2, B2)] ^ MD[2]; - out[ 3] = SD[get_byte(3, B1)] ^ MD[3]; - out[ 4] = SD[get_byte(0, B1)] ^ MD[4]; - out[ 5] = SD[get_byte(1, B0)] ^ MD[5]; - out[ 6] = SD[get_byte(2, B3)] ^ MD[6]; - out[ 7] = SD[get_byte(3, B2)] ^ MD[7]; - out[ 8] = SD[get_byte(0, B2)] ^ MD[8]; - out[ 9] = SD[get_byte(1, B1)] ^ MD[9]; - out[10] = SD[get_byte(2, B0)] ^ MD[10]; - out[11] = SD[get_byte(3, B3)] ^ MD[11]; - out[12] = SD[get_byte(0, B3)] ^ MD[12]; - out[13] = SD[get_byte(1, B2)] ^ MD[13]; - out[14] = SD[get_byte(2, B1)] ^ MD[14]; - out[15] = SD[get_byte(3, B0)] ^ MD[15]; + B0 = TD0[get_byte(0, T0)] ^ TD1[get_byte(1, T3)] ^ + TD2[get_byte(2, T2)] ^ TD3[get_byte(3, T1)] ^ K4; + B1 = TD0[get_byte(0, T1)] ^ TD1[get_byte(1, T0)] ^ + TD2[get_byte(2, T3)] ^ TD3[get_byte(3, T2)] ^ K5; + B2 = TD0[get_byte(0, T2)] ^ TD1[get_byte(1, T1)] ^ + TD2[get_byte(2, T0)] ^ TD3[get_byte(3, T3)] ^ K6; + B3 = TD0[get_byte(0, T3)] ^ TD1[get_byte(1, T2)] ^ + TD2[get_byte(2, T1)] ^ TD3[get_byte(3, T0)] ^ K7; + } + + out[ 0] = SD[get_byte(0, B0)] ^ MD[0]; + out[ 1] = SD[get_byte(1, B3)] ^ MD[1]; + out[ 2] = SD[get_byte(2, B2)] ^ MD[2]; + out[ 3] = SD[get_byte(3, B1)] ^ MD[3]; + out[ 4] = SD[get_byte(0, B1)] ^ MD[4]; + out[ 5] = SD[get_byte(1, B0)] ^ MD[5]; + out[ 6] = SD[get_byte(2, B3)] ^ MD[6]; + out[ 7] = SD[get_byte(3, B2)] ^ MD[7]; + out[ 8] = SD[get_byte(0, B2)] ^ MD[8]; + out[ 9] = SD[get_byte(1, B1)] ^ MD[9]; + out[10] = SD[get_byte(2, B0)] ^ MD[10]; + out[11] = SD[get_byte(3, B3)] ^ MD[11]; + out[12] = SD[get_byte(0, B3)] ^ MD[12]; + out[13] = SD[get_byte(1, B2)] ^ MD[13]; + out[14] = SD[get_byte(2, B1)] ^ MD[14]; + out[15] = SD[get_byte(3, B0)] ^ MD[15]; + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /** diff --git a/src/block/aes/aes.h b/src/block/aes/aes.h index 05e2e3123..768bb09e7 100644 --- a/src/block/aes/aes.h +++ b/src/block/aes/aes.h @@ -1,6 +1,6 @@ /** * AES -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -18,14 +18,16 @@ namespace Botan { class BOTAN_DLL AES : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw(); std::string name() const { return "AES"; } BlockCipher* clone() const { return new AES; } + AES() : BlockCipher(16, 16, 32, 8) { ROUNDS = 14; } AES(u32bit); private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); static u32bit S(u32bit); diff --git a/src/block/aes/info.txt b/src/block/aes/info.txt index 2803ccc4e..0e11603bb 100644 --- a/src/block/aes/info.txt +++ b/src/block/aes/info.txt @@ -1,11 +1,3 @@ realname "AES" define AES - -load_on auto - -<add> -aes.cpp -aes.h -aes_tab.cpp -</add> diff --git a/src/block/block_cipher.h b/src/block/block_cipher.h index 01c45af04..a27609171 100644 --- a/src/block/block_cipher.h +++ b/src/block/block_cipher.h @@ -1,6 +1,6 @@ /** * Block Cipher Base Class -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -45,7 +45,8 @@ class BOTAN_DLL BlockCipher : public SymmetricAlgorithm * @param out The byte array designated to hold the encrypted block. * Must be of length BLOCK_SIZE. */ - void encrypt(const byte in[], byte out[]) const { enc(in, out); } + void encrypt(const byte in[], byte out[]) const + { encrypt_n(in, out, 1); } /** * Decrypt a block. @@ -54,7 +55,8 @@ class BOTAN_DLL BlockCipher : public SymmetricAlgorithm * @param out The byte array designated to hold the decrypted block. * Must be of length BLOCK_SIZE. */ - void decrypt(const byte in[], byte out[]) const { dec(in, out); } + void decrypt(const byte in[], byte out[]) const + { decrypt_n(in, out, 1); } /** * Encrypt a block. @@ -62,7 +64,7 @@ class BOTAN_DLL BlockCipher : public SymmetricAlgorithm * Must be of length BLOCK_SIZE. Will hold the result when the function * has finished. */ - void encrypt(byte block[]) const { enc(block, block); } + void encrypt(byte block[]) const { encrypt_n(block, block, 1); } /** * Decrypt a block. @@ -70,7 +72,12 @@ class BOTAN_DLL BlockCipher : public SymmetricAlgorithm * Must be of length BLOCK_SIZE. Will hold the result when the function * has finished. */ - void decrypt(byte block[]) const { dec(block, block); } + void decrypt(byte block[]) const { decrypt_n(block, block, 1); } + + virtual void encrypt_n(const byte in[], byte out[], + u32bit blocks) const = 0; + virtual void decrypt_n(const byte in[], byte out[], + u32bit blocks) const = 0; /** * Get a new object representing the same algorithm as *this @@ -90,9 +97,6 @@ class BOTAN_DLL BlockCipher : public SymmetricAlgorithm BLOCK_SIZE(block_size) {} virtual ~BlockCipher() {} - private: - virtual void enc(const byte[], byte[]) const = 0; - virtual void dec(const byte[], byte[]) const = 0; }; } diff --git a/src/block/blowfish/blowfish.cpp b/src/block/blowfish/blowfish.cpp index b0599d6c5..312603c3a 100644 --- a/src/block/blowfish/blowfish.cpp +++ b/src/block/blowfish/blowfish.cpp @@ -1,6 +1,6 @@ /* * Blowfish -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -13,59 +13,71 @@ namespace Botan { /* * Blowfish Encryption */ -void Blowfish::enc(const byte in[], byte out[]) const +void Blowfish::encrypt_n(const byte in[], byte out[], u32bit blocks) const { const u32bit* S1 = S + 0; const u32bit* S2 = S + 256; const u32bit* S3 = S + 512; const u32bit* S4 = S + 768; - u32bit L = load_be<u32bit>(in, 0); - u32bit R = load_be<u32bit>(in, 1); - - for(u32bit j = 0; j != 16; j += 2) + for(u32bit i = 0; i != blocks; ++i) { - L ^= P[j]; - R ^= ((S1[get_byte(0, L)] + S2[get_byte(1, L)]) ^ - S3[get_byte(2, L)]) + S4[get_byte(3, L)]; + u32bit L = load_be<u32bit>(in, 0); + u32bit R = load_be<u32bit>(in, 1); - R ^= P[j+1]; - L ^= ((S1[get_byte(0, R)] + S2[get_byte(1, R)]) ^ - S3[get_byte(2, R)]) + S4[get_byte(3, R)]; - } + for(u32bit j = 0; j != 16; j += 2) + { + L ^= P[j]; + R ^= ((S1[get_byte(0, L)] + S2[get_byte(1, L)]) ^ + S3[get_byte(2, L)]) + S4[get_byte(3, L)]; - L ^= P[16]; R ^= P[17]; + R ^= P[j+1]; + L ^= ((S1[get_byte(0, R)] + S2[get_byte(1, R)]) ^ + S3[get_byte(2, R)]) + S4[get_byte(3, R)]; + } + + L ^= P[16]; R ^= P[17]; - store_be(out, R, L); + store_be(out, R, L); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * Blowfish Decryption */ -void Blowfish::dec(const byte in[], byte out[]) const +void Blowfish::decrypt_n(const byte in[], byte out[], u32bit blocks) const { const u32bit* S1 = S + 0; const u32bit* S2 = S + 256; const u32bit* S3 = S + 512; const u32bit* S4 = S + 768; - u32bit L = load_be<u32bit>(in, 0); - u32bit R = load_be<u32bit>(in, 1); - - for(u32bit j = 17; j != 1; j -= 2) + for(u32bit i = 0; i != blocks; ++i) { - L ^= P[j]; - R ^= ((S1[get_byte(0, L)] + S2[get_byte(1, L)]) ^ - S3[get_byte(2, L)]) + S4[get_byte(3, L)]; + u32bit L = load_be<u32bit>(in, 0); + u32bit R = load_be<u32bit>(in, 1); - R ^= P[j-1]; - L ^= ((S1[get_byte(0, R)] + S2[get_byte(1, R)]) ^ - S3[get_byte(2, R)]) + S4[get_byte(3, R)]; - } + for(u32bit j = 17; j != 1; j -= 2) + { + L ^= P[j]; + R ^= ((S1[get_byte(0, L)] + S2[get_byte(1, L)]) ^ + S3[get_byte(2, L)]) + S4[get_byte(3, L)]; - L ^= P[1]; R ^= P[0]; + R ^= P[j-1]; + L ^= ((S1[get_byte(0, R)] + S2[get_byte(1, R)]) ^ + S3[get_byte(2, R)]) + S4[get_byte(3, R)]; + } + + L ^= P[1]; R ^= P[0]; - store_be(out, R, L); + store_be(out, R, L); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/blowfish/blowfish.h b/src/block/blowfish/blowfish.h index f0f26418d..345c1ce49 100644 --- a/src/block/blowfish/blowfish.h +++ b/src/block/blowfish/blowfish.h @@ -1,6 +1,6 @@ /* * Blowfish -* (C) 1999-2008 Jack Lloyd +* (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -18,13 +18,15 @@ namespace Botan { class BOTAN_DLL Blowfish : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw(); std::string name() const { return "Blowfish"; } BlockCipher* clone() const { return new Blowfish; } + Blowfish() : BlockCipher(8, 1, 56) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); void generate_sbox(u32bit[], u32bit, u32bit&, u32bit&) const; diff --git a/src/block/blowfish/info.txt b/src/block/blowfish/info.txt index 0a9d2adc2..c63560989 100644 --- a/src/block/blowfish/info.txt +++ b/src/block/blowfish/info.txt @@ -1,11 +1,3 @@ realname "Blowfish" define BLOWFISH - -load_on auto - -<add> -blfs_tab.cpp -blowfish.cpp -blowfish.h -</add> diff --git a/src/block/cast/cast128.cpp b/src/block/cast/cast128.cpp index 046638ab9..887dcf994 100644 --- a/src/block/cast/cast128.cpp +++ b/src/block/cast/cast128.cpp @@ -48,57 +48,69 @@ inline void R3(u32bit& L, u32bit R, u32bit MK, u32bit RK) /* * CAST-128 Encryption */ -void CAST_128::enc(const byte in[], byte out[]) const +void CAST_128::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit L = load_be<u32bit>(in, 0); - u32bit R = load_be<u32bit>(in, 1); - - R1(L, R, MK[ 0], RK[ 0]); - R2(R, L, MK[ 1], RK[ 1]); - R3(L, R, MK[ 2], RK[ 2]); - R1(R, L, MK[ 3], RK[ 3]); - R2(L, R, MK[ 4], RK[ 4]); - R3(R, L, MK[ 5], RK[ 5]); - R1(L, R, MK[ 6], RK[ 6]); - R2(R, L, MK[ 7], RK[ 7]); - R3(L, R, MK[ 8], RK[ 8]); - R1(R, L, MK[ 9], RK[ 9]); - R2(L, R, MK[10], RK[10]); - R3(R, L, MK[11], RK[11]); - R1(L, R, MK[12], RK[12]); - R2(R, L, MK[13], RK[13]); - R3(L, R, MK[14], RK[14]); - R1(R, L, MK[15], RK[15]); - - store_be(out, R, L); + for(u32bit i = 0; i != blocks; ++i) + { + u32bit L = load_be<u32bit>(in, 0); + u32bit R = load_be<u32bit>(in, 1); + + R1(L, R, MK[ 0], RK[ 0]); + R2(R, L, MK[ 1], RK[ 1]); + R3(L, R, MK[ 2], RK[ 2]); + R1(R, L, MK[ 3], RK[ 3]); + R2(L, R, MK[ 4], RK[ 4]); + R3(R, L, MK[ 5], RK[ 5]); + R1(L, R, MK[ 6], RK[ 6]); + R2(R, L, MK[ 7], RK[ 7]); + R3(L, R, MK[ 8], RK[ 8]); + R1(R, L, MK[ 9], RK[ 9]); + R2(L, R, MK[10], RK[10]); + R3(R, L, MK[11], RK[11]); + R1(L, R, MK[12], RK[12]); + R2(R, L, MK[13], RK[13]); + R3(L, R, MK[14], RK[14]); + R1(R, L, MK[15], RK[15]); + + store_be(out, R, L); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * CAST-128 Decryption */ -void CAST_128::dec(const byte in[], byte out[]) const +void CAST_128::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit L = load_be<u32bit>(in, 0); - u32bit R = load_be<u32bit>(in, 1); - - R1(L, R, MK[15], RK[15]); - R3(R, L, MK[14], RK[14]); - R2(L, R, MK[13], RK[13]); - R1(R, L, MK[12], RK[12]); - R3(L, R, MK[11], RK[11]); - R2(R, L, MK[10], RK[10]); - R1(L, R, MK[ 9], RK[ 9]); - R3(R, L, MK[ 8], RK[ 8]); - R2(L, R, MK[ 7], RK[ 7]); - R1(R, L, MK[ 6], RK[ 6]); - R3(L, R, MK[ 5], RK[ 5]); - R2(R, L, MK[ 4], RK[ 4]); - R1(L, R, MK[ 3], RK[ 3]); - R3(R, L, MK[ 2], RK[ 2]); - R2(L, R, MK[ 1], RK[ 1]); - R1(R, L, MK[ 0], RK[ 0]); - - store_be(out, R, L); + for(u32bit i = 0; i != blocks; ++i) + { + u32bit L = load_be<u32bit>(in, 0); + u32bit R = load_be<u32bit>(in, 1); + + R1(L, R, MK[15], RK[15]); + R3(R, L, MK[14], RK[14]); + R2(L, R, MK[13], RK[13]); + R1(R, L, MK[12], RK[12]); + R3(L, R, MK[11], RK[11]); + R2(R, L, MK[10], RK[10]); + R1(L, R, MK[ 9], RK[ 9]); + R3(R, L, MK[ 8], RK[ 8]); + R2(L, R, MK[ 7], RK[ 7]); + R1(R, L, MK[ 6], RK[ 6]); + R3(L, R, MK[ 5], RK[ 5]); + R2(R, L, MK[ 4], RK[ 4]); + R1(L, R, MK[ 3], RK[ 3]); + R3(R, L, MK[ 2], RK[ 2]); + R2(L, R, MK[ 1], RK[ 1]); + R1(R, L, MK[ 0], RK[ 0]); + + store_be(out, R, L); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/cast/cast128.h b/src/block/cast/cast128.h index 680481482..864a4e47e 100644 --- a/src/block/cast/cast128.h +++ b/src/block/cast/cast128.h @@ -18,13 +18,15 @@ namespace Botan { class BOTAN_DLL CAST_128 : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { MK.clear(); RK.clear(); } std::string name() const { return "CAST-128"; } BlockCipher* clone() const { return new CAST_128; } + CAST_128() : BlockCipher(8, 11, 16) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); static void key_schedule(u32bit[16], u32bit[4]); diff --git a/src/block/cast/cast256.cpp b/src/block/cast/cast256.cpp index 22ff876fa..7a4a4e805 100644 --- a/src/block/cast/cast256.cpp +++ b/src/block/cast/cast256.cpp @@ -48,77 +48,89 @@ void round3(u32bit& out, u32bit in, u32bit mask, u32bit rot) /* * CAST-256 Encryption */ -void CAST_256::enc(const byte in[], byte out[]) const +void CAST_256::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit A = load_be<u32bit>(in, 0); - u32bit B = load_be<u32bit>(in, 1); - u32bit C = load_be<u32bit>(in, 2); - u32bit D = load_be<u32bit>(in, 3); - - round1(C, D, MK[ 0], RK[ 0]); round2(B, C, MK[ 1], RK[ 1]); - round3(A, B, MK[ 2], RK[ 2]); round1(D, A, MK[ 3], RK[ 3]); - round1(C, D, MK[ 4], RK[ 4]); round2(B, C, MK[ 5], RK[ 5]); - round3(A, B, MK[ 6], RK[ 6]); round1(D, A, MK[ 7], RK[ 7]); - round1(C, D, MK[ 8], RK[ 8]); round2(B, C, MK[ 9], RK[ 9]); - round3(A, B, MK[10], RK[10]); round1(D, A, MK[11], RK[11]); - round1(C, D, MK[12], RK[12]); round2(B, C, MK[13], RK[13]); - round3(A, B, MK[14], RK[14]); round1(D, A, MK[15], RK[15]); - round1(C, D, MK[16], RK[16]); round2(B, C, MK[17], RK[17]); - round3(A, B, MK[18], RK[18]); round1(D, A, MK[19], RK[19]); - round1(C, D, MK[20], RK[20]); round2(B, C, MK[21], RK[21]); - round3(A, B, MK[22], RK[22]); round1(D, A, MK[23], RK[23]); - round1(D, A, MK[27], RK[27]); round3(A, B, MK[26], RK[26]); - round2(B, C, MK[25], RK[25]); round1(C, D, MK[24], RK[24]); - round1(D, A, MK[31], RK[31]); round3(A, B, MK[30], RK[30]); - round2(B, C, MK[29], RK[29]); round1(C, D, MK[28], RK[28]); - round1(D, A, MK[35], RK[35]); round3(A, B, MK[34], RK[34]); - round2(B, C, MK[33], RK[33]); round1(C, D, MK[32], RK[32]); - round1(D, A, MK[39], RK[39]); round3(A, B, MK[38], RK[38]); - round2(B, C, MK[37], RK[37]); round1(C, D, MK[36], RK[36]); - round1(D, A, MK[43], RK[43]); round3(A, B, MK[42], RK[42]); - round2(B, C, MK[41], RK[41]); round1(C, D, MK[40], RK[40]); - round1(D, A, MK[47], RK[47]); round3(A, B, MK[46], RK[46]); - round2(B, C, MK[45], RK[45]); round1(C, D, MK[44], RK[44]); - - store_be(out, A, B, C, D); + for(u32bit i = 0; i != blocks; ++i) + { + u32bit A = load_be<u32bit>(in, 0); + u32bit B = load_be<u32bit>(in, 1); + u32bit C = load_be<u32bit>(in, 2); + u32bit D = load_be<u32bit>(in, 3); + + round1(C, D, MK[ 0], RK[ 0]); round2(B, C, MK[ 1], RK[ 1]); + round3(A, B, MK[ 2], RK[ 2]); round1(D, A, MK[ 3], RK[ 3]); + round1(C, D, MK[ 4], RK[ 4]); round2(B, C, MK[ 5], RK[ 5]); + round3(A, B, MK[ 6], RK[ 6]); round1(D, A, MK[ 7], RK[ 7]); + round1(C, D, MK[ 8], RK[ 8]); round2(B, C, MK[ 9], RK[ 9]); + round3(A, B, MK[10], RK[10]); round1(D, A, MK[11], RK[11]); + round1(C, D, MK[12], RK[12]); round2(B, C, MK[13], RK[13]); + round3(A, B, MK[14], RK[14]); round1(D, A, MK[15], RK[15]); + round1(C, D, MK[16], RK[16]); round2(B, C, MK[17], RK[17]); + round3(A, B, MK[18], RK[18]); round1(D, A, MK[19], RK[19]); + round1(C, D, MK[20], RK[20]); round2(B, C, MK[21], RK[21]); + round3(A, B, MK[22], RK[22]); round1(D, A, MK[23], RK[23]); + round1(D, A, MK[27], RK[27]); round3(A, B, MK[26], RK[26]); + round2(B, C, MK[25], RK[25]); round1(C, D, MK[24], RK[24]); + round1(D, A, MK[31], RK[31]); round3(A, B, MK[30], RK[30]); + round2(B, C, MK[29], RK[29]); round1(C, D, MK[28], RK[28]); + round1(D, A, MK[35], RK[35]); round3(A, B, MK[34], RK[34]); + round2(B, C, MK[33], RK[33]); round1(C, D, MK[32], RK[32]); + round1(D, A, MK[39], RK[39]); round3(A, B, MK[38], RK[38]); + round2(B, C, MK[37], RK[37]); round1(C, D, MK[36], RK[36]); + round1(D, A, MK[43], RK[43]); round3(A, B, MK[42], RK[42]); + round2(B, C, MK[41], RK[41]); round1(C, D, MK[40], RK[40]); + round1(D, A, MK[47], RK[47]); round3(A, B, MK[46], RK[46]); + round2(B, C, MK[45], RK[45]); round1(C, D, MK[44], RK[44]); + + store_be(out, A, B, C, D); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * CAST-256 Decryption */ -void CAST_256::dec(const byte in[], byte out[]) const +void CAST_256::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit A = load_be<u32bit>(in, 0); - u32bit B = load_be<u32bit>(in, 1); - u32bit C = load_be<u32bit>(in, 2); - u32bit D = load_be<u32bit>(in, 3); - - round1(C, D, MK[44], RK[44]); round2(B, C, MK[45], RK[45]); - round3(A, B, MK[46], RK[46]); round1(D, A, MK[47], RK[47]); - round1(C, D, MK[40], RK[40]); round2(B, C, MK[41], RK[41]); - round3(A, B, MK[42], RK[42]); round1(D, A, MK[43], RK[43]); - round1(C, D, MK[36], RK[36]); round2(B, C, MK[37], RK[37]); - round3(A, B, MK[38], RK[38]); round1(D, A, MK[39], RK[39]); - round1(C, D, MK[32], RK[32]); round2(B, C, MK[33], RK[33]); - round3(A, B, MK[34], RK[34]); round1(D, A, MK[35], RK[35]); - round1(C, D, MK[28], RK[28]); round2(B, C, MK[29], RK[29]); - round3(A, B, MK[30], RK[30]); round1(D, A, MK[31], RK[31]); - round1(C, D, MK[24], RK[24]); round2(B, C, MK[25], RK[25]); - round3(A, B, MK[26], RK[26]); round1(D, A, MK[27], RK[27]); - round1(D, A, MK[23], RK[23]); round3(A, B, MK[22], RK[22]); - round2(B, C, MK[21], RK[21]); round1(C, D, MK[20], RK[20]); - round1(D, A, MK[19], RK[19]); round3(A, B, MK[18], RK[18]); - round2(B, C, MK[17], RK[17]); round1(C, D, MK[16], RK[16]); - round1(D, A, MK[15], RK[15]); round3(A, B, MK[14], RK[14]); - round2(B, C, MK[13], RK[13]); round1(C, D, MK[12], RK[12]); - round1(D, A, MK[11], RK[11]); round3(A, B, MK[10], RK[10]); - round2(B, C, MK[ 9], RK[ 9]); round1(C, D, MK[ 8], RK[ 8]); - round1(D, A, MK[ 7], RK[ 7]); round3(A, B, MK[ 6], RK[ 6]); - round2(B, C, MK[ 5], RK[ 5]); round1(C, D, MK[ 4], RK[ 4]); - round1(D, A, MK[ 3], RK[ 3]); round3(A, B, MK[ 2], RK[ 2]); - round2(B, C, MK[ 1], RK[ 1]); round1(C, D, MK[ 0], RK[ 0]); - - store_be(out, A, B, C, D); + for(u32bit i = 0; i != blocks; ++i) + { + u32bit A = load_be<u32bit>(in, 0); + u32bit B = load_be<u32bit>(in, 1); + u32bit C = load_be<u32bit>(in, 2); + u32bit D = load_be<u32bit>(in, 3); + + round1(C, D, MK[44], RK[44]); round2(B, C, MK[45], RK[45]); + round3(A, B, MK[46], RK[46]); round1(D, A, MK[47], RK[47]); + round1(C, D, MK[40], RK[40]); round2(B, C, MK[41], RK[41]); + round3(A, B, MK[42], RK[42]); round1(D, A, MK[43], RK[43]); + round1(C, D, MK[36], RK[36]); round2(B, C, MK[37], RK[37]); + round3(A, B, MK[38], RK[38]); round1(D, A, MK[39], RK[39]); + round1(C, D, MK[32], RK[32]); round2(B, C, MK[33], RK[33]); + round3(A, B, MK[34], RK[34]); round1(D, A, MK[35], RK[35]); + round1(C, D, MK[28], RK[28]); round2(B, C, MK[29], RK[29]); + round3(A, B, MK[30], RK[30]); round1(D, A, MK[31], RK[31]); + round1(C, D, MK[24], RK[24]); round2(B, C, MK[25], RK[25]); + round3(A, B, MK[26], RK[26]); round1(D, A, MK[27], RK[27]); + round1(D, A, MK[23], RK[23]); round3(A, B, MK[22], RK[22]); + round2(B, C, MK[21], RK[21]); round1(C, D, MK[20], RK[20]); + round1(D, A, MK[19], RK[19]); round3(A, B, MK[18], RK[18]); + round2(B, C, MK[17], RK[17]); round1(C, D, MK[16], RK[16]); + round1(D, A, MK[15], RK[15]); round3(A, B, MK[14], RK[14]); + round2(B, C, MK[13], RK[13]); round1(C, D, MK[12], RK[12]); + round1(D, A, MK[11], RK[11]); round3(A, B, MK[10], RK[10]); + round2(B, C, MK[ 9], RK[ 9]); round1(C, D, MK[ 8], RK[ 8]); + round1(D, A, MK[ 7], RK[ 7]); round3(A, B, MK[ 6], RK[ 6]); + round2(B, C, MK[ 5], RK[ 5]); round1(C, D, MK[ 4], RK[ 4]); + round1(D, A, MK[ 3], RK[ 3]); round3(A, B, MK[ 2], RK[ 2]); + round2(B, C, MK[ 1], RK[ 1]); round1(C, D, MK[ 0], RK[ 0]); + + store_be(out, A, B, C, D); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/cast/cast256.h b/src/block/cast/cast256.h index cd48edd5e..1be7fa9cf 100644 --- a/src/block/cast/cast256.h +++ b/src/block/cast/cast256.h @@ -18,13 +18,15 @@ namespace Botan { class BOTAN_DLL CAST_256 : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { MK.clear(); RK.clear(); } std::string name() const { return "CAST-256"; } BlockCipher* clone() const { return new CAST_256; } + CAST_256() : BlockCipher(16, 4, 32, 4) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); static const u32bit KEY_MASK[192]; diff --git a/src/block/cast/info.txt b/src/block/cast/info.txt index 73d3f900f..b9259042d 100644 --- a/src/block/cast/info.txt +++ b/src/block/cast/info.txt @@ -1,13 +1,3 @@ realname "CAST" define CAST - -load_on auto - -<add> -cast128.cpp -cast128.h -cast256.cpp -cast256.h -cast_tab.cpp -</add> diff --git a/src/block/des/des.cpp b/src/block/des/des.cpp index 37520e0fc..05287304f 100644 --- a/src/block/des/des.cpp +++ b/src/block/des/des.cpp @@ -139,51 +139,62 @@ void des_decrypt(u32bit& L, u32bit& R, /* * DES Encryption */ -void DES::enc(const byte in[], byte out[]) const +void DES::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u64bit T = (DES_IPTAB1[in[0]] ) | (DES_IPTAB1[in[1]] << 1) | - (DES_IPTAB1[in[2]] << 2) | (DES_IPTAB1[in[3]] << 3) | - (DES_IPTAB1[in[4]] << 4) | (DES_IPTAB1[in[5]] << 5) | - (DES_IPTAB1[in[6]] << 6) | (DES_IPTAB2[in[7]] ); + for(u32bit i = 0; i != blocks; ++i) + { + u64bit T = (DES_IPTAB1[in[0]] ) | (DES_IPTAB1[in[1]] << 1) | + (DES_IPTAB1[in[2]] << 2) | (DES_IPTAB1[in[3]] << 3) | + (DES_IPTAB1[in[4]] << 4) | (DES_IPTAB1[in[5]] << 5) | + (DES_IPTAB1[in[6]] << 6) | (DES_IPTAB2[in[7]] ); - u32bit L = static_cast<u32bit>(T >> 32); - u32bit R = static_cast<u32bit>(T); + u32bit L = static_cast<u32bit>(T >> 32); + u32bit R = static_cast<u32bit>(T); - des_encrypt(L, R, round_key); + des_encrypt(L, R, round_key); - T = (DES_FPTAB1[get_byte(0, L)] << 5) | (DES_FPTAB1[get_byte(1, L)] << 3) | - (DES_FPTAB1[get_byte(2, L)] << 1) | (DES_FPTAB2[get_byte(3, L)] << 1) | - (DES_FPTAB1[get_byte(0, R)] << 4) | (DES_FPTAB1[get_byte(1, R)] << 2) | - (DES_FPTAB1[get_byte(2, R)] ) | (DES_FPTAB2[get_byte(3, R)] ); + T = (DES_FPTAB1[get_byte(0, L)] << 5) | (DES_FPTAB1[get_byte(1, L)] << 3) | + (DES_FPTAB1[get_byte(2, L)] << 1) | (DES_FPTAB2[get_byte(3, L)] << 1) | + (DES_FPTAB1[get_byte(0, R)] << 4) | (DES_FPTAB1[get_byte(1, R)] << 2) | + (DES_FPTAB1[get_byte(2, R)] ) | (DES_FPTAB2[get_byte(3, R)] ); + T = rotate_left(T, 32); - T = rotate_left(T, 32); + store_be(T, out); - store_be(T, out); + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * DES Decryption */ -void DES::dec(const byte in[], byte out[]) const +void DES::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u64bit T = (DES_IPTAB1[in[0]] ) | (DES_IPTAB1[in[1]] << 1) | - (DES_IPTAB1[in[2]] << 2) | (DES_IPTAB1[in[3]] << 3) | - (DES_IPTAB1[in[4]] << 4) | (DES_IPTAB1[in[5]] << 5) | - (DES_IPTAB1[in[6]] << 6) | (DES_IPTAB2[in[7]] ); + for(u32bit i = 0; i != blocks; ++i) + { + u64bit T = (DES_IPTAB1[in[0]] ) | (DES_IPTAB1[in[1]] << 1) | + (DES_IPTAB1[in[2]] << 2) | (DES_IPTAB1[in[3]] << 3) | + (DES_IPTAB1[in[4]] << 4) | (DES_IPTAB1[in[5]] << 5) | + (DES_IPTAB1[in[6]] << 6) | (DES_IPTAB2[in[7]] ); - u32bit L = static_cast<u32bit>(T >> 32); - u32bit R = static_cast<u32bit>(T); + u32bit L = static_cast<u32bit>(T >> 32); + u32bit R = static_cast<u32bit>(T); - des_decrypt(L, R, round_key); + des_decrypt(L, R, round_key); - T = (DES_FPTAB1[get_byte(0, L)] << 5) | (DES_FPTAB1[get_byte(1, L)] << 3) | - (DES_FPTAB1[get_byte(2, L)] << 1) | (DES_FPTAB2[get_byte(3, L)] << 1) | - (DES_FPTAB1[get_byte(0, R)] << 4) | (DES_FPTAB1[get_byte(1, R)] << 2) | - (DES_FPTAB1[get_byte(2, R)] ) | (DES_FPTAB2[get_byte(3, R)] ); + T = (DES_FPTAB1[get_byte(0, L)] << 5) | (DES_FPTAB1[get_byte(1, L)] << 3) | + (DES_FPTAB1[get_byte(2, L)] << 1) | (DES_FPTAB2[get_byte(3, L)] << 1) | + (DES_FPTAB1[get_byte(0, R)] << 4) | (DES_FPTAB1[get_byte(1, R)] << 2) | + (DES_FPTAB1[get_byte(2, R)] ) | (DES_FPTAB2[get_byte(3, R)] ); - T = rotate_left(T, 32); + T = rotate_left(T, 32); - store_be(T, out); + store_be(T, out); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* @@ -197,55 +208,67 @@ void DES::key_schedule(const byte key[], u32bit) /* * TripleDES Encryption */ -void TripleDES::enc(const byte in[], byte out[]) const +void TripleDES::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u64bit T = (DES_IPTAB1[in[0]] ) | (DES_IPTAB1[in[1]] << 1) | - (DES_IPTAB1[in[2]] << 2) | (DES_IPTAB1[in[3]] << 3) | - (DES_IPTAB1[in[4]] << 4) | (DES_IPTAB1[in[5]] << 5) | - (DES_IPTAB1[in[6]] << 6) | (DES_IPTAB2[in[7]] ); + for(u32bit i = 0; i != blocks; ++i) + { + u64bit T = (DES_IPTAB1[in[0]] ) | (DES_IPTAB1[in[1]] << 1) | + (DES_IPTAB1[in[2]] << 2) | (DES_IPTAB1[in[3]] << 3) | + (DES_IPTAB1[in[4]] << 4) | (DES_IPTAB1[in[5]] << 5) | + (DES_IPTAB1[in[6]] << 6) | (DES_IPTAB2[in[7]] ); - u32bit L = static_cast<u32bit>(T >> 32); - u32bit R = static_cast<u32bit>(T); + u32bit L = static_cast<u32bit>(T >> 32); + u32bit R = static_cast<u32bit>(T); - des_encrypt(L, R, round_key); - des_decrypt(R, L, round_key + 32); - des_encrypt(L, R, round_key + 64); + des_encrypt(L, R, round_key); + des_decrypt(R, L, round_key + 32); + des_encrypt(L, R, round_key + 64); - T = (DES_FPTAB1[get_byte(0, L)] << 5) | (DES_FPTAB1[get_byte(1, L)] << 3) | - (DES_FPTAB1[get_byte(2, L)] << 1) | (DES_FPTAB2[get_byte(3, L)] << 1) | - (DES_FPTAB1[get_byte(0, R)] << 4) | (DES_FPTAB1[get_byte(1, R)] << 2) | - (DES_FPTAB1[get_byte(2, R)] ) | (DES_FPTAB2[get_byte(3, R)] ); + T = (DES_FPTAB1[get_byte(0, L)] << 5) | (DES_FPTAB1[get_byte(1, L)] << 3) | + (DES_FPTAB1[get_byte(2, L)] << 1) | (DES_FPTAB2[get_byte(3, L)] << 1) | + (DES_FPTAB1[get_byte(0, R)] << 4) | (DES_FPTAB1[get_byte(1, R)] << 2) | + (DES_FPTAB1[get_byte(2, R)] ) | (DES_FPTAB2[get_byte(3, R)] ); - T = rotate_left(T, 32); + T = rotate_left(T, 32); - store_be(T, out); + store_be(T, out); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * TripleDES Decryption */ -void TripleDES::dec(const byte in[], byte out[]) const +void TripleDES::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u64bit T = (DES_IPTAB1[in[0]] ) | (DES_IPTAB1[in[1]] << 1) | - (DES_IPTAB1[in[2]] << 2) | (DES_IPTAB1[in[3]] << 3) | - (DES_IPTAB1[in[4]] << 4) | (DES_IPTAB1[in[5]] << 5) | - (DES_IPTAB1[in[6]] << 6) | (DES_IPTAB2[in[7]] ); + for(u32bit i = 0; i != blocks; ++i) + { + u64bit T = (DES_IPTAB1[in[0]] ) | (DES_IPTAB1[in[1]] << 1) | + (DES_IPTAB1[in[2]] << 2) | (DES_IPTAB1[in[3]] << 3) | + (DES_IPTAB1[in[4]] << 4) | (DES_IPTAB1[in[5]] << 5) | + (DES_IPTAB1[in[6]] << 6) | (DES_IPTAB2[in[7]] ); - u32bit L = static_cast<u32bit>(T >> 32); - u32bit R = static_cast<u32bit>(T); + u32bit L = static_cast<u32bit>(T >> 32); + u32bit R = static_cast<u32bit>(T); - des_decrypt(L, R, round_key + 64); - des_encrypt(R, L, round_key + 32); - des_decrypt(L, R, round_key); + des_decrypt(L, R, round_key + 64); + des_encrypt(R, L, round_key + 32); + des_decrypt(L, R, round_key); - T = (DES_FPTAB1[get_byte(0, L)] << 5) | (DES_FPTAB1[get_byte(1, L)] << 3) | - (DES_FPTAB1[get_byte(2, L)] << 1) | (DES_FPTAB2[get_byte(3, L)] << 1) | - (DES_FPTAB1[get_byte(0, R)] << 4) | (DES_FPTAB1[get_byte(1, R)] << 2) | - (DES_FPTAB1[get_byte(2, R)] ) | (DES_FPTAB2[get_byte(3, R)] ); + T = (DES_FPTAB1[get_byte(0, L)] << 5) | (DES_FPTAB1[get_byte(1, L)] << 3) | + (DES_FPTAB1[get_byte(2, L)] << 1) | (DES_FPTAB2[get_byte(3, L)] << 1) | + (DES_FPTAB1[get_byte(0, R)] << 4) | (DES_FPTAB1[get_byte(1, R)] << 2) | + (DES_FPTAB1[get_byte(2, R)] ) | (DES_FPTAB2[get_byte(3, R)] ); - T = rotate_left(T, 32); + T = rotate_left(T, 32); - store_be(T, out); + store_be(T, out); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/des/des.h b/src/block/des/des.h index 6fa59de5e..856aaf60c 100644 --- a/src/block/des/des.h +++ b/src/block/des/des.h @@ -18,13 +18,15 @@ namespace Botan { class BOTAN_DLL DES : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { round_key.clear(); } std::string name() const { return "DES"; } BlockCipher* clone() const { return new DES; } + DES() : BlockCipher(8, 8) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); SecureBuffer<u32bit, 32> round_key; @@ -36,13 +38,15 @@ class BOTAN_DLL DES : public BlockCipher class BOTAN_DLL TripleDES : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { round_key.clear(); } std::string name() const { return "TripleDES"; } BlockCipher* clone() const { return new TripleDES; } + TripleDES() : BlockCipher(8, 16, 24, 8) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); SecureBuffer<u32bit, 96> round_key; diff --git a/src/block/des/desx.cpp b/src/block/des/desx.cpp index e557901d3..1fc1c47f2 100644 --- a/src/block/des/desx.cpp +++ b/src/block/des/desx.cpp @@ -13,21 +13,33 @@ namespace Botan { /* * DESX Encryption */ -void DESX::enc(const byte in[], byte out[]) const +void DESX::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - xor_buf(out, in, K1.begin(), BLOCK_SIZE); - des.encrypt(out); - xor_buf(out, K2.begin(), BLOCK_SIZE); + for(u32bit i = 0; i != blocks; ++i) + { + xor_buf(out, in, K1.begin(), BLOCK_SIZE); + des.encrypt(out); + xor_buf(out, K2.begin(), BLOCK_SIZE); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * DESX Decryption */ -void DESX::dec(const byte in[], byte out[]) const +void DESX::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - xor_buf(out, in, K2.begin(), BLOCK_SIZE); - des.decrypt(out); - xor_buf(out, K1.begin(), BLOCK_SIZE); + for(u32bit i = 0; i != blocks; ++i) + { + xor_buf(out, in, K2.begin(), BLOCK_SIZE); + des.decrypt(out); + xor_buf(out, K1.begin(), BLOCK_SIZE); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/des/desx.h b/src/block/des/desx.h index 49ecc2421..d22895296 100644 --- a/src/block/des/desx.h +++ b/src/block/des/desx.h @@ -18,13 +18,15 @@ namespace Botan { class BOTAN_DLL DESX : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { des.clear(); K1.clear(); K2.clear(); } std::string name() const { return "DESX"; } BlockCipher* clone() const { return new DESX; } + DESX() : BlockCipher(8, 24) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); SecureBuffer<byte, 8> K1, K2; DES des; diff --git a/src/block/des/info.txt b/src/block/des/info.txt index ed05979c9..6eec591a0 100644 --- a/src/block/des/info.txt +++ b/src/block/des/info.txt @@ -1,13 +1,3 @@ realname "DES" define DES - -load_on auto - -<add> -des.cpp -des.h -des_tab.cpp -desx.h -desx.cpp -</add> diff --git a/src/block/gost_28147/gost_28147.cpp b/src/block/gost_28147/gost_28147.cpp index bfd092c56..272f1bcab 100644 --- a/src/block/gost_28147/gost_28147.cpp +++ b/src/block/gost_28147/gost_28147.cpp @@ -84,47 +84,58 @@ GOST_28147_89::GOST_28147_89(const GOST_28147_89_Params& param) : /* * GOST Encryption */ -void GOST_28147_89::enc(const byte in[], byte out[]) const +void GOST_28147_89::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit N1 = load_le<u32bit>(in, 0), N2 = load_le<u32bit>(in, 1); - - for(size_t i = 0; i != 3; ++i) + for(u32bit i = 0; i != blocks; ++i) { - GOST_2ROUND(N1, N2, 0, 1); - GOST_2ROUND(N1, N2, 2, 3); - GOST_2ROUND(N1, N2, 4, 5); - GOST_2ROUND(N1, N2, 6, 7); - } + u32bit N1 = load_le<u32bit>(in, 0), N2 = load_le<u32bit>(in, 1); - GOST_2ROUND(N1, N2, 7, 6); - GOST_2ROUND(N1, N2, 5, 4); - GOST_2ROUND(N1, N2, 3, 2); - GOST_2ROUND(N1, N2, 1, 0); + for(size_t j = 0; j != 3; ++j) + { + GOST_2ROUND(N1, N2, 0, 1); + GOST_2ROUND(N1, N2, 2, 3); + GOST_2ROUND(N1, N2, 4, 5); + GOST_2ROUND(N1, N2, 6, 7); + } - store_le(out, N2, N1); + GOST_2ROUND(N1, N2, 7, 6); + GOST_2ROUND(N1, N2, 5, 4); + GOST_2ROUND(N1, N2, 3, 2); + GOST_2ROUND(N1, N2, 1, 0); + + store_le(out, N2, N1); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * GOST Decryption */ -void GOST_28147_89::dec(const byte in[], byte out[]) const +void GOST_28147_89::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit N1 = load_le<u32bit>(in, 0), N2 = load_le<u32bit>(in, 1); + for(u32bit i = 0; i != blocks; ++i) + { + u32bit N1 = load_le<u32bit>(in, 0), N2 = load_le<u32bit>(in, 1); - GOST_2ROUND(N1, N2, 0, 1); - GOST_2ROUND(N1, N2, 2, 3); - GOST_2ROUND(N1, N2, 4, 5); - GOST_2ROUND(N1, N2, 6, 7); + GOST_2ROUND(N1, N2, 0, 1); + GOST_2ROUND(N1, N2, 2, 3); + GOST_2ROUND(N1, N2, 4, 5); + GOST_2ROUND(N1, N2, 6, 7); - for(size_t i = 0; i != 3; ++i) - { - GOST_2ROUND(N1, N2, 7, 6); - GOST_2ROUND(N1, N2, 5, 4); - GOST_2ROUND(N1, N2, 3, 2); - GOST_2ROUND(N1, N2, 1, 0); - } + for(size_t i = 0; i != 3; ++i) + { + GOST_2ROUND(N1, N2, 7, 6); + GOST_2ROUND(N1, N2, 5, 4); + GOST_2ROUND(N1, N2, 3, 2); + GOST_2ROUND(N1, N2, 1, 0); + } - store_le(out, N2, N1); + store_le(out, N2, N1); + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/gost_28147/gost_28147.h b/src/block/gost_28147/gost_28147.h index 96d24c669..18c1d0a29 100644 --- a/src/block/gost_28147/gost_28147.h +++ b/src/block/gost_28147/gost_28147.h @@ -44,6 +44,9 @@ class GOST_28147_89_Params class BOTAN_DLL GOST_28147_89 : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { EK.clear(); } std::string name() const { return "GOST-28147-89"; } @@ -54,8 +57,6 @@ class BOTAN_DLL GOST_28147_89 : public BlockCipher GOST_28147_89(const SecureBuffer<u32bit, 1024>& other_SBOX) : BlockCipher(8, 32), SBOX(other_SBOX) {} - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); SecureBuffer<u32bit, 1024> SBOX; diff --git a/src/block/gost_28147/info.txt b/src/block/gost_28147/info.txt index 6e187fd48..9b24d1e22 100644 --- a/src/block/gost_28147/info.txt +++ b/src/block/gost_28147/info.txt @@ -1,10 +1,3 @@ realname "GOST 28147-89" define GOST_28147_89 - -load_on auto - -<add> -gost_28147.cpp -gost_28147.h -</add> diff --git a/src/block/idea/idea.cpp b/src/block/idea/idea.cpp index 5bbe47087..fb5fe83f1 100644 --- a/src/block/idea/idea.cpp +++ b/src/block/idea/idea.cpp @@ -60,77 +60,89 @@ u16bit mul_inv(u16bit x) /* * IDEA Encryption */ -void IDEA::enc(const byte in[], byte out[]) const +void IDEA::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - 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) + for(u32bit i = 0; i != blocks; ++i) { - X1 = mul(X1, EK[6*j+0]); - X2 += EK[6*j+1]; - X3 += EK[6*j+2]; - X4 = mul(X4, EK[6*j+3]); - - u16bit T0 = X3; - X3 = mul(X3 ^ X1, EK[6*j+4]); - - u16bit T1 = X2; - X2 = mul((X2 ^ X4) + X3, EK[6*j+5]); - X3 += X2; - - X1 ^= X2; - X4 ^= X3; - X2 ^= T0; - X3 ^= T1; + 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, EK[6*j+0]); + X2 += EK[6*j+1]; + X3 += EK[6*j+2]; + X4 = mul(X4, EK[6*j+3]); + + u16bit T0 = X3; + X3 = mul(X3 ^ X1, EK[6*j+4]); + + u16bit T1 = X2; + X2 = mul((X2 ^ X4) + X3, EK[6*j+5]); + X3 += X2; + + X1 ^= X2; + X4 ^= X3; + X2 ^= T0; + X3 ^= T1; + } + + X1 = mul(X1, EK[48]); + X2 += EK[50]; + X3 += EK[49]; + X4 = mul(X4, EK[51]); + + store_be(out, X1, X3, X2, X4); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; } - - X1 = mul(X1, EK[48]); - X2 += EK[50]; - X3 += EK[49]; - X4 = mul(X4, EK[51]); - - store_be(out, X1, X3, X2, X4); } /* * IDEA Decryption */ -void IDEA::dec(const byte in[], byte out[]) const +void IDEA::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - 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) + for(u32bit i = 0; i != blocks; ++i) { - 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; + 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; } - - X1 = mul(X1, DK[48]); - X2 += DK[50]; - X3 += DK[49]; - X4 = mul(X4, DK[51]); - - store_be(out, X1, X3, X2, X4); } /* diff --git a/src/block/idea/idea.h b/src/block/idea/idea.h index 2c53cd0e4..59484531b 100644 --- a/src/block/idea/idea.h +++ b/src/block/idea/idea.h @@ -18,13 +18,15 @@ namespace Botan { class BOTAN_DLL IDEA : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { EK.clear(); DK.clear(); } std::string name() const { return "IDEA"; } BlockCipher* clone() const { return new IDEA; } + IDEA() : BlockCipher(8, 16) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); SecureBuffer<u16bit, 52> EK, DK; }; diff --git a/src/block/idea/info.txt b/src/block/idea/info.txt index 2da3ffb43..f11b3d224 100644 --- a/src/block/idea/info.txt +++ b/src/block/idea/info.txt @@ -1,10 +1,3 @@ realname "IDEA" define IDEA - -load_on auto - -<add> -idea.cpp -idea.h -</add> diff --git a/src/block/info.txt b/src/block/info.txt index ff48fb04a..f5840bf79 100644 --- a/src/block/info.txt +++ b/src/block/info.txt @@ -1,13 +1,7 @@ realname "Block Ciphers" -load_on auto - define BLOCK_CIPHER -<add> -block_cipher.h -</add> - <requires> sym_algo </requires> diff --git a/src/block/kasumi/info.txt b/src/block/kasumi/info.txt index 8ea879b6d..e310488b3 100644 --- a/src/block/kasumi/info.txt +++ b/src/block/kasumi/info.txt @@ -1,10 +1,3 @@ realname "Kasumi" define KASUMI - -load_on auto - -<add> -kasumi.cpp -kasumi.h -</add> diff --git a/src/block/kasumi/kasumi.cpp b/src/block/kasumi/kasumi.cpp index e051ddefb..dff6db13c 100644 --- a/src/block/kasumi/kasumi.cpp +++ b/src/block/kasumi/kasumi.cpp @@ -109,79 +109,91 @@ u16bit FI(u16bit I, u16bit K) /* * KASUMI Encryption */ -void KASUMI::enc(const byte in[], byte out[]) const +void KASUMI::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u16bit B0 = load_be<u16bit>(in, 0); - u16bit B1 = load_be<u16bit>(in, 1); - u16bit B2 = load_be<u16bit>(in, 2); - u16bit B3 = load_be<u16bit>(in, 3); - - for(u32bit j = 0; j != 8; j += 2) + for(u32bit i = 0; i != blocks; ++i) { - const u16bit* K = EK + 8*j; + u16bit B0 = load_be<u16bit>(in, 0); + u16bit B1 = load_be<u16bit>(in, 1); + u16bit B2 = load_be<u16bit>(in, 2); + u16bit B3 = load_be<u16bit>(in, 3); - u16bit R = B1 ^ (rotate_left(B0, 1) & K[0]); - u16bit L = B0 ^ (rotate_left(R, 1) | K[1]); + for(u32bit j = 0; j != 8; j += 2) + { + const u16bit* K = EK + 8*j; - L = FI(L ^ K[ 2], K[ 3]) ^ R; - R = FI(R ^ K[ 4], K[ 5]) ^ L; - L = FI(L ^ K[ 6], K[ 7]) ^ R; + u16bit R = B1 ^ (rotate_left(B0, 1) & K[0]); + u16bit L = B0 ^ (rotate_left(R, 1) | K[1]); - R = B2 ^= R; - L = B3 ^= L; + L = FI(L ^ K[ 2], K[ 3]) ^ R; + R = FI(R ^ K[ 4], K[ 5]) ^ L; + L = FI(L ^ K[ 6], K[ 7]) ^ R; - R = FI(R ^ K[10], K[11]) ^ L; - L = FI(L ^ K[12], K[13]) ^ R; - R = FI(R ^ K[14], K[15]) ^ L; + R = B2 ^= R; + L = B3 ^= L; - R ^= (rotate_left(L, 1) & K[8]); - L ^= (rotate_left(R, 1) | K[9]); + R = FI(R ^ K[10], K[11]) ^ L; + L = FI(L ^ K[12], K[13]) ^ R; + R = FI(R ^ K[14], K[15]) ^ L; - B0 ^= L; - B1 ^= R; - } + R ^= (rotate_left(L, 1) & K[8]); + L ^= (rotate_left(R, 1) | K[9]); + + B0 ^= L; + B1 ^= R; + } - store_be(out, B0, B1, B2, B3); + store_be(out, B0, B1, B2, B3); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * KASUMI Decryption */ -void KASUMI::dec(const byte in[], byte out[]) const +void KASUMI::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u16bit B0 = load_be<u16bit>(in, 0); - u16bit B1 = load_be<u16bit>(in, 1); - u16bit B2 = load_be<u16bit>(in, 2); - u16bit B3 = load_be<u16bit>(in, 3); - - for(u32bit j = 0; j != 8; j += 2) + for(u32bit i = 0; i != blocks; ++i) { - const u16bit* K = EK + 8*(6-j); + u16bit B0 = load_be<u16bit>(in, 0); + u16bit B1 = load_be<u16bit>(in, 1); + u16bit B2 = load_be<u16bit>(in, 2); + u16bit B3 = load_be<u16bit>(in, 3); - u16bit L = B2, R = B3; + for(u32bit j = 0; j != 8; j += 2) + { + const u16bit* K = EK + 8*(6-j); - L = FI(L ^ K[10], K[11]) ^ R; - R = FI(R ^ K[12], K[13]) ^ L; - L = FI(L ^ K[14], K[15]) ^ R; + u16bit L = B2, R = B3; - L ^= (rotate_left(R, 1) & K[8]); - R ^= (rotate_left(L, 1) | K[9]); + L = FI(L ^ K[10], K[11]) ^ R; + R = FI(R ^ K[12], K[13]) ^ L; + L = FI(L ^ K[14], K[15]) ^ R; - R = B0 ^= R; - L = B1 ^= L; + L ^= (rotate_left(R, 1) & K[8]); + R ^= (rotate_left(L, 1) | K[9]); - L ^= (rotate_left(R, 1) & K[0]); - R ^= (rotate_left(L, 1) | K[1]); + R = B0 ^= R; + L = B1 ^= L; - R = FI(R ^ K[2], K[3]) ^ L; - L = FI(L ^ K[4], K[5]) ^ R; - R = FI(R ^ K[6], K[7]) ^ L; + L ^= (rotate_left(R, 1) & K[0]); + R ^= (rotate_left(L, 1) | K[1]); - B2 ^= L; - B3 ^= R; - } + R = FI(R ^ K[2], K[3]) ^ L; + L = FI(L ^ K[4], K[5]) ^ R; + R = FI(R ^ K[6], K[7]) ^ L; + + B2 ^= L; + B3 ^= R; + } - store_be(out, B0, B1, B2, B3); + store_be(out, B0, B1, B2, B3); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/kasumi/kasumi.h b/src/block/kasumi/kasumi.h index df49fa9eb..0f5a5d182 100644 --- a/src/block/kasumi/kasumi.h +++ b/src/block/kasumi/kasumi.h @@ -18,14 +18,15 @@ namespace Botan { class BOTAN_DLL KASUMI : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { EK.clear(); } std::string name() const { return "KASUMI"; } BlockCipher* clone() const { return new KASUMI; } KASUMI() : BlockCipher(8, 16) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); SecureBuffer<u16bit, 64> EK; diff --git a/src/block/lion/info.txt b/src/block/lion/info.txt index 81ef58511..64f2989b1 100644 --- a/src/block/lion/info.txt +++ b/src/block/lion/info.txt @@ -2,13 +2,6 @@ realname "Lion" define LION -load_on auto - -<add> -lion.cpp -lion.h -</add> - <requires> hash stream diff --git a/src/block/lion/lion.cpp b/src/block/lion/lion.cpp index c7cdf6d13..83c1e3aa3 100644 --- a/src/block/lion/lion.cpp +++ b/src/block/lion/lion.cpp @@ -14,41 +14,53 @@ namespace Botan { /* * Lion Encryption */ -void Lion::enc(const byte in[], byte out[]) const +void Lion::encrypt_n(const byte in[], byte out[], u32bit blocks) const { SecureVector<byte> buffer(LEFT_SIZE); - xor_buf(buffer, in, key1, LEFT_SIZE); - cipher->set_key(buffer, LEFT_SIZE); - cipher->encrypt(in + LEFT_SIZE, out + LEFT_SIZE, RIGHT_SIZE); + for(u32bit i = 0; i != blocks; ++i) + { + xor_buf(buffer, in, key1, LEFT_SIZE); + cipher->set_key(buffer, LEFT_SIZE); + cipher->encrypt(in + LEFT_SIZE, out + LEFT_SIZE, RIGHT_SIZE); - hash->update(out + LEFT_SIZE, RIGHT_SIZE); - hash->final(buffer); - xor_buf(out, in, buffer, LEFT_SIZE); + hash->update(out + LEFT_SIZE, RIGHT_SIZE); + hash->final(buffer); + xor_buf(out, in, buffer, LEFT_SIZE); - xor_buf(buffer, out, key2, LEFT_SIZE); - cipher->set_key(buffer, LEFT_SIZE); - cipher->encrypt(out + LEFT_SIZE, RIGHT_SIZE); + xor_buf(buffer, out, key2, LEFT_SIZE); + cipher->set_key(buffer, LEFT_SIZE); + cipher->encrypt(out + LEFT_SIZE, RIGHT_SIZE); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * Lion Decryption */ -void Lion::dec(const byte in[], byte out[]) const +void Lion::decrypt_n(const byte in[], byte out[], u32bit blocks) const { SecureVector<byte> buffer(LEFT_SIZE); - xor_buf(buffer, in, key2, LEFT_SIZE); - cipher->set_key(buffer, LEFT_SIZE); - cipher->encrypt(in + LEFT_SIZE, out + LEFT_SIZE, RIGHT_SIZE); + for(u32bit i = 0; i != blocks; ++i) + { + xor_buf(buffer, in, key2, LEFT_SIZE); + cipher->set_key(buffer, LEFT_SIZE); + cipher->encrypt(in + LEFT_SIZE, out + LEFT_SIZE, RIGHT_SIZE); + + hash->update(out + LEFT_SIZE, RIGHT_SIZE); + hash->final(buffer); + xor_buf(out, in, buffer, LEFT_SIZE); - hash->update(out + LEFT_SIZE, RIGHT_SIZE); - hash->final(buffer); - xor_buf(out, in, buffer, LEFT_SIZE); + xor_buf(buffer, out, key1, LEFT_SIZE); + cipher->set_key(buffer, LEFT_SIZE); + cipher->encrypt(out + LEFT_SIZE, RIGHT_SIZE); - xor_buf(buffer, out, key1, LEFT_SIZE); - cipher->set_key(buffer, LEFT_SIZE); - cipher->encrypt(out + LEFT_SIZE, RIGHT_SIZE); + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/lion/lion.h b/src/block/lion/lion.h index 5bc4e72c0..d421771d6 100644 --- a/src/block/lion/lion.h +++ b/src/block/lion/lion.h @@ -20,6 +20,9 @@ namespace Botan { class BOTAN_DLL Lion : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw(); std::string name() const; BlockCipher* clone() const; @@ -27,8 +30,6 @@ class BOTAN_DLL Lion : public BlockCipher Lion(HashFunction*, StreamCipher*, u32bit); ~Lion() { delete hash; delete cipher; } private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); const u32bit LEFT_SIZE, RIGHT_SIZE; diff --git a/src/block/lubyrack/info.txt b/src/block/lubyrack/info.txt index a478526f4..d915781d8 100644 --- a/src/block/lubyrack/info.txt +++ b/src/block/lubyrack/info.txt @@ -2,13 +2,6 @@ realname "Luby-Rackoff" define LUBY_RACKOFF -load_on auto - -<add> -lubyrack.cpp -lubyrack.h -</add> - <requires> hash </requires> diff --git a/src/block/lubyrack/lubyrack.cpp b/src/block/lubyrack/lubyrack.cpp index a9d2b1db2..6ad64f2b0 100644 --- a/src/block/lubyrack/lubyrack.cpp +++ b/src/block/lubyrack/lubyrack.cpp @@ -13,59 +13,71 @@ namespace Botan { /* * Luby-Rackoff Encryption */ -void LubyRackoff::enc(const byte in[], byte out[]) const +void LubyRackoff::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - const u32bit len = hash->OUTPUT_LENGTH; - - SecureVector<byte> buffer(len); - hash->update(K1); - hash->update(in, len); - hash->final(buffer); - xor_buf(out + len, in + len, buffer, len); - - hash->update(K2); - hash->update(out + len, len); - hash->final(buffer); - xor_buf(out, in, buffer, len); - - hash->update(K1); - hash->update(out, len); - hash->final(buffer); - xor_buf(out + len, buffer, len); - - hash->update(K2); - hash->update(out + len, len); - hash->final(buffer); - xor_buf(out, buffer, len); + for(u32bit i = 0; i != blocks; ++i) + { + const u32bit len = hash->OUTPUT_LENGTH; + + SecureVector<byte> buffer(len); + hash->update(K1); + hash->update(in, len); + hash->final(buffer); + xor_buf(out + len, in + len, buffer, len); + + hash->update(K2); + hash->update(out + len, len); + hash->final(buffer); + xor_buf(out, in, buffer, len); + + hash->update(K1); + hash->update(out, len); + hash->final(buffer); + xor_buf(out + len, buffer, len); + + hash->update(K2); + hash->update(out + len, len); + hash->final(buffer); + xor_buf(out, buffer, len); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * Luby-Rackoff Decryption */ -void LubyRackoff::dec(const byte in[], byte out[]) const +void LubyRackoff::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - const u32bit len = hash->OUTPUT_LENGTH; - - SecureVector<byte> buffer(len); - hash->update(K2); - hash->update(in + len, len); - hash->final(buffer); - xor_buf(out, in, buffer, len); - - hash->update(K1); - hash->update(out, len); - hash->final(buffer); - xor_buf(out + len, in + len, buffer, len); - - hash->update(K2); - hash->update(out + len, len); - hash->final(buffer); - xor_buf(out, buffer, len); - - hash->update(K1); - hash->update(out, len); - hash->final(buffer); - xor_buf(out + len, buffer, len); + for(u32bit i = 0; i != blocks; ++i) + { + const u32bit len = hash->OUTPUT_LENGTH; + + SecureVector<byte> buffer(len); + hash->update(K2); + hash->update(in + len, len); + hash->final(buffer); + xor_buf(out, in, buffer, len); + + hash->update(K1); + hash->update(out, len); + hash->final(buffer); + xor_buf(out + len, in + len, buffer, len); + + hash->update(K2); + hash->update(out + len, len); + hash->final(buffer); + xor_buf(out, buffer, len); + + hash->update(K1); + hash->update(out, len); + hash->final(buffer); + xor_buf(out + len, buffer, len); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/lubyrack/lubyrack.h b/src/block/lubyrack/lubyrack.h index ebde31304..940b34603 100644 --- a/src/block/lubyrack/lubyrack.h +++ b/src/block/lubyrack/lubyrack.h @@ -19,6 +19,9 @@ namespace Botan { class BOTAN_DLL LubyRackoff : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw(); std::string name() const; BlockCipher* clone() const; @@ -26,9 +29,8 @@ class BOTAN_DLL LubyRackoff : public BlockCipher LubyRackoff(HashFunction* hash); ~LubyRackoff() { delete hash; } private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); + HashFunction* hash; SecureVector<byte> K1, K2; }; diff --git a/src/block/mars/info.txt b/src/block/mars/info.txt index b0ad8af9c..ec958eaf5 100644 --- a/src/block/mars/info.txt +++ b/src/block/mars/info.txt @@ -1,11 +1,3 @@ realname "MARS" define MARS - -load_on auto - -<add> -mars.cpp -mars.h -mars_tab.cpp -</add> diff --git a/src/block/mars/mars.cpp b/src/block/mars/mars.cpp index 08c8409c5..69556acb3 100644 --- a/src/block/mars/mars.cpp +++ b/src/block/mars/mars.cpp @@ -1,6 +1,6 @@ /* * MARS -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -50,75 +50,87 @@ u32bit gen_mask(u32bit input) /* * MARS Encryption */ -void MARS::enc(const byte in[], byte out[]) const +void MARS::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit A = load_le<u32bit>(in, 0) + EK[0]; - u32bit B = load_le<u32bit>(in, 1) + EK[1]; - u32bit C = load_le<u32bit>(in, 2) + EK[2]; - u32bit D = load_le<u32bit>(in, 3) + EK[3]; - - forward_mix(A, B, C, D); - - encrypt_round(A, B, C, D, 0); - encrypt_round(B, C, D, A, 1); - encrypt_round(C, D, A, B, 2); - encrypt_round(D, A, B, C, 3); - encrypt_round(A, B, C, D, 4); - encrypt_round(B, C, D, A, 5); - encrypt_round(C, D, A, B, 6); - encrypt_round(D, A, B, C, 7); - - encrypt_round(A, D, C, B, 8); - encrypt_round(B, A, D, C, 9); - encrypt_round(C, B, A, D, 10); - encrypt_round(D, C, B, A, 11); - encrypt_round(A, D, C, B, 12); - encrypt_round(B, A, D, C, 13); - encrypt_round(C, B, A, D, 14); - encrypt_round(D, C, B, A, 15); - - reverse_mix(A, B, C, D); - - A -= EK[36]; B -= EK[37]; C -= EK[38]; D -= EK[39]; - - store_le(out, A, B, C, D); + for(u32bit i = 0; i != blocks; ++i) + { + u32bit A = load_le<u32bit>(in, 0) + EK[0]; + u32bit B = load_le<u32bit>(in, 1) + EK[1]; + u32bit C = load_le<u32bit>(in, 2) + EK[2]; + u32bit D = load_le<u32bit>(in, 3) + EK[3]; + + forward_mix(A, B, C, D); + + encrypt_round(A, B, C, D, 0); + encrypt_round(B, C, D, A, 1); + encrypt_round(C, D, A, B, 2); + encrypt_round(D, A, B, C, 3); + encrypt_round(A, B, C, D, 4); + encrypt_round(B, C, D, A, 5); + encrypt_round(C, D, A, B, 6); + encrypt_round(D, A, B, C, 7); + + encrypt_round(A, D, C, B, 8); + encrypt_round(B, A, D, C, 9); + encrypt_round(C, B, A, D, 10); + encrypt_round(D, C, B, A, 11); + encrypt_round(A, D, C, B, 12); + encrypt_round(B, A, D, C, 13); + encrypt_round(C, B, A, D, 14); + encrypt_round(D, C, B, A, 15); + + reverse_mix(A, B, C, D); + + A -= EK[36]; B -= EK[37]; C -= EK[38]; D -= EK[39]; + + store_le(out, A, B, C, D); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * MARS Decryption */ -void MARS::dec(const byte in[], byte out[]) const +void MARS::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit A = load_le<u32bit>(in, 3) + EK[39]; - u32bit B = load_le<u32bit>(in, 2) + EK[38]; - u32bit C = load_le<u32bit>(in, 1) + EK[37]; - u32bit D = load_le<u32bit>(in, 0) + EK[36]; - - forward_mix(A, B, C, D); - - decrypt_round(A, B, C, D, 15); - decrypt_round(B, C, D, A, 14); - decrypt_round(C, D, A, B, 13); - decrypt_round(D, A, B, C, 12); - decrypt_round(A, B, C, D, 11); - decrypt_round(B, C, D, A, 10); - decrypt_round(C, D, A, B, 9); - decrypt_round(D, A, B, C, 8); - - decrypt_round(A, D, C, B, 7); - decrypt_round(B, A, D, C, 6); - decrypt_round(C, B, A, D, 5); - decrypt_round(D, C, B, A, 4); - decrypt_round(A, D, C, B, 3); - decrypt_round(B, A, D, C, 2); - decrypt_round(C, B, A, D, 1); - decrypt_round(D, C, B, A, 0); - - reverse_mix(A, B, C, D); - - A -= EK[3]; B -= EK[2]; C -= EK[1]; D -= EK[0]; - - store_le(out, D, C, B, A); + for(u32bit i = 0; i != blocks; ++i) + { + u32bit A = load_le<u32bit>(in, 3) + EK[39]; + u32bit B = load_le<u32bit>(in, 2) + EK[38]; + u32bit C = load_le<u32bit>(in, 1) + EK[37]; + u32bit D = load_le<u32bit>(in, 0) + EK[36]; + + forward_mix(A, B, C, D); + + decrypt_round(A, B, C, D, 15); + decrypt_round(B, C, D, A, 14); + decrypt_round(C, D, A, B, 13); + decrypt_round(D, A, B, C, 12); + decrypt_round(A, B, C, D, 11); + decrypt_round(B, C, D, A, 10); + decrypt_round(C, D, A, B, 9); + decrypt_round(D, A, B, C, 8); + + decrypt_round(A, D, C, B, 7); + decrypt_round(B, A, D, C, 6); + decrypt_round(C, B, A, D, 5); + decrypt_round(D, C, B, A, 4); + decrypt_round(A, D, C, B, 3); + decrypt_round(B, A, D, C, 2); + decrypt_round(C, B, A, D, 1); + decrypt_round(D, C, B, A, 0); + + reverse_mix(A, B, C, D); + + A -= EK[3]; B -= EK[2]; C -= EK[1]; D -= EK[0]; + + store_le(out, D, C, B, A); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/mars/mars.h b/src/block/mars/mars.h index ca49695af..7d0bfe4fa 100644 --- a/src/block/mars/mars.h +++ b/src/block/mars/mars.h @@ -15,13 +15,15 @@ namespace Botan { class BOTAN_DLL MARS : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { EK.clear(); } std::string name() const { return "MARS"; } BlockCipher* clone() const { return new MARS; } + MARS() : BlockCipher(16, 16, 32, 4) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); void encrypt_round(u32bit&, u32bit&, u32bit&, u32bit&, u32bit) const; diff --git a/src/block/misty1/info.txt b/src/block/misty1/info.txt index d45058bd4..38087c83d 100644 --- a/src/block/misty1/info.txt +++ b/src/block/misty1/info.txt @@ -1,10 +1,3 @@ realname "MISTY-1" define MISTY1 - -load_on auto - -<add> -misty1.cpp -misty1.h -</add> diff --git a/src/block/misty1/misty1.cpp b/src/block/misty1/misty1.cpp index a35ff584d..8a92824cc 100644 --- a/src/block/misty1/misty1.cpp +++ b/src/block/misty1/misty1.cpp @@ -1,6 +1,6 @@ /* * MISTY1 -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -102,89 +102,101 @@ u16bit FI(u16bit input, u16bit key7, u16bit key9) /* * MISTY1 Encryption */ -void MISTY1::enc(const byte in[], byte out[]) const +void MISTY1::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u16bit B0 = load_be<u16bit>(in, 0); - u16bit B1 = load_be<u16bit>(in, 1); - u16bit B2 = load_be<u16bit>(in, 2); - u16bit B3 = load_be<u16bit>(in, 3); - - for(u32bit j = 0; j != 12; j += 3) + for(u32bit i = 0; i != blocks; ++i) { - const u16bit* RK = EK + 8 * j; + u16bit B0 = load_be<u16bit>(in, 0); + u16bit B1 = load_be<u16bit>(in, 1); + u16bit B2 = load_be<u16bit>(in, 2); + u16bit B3 = load_be<u16bit>(in, 3); - B1 ^= B0 & RK[0]; - B0 ^= B1 | RK[1]; - B3 ^= B2 & RK[2]; - B2 ^= B3 | RK[3]; + for(u32bit j = 0; j != 12; j += 3) + { + const u16bit* RK = EK + 8 * j; - u32bit T0, T1; + B1 ^= B0 & RK[0]; + B0 ^= B1 | RK[1]; + B3 ^= B2 & RK[2]; + B2 ^= B3 | RK[3]; - T0 = FI(B0 ^ RK[ 4], RK[ 5], RK[ 6]) ^ B1; - T1 = FI(B1 ^ RK[ 7], RK[ 8], RK[ 9]) ^ T0; - T0 = FI(T0 ^ RK[10], RK[11], RK[12]) ^ T1; + u32bit T0, T1; - B2 ^= T1 ^ RK[13]; - B3 ^= T0; + T0 = FI(B0 ^ RK[ 4], RK[ 5], RK[ 6]) ^ B1; + T1 = FI(B1 ^ RK[ 7], RK[ 8], RK[ 9]) ^ T0; + T0 = FI(T0 ^ RK[10], RK[11], RK[12]) ^ T1; - T0 = FI(B2 ^ RK[14], RK[15], RK[16]) ^ B3; - T1 = FI(B3 ^ RK[17], RK[18], RK[19]) ^ T0; - T0 = FI(T0 ^ RK[20], RK[21], RK[22]) ^ T1; + B2 ^= T1 ^ RK[13]; + B3 ^= T0; - B0 ^= T1 ^ RK[23]; - B1 ^= T0; - } + T0 = FI(B2 ^ RK[14], RK[15], RK[16]) ^ B3; + T1 = FI(B3 ^ RK[17], RK[18], RK[19]) ^ T0; + T0 = FI(T0 ^ RK[20], RK[21], RK[22]) ^ T1; + + B0 ^= T1 ^ RK[23]; + B1 ^= T0; + } - B1 ^= B0 & EK[96]; - B0 ^= B1 | EK[97]; - B3 ^= B2 & EK[98]; - B2 ^= B3 | EK[99]; + B1 ^= B0 & EK[96]; + B0 ^= B1 | EK[97]; + B3 ^= B2 & EK[98]; + B2 ^= B3 | EK[99]; - store_be(out, B2, B3, B0, B1); + store_be(out, B2, B3, B0, B1); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * MISTY1 Decryption */ -void MISTY1::dec(const byte in[], byte out[]) const +void MISTY1::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u16bit B0 = load_be<u16bit>(in, 2); - u16bit B1 = load_be<u16bit>(in, 3); - u16bit B2 = load_be<u16bit>(in, 0); - u16bit B3 = load_be<u16bit>(in, 1); - - for(u32bit j = 0; j != 12; j += 3) + for(u32bit i = 0; i != blocks; ++i) { - const u16bit* RK = DK + 8 * j; + u16bit B0 = load_be<u16bit>(in, 2); + u16bit B1 = load_be<u16bit>(in, 3); + u16bit B2 = load_be<u16bit>(in, 0); + u16bit B3 = load_be<u16bit>(in, 1); - B2 ^= B3 | RK[0]; - B3 ^= B2 & RK[1]; - B0 ^= B1 | RK[2]; - B1 ^= B0 & RK[3]; + for(u32bit j = 0; j != 12; j += 3) + { + const u16bit* RK = DK + 8 * j; - u32bit T0, T1; + B2 ^= B3 | RK[0]; + B3 ^= B2 & RK[1]; + B0 ^= B1 | RK[2]; + B1 ^= B0 & RK[3]; - T0 = FI(B2 ^ RK[ 4], RK[ 5], RK[ 6]) ^ B3; - T1 = FI(B3 ^ RK[ 7], RK[ 8], RK[ 9]) ^ T0; - T0 = FI(T0 ^ RK[10], RK[11], RK[12]) ^ T1; + u32bit T0, T1; - B0 ^= T1 ^ RK[13]; - B1 ^= T0; + T0 = FI(B2 ^ RK[ 4], RK[ 5], RK[ 6]) ^ B3; + T1 = FI(B3 ^ RK[ 7], RK[ 8], RK[ 9]) ^ T0; + T0 = FI(T0 ^ RK[10], RK[11], RK[12]) ^ T1; - T0 = FI(B0 ^ RK[14], RK[15], RK[16]) ^ B1; - T1 = FI(B1 ^ RK[17], RK[18], RK[19]) ^ T0; - T0 = FI(T0 ^ RK[20], RK[21], RK[22]) ^ T1; + B0 ^= T1 ^ RK[13]; + B1 ^= T0; - B2 ^= T1 ^ RK[23]; - B3 ^= T0; - } + T0 = FI(B0 ^ RK[14], RK[15], RK[16]) ^ B1; + T1 = FI(B1 ^ RK[17], RK[18], RK[19]) ^ T0; + T0 = FI(T0 ^ RK[20], RK[21], RK[22]) ^ T1; + + B2 ^= T1 ^ RK[23]; + B3 ^= T0; + } - B2 ^= B3 | DK[96]; - B3 ^= B2 & DK[97]; - B0 ^= B1 | DK[98]; - B1 ^= B0 & DK[99]; + B2 ^= B3 | DK[96]; + B3 ^= B2 & DK[97]; + B0 ^= B1 | DK[98]; + B1 ^= B0 & DK[99]; - store_be(out, B0, B1, B2, B3); + store_be(out, B0, B1, B2, B3); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/misty1/misty1.h b/src/block/misty1/misty1.h index 62d4f856f..8db6881de 100644 --- a/src/block/misty1/misty1.h +++ b/src/block/misty1/misty1.h @@ -18,13 +18,15 @@ namespace Botan { class BOTAN_DLL MISTY1 : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { EK.clear(); DK.clear(); } std::string name() const { return "MISTY1"; } BlockCipher* clone() const { return new MISTY1; } + MISTY1(u32bit = 8); private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); SecureBuffer<u16bit, 100> EK, DK; diff --git a/src/block/noekeon/info.txt b/src/block/noekeon/info.txt index 8025c2073..6e940bb62 100644 --- a/src/block/noekeon/info.txt +++ b/src/block/noekeon/info.txt @@ -1,10 +1,3 @@ realname "Noekeon" define NOEKEON - -load_on auto - -<add> -noekeon.cpp -noekeon.h -</add> diff --git a/src/block/noekeon/noekeon.cpp b/src/block/noekeon/noekeon.cpp index 90eb9ad2b..1b327aa47 100644 --- a/src/block/noekeon/noekeon.cpp +++ b/src/block/noekeon/noekeon.cpp @@ -84,65 +84,77 @@ const byte Noekeon::RC[] = { /* * Noekeon Encryption */ -void Noekeon::enc(const byte in[], byte out[]) const +void Noekeon::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit A0 = load_be<u32bit>(in, 0); - u32bit A1 = load_be<u32bit>(in, 1); - u32bit A2 = load_be<u32bit>(in, 2); - u32bit A3 = load_be<u32bit>(in, 3); - - for(u32bit j = 0; j != 16; ++j) + for(u32bit i = 0; i != blocks; ++i) { - A0 ^= RC[j]; - theta(A0, A1, A2, A3, EK); + u32bit A0 = load_be<u32bit>(in, 0); + u32bit A1 = load_be<u32bit>(in, 1); + u32bit A2 = load_be<u32bit>(in, 2); + u32bit A3 = load_be<u32bit>(in, 3); - A1 = rotate_left(A1, 1); - A2 = rotate_left(A2, 5); - A3 = rotate_left(A3, 2); + for(u32bit j = 0; j != 16; ++j) + { + A0 ^= RC[j]; + theta(A0, A1, A2, A3, EK); - gamma(A0, A1, A2, A3); + A1 = rotate_left(A1, 1); + A2 = rotate_left(A2, 5); + A3 = rotate_left(A3, 2); - A1 = rotate_right(A1, 1); - A2 = rotate_right(A2, 5); - A3 = rotate_right(A3, 2); - } + gamma(A0, A1, A2, A3); - A0 ^= RC[16]; - theta(A0, A1, A2, A3, EK); + A1 = rotate_right(A1, 1); + A2 = rotate_right(A2, 5); + A3 = rotate_right(A3, 2); + } + + A0 ^= RC[16]; + theta(A0, A1, A2, A3, EK); + + store_be(out, A0, A1, A2, A3); - store_be(out, A0, A1, A2, A3); + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * Noekeon Encryption */ -void Noekeon::dec(const byte in[], byte out[]) const +void Noekeon::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit A0 = load_be<u32bit>(in, 0); - u32bit A1 = load_be<u32bit>(in, 1); - u32bit A2 = load_be<u32bit>(in, 2); - u32bit A3 = load_be<u32bit>(in, 3); - - for(u32bit j = 16; j != 0; --j) + for(u32bit i = 0; i != blocks; ++i) { - theta(A0, A1, A2, A3, DK); - A0 ^= RC[j]; + u32bit A0 = load_be<u32bit>(in, 0); + u32bit A1 = load_be<u32bit>(in, 1); + u32bit A2 = load_be<u32bit>(in, 2); + u32bit A3 = load_be<u32bit>(in, 3); - A1 = rotate_left(A1, 1); - A2 = rotate_left(A2, 5); - A3 = rotate_left(A3, 2); + for(u32bit j = 16; j != 0; --j) + { + theta(A0, A1, A2, A3, DK); + A0 ^= RC[j]; - gamma(A0, A1, A2, A3); + A1 = rotate_left(A1, 1); + A2 = rotate_left(A2, 5); + A3 = rotate_left(A3, 2); - A1 = rotate_right(A1, 1); - A2 = rotate_right(A2, 5); - A3 = rotate_right(A3, 2); - } + gamma(A0, A1, A2, A3); - theta(A0, A1, A2, A3, DK); - A0 ^= RC[0]; + A1 = rotate_right(A1, 1); + A2 = rotate_right(A2, 5); + A3 = rotate_right(A3, 2); + } - store_be(out, A0, A1, A2, A3); + theta(A0, A1, A2, A3, DK); + A0 ^= RC[0]; + + store_be(out, A0, A1, A2, A3); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/noekeon/noekeon.h b/src/block/noekeon/noekeon.h index 893892446..37b24fb7d 100644 --- a/src/block/noekeon/noekeon.h +++ b/src/block/noekeon/noekeon.h @@ -18,13 +18,15 @@ namespace Botan { class BOTAN_DLL Noekeon : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw(); std::string name() const { return "Noekeon"; } BlockCipher* clone() const { return new Noekeon; } + Noekeon() : BlockCipher(16, 16) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); static const byte RC[17]; diff --git a/src/block/rc2/info.txt b/src/block/rc2/info.txt index 099141de7..7ec018422 100644 --- a/src/block/rc2/info.txt +++ b/src/block/rc2/info.txt @@ -1,10 +1,3 @@ realname "RC2" define RC2 - -load_on auto - -<add> -rc2.cpp -rc2.h -</add> diff --git a/src/block/rc2/rc2.cpp b/src/block/rc2/rc2.cpp index 5827bdb68..b5e4a7d50 100644 --- a/src/block/rc2/rc2.cpp +++ b/src/block/rc2/rc2.cpp @@ -14,73 +14,85 @@ namespace Botan { /* * RC2 Encryption */ -void RC2::enc(const byte in[], byte out[]) const +void RC2::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u16bit R0 = load_le<u16bit>(in, 0); - u16bit R1 = load_le<u16bit>(in, 1); - u16bit R2 = load_le<u16bit>(in, 2); - u16bit R3 = load_le<u16bit>(in, 3); - - for(u32bit j = 0; j != 16; ++j) + for(u32bit i = 0; i != blocks; ++i) { - R0 += (R1 & ~R3) + (R2 & R3) + K[4*j]; - R0 = rotate_left(R0, 1); + u16bit R0 = load_le<u16bit>(in, 0); + u16bit R1 = load_le<u16bit>(in, 1); + u16bit R2 = load_le<u16bit>(in, 2); + u16bit R3 = load_le<u16bit>(in, 3); + + for(u32bit j = 0; j != 16; ++j) + { + R0 += (R1 & ~R3) + (R2 & R3) + K[4*j]; + R0 = rotate_left(R0, 1); - R1 += (R2 & ~R0) + (R3 & R0) + K[4*j + 1]; - R1 = rotate_left(R1, 2); + R1 += (R2 & ~R0) + (R3 & R0) + K[4*j + 1]; + R1 = rotate_left(R1, 2); - R2 += (R3 & ~R1) + (R0 & R1) + K[4*j + 2]; - R2 = rotate_left(R2, 3); + R2 += (R3 & ~R1) + (R0 & R1) + K[4*j + 2]; + R2 = rotate_left(R2, 3); - R3 += (R0 & ~R2) + (R1 & R2) + K[4*j + 3]; - R3 = rotate_left(R3, 5); + R3 += (R0 & ~R2) + (R1 & R2) + K[4*j + 3]; + R3 = rotate_left(R3, 5); - if(j == 4 || j == 10) - { - R0 += K[R3 % 64]; - R1 += K[R0 % 64]; - R2 += K[R1 % 64]; - R3 += K[R2 % 64]; + if(j == 4 || j == 10) + { + R0 += K[R3 % 64]; + R1 += K[R0 % 64]; + R2 += K[R1 % 64]; + R3 += K[R2 % 64]; + } } - } - store_le(out, R0, R1, R2, R3); + store_le(out, R0, R1, R2, R3); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * RC2 Decryption */ -void RC2::dec(const byte in[], byte out[]) const +void RC2::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u16bit R0 = load_le<u16bit>(in, 0); - u16bit R1 = load_le<u16bit>(in, 1); - u16bit R2 = load_le<u16bit>(in, 2); - u16bit R3 = load_le<u16bit>(in, 3); - - for(u32bit j = 0; j != 16; ++j) + for(u32bit i = 0; i != blocks; ++i) { - R3 = rotate_right(R3, 5); - R3 -= (R0 & ~R2) + (R1 & R2) + K[63 - (4*j + 0)]; + u16bit R0 = load_le<u16bit>(in, 0); + u16bit R1 = load_le<u16bit>(in, 1); + u16bit R2 = load_le<u16bit>(in, 2); + u16bit R3 = load_le<u16bit>(in, 3); + + for(u32bit j = 0; j != 16; ++j) + { + R3 = rotate_right(R3, 5); + R3 -= (R0 & ~R2) + (R1 & R2) + K[63 - (4*j + 0)]; - R2 = rotate_right(R2, 3); - R2 -= (R3 & ~R1) + (R0 & R1) + K[63 - (4*j + 1)]; + R2 = rotate_right(R2, 3); + R2 -= (R3 & ~R1) + (R0 & R1) + K[63 - (4*j + 1)]; - R1 = rotate_right(R1, 2); - R1 -= (R2 & ~R0) + (R3 & R0) + K[63 - (4*j + 2)]; + R1 = rotate_right(R1, 2); + R1 -= (R2 & ~R0) + (R3 & R0) + K[63 - (4*j + 2)]; - R0 = rotate_right(R0, 1); - R0 -= (R1 & ~R3) + (R2 & R3) + K[63 - (4*j + 3)]; + R0 = rotate_right(R0, 1); + R0 -= (R1 & ~R3) + (R2 & R3) + K[63 - (4*j + 3)]; - if(j == 4 || j == 10) - { - R3 -= K[R2 % 64]; - R2 -= K[R1 % 64]; - R1 -= K[R0 % 64]; - R0 -= K[R3 % 64]; + if(j == 4 || j == 10) + { + R3 -= K[R2 % 64]; + R2 -= K[R1 % 64]; + R1 -= K[R0 % 64]; + R0 -= K[R3 % 64]; + } } - } - store_le(out, R0, R1, R2, R3); + store_le(out, R0, R1, R2, R3); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/rc2/rc2.h b/src/block/rc2/rc2.h index cb6f58f04..db623b385 100644 --- a/src/block/rc2/rc2.h +++ b/src/block/rc2/rc2.h @@ -18,15 +18,17 @@ namespace Botan { class BOTAN_DLL RC2 : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + static byte EKB_code(u32bit); void clear() throw() { K.clear(); } std::string name() const { return "RC2"; } BlockCipher* clone() const { return new RC2; } + RC2() : BlockCipher(8, 1, 32) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); SecureBuffer<u16bit, 64> K; diff --git a/src/block/rc5/info.txt b/src/block/rc5/info.txt index 4a150c3b0..2032b406f 100644 --- a/src/block/rc5/info.txt +++ b/src/block/rc5/info.txt @@ -1,10 +1,3 @@ realname "RC5" define RC5 - -load_on auto - -<add> -rc5.cpp -rc5.h -</add> diff --git a/src/block/rc5/rc5.cpp b/src/block/rc5/rc5.cpp index 5d83d5a4e..4bfa27ea0 100644 --- a/src/block/rc5/rc5.cpp +++ b/src/block/rc5/rc5.cpp @@ -16,47 +16,59 @@ namespace Botan { /* * RC5 Encryption */ -void RC5::enc(const byte in[], byte out[]) const +void RC5::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit A = load_le<u32bit>(in, 0), B = load_le<u32bit>(in, 1); - - A += S[0]; B += S[1]; - for(u32bit j = 0; j != ROUNDS; j += 4) + for(u32bit i = 0; i != blocks; ++i) { - A = rotate_left(A ^ B, B % 32) + S[2*j+2]; - B = rotate_left(B ^ A, A % 32) + S[2*j+3]; - A = rotate_left(A ^ B, B % 32) + S[2*j+4]; - B = rotate_left(B ^ A, A % 32) + S[2*j+5]; - A = rotate_left(A ^ B, B % 32) + S[2*j+6]; - B = rotate_left(B ^ A, A % 32) + S[2*j+7]; - A = rotate_left(A ^ B, B % 32) + S[2*j+8]; - B = rotate_left(B ^ A, A % 32) + S[2*j+9]; - } + u32bit A = load_le<u32bit>(in, 0), B = load_le<u32bit>(in, 1); + + A += S[0]; B += S[1]; + for(u32bit j = 0; j != ROUNDS; j += 4) + { + A = rotate_left(A ^ B, B % 32) + S[2*j+2]; + B = rotate_left(B ^ A, A % 32) + S[2*j+3]; + A = rotate_left(A ^ B, B % 32) + S[2*j+4]; + B = rotate_left(B ^ A, A % 32) + S[2*j+5]; + A = rotate_left(A ^ B, B % 32) + S[2*j+6]; + B = rotate_left(B ^ A, A % 32) + S[2*j+7]; + A = rotate_left(A ^ B, B % 32) + S[2*j+8]; + B = rotate_left(B ^ A, A % 32) + S[2*j+9]; + } - store_le(out, A, B); + store_le(out, A, B); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * RC5 Decryption */ -void RC5::dec(const byte in[], byte out[]) const +void RC5::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit A = load_le<u32bit>(in, 0), B = load_le<u32bit>(in, 1); - - for(u32bit j = ROUNDS; j != 0; j -= 4) + for(u32bit i = 0; i != blocks; ++i) { - B = rotate_right(B - S[2*j+1], A % 32) ^ A; - A = rotate_right(A - S[2*j ], B % 32) ^ B; - B = rotate_right(B - S[2*j-1], A % 32) ^ A; - A = rotate_right(A - S[2*j-2], B % 32) ^ B; - B = rotate_right(B - S[2*j-3], A % 32) ^ A; - A = rotate_right(A - S[2*j-4], B % 32) ^ B; - B = rotate_right(B - S[2*j-5], A % 32) ^ A; - A = rotate_right(A - S[2*j-6], B % 32) ^ B; - } - B -= S[1]; A -= S[0]; + u32bit A = load_le<u32bit>(in, 0), B = load_le<u32bit>(in, 1); + + for(u32bit j = ROUNDS; j != 0; j -= 4) + { + B = rotate_right(B - S[2*j+1], A % 32) ^ A; + A = rotate_right(A - S[2*j ], B % 32) ^ B; + B = rotate_right(B - S[2*j-1], A % 32) ^ A; + A = rotate_right(A - S[2*j-2], B % 32) ^ B; + B = rotate_right(B - S[2*j-3], A % 32) ^ A; + A = rotate_right(A - S[2*j-4], B % 32) ^ B; + B = rotate_right(B - S[2*j-5], A % 32) ^ A; + A = rotate_right(A - S[2*j-6], B % 32) ^ B; + } + B -= S[1]; A -= S[0]; - store_le(out, A, B); + store_le(out, A, B); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/rc5/rc5.h b/src/block/rc5/rc5.h index 083224720..ff9204710 100644 --- a/src/block/rc5/rc5.h +++ b/src/block/rc5/rc5.h @@ -18,13 +18,15 @@ namespace Botan { class BOTAN_DLL RC5 : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { S.clear(); } std::string name() const; BlockCipher* clone() const { return new RC5(ROUNDS); } + RC5(u32bit); private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); SecureVector<u32bit> S; const u32bit ROUNDS; diff --git a/src/block/rc6/info.txt b/src/block/rc6/info.txt index 1457e78c1..2897bc1f3 100644 --- a/src/block/rc6/info.txt +++ b/src/block/rc6/info.txt @@ -1,10 +1,3 @@ realname "RC6" define RC6 - -load_on auto - -<add> -rc6.cpp -rc6.h -</add> diff --git a/src/block/rc6/rc6.cpp b/src/block/rc6/rc6.cpp index 3b30ea93a..8bda62259 100644 --- a/src/block/rc6/rc6.cpp +++ b/src/block/rc6/rc6.cpp @@ -15,85 +15,97 @@ namespace Botan { /* * RC6 Encryption */ -void RC6::enc(const byte in[], byte out[]) const +void RC6::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit A = load_le<u32bit>(in, 0); - u32bit B = load_le<u32bit>(in, 1); - u32bit C = load_le<u32bit>(in, 2); - u32bit D = load_le<u32bit>(in, 3); + for(u32bit i = 0; i != blocks; ++i) + { + u32bit A = load_le<u32bit>(in, 0); + u32bit B = load_le<u32bit>(in, 1); + u32bit C = load_le<u32bit>(in, 2); + u32bit D = load_le<u32bit>(in, 3); - B += S[0]; D += S[1]; + B += S[0]; D += S[1]; - for(u32bit j = 0; j != 20; j += 4) - { - u32bit T1, T2; - - T1 = rotate_left(B*(2*B+1), 5); - T2 = rotate_left(D*(2*D+1), 5); - A = rotate_left(A ^ T1, T2 % 32) + S[2*j+2]; - C = rotate_left(C ^ T2, T1 % 32) + S[2*j+3]; - - T1 = rotate_left(C*(2*C+1), 5); - T2 = rotate_left(A*(2*A+1), 5); - B = rotate_left(B ^ T1, T2 % 32) + S[2*j+4]; - D = rotate_left(D ^ T2, T1 % 32) + S[2*j+5]; - - T1 = rotate_left(D*(2*D+1), 5); - T2 = rotate_left(B*(2*B+1), 5); - C = rotate_left(C ^ T1, T2 % 32) + S[2*j+6]; - A = rotate_left(A ^ T2, T1 % 32) + S[2*j+7]; - - T1 = rotate_left(A*(2*A+1), 5); - T2 = rotate_left(C*(2*C+1), 5); - D = rotate_left(D ^ T1, T2 % 32) + S[2*j+8]; - B = rotate_left(B ^ T2, T1 % 32) + S[2*j+9]; - } + for(u32bit j = 0; j != 20; j += 4) + { + u32bit T1, T2; + + T1 = rotate_left(B*(2*B+1), 5); + T2 = rotate_left(D*(2*D+1), 5); + A = rotate_left(A ^ T1, T2 % 32) + S[2*j+2]; + C = rotate_left(C ^ T2, T1 % 32) + S[2*j+3]; + + T1 = rotate_left(C*(2*C+1), 5); + T2 = rotate_left(A*(2*A+1), 5); + B = rotate_left(B ^ T1, T2 % 32) + S[2*j+4]; + D = rotate_left(D ^ T2, T1 % 32) + S[2*j+5]; - A += S[42]; C += S[43]; + T1 = rotate_left(D*(2*D+1), 5); + T2 = rotate_left(B*(2*B+1), 5); + C = rotate_left(C ^ T1, T2 % 32) + S[2*j+6]; + A = rotate_left(A ^ T2, T1 % 32) + S[2*j+7]; - store_le(out, A, B, C, D); + T1 = rotate_left(A*(2*A+1), 5); + T2 = rotate_left(C*(2*C+1), 5); + D = rotate_left(D ^ T1, T2 % 32) + S[2*j+8]; + B = rotate_left(B ^ T2, T1 % 32) + S[2*j+9]; + } + + A += S[42]; C += S[43]; + + store_le(out, A, B, C, D); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * RC6 Decryption */ -void RC6::dec(const byte in[], byte out[]) const +void RC6::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit A = load_le<u32bit>(in, 0); - u32bit B = load_le<u32bit>(in, 1); - u32bit C = load_le<u32bit>(in, 2); - u32bit D = load_le<u32bit>(in, 3); + for(u32bit i = 0; i != blocks; ++i) + { + u32bit A = load_le<u32bit>(in, 0); + u32bit B = load_le<u32bit>(in, 1); + u32bit C = load_le<u32bit>(in, 2); + u32bit D = load_le<u32bit>(in, 3); - C -= S[43]; A -= S[42]; + C -= S[43]; A -= S[42]; - for(u32bit j = 0; j != 20; j += 4) - { - u32bit T1, T2; - - T1 = rotate_left(A*(2*A+1), 5); - T2 = rotate_left(C*(2*C+1), 5); - B = rotate_right(B - S[41 - 2*j], T1 % 32) ^ T2; - D = rotate_right(D - S[40 - 2*j], T2 % 32) ^ T1; - - T1 = rotate_left(D*(2*D+1), 5); - T2 = rotate_left(B*(2*B+1), 5); - A = rotate_right(A - S[39 - 2*j], T1 % 32) ^ T2; - C = rotate_right(C - S[38 - 2*j], T2 % 32) ^ T1; - - T1 = rotate_left(C*(2*C+1), 5); - T2 = rotate_left(A*(2*A+1), 5); - D = rotate_right(D - S[37 - 2*j], T1 % 32) ^ T2; - B = rotate_right(B - S[36 - 2*j], T2 % 32) ^ T1; - - T1 = rotate_left(B*(2*B+1), 5); - T2 = rotate_left(D*(2*D+1), 5); - C = rotate_right(C - S[35 - 2*j], T1 % 32) ^ T2; - A = rotate_right(A - S[34 - 2*j], T2 % 32) ^ T1; - } + for(u32bit j = 0; j != 20; j += 4) + { + u32bit T1, T2; + + T1 = rotate_left(A*(2*A+1), 5); + T2 = rotate_left(C*(2*C+1), 5); + B = rotate_right(B - S[41 - 2*j], T1 % 32) ^ T2; + D = rotate_right(D - S[40 - 2*j], T2 % 32) ^ T1; + + T1 = rotate_left(D*(2*D+1), 5); + T2 = rotate_left(B*(2*B+1), 5); + A = rotate_right(A - S[39 - 2*j], T1 % 32) ^ T2; + C = rotate_right(C - S[38 - 2*j], T2 % 32) ^ T1; - D -= S[1]; B -= S[0]; + T1 = rotate_left(C*(2*C+1), 5); + T2 = rotate_left(A*(2*A+1), 5); + D = rotate_right(D - S[37 - 2*j], T1 % 32) ^ T2; + B = rotate_right(B - S[36 - 2*j], T2 % 32) ^ T1; - store_le(out, A, B, C, D); + T1 = rotate_left(B*(2*B+1), 5); + T2 = rotate_left(D*(2*D+1), 5); + C = rotate_right(C - S[35 - 2*j], T1 % 32) ^ T2; + A = rotate_right(A - S[34 - 2*j], T2 % 32) ^ T1; + } + + D -= S[1]; B -= S[0]; + + store_le(out, A, B, C, D); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/rc6/rc6.h b/src/block/rc6/rc6.h index cb2800be7..5171006f5 100644 --- a/src/block/rc6/rc6.h +++ b/src/block/rc6/rc6.h @@ -18,13 +18,15 @@ namespace Botan { class BOTAN_DLL RC6 : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { S.clear(); } std::string name() const { return "RC6"; } BlockCipher* clone() const { return new RC6; } + RC6() : BlockCipher(16, 1, 32) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); SecureBuffer<u32bit, 44> S; diff --git a/src/block/safer/info.txt b/src/block/safer/info.txt index 973cbff19..7c8067472 100644 --- a/src/block/safer/info.txt +++ b/src/block/safer/info.txt @@ -1,11 +1,3 @@ realname "SAFER" define SAFER - -load_on auto - -<add> -safe_tab.cpp -safer_sk.cpp -safer_sk.h -</add> diff --git a/src/block/safer/safer_sk.cpp b/src/block/safer/safer_sk.cpp index f72c4773b..eb5c22fc9 100644 --- a/src/block/safer/safer_sk.cpp +++ b/src/block/safer/safer_sk.cpp @@ -1,6 +1,6 @@ /* * SAFER-SK -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -15,54 +15,75 @@ namespace Botan { /* * SAFER-SK Encryption */ -void SAFER_SK::enc(const byte in[], byte out[]) const +void SAFER_SK::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - byte A = in[0], B = in[1], C = in[2], D = in[3], - E = in[4], F = in[5], G = in[6], H = in[7], X, Y; - for(u32bit j = 0; j != 16*ROUNDS; j += 16) + for(u32bit i = 0; i != blocks; ++i) { - A = EXP[A ^ EK[j ]]; B = LOG[B + EK[j+1]]; - C = LOG[C + EK[j+2]]; D = EXP[D ^ EK[j+3]]; - E = EXP[E ^ EK[j+4]]; F = LOG[F + EK[j+5]]; - G = LOG[G + EK[j+6]]; H = EXP[H ^ EK[j+7]]; - A += EK[j+ 8]; B ^= EK[j+ 9]; C ^= EK[j+10]; D += EK[j+11]; - E += EK[j+12]; F ^= EK[j+13]; G ^= EK[j+14]; H += EK[j+15]; - B += A; D += C; F += E; H += G; A += B; C += D; E += F; G += H; - C += A; G += E; D += B; H += F; A += C; E += G; B += D; F += H; - H += D; Y = D + H; D = B + F; X = B + D; B = A + E; - A += B; F = C + G; E = C + F; C = X; G = Y; + byte A = in[0], B = in[1], C = in[2], D = in[3], + E = in[4], F = in[5], G = in[6], H = in[7], X, Y; + + for(u32bit j = 0; j != 16*ROUNDS; j += 16) + { + A = EXP[A ^ EK[j ]]; B = LOG[B + EK[j+1]]; + C = LOG[C + EK[j+2]]; D = EXP[D ^ EK[j+3]]; + E = EXP[E ^ EK[j+4]]; F = LOG[F + EK[j+5]]; + G = LOG[G + EK[j+6]]; H = EXP[H ^ EK[j+7]]; + + A += EK[j+ 8]; B ^= EK[j+ 9]; C ^= EK[j+10]; D += EK[j+11]; + E += EK[j+12]; F ^= EK[j+13]; G ^= EK[j+14]; H += EK[j+15]; + + B += A; D += C; F += E; H += G; A += B; C += D; E += F; G += H; + C += A; G += E; D += B; H += F; A += C; E += G; B += D; F += H; + H += D; Y = D + H; D = B + F; X = B + D; B = A + E; + A += B; F = C + G; E = C + F; C = X; G = Y; + } + + out[0] = A ^ EK[16*ROUNDS+0]; out[1] = B + EK[16*ROUNDS+1]; + out[2] = C + EK[16*ROUNDS+2]; out[3] = D ^ EK[16*ROUNDS+3]; + out[4] = E ^ EK[16*ROUNDS+4]; out[5] = F + EK[16*ROUNDS+5]; + out[6] = G + EK[16*ROUNDS+6]; out[7] = H ^ EK[16*ROUNDS+7]; + + in += BLOCK_SIZE; + out += BLOCK_SIZE; } - out[0] = A ^ EK[16*ROUNDS+0]; out[1] = B + EK[16*ROUNDS+1]; - out[2] = C + EK[16*ROUNDS+2]; out[3] = D ^ EK[16*ROUNDS+3]; - out[4] = E ^ EK[16*ROUNDS+4]; out[5] = F + EK[16*ROUNDS+5]; - out[6] = G + EK[16*ROUNDS+6]; out[7] = H ^ EK[16*ROUNDS+7]; } /* * SAFER-SK Decryption */ -void SAFER_SK::dec(const byte in[], byte out[]) const +void SAFER_SK::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - byte A = in[0], B = in[1], C = in[2], D = in[3], - E = in[4], F = in[5], G = in[6], H = in[7]; - A ^= EK[16*ROUNDS+0]; B -= EK[16*ROUNDS+1]; C -= EK[16*ROUNDS+2]; - D ^= EK[16*ROUNDS+3]; E ^= EK[16*ROUNDS+4]; F -= EK[16*ROUNDS+5]; - G -= EK[16*ROUNDS+6]; H ^= EK[16*ROUNDS+7]; - for(s32bit j = 16*(ROUNDS-1); j >= 0; j -= 16) + for(u32bit i = 0; i != blocks; ++i) { - byte T = E; E = B; B = C; C = T; T = F; F = D; D = G; G = T; - A -= E; B -= F; C -= G; D -= H; E -= A; F -= B; G -= C; H -= D; - A -= C; E -= G; B -= D; F -= H; C -= A; G -= E; D -= B; H -= F; - A -= B; C -= D; E -= F; G -= H; B -= A; D -= C; F -= E; H -= G; - A = LOG[A - EK[j+8 ] + 256]; B = EXP[B ^ EK[j+9 ]]; - C = EXP[C ^ EK[j+10]]; D = LOG[D - EK[j+11] + 256]; - E = LOG[E - EK[j+12] + 256]; F = EXP[F ^ EK[j+13]]; - G = EXP[G ^ EK[j+14]]; H = LOG[H - EK[j+15] + 256]; - A ^= EK[j+0]; B -= EK[j+1]; C -= EK[j+2]; D ^= EK[j+3]; - E ^= EK[j+4]; F -= EK[j+5]; G -= EK[j+6]; H ^= EK[j+7]; + byte A = in[0], B = in[1], C = in[2], D = in[3], + E = in[4], F = in[5], G = in[6], H = in[7]; + + A ^= EK[16*ROUNDS+0]; B -= EK[16*ROUNDS+1]; C -= EK[16*ROUNDS+2]; + D ^= EK[16*ROUNDS+3]; E ^= EK[16*ROUNDS+4]; F -= EK[16*ROUNDS+5]; + G -= EK[16*ROUNDS+6]; H ^= EK[16*ROUNDS+7]; + + for(s32bit j = 16*(ROUNDS-1); j >= 0; j -= 16) + { + byte T = E; E = B; B = C; C = T; T = F; F = D; D = G; G = T; + A -= E; B -= F; C -= G; D -= H; E -= A; F -= B; G -= C; H -= D; + A -= C; E -= G; B -= D; F -= H; C -= A; G -= E; D -= B; H -= F; + A -= B; C -= D; E -= F; G -= H; B -= A; D -= C; F -= E; H -= G; + + A = LOG[A - EK[j+8 ] + 256]; B = EXP[B ^ EK[j+9 ]]; + C = EXP[C ^ EK[j+10]]; D = LOG[D - EK[j+11] + 256]; + E = LOG[E - EK[j+12] + 256]; F = EXP[F ^ EK[j+13]]; + G = EXP[G ^ EK[j+14]]; H = LOG[H - EK[j+15] + 256]; + + A ^= EK[j+0]; B -= EK[j+1]; C -= EK[j+2]; D ^= EK[j+3]; + E ^= EK[j+4]; F -= EK[j+5]; G -= EK[j+6]; H ^= EK[j+7]; + } + + out[0] = A; out[1] = B; out[2] = C; out[3] = D; + out[4] = E; out[5] = F; out[6] = G; out[7] = H; + + in += BLOCK_SIZE; + out += BLOCK_SIZE; } - out[0] = A; out[1] = B; out[2] = C; out[3] = D; - out[4] = E; out[5] = F; out[6] = G; out[7] = H; } /* diff --git a/src/block/safer/safer_sk.h b/src/block/safer/safer_sk.h index e52c5837c..4d17bba51 100644 --- a/src/block/safer/safer_sk.h +++ b/src/block/safer/safer_sk.h @@ -18,19 +18,22 @@ namespace Botan { class BOTAN_DLL SAFER_SK : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { EK.clear(); } std::string name() const; BlockCipher* clone() const; + SAFER_SK(u32bit); private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); static const byte EXP[256]; static const byte LOG[512]; static const byte BIAS[208]; static const byte KEY_INDEX[208]; + SecureVector<byte> EK; const u32bit ROUNDS; }; diff --git a/src/block/seed/info.txt b/src/block/seed/info.txt index d04979335..c66e0c2cd 100644 --- a/src/block/seed/info.txt +++ b/src/block/seed/info.txt @@ -1,11 +1,3 @@ realname "SEED" define SEED - -load_on auto - -<add> -seed.cpp -seed.h -seed_tab.cpp -</add> diff --git a/src/block/seed/seed.cpp b/src/block/seed/seed.cpp index b06a7cd77..378be16e4 100644 --- a/src/block/seed/seed.cpp +++ b/src/block/seed/seed.cpp @@ -22,69 +22,81 @@ u32bit SEED::G_FUNC::operator()(u32bit X) const /* * SEED Encryption */ -void SEED::enc(const byte in[], byte out[]) const +void SEED::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit B0 = load_be<u32bit>(in, 0); - u32bit B1 = load_be<u32bit>(in, 1); - u32bit B2 = load_be<u32bit>(in, 2); - u32bit B3 = load_be<u32bit>(in, 3); - - G_FUNC G; - - for(u32bit j = 0; j != 16; j += 2) + for(u32bit i = 0; i != blocks; ++i) { - u32bit T0, T1; - - T0 = B2 ^ K[2*j]; - T1 = G(B2 ^ B3 ^ K[2*j+1]); - T0 = G(T1 + T0); - T1 = G(T1 + T0); - B1 ^= T1; - B0 ^= T0 + T1; - - T0 = B0 ^ K[2*j+2]; - T1 = G(B0 ^ B1 ^ K[2*j+3]); - T0 = G(T1 + T0); - T1 = G(T1 + T0); - B3 ^= T1; - B2 ^= T0 + T1; + u32bit B0 = load_be<u32bit>(in, 0); + u32bit B1 = load_be<u32bit>(in, 1); + u32bit B2 = load_be<u32bit>(in, 2); + u32bit B3 = load_be<u32bit>(in, 3); + + G_FUNC G; + + for(u32bit j = 0; j != 16; j += 2) + { + u32bit T0, T1; + + T0 = B2 ^ K[2*j]; + T1 = G(B2 ^ B3 ^ K[2*j+1]); + T0 = G(T1 + T0); + T1 = G(T1 + T0); + B1 ^= T1; + B0 ^= T0 + T1; + + T0 = B0 ^ K[2*j+2]; + T1 = G(B0 ^ B1 ^ K[2*j+3]); + T0 = G(T1 + T0); + T1 = G(T1 + T0); + B3 ^= T1; + B2 ^= T0 + T1; + } + + store_be(out, B2, B3, B0, B1); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; } - - store_be(out, B2, B3, B0, B1); } /* * SEED Decryption */ -void SEED::dec(const byte in[], byte out[]) const +void SEED::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit B0 = load_be<u32bit>(in, 0); - u32bit B1 = load_be<u32bit>(in, 1); - u32bit B2 = load_be<u32bit>(in, 2); - u32bit B3 = load_be<u32bit>(in, 3); - - G_FUNC G; - - for(u32bit j = 0; j != 16; j += 2) + for(u32bit i = 0; i != blocks; ++i) { - u32bit T0, T1; - - T0 = B2 ^ K[30-2*j]; - T1 = G(B2 ^ B3 ^ K[31-2*j]); - T0 = G(T1 + T0); - T1 = G(T1 + T0); - B1 ^= T1; - B0 ^= T0 + T1; - - T0 = B0 ^ K[28-2*j]; - T1 = G(B0 ^ B1 ^ K[29-2*j]); - T0 = G(T1 + T0); - T1 = G(T1 + T0); - B3 ^= T1; - B2 ^= T0 + T1; + u32bit B0 = load_be<u32bit>(in, 0); + u32bit B1 = load_be<u32bit>(in, 1); + u32bit B2 = load_be<u32bit>(in, 2); + u32bit B3 = load_be<u32bit>(in, 3); + + G_FUNC G; + + for(u32bit j = 0; j != 16; j += 2) + { + u32bit T0, T1; + + T0 = B2 ^ K[30-2*j]; + T1 = G(B2 ^ B3 ^ K[31-2*j]); + T0 = G(T1 + T0); + T1 = G(T1 + T0); + B1 ^= T1; + B0 ^= T0 + T1; + + T0 = B0 ^ K[28-2*j]; + T1 = G(B0 ^ B1 ^ K[29-2*j]); + T0 = G(T1 + T0); + T1 = G(T1 + T0); + B3 ^= T1; + B2 ^= T0 + T1; + } + + store_be(out, B2, B3, B0, B1); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; } - - store_be(out, B2, B3, B0, B1); } /* diff --git a/src/block/seed/seed.h b/src/block/seed/seed.h index 54c25d580..5a5a512e7 100644 --- a/src/block/seed/seed.h +++ b/src/block/seed/seed.h @@ -18,13 +18,15 @@ namespace Botan { class BOTAN_DLL SEED : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { K.clear(); } std::string name() const { return "SEED"; } BlockCipher* clone() const { return new SEED; } + SEED() : BlockCipher(16, 16) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); class G_FUNC diff --git a/src/block/serpent/info.txt b/src/block/serpent/info.txt index baaccbf01..4031a3f5f 100644 --- a/src/block/serpent/info.txt +++ b/src/block/serpent/info.txt @@ -1,10 +1,3 @@ realname "Serpent" define SERPENT - -load_on auto - -<add> -serpent.cpp -serpent.h -</add> diff --git a/src/block/serpent/serpent.cpp b/src/block/serpent/serpent.cpp index df7592fea..2fa27308f 100644 --- a/src/block/serpent/serpent.cpp +++ b/src/block/serpent/serpent.cpp @@ -243,93 +243,105 @@ inline void i_transform(u32bit& B0, u32bit& B1, u32bit& B2, u32bit& B3) /* * Serpent Encryption */ -void Serpent::enc(const byte in[], byte out[]) const +void Serpent::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit B0 = load_le<u32bit>(in, 0); - u32bit B1 = load_le<u32bit>(in, 1); - u32bit B2 = load_le<u32bit>(in, 2); - u32bit B3 = load_le<u32bit>(in, 3); - - key_xor( 0,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor( 1,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor( 2,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor( 3,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor( 4,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor( 5,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor( 6,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor( 7,B0,B1,B2,B3); SBoxE8(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor( 8,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor( 9,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(10,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(11,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(12,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(13,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(14,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(15,B0,B1,B2,B3); SBoxE8(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(16,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(17,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(18,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(19,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(20,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(21,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(22,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(23,B0,B1,B2,B3); SBoxE8(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(24,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(25,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(26,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(27,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(28,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(29,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(30,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(31,B0,B1,B2,B3); SBoxE8(B0,B1,B2,B3); key_xor(32,B0,B1,B2,B3); - - store_le(out, B0, B1, B2, B3); + for(u32bit i = 0; i != blocks; ++i) + { + u32bit B0 = load_le<u32bit>(in, 0); + u32bit B1 = load_le<u32bit>(in, 1); + u32bit B2 = load_le<u32bit>(in, 2); + u32bit B3 = load_le<u32bit>(in, 3); + + key_xor( 0,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 1,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 2,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 3,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 4,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 5,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 6,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 7,B0,B1,B2,B3); SBoxE8(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 8,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 9,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(10,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(11,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(12,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(13,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(14,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(15,B0,B1,B2,B3); SBoxE8(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(16,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(17,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(18,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(19,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(20,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(21,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(22,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(23,B0,B1,B2,B3); SBoxE8(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(24,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(25,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(26,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(27,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(28,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(29,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(30,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(31,B0,B1,B2,B3); SBoxE8(B0,B1,B2,B3); key_xor(32,B0,B1,B2,B3); + + store_le(out, B0, B1, B2, B3); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * Serpent Decryption */ -void Serpent::dec(const byte in[], byte out[]) const +void Serpent::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit B0 = load_le<u32bit>(in, 0); - u32bit B1 = load_le<u32bit>(in, 1); - u32bit B2 = load_le<u32bit>(in, 2); - u32bit B3 = load_le<u32bit>(in, 3); - - key_xor(32,B0,B1,B2,B3); SBoxD8(B0,B1,B2,B3); key_xor(31,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor(30,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor(29,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor(28,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor(27,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor(26,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor(25,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor(24,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD8(B0,B1,B2,B3); key_xor(23,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor(22,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor(21,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor(20,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor(19,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor(18,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor(17,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor(16,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD8(B0,B1,B2,B3); key_xor(15,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor(14,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor(13,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor(12,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor(11,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor(10,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor( 9,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor( 8,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD8(B0,B1,B2,B3); key_xor( 7,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor( 6,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor( 5,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor( 4,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor( 3,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor( 2,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor( 1,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor( 0,B0,B1,B2,B3); - - store_le(out, B0, B1, B2, B3); + for(u32bit i = 0; i != blocks; ++i) + { + u32bit B0 = load_le<u32bit>(in, 0); + u32bit B1 = load_le<u32bit>(in, 1); + u32bit B2 = load_le<u32bit>(in, 2); + u32bit B3 = load_le<u32bit>(in, 3); + + key_xor(32,B0,B1,B2,B3); SBoxD8(B0,B1,B2,B3); key_xor(31,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor(30,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor(29,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor(28,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor(27,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor(26,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor(25,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor(24,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD8(B0,B1,B2,B3); key_xor(23,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor(22,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor(21,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor(20,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor(19,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor(18,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor(17,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor(16,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD8(B0,B1,B2,B3); key_xor(15,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor(14,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor(13,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor(12,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor(11,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor(10,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor( 9,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor( 8,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD8(B0,B1,B2,B3); key_xor( 7,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor( 6,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor( 5,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor( 4,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor( 3,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor( 2,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor( 1,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor( 0,B0,B1,B2,B3); + + store_le(out, B0, B1, B2, B3); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/serpent/serpent.h b/src/block/serpent/serpent.h index 5b9be257f..d919c3008 100644 --- a/src/block/serpent/serpent.h +++ b/src/block/serpent/serpent.h @@ -18,13 +18,14 @@ namespace Botan { class BOTAN_DLL Serpent : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { round_key.clear(); } std::string name() const { return "Serpent"; } BlockCipher* clone() const { return new Serpent; } Serpent() : BlockCipher(16, 16, 32, 8) {} protected: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); SecureBuffer<u32bit, 132> round_key; diff --git a/src/block/serpent_ia32/info.txt b/src/block/serpent_ia32/info.txt index ea0506299..48d589724 100644 --- a/src/block/serpent_ia32/info.txt +++ b/src/block/serpent_ia32/info.txt @@ -4,12 +4,6 @@ define SERPENT_IA32 load_on asm_ok -<add> -serp_ia32_imp.S -serp_ia32.cpp -serp_ia32.h -</add> - <arch> ia32 </arch> diff --git a/src/block/serpent_ia32/serp_ia32.cpp b/src/block/serpent_ia32/serp_ia32.cpp index 37dd4e637..721584b18 100644 --- a/src/block/serpent_ia32/serp_ia32.cpp +++ b/src/block/serpent_ia32/serp_ia32.cpp @@ -21,17 +21,27 @@ void botan_serpent_ia32_key_schedule(u32bit[140]); /* * Serpent Encryption */ -void Serpent_IA32::enc(const byte in[], byte out[]) const +void Serpent_IA32::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - botan_serpent_ia32_encrypt(in, out, round_key); + for(u32bit i = 0; i != blocks; ++i) + { + botan_serpent_ia32_encrypt(in, out, round_key); + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * Serpent Decryption */ -void Serpent_IA32::dec(const byte in[], byte out[]) const +void Serpent_IA32::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - botan_serpent_ia32_decrypt(in, out, round_key); + for(u32bit i = 0; i != blocks; ++i) + { + botan_serpent_ia32_decrypt(in, out, round_key); + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* @@ -41,7 +51,7 @@ void Serpent_IA32::key_schedule(const byte key[], u32bit length) { SecureBuffer<u32bit, 140> W; for(u32bit j = 0; j != length / 4; ++j) - W[j] = make_u32bit(key[4*j+3], key[4*j+2], key[4*j+1], key[4*j]); + W[j] = load_le<u32bit>(key, j); W[length / 4] |= u32bit(1) << ((length%4)*8); botan_serpent_ia32_key_schedule(W); diff --git a/src/block/serpent_ia32/serp_ia32.h b/src/block/serpent_ia32/serp_ia32.h index 565e9889d..dc6beaf13 100644 --- a/src/block/serpent_ia32/serp_ia32.h +++ b/src/block/serpent_ia32/serp_ia32.h @@ -18,10 +18,11 @@ namespace Botan { class BOTAN_DLL Serpent_IA32 : public Serpent { 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 Serpent_IA32; } private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); }; diff --git a/src/block/serpent_sse2/info.txt b/src/block/serpent_sse2/info.txt new file mode 100644 index 000000000..da7eef6bc --- /dev/null +++ b/src/block/serpent_sse2/info.txt @@ -0,0 +1,8 @@ +realname "Serpent (SSE2)" + +define SERPENT_SSE2 + +<requires> +serpent +sse2_eng +</requires> diff --git a/src/block/serpent_sse2/serp_sse2.cpp b/src/block/serpent_sse2/serp_sse2.cpp new file mode 100644 index 000000000..c51bb69ab --- /dev/null +++ b/src/block/serpent_sse2/serp_sse2.cpp @@ -0,0 +1,240 @@ +/* +* Serpent (SSE2) +* (C) 2009 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/serp_sse2.h> +#include <botan/serp_sse2_sbox.h> +#include <botan/loadstor.h> +#include <emmintrin.h> + +namespace Botan { + +namespace { + +#define key_xor(round, B0, B1, B2, B3) \ + do { \ + __m128i key = _mm_loadu_si128(keys + round); \ + B0 = _mm_xor_si128(B0, _mm_shuffle_epi32(key, _MM_SHUFFLE(0,0,0,0))); \ + B1 = _mm_xor_si128(B1, _mm_shuffle_epi32(key, _MM_SHUFFLE(1,1,1,1))); \ + B2 = _mm_xor_si128(B2, _mm_shuffle_epi32(key, _MM_SHUFFLE(2,2,2,2))); \ + B3 = _mm_xor_si128(B3, _mm_shuffle_epi32(key, _MM_SHUFFLE(3,3,3,3))); \ + } while(0); + +/* +* Serpent's linear transformations +*/ +#define rotate_left_m128(vec, rot) \ + _mm_or_si128(_mm_slli_epi32(vec, rot), _mm_srli_epi32(vec, 32-rot)) + +#define rotate_right_m128(vec, rot) \ + _mm_or_si128(_mm_srli_epi32(vec, rot), _mm_slli_epi32(vec, 32-rot)) + +#define transform(B0, B1, B2, B3) \ + do { \ + B0 = rotate_left_m128(B0, 13); \ + B2 = rotate_left_m128(B2, 3); \ + B1 = _mm_xor_si128(B1, _mm_xor_si128(B0, B2)); \ + B3 = _mm_xor_si128(B3, _mm_xor_si128(B2, _mm_slli_epi32(B0, 3))); \ + B1 = rotate_left_m128(B1, 1); \ + B3 = rotate_left_m128(B3, 7); \ + B0 = _mm_xor_si128(B0, _mm_xor_si128(B1, B3)); \ + B2 = _mm_xor_si128(B2, _mm_xor_si128(B3, _mm_slli_epi32(B1, 7))); \ + B0 = rotate_left_m128(B0, 5); \ + B2 = rotate_left_m128(B2, 22); \ + } while(0); + +#define i_transform(B0, B1, B2, B3) \ + do { \ + B2 = rotate_right_m128(B2, 22); \ + B0 = rotate_right_m128(B0, 5); \ + B2 = _mm_xor_si128(B2, _mm_xor_si128(B3, _mm_slli_epi32(B1, 7))); \ + B0 = _mm_xor_si128(B0, _mm_xor_si128(B1, B3)); \ + B3 = rotate_right_m128(B3, 7); \ + B1 = rotate_right_m128(B1, 1); \ + B3 = _mm_xor_si128(B3, _mm_xor_si128(B2, _mm_slli_epi32(B0, 3))); \ + B1 = _mm_xor_si128(B1, _mm_xor_si128(B0, B2)); \ + B2 = rotate_right_m128(B2, 3); \ + B0 = rotate_right_m128(B0, 13); \ + } while(0); + +/* +* 4x4 SSE2 integer matrix transpose +*/ +#define transpose(B0, B1, B2, B3) \ + do { \ + __m128i T0 = _mm_unpacklo_epi32(B0, B1); \ + __m128i T1 = _mm_unpacklo_epi32(B2, B3); \ + __m128i T2 = _mm_unpackhi_epi32(B0, B1); \ + __m128i T3 = _mm_unpackhi_epi32(B2, B3); \ + B0 = _mm_unpacklo_epi64(T0, T1); \ + B1 = _mm_unpackhi_epi64(T0, T1); \ + B2 = _mm_unpacklo_epi64(T2, T3); \ + B3 = _mm_unpackhi_epi64(T2, T3); \ + } while(0); + +/* +* SSE2 Serpent Encryption of 4 blocks in parallel +*/ +void serpent_encrypt_4(const byte in[64], + byte out[64], + const u32bit keys_32[132]) + { + const __m128i all_ones = _mm_set1_epi8(0xFF); + + const __m128i* keys = (const __m128i*)(keys_32); + __m128i* out_mm = (__m128i*)(out); + __m128i* in_mm = (__m128i*)(in); + + __m128i B0 = _mm_loadu_si128(in_mm); + __m128i B1 = _mm_loadu_si128(in_mm + 1); + __m128i B2 = _mm_loadu_si128(in_mm + 2); + __m128i B3 = _mm_loadu_si128(in_mm + 3); + + transpose(B0, B1, B2, B3); + + key_xor( 0,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 1,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 2,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 3,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 4,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 5,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 6,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 7,B0,B1,B2,B3); SBoxE8(B0,B1,B2,B3); transform(B0,B1,B2,B3); + + key_xor( 8,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 9,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(10,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(11,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(12,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(13,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(14,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(15,B0,B1,B2,B3); SBoxE8(B0,B1,B2,B3); transform(B0,B1,B2,B3); + + key_xor(16,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(17,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(18,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(19,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(20,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(21,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(22,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(23,B0,B1,B2,B3); SBoxE8(B0,B1,B2,B3); transform(B0,B1,B2,B3); + + key_xor(24,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(25,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(26,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(27,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(28,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(29,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(30,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(31,B0,B1,B2,B3); SBoxE8(B0,B1,B2,B3); key_xor(32,B0,B1,B2,B3); + + transpose(B0, B1, B2, B3); + + _mm_storeu_si128(out_mm , B0); + _mm_storeu_si128(out_mm + 1, B1); + _mm_storeu_si128(out_mm + 2, B2); + _mm_storeu_si128(out_mm + 3, B3); + } + +/* +* SSE2 Serpent Decryption of 4 blocks in parallel +*/ +void serpent_decrypt_4(const byte in[64], + byte out[64], + const u32bit keys_32[132]) + { + const __m128i all_ones = _mm_set1_epi8(0xFF); + + const __m128i* keys = (const __m128i*)(keys_32); + __m128i* out_mm = (__m128i*)(out); + __m128i* in_mm = (__m128i*)(in); + + __m128i B0 = _mm_loadu_si128(in_mm); + __m128i B1 = _mm_loadu_si128(in_mm + 1); + __m128i B2 = _mm_loadu_si128(in_mm + 2); + __m128i B3 = _mm_loadu_si128(in_mm + 3); + + transpose(B0, B1, B2, B3); + + key_xor(32,B0,B1,B2,B3); SBoxD8(B0,B1,B2,B3); key_xor(31,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor(30,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor(29,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor(28,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor(27,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor(26,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor(25,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor(24,B0,B1,B2,B3); + + i_transform(B0,B1,B2,B3); SBoxD8(B0,B1,B2,B3); key_xor(23,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor(22,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor(21,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor(20,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor(19,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor(18,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor(17,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor(16,B0,B1,B2,B3); + + i_transform(B0,B1,B2,B3); SBoxD8(B0,B1,B2,B3); key_xor(15,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor(14,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor(13,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor(12,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor(11,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor(10,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor( 9,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor( 8,B0,B1,B2,B3); + + i_transform(B0,B1,B2,B3); SBoxD8(B0,B1,B2,B3); key_xor( 7,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor( 6,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor( 5,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor( 4,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor( 3,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor( 2,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor( 1,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor( 0,B0,B1,B2,B3); + + transpose(B0, B1, B2, B3); + + _mm_storeu_si128(out_mm , B0); + _mm_storeu_si128(out_mm + 1, B1); + _mm_storeu_si128(out_mm + 2, B2); + _mm_storeu_si128(out_mm + 3, B3); + } + +} + +/* +* Serpent Encryption +*/ +void Serpent_SSE2::encrypt_n(const byte in[], byte out[], u32bit blocks) const + { + while(blocks >= 4) + { + serpent_encrypt_4(in, out, this->round_key); + in += 4 * BLOCK_SIZE; + out += 4 * BLOCK_SIZE; + blocks -= 4; + } + + Serpent::encrypt_n(in, out, blocks); + } + +/* +* Serpent Decryption +*/ +void Serpent_SSE2::decrypt_n(const byte in[], byte out[], u32bit blocks) const + { + while(blocks >= 4) + { + serpent_decrypt_4(in, out, this->round_key); + in += 4 * BLOCK_SIZE; + out += 4 * BLOCK_SIZE; + blocks -= 4; + } + + Serpent::decrypt_n(in, out, blocks); + } + +} diff --git a/src/block/serpent_sse2/serp_sse2.h b/src/block/serpent_sse2/serp_sse2.h new file mode 100644 index 000000000..f1e5c2028 --- /dev/null +++ b/src/block/serpent_sse2/serp_sse2.h @@ -0,0 +1,29 @@ +/* +* Serpent (SSE2) +* (C) 2009 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_SERPENT_SSE2_H__ +#define BOTAN_SERPENT_SSE2_H__ + +#include <botan/serpent.h> + +namespace Botan { + +/* +* Serpent +*/ +class BOTAN_DLL Serpent_SSE2 : public Serpent + { + 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 Serpent_SSE2; } + }; + +} + +#endif diff --git a/src/block/serpent_sse2/serp_sse2_sbox.h b/src/block/serpent_sse2/serp_sse2_sbox.h new file mode 100644 index 000000000..40c552e87 --- /dev/null +++ b/src/block/serpent_sse2/serp_sse2_sbox.h @@ -0,0 +1,434 @@ +/* +* Serpent Sboxes in SSE2 form +* (C) 2009 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef SERPENT_SSE2_SBOXES_H__ +#define SERPENT_SSE2_SBOXES_H__ + +#define SBoxE1(B0, B1, B2, B3) \ + do { \ + B3 = _mm_xor_si128(B3, B0); \ + __m128i B4 = B1; \ + B1 = _mm_and_si128(B1, B3); \ + B4 = _mm_xor_si128(B4, B2); \ + B1 = _mm_xor_si128(B1, B0); \ + B0 = _mm_or_si128(B0, B3); \ + B0 = _mm_xor_si128(B0, B4); \ + B4 = _mm_xor_si128(B4, B3); \ + B3 = _mm_xor_si128(B3, B2); \ + B2 = _mm_or_si128(B2, B1); \ + B2 = _mm_xor_si128(B2, B4); \ + B4 = _mm_xor_si128(B4, all_ones); \ + B4 = _mm_or_si128(B4, B1); \ + B1 = _mm_xor_si128(B1, B3); \ + B1 = _mm_xor_si128(B1, B4); \ + B3 = _mm_or_si128(B3, B0); \ + B1 = _mm_xor_si128(B1, B3); \ + B4 = _mm_xor_si128(B4, B3); \ + B3 = B0; \ + B0 = B1; \ + B1 = B4; \ + } while(0); + +#define SBoxE2(B0, B1, B2, B3) \ + do { \ + B0 = _mm_xor_si128(B0, all_ones); \ + B2 = _mm_xor_si128(B2, all_ones); \ + __m128i B4 = B0; \ + B0 = _mm_and_si128(B0, B1); \ + B2 = _mm_xor_si128(B2, B0); \ + B0 = _mm_or_si128(B0, B3); \ + B3 = _mm_xor_si128(B3, B2); \ + B1 = _mm_xor_si128(B1, B0); \ + B0 = _mm_xor_si128(B0, B4); \ + B4 = _mm_or_si128(B4, B1); \ + B1 = _mm_xor_si128(B1, B3); \ + B2 = _mm_or_si128(B2, B0); \ + B2 = _mm_and_si128(B2, B4); \ + B0 = _mm_xor_si128(B0, B1); \ + B1 = _mm_and_si128(B1, B2); \ + B1 = _mm_xor_si128(B1, B0); \ + B0 = _mm_and_si128(B0, B2); \ + B4 = _mm_xor_si128(B4, B0); \ + B0 = B2; \ + B2 = B3; \ + B3 = B1; \ + B1 = B4; \ + } while(0); + +#define SBoxE3(B0, B1, B2, B3) \ + do { \ + __m128i B4 = B0; \ + B0 = _mm_and_si128(B0, B2); \ + B0 = _mm_xor_si128(B0, B3); \ + B2 = _mm_xor_si128(B2, B1); \ + B2 = _mm_xor_si128(B2, B0); \ + B3 = _mm_or_si128(B3, B4); \ + B3 = _mm_xor_si128(B3, B1); \ + B4 = _mm_xor_si128(B4, B2); \ + B1 = B3; \ + B3 = _mm_or_si128(B3, B4); \ + B3 = _mm_xor_si128(B3, B0); \ + B0 = _mm_and_si128(B0, B1); \ + B4 = _mm_xor_si128(B4, B0); \ + B1 = _mm_xor_si128(B1, B3); \ + B1 = _mm_xor_si128(B1, B4); \ + B4 = _mm_xor_si128(B4, all_ones); \ + B0 = B2; \ + B2 = B1; \ + B1 = B3; \ + B3 = B4; \ + } while(0); + +#define SBoxE4(B0, B1, B2, B3) \ + do { \ + __m128i B4 = B0; \ + B0 = _mm_or_si128(B0, B3); \ + B3 = _mm_xor_si128(B3, B1); \ + B1 = _mm_and_si128(B1, B4); \ + B4 = _mm_xor_si128(B4, B2); \ + B2 = _mm_xor_si128(B2, B3); \ + B3 = _mm_and_si128(B3, B0); \ + B4 = _mm_or_si128(B4, B1); \ + B3 = _mm_xor_si128(B3, B4); \ + B0 = _mm_xor_si128(B0, B1); \ + B4 = _mm_and_si128(B4, B0); \ + B1 = _mm_xor_si128(B1, B3); \ + B4 = _mm_xor_si128(B4, B2); \ + B1 = _mm_or_si128(B1, B0); \ + B1 = _mm_xor_si128(B1, B2); \ + B0 = _mm_xor_si128(B0, B3); \ + B2 = B1; \ + B1 = _mm_or_si128(B1, B3); \ + B0 = _mm_xor_si128(B0, B1); \ + B1 = B2; \ + B2 = B3; \ + B3 = B4; \ + } while(0); + +#define SBoxE5(B0, B1, B2, B3) \ + do { \ + B1 = _mm_xor_si128(B1, B3); \ + B3 = _mm_xor_si128(B3, all_ones); \ + B2 = _mm_xor_si128(B2, B3); \ + B3 = _mm_xor_si128(B3, B0); \ + __m128i B4 = B1; \ + B1 = _mm_and_si128(B1, B3); \ + B1 = _mm_xor_si128(B1, B2); \ + B4 = _mm_xor_si128(B4, B3); \ + B0 = _mm_xor_si128(B0, B4); \ + B2 = _mm_and_si128(B2, B4); \ + B2 = _mm_xor_si128(B2, B0); \ + B0 = _mm_and_si128(B0, B1); \ + B3 = _mm_xor_si128(B3, B0); \ + B4 = _mm_or_si128(B4, B1); \ + B4 = _mm_xor_si128(B4, B0); \ + B0 = _mm_or_si128(B0, B3); \ + B0 = _mm_xor_si128(B0, B2); \ + B2 = _mm_and_si128(B2, B3); \ + B0 = _mm_xor_si128(B0, all_ones); \ + B4 = _mm_xor_si128(B4, B2); \ + B2 = B0; \ + B0 = B1; \ + B1 = B4; \ + } while(0); + +#define SBoxE6(B0, B1, B2, B3) \ + do { \ + B0 = _mm_xor_si128(B0, B1); \ + B1 = _mm_xor_si128(B1, B3); \ + B3 = _mm_xor_si128(B3, all_ones); \ + __m128i B4 = B1; \ + B1 = _mm_and_si128(B1, B0); \ + B2 = _mm_xor_si128(B2, B3); \ + B1 = _mm_xor_si128(B1, B2); \ + B2 = _mm_or_si128(B2, B4); \ + B4 = _mm_xor_si128(B4, B3); \ + B3 = _mm_and_si128(B3, B1); \ + B3 = _mm_xor_si128(B3, B0); \ + B4 = _mm_xor_si128(B4, B1); \ + B4 = _mm_xor_si128(B4, B2); \ + B2 = _mm_xor_si128(B2, B0); \ + B0 = _mm_and_si128(B0, B3); \ + B2 = _mm_xor_si128(B2, all_ones); \ + B0 = _mm_xor_si128(B0, B4); \ + B4 = _mm_or_si128(B4, B3); \ + B4 = _mm_xor_si128(B4, B2); \ + B2 = B0; \ + B0 = B1; \ + B1 = B3; \ + B3 = B4; \ + } while(0); + +#define SBoxE7(B0, B1, B2, B3) \ + do { \ + B2 = _mm_xor_si128(B2, all_ones); \ + __m128i B4 = B3; \ + B3 = _mm_and_si128(B3, B0); \ + B0 = _mm_xor_si128(B0, B4); \ + B3 = _mm_xor_si128(B3, B2); \ + B2 = _mm_or_si128(B2, B4); \ + B1 = _mm_xor_si128(B1, B3); \ + B2 = _mm_xor_si128(B2, B0); \ + B0 = _mm_or_si128(B0, B1); \ + B2 = _mm_xor_si128(B2, B1); \ + B4 = _mm_xor_si128(B4, B0); \ + B0 = _mm_or_si128(B0, B3); \ + B0 = _mm_xor_si128(B0, B2); \ + B4 = _mm_xor_si128(B4, B3); \ + B4 = _mm_xor_si128(B4, B0); \ + B3 = _mm_xor_si128(B3, all_ones); \ + B2 = _mm_and_si128(B2, B4); \ + B3 = _mm_xor_si128(B3, B2); \ + B2 = B4; \ + } while(0); + +#define SBoxE8(B0, B1, B2, B3) \ + do { \ + __m128i B4 = B1; \ + B1 = _mm_or_si128(B1, B2); \ + B1 = _mm_xor_si128(B1, B3); \ + B4 = _mm_xor_si128(B4, B2); \ + B2 = _mm_xor_si128(B2, B1); \ + B3 = _mm_or_si128(B3, B4); \ + B3 = _mm_and_si128(B3, B0); \ + B4 = _mm_xor_si128(B4, B2); \ + B3 = _mm_xor_si128(B3, B1); \ + B1 = _mm_or_si128(B1, B4); \ + B1 = _mm_xor_si128(B1, B0); \ + B0 = _mm_or_si128(B0, B4); \ + B0 = _mm_xor_si128(B0, B2); \ + B1 = _mm_xor_si128(B1, B4); \ + B2 = _mm_xor_si128(B2, B1); \ + B1 = _mm_and_si128(B1, B0); \ + B1 = _mm_xor_si128(B1, B4); \ + B2 = _mm_xor_si128(B2, all_ones); \ + B2 = _mm_or_si128(B2, B0); \ + B4 = _mm_xor_si128(B4, B2); \ + B2 = B1; \ + B1 = B3; \ + B3 = B0; \ + B0 = B4; \ + } while(0); + +#define SBoxD1(B0, B1, B2, B3) \ + do \ + { \ + B2 = _mm_xor_si128(B2, all_ones); \ + __m128i B4 = B1; \ + B1 = _mm_or_si128(B1, B0); \ + B4 = _mm_xor_si128(B4, all_ones); \ + B1 = _mm_xor_si128(B1, B2); \ + B2 = _mm_or_si128(B2, B4); \ + B1 = _mm_xor_si128(B1, B3); \ + B0 = _mm_xor_si128(B0, B4); \ + B2 = _mm_xor_si128(B2, B0); \ + B0 = _mm_and_si128(B0, B3); \ + B4 = _mm_xor_si128(B4, B0); \ + B0 = _mm_or_si128(B0, B1); \ + B0 = _mm_xor_si128(B0, B2); \ + B3 = _mm_xor_si128(B3, B4); \ + B2 = _mm_xor_si128(B2, B1); \ + B3 = _mm_xor_si128(B3, B0); \ + B3 = _mm_xor_si128(B3, B1); \ + B2 = _mm_and_si128(B2, B3); \ + B4 = _mm_xor_si128(B4, B2); \ + B2 = B1; \ + B1 = B4; \ + } while(0); + +#define SBoxD2(B0, B1, B2, B3) \ + do \ + { \ + __m128i B4 = B1; \ + B1 = _mm_xor_si128(B1, B3); \ + B3 = _mm_and_si128(B3, B1); \ + B4 = _mm_xor_si128(B4, B2); \ + B3 = _mm_xor_si128(B3, B0); \ + B0 = _mm_or_si128(B0, B1); \ + B2 = _mm_xor_si128(B2, B3); \ + B0 = _mm_xor_si128(B0, B4); \ + B0 = _mm_or_si128(B0, B2); \ + B1 = _mm_xor_si128(B1, B3); \ + B0 = _mm_xor_si128(B0, B1); \ + B1 = _mm_or_si128(B1, B3); \ + B1 = _mm_xor_si128(B1, B0); \ + B4 = _mm_xor_si128(B4, all_ones); \ + B4 = _mm_xor_si128(B4, B1); \ + B1 = _mm_or_si128(B1, B0); \ + B1 = _mm_xor_si128(B1, B0); \ + B1 = _mm_or_si128(B1, B4); \ + B3 = _mm_xor_si128(B3, B1); \ + B1 = B0; \ + B0 = B4; \ + B4 = B2; \ + B2 = B3; \ + B3 = B4; \ + } while(0); + +#define SBoxD3(B0, B1, B2, B3) \ + do \ + { \ + B2 = _mm_xor_si128(B2, B3); \ + B3 = _mm_xor_si128(B3, B0); \ + __m128i B4 = B3; \ + B3 = _mm_and_si128(B3, B2); \ + B3 = _mm_xor_si128(B3, B1); \ + B1 = _mm_or_si128(B1, B2); \ + B1 = _mm_xor_si128(B1, B4); \ + B4 = _mm_and_si128(B4, B3); \ + B2 = _mm_xor_si128(B2, B3); \ + B4 = _mm_and_si128(B4, B0); \ + B4 = _mm_xor_si128(B4, B2); \ + B2 = _mm_and_si128(B2, B1); \ + B2 = _mm_or_si128(B2, B0); \ + B3 = _mm_xor_si128(B3, all_ones); \ + B2 = _mm_xor_si128(B2, B3); \ + B0 = _mm_xor_si128(B0, B3); \ + B0 = _mm_and_si128(B0, B1); \ + B3 = _mm_xor_si128(B3, B4); \ + B3 = _mm_xor_si128(B3, B0); \ + B0 = B1; \ + B1 = B4; \ + } while(0); + +#define SBoxD4(B0, B1, B2, B3) \ + do \ + { \ + __m128i B4 = B2; \ + B2 = _mm_xor_si128(B2, B1); \ + B0 = _mm_xor_si128(B0, B2); \ + B4 = _mm_and_si128(B4, B2); \ + B4 = _mm_xor_si128(B4, B0); \ + B0 = _mm_and_si128(B0, B1); \ + B1 = _mm_xor_si128(B1, B3); \ + B3 = _mm_or_si128(B3, B4); \ + B2 = _mm_xor_si128(B2, B3); \ + B0 = _mm_xor_si128(B0, B3); \ + B1 = _mm_xor_si128(B1, B4); \ + B3 = _mm_and_si128(B3, B2); \ + B3 = _mm_xor_si128(B3, B1); \ + B1 = _mm_xor_si128(B1, B0); \ + B1 = _mm_or_si128(B1, B2); \ + B0 = _mm_xor_si128(B0, B3); \ + B1 = _mm_xor_si128(B1, B4); \ + B0 = _mm_xor_si128(B0, B1); \ + B4 = B0; \ + B0 = B2; \ + B2 = B3; \ + B3 = B4; \ + } while(0); + +#define SBoxD5(B0, B1, B2, B3) \ + do \ + { \ + __m128i B4 = B2; \ + B2 = _mm_and_si128(B2, B3); \ + B2 = _mm_xor_si128(B2, B1); \ + B1 = _mm_or_si128(B1, B3); \ + B1 = _mm_and_si128(B1, B0); \ + B4 = _mm_xor_si128(B4, B2); \ + B4 = _mm_xor_si128(B4, B1); \ + B1 = _mm_and_si128(B1, B2); \ + B0 = _mm_xor_si128(B0, all_ones); \ + B3 = _mm_xor_si128(B3, B4); \ + B1 = _mm_xor_si128(B1, B3); \ + B3 = _mm_and_si128(B3, B0); \ + B3 = _mm_xor_si128(B3, B2); \ + B0 = _mm_xor_si128(B0, B1); \ + B2 = _mm_and_si128(B2, B0); \ + B3 = _mm_xor_si128(B3, B0); \ + B2 = _mm_xor_si128(B2, B4); \ + B2 = _mm_or_si128(B2, B3); \ + B3 = _mm_xor_si128(B3, B0); \ + B2 = _mm_xor_si128(B2, B1); \ + B1 = B3; \ + B3 = B4; \ + } while(0); + +#define SBoxD6(B0, B1, B2, B3) \ + do \ + { \ + B1 = _mm_xor_si128(B1, all_ones); \ + __m128i B4 = B3; \ + B2 = _mm_xor_si128(B2, B1); \ + B3 = _mm_or_si128(B3, B0); \ + B3 = _mm_xor_si128(B3, B2); \ + B2 = _mm_or_si128(B2, B1); \ + B2 = _mm_and_si128(B2, B0); \ + B4 = _mm_xor_si128(B4, B3); \ + B2 = _mm_xor_si128(B2, B4); \ + B4 = _mm_or_si128(B4, B0); \ + B4 = _mm_xor_si128(B4, B1); \ + B1 = _mm_and_si128(B1, B2); \ + B1 = _mm_xor_si128(B1, B3); \ + B4 = _mm_xor_si128(B4, B2); \ + B3 = _mm_and_si128(B3, B4); \ + B4 = _mm_xor_si128(B4, B1); \ + B3 = _mm_xor_si128(B3, B4); \ + B4 = _mm_xor_si128(B4, all_ones); \ + B3 = _mm_xor_si128(B3, B0); \ + B0 = B1; \ + B1 = B4; \ + B4 = B3; \ + B3 = B2; \ + B2 = B4; \ + } while(0); + +#define SBoxD7(B0, B1, B2, B3) \ + do \ + { \ + B0 = _mm_xor_si128(B0, B2); \ + __m128i B4 = B2; \ + B2 = _mm_and_si128(B2, B0); \ + B4 = _mm_xor_si128(B4, B3); \ + B2 = _mm_xor_si128(B2, all_ones); \ + B3 = _mm_xor_si128(B3, B1); \ + B2 = _mm_xor_si128(B2, B3); \ + B4 = _mm_or_si128(B4, B0); \ + B0 = _mm_xor_si128(B0, B2); \ + B3 = _mm_xor_si128(B3, B4); \ + B4 = _mm_xor_si128(B4, B1); \ + B1 = _mm_and_si128(B1, B3); \ + B1 = _mm_xor_si128(B1, B0); \ + B0 = _mm_xor_si128(B0, B3); \ + B0 = _mm_or_si128(B0, B2); \ + B3 = _mm_xor_si128(B3, B1); \ + B4 = _mm_xor_si128(B4, B0); \ + B0 = B1; \ + B1 = B2; \ + B2 = B4; \ + } while(0); + +#define SBoxD8(B0, B1, B2, B3) \ + do \ + { \ + __m128i B4 = B2; \ + B2 = _mm_xor_si128(B2, B0); \ + B0 = _mm_and_si128(B0, B3); \ + B4 = _mm_or_si128(B4, B3); \ + B2 = _mm_xor_si128(B2, all_ones); \ + B3 = _mm_xor_si128(B3, B1); \ + B1 = _mm_or_si128(B1, B0); \ + B0 = _mm_xor_si128(B0, B2); \ + B2 = _mm_and_si128(B2, B4); \ + B3 = _mm_and_si128(B3, B4); \ + B1 = _mm_xor_si128(B1, B2); \ + B2 = _mm_xor_si128(B2, B0); \ + B0 = _mm_or_si128(B0, B2); \ + B4 = _mm_xor_si128(B4, B1); \ + B0 = _mm_xor_si128(B0, B3); \ + B3 = _mm_xor_si128(B3, B4); \ + B4 = _mm_or_si128(B4, B0); \ + B3 = _mm_xor_si128(B3, B2); \ + B4 = _mm_xor_si128(B4, B2); \ + B2 = B1; \ + B1 = B0; \ + B0 = B3; \ + B3 = B4; \ + } while(0); + +#endif diff --git a/src/block/skipjack/info.txt b/src/block/skipjack/info.txt index 4b38d6d28..9cdddfe6b 100644 --- a/src/block/skipjack/info.txt +++ b/src/block/skipjack/info.txt @@ -1,10 +1,3 @@ realname "Skipjack" define SKIPJACK - -load_on auto - -<add> -skipjack.cpp -skipjack.h -</add> diff --git a/src/block/skipjack/skipjack.cpp b/src/block/skipjack/skipjack.cpp index f5ffc861e..6c308c0f8 100644 --- a/src/block/skipjack/skipjack.cpp +++ b/src/block/skipjack/skipjack.cpp @@ -13,51 +13,63 @@ namespace Botan { /* * Skipjack Encryption */ -void Skipjack::enc(const byte in[], byte out[]) const +void Skipjack::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u16bit W1 = load_le<u16bit>(in, 3); - u16bit W2 = load_le<u16bit>(in, 2); - u16bit W3 = load_le<u16bit>(in, 1); - u16bit W4 = load_le<u16bit>(in, 0); + for(u32bit i = 0; i != blocks; ++i) + { + u16bit W1 = load_le<u16bit>(in, 3); + u16bit W2 = load_le<u16bit>(in, 2); + u16bit W3 = load_le<u16bit>(in, 1); + u16bit W4 = load_le<u16bit>(in, 0); - step_A(W1,W4, 1); step_A(W4,W3, 2); step_A(W3,W2, 3); step_A(W2,W1, 4); - step_A(W1,W4, 5); step_A(W4,W3, 6); step_A(W3,W2, 7); step_A(W2,W1, 8); + step_A(W1,W4, 1); step_A(W4,W3, 2); step_A(W3,W2, 3); step_A(W2,W1, 4); + step_A(W1,W4, 5); step_A(W4,W3, 6); step_A(W3,W2, 7); step_A(W2,W1, 8); - step_B(W1,W2, 9); step_B(W4,W1,10); step_B(W3,W4,11); step_B(W2,W3,12); - step_B(W1,W2,13); step_B(W4,W1,14); step_B(W3,W4,15); step_B(W2,W3,16); + step_B(W1,W2, 9); step_B(W4,W1,10); step_B(W3,W4,11); step_B(W2,W3,12); + step_B(W1,W2,13); step_B(W4,W1,14); step_B(W3,W4,15); step_B(W2,W3,16); - step_A(W1,W4,17); step_A(W4,W3,18); step_A(W3,W2,19); step_A(W2,W1,20); - step_A(W1,W4,21); step_A(W4,W3,22); step_A(W3,W2,23); step_A(W2,W1,24); + step_A(W1,W4,17); step_A(W4,W3,18); step_A(W3,W2,19); step_A(W2,W1,20); + step_A(W1,W4,21); step_A(W4,W3,22); step_A(W3,W2,23); step_A(W2,W1,24); - step_B(W1,W2,25); step_B(W4,W1,26); step_B(W3,W4,27); step_B(W2,W3,28); - step_B(W1,W2,29); step_B(W4,W1,30); step_B(W3,W4,31); step_B(W2,W3,32); + step_B(W1,W2,25); step_B(W4,W1,26); step_B(W3,W4,27); step_B(W2,W3,28); + step_B(W1,W2,29); step_B(W4,W1,30); step_B(W3,W4,31); step_B(W2,W3,32); - store_le(out, W4, W3, W2, W1); + store_le(out, W4, W3, W2, W1); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * Skipjack Decryption */ -void Skipjack::dec(const byte in[], byte out[]) const +void Skipjack::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u16bit W1 = load_le<u16bit>(in, 3); - u16bit W2 = load_le<u16bit>(in, 2); - u16bit W3 = load_le<u16bit>(in, 1); - u16bit W4 = load_le<u16bit>(in, 0); + for(u32bit i = 0; i != blocks; ++i) + { + u16bit W1 = load_le<u16bit>(in, 3); + u16bit W2 = load_le<u16bit>(in, 2); + u16bit W3 = load_le<u16bit>(in, 1); + u16bit W4 = load_le<u16bit>(in, 0); + + step_Bi(W2,W3,32); step_Bi(W3,W4,31); step_Bi(W4,W1,30); step_Bi(W1,W2,29); + step_Bi(W2,W3,28); step_Bi(W3,W4,27); step_Bi(W4,W1,26); step_Bi(W1,W2,25); - step_Bi(W2,W3,32); step_Bi(W3,W4,31); step_Bi(W4,W1,30); step_Bi(W1,W2,29); - step_Bi(W2,W3,28); step_Bi(W3,W4,27); step_Bi(W4,W1,26); step_Bi(W1,W2,25); + step_Ai(W1,W2,24); step_Ai(W2,W3,23); step_Ai(W3,W4,22); step_Ai(W4,W1,21); + step_Ai(W1,W2,20); step_Ai(W2,W3,19); step_Ai(W3,W4,18); step_Ai(W4,W1,17); - step_Ai(W1,W2,24); step_Ai(W2,W3,23); step_Ai(W3,W4,22); step_Ai(W4,W1,21); - step_Ai(W1,W2,20); step_Ai(W2,W3,19); step_Ai(W3,W4,18); step_Ai(W4,W1,17); + step_Bi(W2,W3,16); step_Bi(W3,W4,15); step_Bi(W4,W1,14); step_Bi(W1,W2,13); + step_Bi(W2,W3,12); step_Bi(W3,W4,11); step_Bi(W4,W1,10); step_Bi(W1,W2, 9); - step_Bi(W2,W3,16); step_Bi(W3,W4,15); step_Bi(W4,W1,14); step_Bi(W1,W2,13); - step_Bi(W2,W3,12); step_Bi(W3,W4,11); step_Bi(W4,W1,10); step_Bi(W1,W2, 9); + step_Ai(W1,W2, 8); step_Ai(W2,W3, 7); step_Ai(W3,W4, 6); step_Ai(W4,W1, 5); + step_Ai(W1,W2, 4); step_Ai(W2,W3, 3); step_Ai(W3,W4, 2); step_Ai(W4,W1, 1); - step_Ai(W1,W2, 8); step_Ai(W2,W3, 7); step_Ai(W3,W4, 6); step_Ai(W4,W1, 5); - step_Ai(W1,W2, 4); step_Ai(W2,W3, 3); step_Ai(W3,W4, 2); step_Ai(W4,W1, 1); + store_le(out, W4, W3, W2, W1); - store_le(out, W4, W3, W2, W1); + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/skipjack/skipjack.h b/src/block/skipjack/skipjack.h index 231cd9c87..f12032f36 100644 --- a/src/block/skipjack/skipjack.h +++ b/src/block/skipjack/skipjack.h @@ -18,18 +18,21 @@ namespace Botan { class BOTAN_DLL Skipjack : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw(); std::string name() const { return "Skipjack"; } BlockCipher* clone() const { return new Skipjack; } + Skipjack() : BlockCipher(8, 10) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); void step_A(u16bit&, u16bit&, u32bit) const; void step_B(u16bit&, u16bit&, u32bit) const; void step_Ai(u16bit&, u16bit&, u32bit) const; void step_Bi(u16bit&, u16bit&, u32bit) const; + SecureBuffer<byte, 256> FTABLE[10]; }; diff --git a/src/block/square/info.txt b/src/block/square/info.txt index a20697923..7c517be71 100644 --- a/src/block/square/info.txt +++ b/src/block/square/info.txt @@ -1,11 +1,3 @@ realname "Square" define SQUARE - -load_on auto - -<add> -sqr_tab.cpp -square.cpp -square.h -</add> diff --git a/src/block/square/square.cpp b/src/block/square/square.cpp index cb226542d..fdd47d3b2 100644 --- a/src/block/square/square.cpp +++ b/src/block/square/square.cpp @@ -14,103 +14,123 @@ namespace Botan { /* * Square Encryption */ -void Square::enc(const byte in[], byte out[]) const +void Square::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit T0, T1, T2, T3, B0, B1, B2, B3; - B0 = TE0[in[ 0] ^ ME[ 0]] ^ TE1[in[ 4] ^ ME[ 4]] ^ - TE2[in[ 8] ^ ME[ 8]] ^ TE3[in[12] ^ ME[12]] ^ EK[0]; - B1 = TE0[in[ 1] ^ ME[ 1]] ^ TE1[in[ 5] ^ ME[ 5]] ^ - TE2[in[ 9] ^ ME[ 9]] ^ TE3[in[13] ^ ME[13]] ^ EK[1]; - B2 = TE0[in[ 2] ^ ME[ 2]] ^ TE1[in[ 6] ^ ME[ 6]] ^ - TE2[in[10] ^ ME[10]] ^ TE3[in[14] ^ ME[14]] ^ EK[2]; - B3 = TE0[in[ 3] ^ ME[ 3]] ^ TE1[in[ 7] ^ ME[ 7]] ^ - TE2[in[11] ^ ME[11]] ^ TE3[in[15] ^ ME[15]] ^ EK[3]; - for(u32bit j = 1; j != 7; j += 2) + for(u32bit i = 0; i != blocks; ++i) { - T0 = TE0[get_byte(0, B0)] ^ TE1[get_byte(0, B1)] ^ - TE2[get_byte(0, B2)] ^ TE3[get_byte(0, B3)] ^ EK[4*j+0]; - T1 = TE0[get_byte(1, B0)] ^ TE1[get_byte(1, B1)] ^ - TE2[get_byte(1, B2)] ^ TE3[get_byte(1, B3)] ^ EK[4*j+1]; - T2 = TE0[get_byte(2, B0)] ^ TE1[get_byte(2, B1)] ^ - TE2[get_byte(2, B2)] ^ TE3[get_byte(2, B3)] ^ EK[4*j+2]; - T3 = TE0[get_byte(3, B0)] ^ TE1[get_byte(3, B1)] ^ - TE2[get_byte(3, B2)] ^ TE3[get_byte(3, B3)] ^ EK[4*j+3]; - B0 = TE0[get_byte(0, T0)] ^ TE1[get_byte(0, T1)] ^ - TE2[get_byte(0, T2)] ^ TE3[get_byte(0, T3)] ^ EK[4*j+4]; - B1 = TE0[get_byte(1, T0)] ^ TE1[get_byte(1, T1)] ^ - TE2[get_byte(1, T2)] ^ TE3[get_byte(1, T3)] ^ EK[4*j+5]; - B2 = TE0[get_byte(2, T0)] ^ TE1[get_byte(2, T1)] ^ - TE2[get_byte(2, T2)] ^ TE3[get_byte(2, T3)] ^ EK[4*j+6]; - B3 = TE0[get_byte(3, T0)] ^ TE1[get_byte(3, T1)] ^ - TE2[get_byte(3, T2)] ^ TE3[get_byte(3, T3)] ^ EK[4*j+7]; + u32bit T0, T1, T2, T3, B0, B1, B2, B3; + + B0 = TE0[in[ 0] ^ ME[ 0]] ^ TE1[in[ 4] ^ ME[ 4]] ^ + TE2[in[ 8] ^ ME[ 8]] ^ TE3[in[12] ^ ME[12]] ^ EK[0]; + B1 = TE0[in[ 1] ^ ME[ 1]] ^ TE1[in[ 5] ^ ME[ 5]] ^ + TE2[in[ 9] ^ ME[ 9]] ^ TE3[in[13] ^ ME[13]] ^ EK[1]; + B2 = TE0[in[ 2] ^ ME[ 2]] ^ TE1[in[ 6] ^ ME[ 6]] ^ + TE2[in[10] ^ ME[10]] ^ TE3[in[14] ^ ME[14]] ^ EK[2]; + B3 = TE0[in[ 3] ^ ME[ 3]] ^ TE1[in[ 7] ^ ME[ 7]] ^ + TE2[in[11] ^ ME[11]] ^ TE3[in[15] ^ ME[15]] ^ EK[3]; + + for(u32bit j = 1; j != 7; j += 2) + { + T0 = TE0[get_byte(0, B0)] ^ TE1[get_byte(0, B1)] ^ + TE2[get_byte(0, B2)] ^ TE3[get_byte(0, B3)] ^ EK[4*j+0]; + T1 = TE0[get_byte(1, B0)] ^ TE1[get_byte(1, B1)] ^ + TE2[get_byte(1, B2)] ^ TE3[get_byte(1, B3)] ^ EK[4*j+1]; + T2 = TE0[get_byte(2, B0)] ^ TE1[get_byte(2, B1)] ^ + TE2[get_byte(2, B2)] ^ TE3[get_byte(2, B3)] ^ EK[4*j+2]; + T3 = TE0[get_byte(3, B0)] ^ TE1[get_byte(3, B1)] ^ + TE2[get_byte(3, B2)] ^ TE3[get_byte(3, B3)] ^ EK[4*j+3]; + + B0 = TE0[get_byte(0, T0)] ^ TE1[get_byte(0, T1)] ^ + TE2[get_byte(0, T2)] ^ TE3[get_byte(0, T3)] ^ EK[4*j+4]; + B1 = TE0[get_byte(1, T0)] ^ TE1[get_byte(1, T1)] ^ + TE2[get_byte(1, T2)] ^ TE3[get_byte(1, T3)] ^ EK[4*j+5]; + B2 = TE0[get_byte(2, T0)] ^ TE1[get_byte(2, T1)] ^ + TE2[get_byte(2, T2)] ^ TE3[get_byte(2, T3)] ^ EK[4*j+6]; + B3 = TE0[get_byte(3, T0)] ^ TE1[get_byte(3, T1)] ^ + TE2[get_byte(3, T2)] ^ TE3[get_byte(3, T3)] ^ EK[4*j+7]; + } + + out[ 0] = SE[get_byte(0, B0)] ^ ME[16]; + out[ 1] = SE[get_byte(0, B1)] ^ ME[17]; + out[ 2] = SE[get_byte(0, B2)] ^ ME[18]; + out[ 3] = SE[get_byte(0, B3)] ^ ME[19]; + out[ 4] = SE[get_byte(1, B0)] ^ ME[20]; + out[ 5] = SE[get_byte(1, B1)] ^ ME[21]; + out[ 6] = SE[get_byte(1, B2)] ^ ME[22]; + out[ 7] = SE[get_byte(1, B3)] ^ ME[23]; + out[ 8] = SE[get_byte(2, B0)] ^ ME[24]; + out[ 9] = SE[get_byte(2, B1)] ^ ME[25]; + out[10] = SE[get_byte(2, B2)] ^ ME[26]; + out[11] = SE[get_byte(2, B3)] ^ ME[27]; + out[12] = SE[get_byte(3, B0)] ^ ME[28]; + out[13] = SE[get_byte(3, B1)] ^ ME[29]; + out[14] = SE[get_byte(3, B2)] ^ ME[30]; + out[15] = SE[get_byte(3, B3)] ^ ME[31]; + + in += BLOCK_SIZE; + out += BLOCK_SIZE; } - out[ 0] = SE[get_byte(0, B0)] ^ ME[16]; - out[ 1] = SE[get_byte(0, B1)] ^ ME[17]; - out[ 2] = SE[get_byte(0, B2)] ^ ME[18]; - out[ 3] = SE[get_byte(0, B3)] ^ ME[19]; - out[ 4] = SE[get_byte(1, B0)] ^ ME[20]; - out[ 5] = SE[get_byte(1, B1)] ^ ME[21]; - out[ 6] = SE[get_byte(1, B2)] ^ ME[22]; - out[ 7] = SE[get_byte(1, B3)] ^ ME[23]; - out[ 8] = SE[get_byte(2, B0)] ^ ME[24]; - out[ 9] = SE[get_byte(2, B1)] ^ ME[25]; - out[10] = SE[get_byte(2, B2)] ^ ME[26]; - out[11] = SE[get_byte(2, B3)] ^ ME[27]; - out[12] = SE[get_byte(3, B0)] ^ ME[28]; - out[13] = SE[get_byte(3, B1)] ^ ME[29]; - out[14] = SE[get_byte(3, B2)] ^ ME[30]; - out[15] = SE[get_byte(3, B3)] ^ ME[31]; } /* * Square Decryption */ -void Square::dec(const byte in[], byte out[]) const +void Square::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit T0, T1, T2, T3, B0, B1, B2, B3; - B0 = TD0[in[ 0] ^ MD[ 0]] ^ TD1[in[ 4] ^ MD[ 4]] ^ - TD2[in[ 8] ^ MD[ 8]] ^ TD3[in[12] ^ MD[12]] ^ DK[0]; - B1 = TD0[in[ 1] ^ MD[ 1]] ^ TD1[in[ 5] ^ MD[ 5]] ^ - TD2[in[ 9] ^ MD[ 9]] ^ TD3[in[13] ^ MD[13]] ^ DK[1]; - B2 = TD0[in[ 2] ^ MD[ 2]] ^ TD1[in[ 6] ^ MD[ 6]] ^ - TD2[in[10] ^ MD[10]] ^ TD3[in[14] ^ MD[14]] ^ DK[2]; - B3 = TD0[in[ 3] ^ MD[ 3]] ^ TD1[in[ 7] ^ MD[ 7]] ^ - TD2[in[11] ^ MD[11]] ^ TD3[in[15] ^ MD[15]] ^ DK[3]; - for(u32bit j = 1; j != 7; j += 2) + for(u32bit i = 0; i != blocks; ++i) { - T0 = TD0[get_byte(0, B0)] ^ TD1[get_byte(0, B1)] ^ - TD2[get_byte(0, B2)] ^ TD3[get_byte(0, B3)] ^ DK[4*j+0]; - T1 = TD0[get_byte(1, B0)] ^ TD1[get_byte(1, B1)] ^ - TD2[get_byte(1, B2)] ^ TD3[get_byte(1, B3)] ^ DK[4*j+1]; - T2 = TD0[get_byte(2, B0)] ^ TD1[get_byte(2, B1)] ^ - TD2[get_byte(2, B2)] ^ TD3[get_byte(2, B3)] ^ DK[4*j+2]; - T3 = TD0[get_byte(3, B0)] ^ TD1[get_byte(3, B1)] ^ - TD2[get_byte(3, B2)] ^ TD3[get_byte(3, B3)] ^ DK[4*j+3]; - B0 = TD0[get_byte(0, T0)] ^ TD1[get_byte(0, T1)] ^ - TD2[get_byte(0, T2)] ^ TD3[get_byte(0, T3)] ^ DK[4*j+4]; - B1 = TD0[get_byte(1, T0)] ^ TD1[get_byte(1, T1)] ^ - TD2[get_byte(1, T2)] ^ TD3[get_byte(1, T3)] ^ DK[4*j+5]; - B2 = TD0[get_byte(2, T0)] ^ TD1[get_byte(2, T1)] ^ - TD2[get_byte(2, T2)] ^ TD3[get_byte(2, T3)] ^ DK[4*j+6]; - B3 = TD0[get_byte(3, T0)] ^ TD1[get_byte(3, T1)] ^ - TD2[get_byte(3, T2)] ^ TD3[get_byte(3, T3)] ^ DK[4*j+7]; + u32bit T0, T1, T2, T3, B0, B1, B2, B3; + + B0 = TD0[in[ 0] ^ MD[ 0]] ^ TD1[in[ 4] ^ MD[ 4]] ^ + TD2[in[ 8] ^ MD[ 8]] ^ TD3[in[12] ^ MD[12]] ^ DK[0]; + B1 = TD0[in[ 1] ^ MD[ 1]] ^ TD1[in[ 5] ^ MD[ 5]] ^ + TD2[in[ 9] ^ MD[ 9]] ^ TD3[in[13] ^ MD[13]] ^ DK[1]; + B2 = TD0[in[ 2] ^ MD[ 2]] ^ TD1[in[ 6] ^ MD[ 6]] ^ + TD2[in[10] ^ MD[10]] ^ TD3[in[14] ^ MD[14]] ^ DK[2]; + B3 = TD0[in[ 3] ^ MD[ 3]] ^ TD1[in[ 7] ^ MD[ 7]] ^ + TD2[in[11] ^ MD[11]] ^ TD3[in[15] ^ MD[15]] ^ DK[3]; + + for(u32bit j = 1; j != 7; j += 2) + { + T0 = TD0[get_byte(0, B0)] ^ TD1[get_byte(0, B1)] ^ + TD2[get_byte(0, B2)] ^ TD3[get_byte(0, B3)] ^ DK[4*j+0]; + T1 = TD0[get_byte(1, B0)] ^ TD1[get_byte(1, B1)] ^ + TD2[get_byte(1, B2)] ^ TD3[get_byte(1, B3)] ^ DK[4*j+1]; + T2 = TD0[get_byte(2, B0)] ^ TD1[get_byte(2, B1)] ^ + TD2[get_byte(2, B2)] ^ TD3[get_byte(2, B3)] ^ DK[4*j+2]; + T3 = TD0[get_byte(3, B0)] ^ TD1[get_byte(3, B1)] ^ + TD2[get_byte(3, B2)] ^ TD3[get_byte(3, B3)] ^ DK[4*j+3]; + + B0 = TD0[get_byte(0, T0)] ^ TD1[get_byte(0, T1)] ^ + TD2[get_byte(0, T2)] ^ TD3[get_byte(0, T3)] ^ DK[4*j+4]; + B1 = TD0[get_byte(1, T0)] ^ TD1[get_byte(1, T1)] ^ + TD2[get_byte(1, T2)] ^ TD3[get_byte(1, T3)] ^ DK[4*j+5]; + B2 = TD0[get_byte(2, T0)] ^ TD1[get_byte(2, T1)] ^ + TD2[get_byte(2, T2)] ^ TD3[get_byte(2, T3)] ^ DK[4*j+6]; + B3 = TD0[get_byte(3, T0)] ^ TD1[get_byte(3, T1)] ^ + TD2[get_byte(3, T2)] ^ TD3[get_byte(3, T3)] ^ DK[4*j+7]; + } + + out[ 0] = SD[get_byte(0, B0)] ^ MD[16]; + out[ 1] = SD[get_byte(0, B1)] ^ MD[17]; + out[ 2] = SD[get_byte(0, B2)] ^ MD[18]; + out[ 3] = SD[get_byte(0, B3)] ^ MD[19]; + out[ 4] = SD[get_byte(1, B0)] ^ MD[20]; + out[ 5] = SD[get_byte(1, B1)] ^ MD[21]; + out[ 6] = SD[get_byte(1, B2)] ^ MD[22]; + out[ 7] = SD[get_byte(1, B3)] ^ MD[23]; + out[ 8] = SD[get_byte(2, B0)] ^ MD[24]; + out[ 9] = SD[get_byte(2, B1)] ^ MD[25]; + out[10] = SD[get_byte(2, B2)] ^ MD[26]; + out[11] = SD[get_byte(2, B3)] ^ MD[27]; + out[12] = SD[get_byte(3, B0)] ^ MD[28]; + out[13] = SD[get_byte(3, B1)] ^ MD[29]; + out[14] = SD[get_byte(3, B2)] ^ MD[30]; + out[15] = SD[get_byte(3, B3)] ^ MD[31]; + + in += BLOCK_SIZE; + out += BLOCK_SIZE; } - out[ 0] = SD[get_byte(0, B0)] ^ MD[16]; - out[ 1] = SD[get_byte(0, B1)] ^ MD[17]; - out[ 2] = SD[get_byte(0, B2)] ^ MD[18]; - out[ 3] = SD[get_byte(0, B3)] ^ MD[19]; - out[ 4] = SD[get_byte(1, B0)] ^ MD[20]; - out[ 5] = SD[get_byte(1, B1)] ^ MD[21]; - out[ 6] = SD[get_byte(1, B2)] ^ MD[22]; - out[ 7] = SD[get_byte(1, B3)] ^ MD[23]; - out[ 8] = SD[get_byte(2, B0)] ^ MD[24]; - out[ 9] = SD[get_byte(2, B1)] ^ MD[25]; - out[10] = SD[get_byte(2, B2)] ^ MD[26]; - out[11] = SD[get_byte(2, B3)] ^ MD[27]; - out[12] = SD[get_byte(3, B0)] ^ MD[28]; - out[13] = SD[get_byte(3, B1)] ^ MD[29]; - out[14] = SD[get_byte(3, B2)] ^ MD[30]; - out[15] = SD[get_byte(3, B3)] ^ MD[31]; } /* diff --git a/src/block/square/square.h b/src/block/square/square.h index 94a1fc370..5d9cfc78c 100644 --- a/src/block/square/square.h +++ b/src/block/square/square.h @@ -18,13 +18,15 @@ namespace Botan { class BOTAN_DLL Square : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw(); std::string name() const { return "Square"; } BlockCipher* clone() const { return new Square; } + Square() : BlockCipher(16, 16) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); static void transform(u32bit[4]); diff --git a/src/block/tea/info.txt b/src/block/tea/info.txt index 6a0e76b15..85a19ee4c 100644 --- a/src/block/tea/info.txt +++ b/src/block/tea/info.txt @@ -1,10 +1,3 @@ realname "TEA" define TEA - -load_on auto - -<add> -tea.cpp -tea.h -</add> diff --git a/src/block/tea/tea.cpp b/src/block/tea/tea.cpp index 2b4212d9c..de30858da 100644 --- a/src/block/tea/tea.cpp +++ b/src/block/tea/tea.cpp @@ -13,37 +13,49 @@ namespace Botan { /* * TEA Encryption */ -void TEA::enc(const byte in[], byte out[]) const +void TEA::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit L = load_be<u32bit>(in, 0), R = load_be<u32bit>(in, 1); - - u32bit S = 0; - for(u32bit j = 0; j != 32; ++j) + for(u32bit i = 0; i != blocks; ++i) { - S += 0x9E3779B9; - L += ((R << 4) + K[0]) ^ (R + S) ^ ((R >> 5) + K[1]); - R += ((L << 4) + K[2]) ^ (L + S) ^ ((L >> 5) + K[3]); - } + u32bit L = load_be<u32bit>(in, 0), R = load_be<u32bit>(in, 1); + + u32bit S = 0; + for(u32bit j = 0; j != 32; ++j) + { + S += 0x9E3779B9; + L += ((R << 4) + K[0]) ^ (R + S) ^ ((R >> 5) + K[1]); + R += ((L << 4) + K[2]) ^ (L + S) ^ ((L >> 5) + K[3]); + } - store_be(out, L, R); + store_be(out, L, R); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * TEA Decryption */ -void TEA::dec(const byte in[], byte out[]) const +void TEA::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit L = load_be<u32bit>(in, 0), R = load_be<u32bit>(in, 1); - - u32bit S = 0xC6EF3720; - for(u32bit j = 0; j != 32; ++j) + for(u32bit i = 0; i != blocks; ++i) { - R -= ((L << 4) + K[2]) ^ (L + S) ^ ((L >> 5) + K[3]); - L -= ((R << 4) + K[0]) ^ (R + S) ^ ((R >> 5) + K[1]); - S -= 0x9E3779B9; - } + u32bit L = load_be<u32bit>(in, 0), R = load_be<u32bit>(in, 1); + + u32bit S = 0xC6EF3720; + for(u32bit j = 0; j != 32; ++j) + { + R -= ((L << 4) + K[2]) ^ (L + S) ^ ((L >> 5) + K[3]); + L -= ((R << 4) + K[0]) ^ (R + S) ^ ((R >> 5) + K[1]); + S -= 0x9E3779B9; + } - store_be(out, L, R); + store_be(out, L, R); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/tea/tea.h b/src/block/tea/tea.h index 8ddf3e330..825a051aa 100644 --- a/src/block/tea/tea.h +++ b/src/block/tea/tea.h @@ -18,13 +18,15 @@ namespace Botan { class BOTAN_DLL TEA : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { K.clear(); } std::string name() const { return "TEA"; } BlockCipher* clone() const { return new TEA; } + TEA() : BlockCipher(8, 16) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); SecureBuffer<u32bit, 4> K; }; diff --git a/src/block/twofish/info.txt b/src/block/twofish/info.txt index 35639d858..319da6e6e 100644 --- a/src/block/twofish/info.txt +++ b/src/block/twofish/info.txt @@ -1,11 +1,3 @@ realname "Twofish" define TWOFISH - -load_on auto - -<add> -two_tab.cpp -twofish.cpp -twofish.h -</add> diff --git a/src/block/twofish/twofish.cpp b/src/block/twofish/twofish.cpp index 9784b00a2..6a482a8f3 100644 --- a/src/block/twofish/twofish.cpp +++ b/src/block/twofish/twofish.cpp @@ -14,91 +14,103 @@ namespace Botan { /* * Twofish Encryption */ -void Twofish::enc(const byte in[], byte out[]) const +void Twofish::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit A = load_le<u32bit>(in, 0) ^ round_key[0]; - u32bit B = load_le<u32bit>(in, 1) ^ round_key[1]; - u32bit C = load_le<u32bit>(in, 2) ^ round_key[2]; - u32bit D = load_le<u32bit>(in, 3) ^ round_key[3]; - - for(u32bit j = 0; j != 16; j += 2) + for(u32bit i = 0; i != blocks; ++i) { - u32bit X, Y; - - X = SBox0[get_byte(3, A)] ^ SBox1[get_byte(2, A)] ^ - SBox2[get_byte(1, A)] ^ SBox3[get_byte(0, A)]; - Y = SBox0[get_byte(0, B)] ^ SBox1[get_byte(3, B)] ^ - SBox2[get_byte(2, B)] ^ SBox3[get_byte(1, B)]; - X += Y; - Y += X + round_key[2*j + 9]; - X += round_key[2*j + 8]; - - C = rotate_right(C ^ X, 1); - D = rotate_left(D, 1) ^ Y; - - X = SBox0[get_byte(3, C)] ^ SBox1[get_byte(2, C)] ^ - SBox2[get_byte(1, C)] ^ SBox3[get_byte(0, C)]; - Y = SBox0[get_byte(0, D)] ^ SBox1[get_byte(3, D)] ^ - SBox2[get_byte(2, D)] ^ SBox3[get_byte(1, D)]; - X += Y; - Y += X + round_key[2*j + 11]; - X += round_key[2*j + 10]; - - A = rotate_right(A ^ X, 1); - B = rotate_left(B, 1) ^ Y; - } + u32bit A = load_le<u32bit>(in, 0) ^ round_key[0]; + u32bit B = load_le<u32bit>(in, 1) ^ round_key[1]; + u32bit C = load_le<u32bit>(in, 2) ^ round_key[2]; + u32bit D = load_le<u32bit>(in, 3) ^ round_key[3]; - C ^= round_key[4]; - D ^= round_key[5]; - A ^= round_key[6]; - B ^= round_key[7]; + for(u32bit j = 0; j != 16; j += 2) + { + u32bit X, Y; + + X = SBox0[get_byte(3, A)] ^ SBox1[get_byte(2, A)] ^ + SBox2[get_byte(1, A)] ^ SBox3[get_byte(0, A)]; + Y = SBox0[get_byte(0, B)] ^ SBox1[get_byte(3, B)] ^ + SBox2[get_byte(2, B)] ^ SBox3[get_byte(1, B)]; + X += Y; + Y += X + round_key[2*j + 9]; + X += round_key[2*j + 8]; + + C = rotate_right(C ^ X, 1); + D = rotate_left(D, 1) ^ Y; + + X = SBox0[get_byte(3, C)] ^ SBox1[get_byte(2, C)] ^ + SBox2[get_byte(1, C)] ^ SBox3[get_byte(0, C)]; + Y = SBox0[get_byte(0, D)] ^ SBox1[get_byte(3, D)] ^ + SBox2[get_byte(2, D)] ^ SBox3[get_byte(1, D)]; + X += Y; + Y += X + round_key[2*j + 11]; + X += round_key[2*j + 10]; + + A = rotate_right(A ^ X, 1); + B = rotate_left(B, 1) ^ Y; + } - store_le(out, C, D, A, B); + C ^= round_key[4]; + D ^= round_key[5]; + A ^= round_key[6]; + B ^= round_key[7]; + + store_le(out, C, D, A, B); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * Twofish Decryption */ -void Twofish::dec(const byte in[], byte out[]) const +void Twofish::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit A = load_le<u32bit>(in, 0) ^ round_key[4]; - u32bit B = load_le<u32bit>(in, 1) ^ round_key[5]; - u32bit C = load_le<u32bit>(in, 2) ^ round_key[6]; - u32bit D = load_le<u32bit>(in, 3) ^ round_key[7]; - - for(u32bit j = 0; j != 16; j += 2) + for(u32bit i = 0; i != blocks; ++i) { - u32bit X, Y; - - X = SBox0[get_byte(3, A)] ^ SBox1[get_byte(2, A)] ^ - SBox2[get_byte(1, A)] ^ SBox3[get_byte(0, A)]; - Y = SBox0[get_byte(0, B)] ^ SBox1[get_byte(3, B)] ^ - SBox2[get_byte(2, B)] ^ SBox3[get_byte(1, B)]; - X += Y; - Y += X + round_key[39 - 2*j]; - X += round_key[38 - 2*j]; - - C = rotate_left(C, 1) ^ X; - D = rotate_right(D ^ Y, 1); - - X = SBox0[get_byte(3, C)] ^ SBox1[get_byte(2, C)] ^ - SBox2[get_byte(1, C)] ^ SBox3[get_byte(0, C)]; - Y = SBox0[get_byte(0, D)] ^ SBox1[get_byte(3, D)] ^ - SBox2[get_byte(2, D)] ^ SBox3[get_byte(1, D)]; - X += Y; - Y += X + round_key[37 - 2*j]; - X += round_key[36 - 2*j]; - - A = rotate_left(A, 1) ^ X; - B = rotate_right(B ^ Y, 1); - } + u32bit A = load_le<u32bit>(in, 0) ^ round_key[4]; + u32bit B = load_le<u32bit>(in, 1) ^ round_key[5]; + u32bit C = load_le<u32bit>(in, 2) ^ round_key[6]; + u32bit D = load_le<u32bit>(in, 3) ^ round_key[7]; - C ^= round_key[0]; - D ^= round_key[1]; - A ^= round_key[2]; - B ^= round_key[3]; + for(u32bit j = 0; j != 16; j += 2) + { + u32bit X, Y; + + X = SBox0[get_byte(3, A)] ^ SBox1[get_byte(2, A)] ^ + SBox2[get_byte(1, A)] ^ SBox3[get_byte(0, A)]; + Y = SBox0[get_byte(0, B)] ^ SBox1[get_byte(3, B)] ^ + SBox2[get_byte(2, B)] ^ SBox3[get_byte(1, B)]; + X += Y; + Y += X + round_key[39 - 2*j]; + X += round_key[38 - 2*j]; + + C = rotate_left(C, 1) ^ X; + D = rotate_right(D ^ Y, 1); + + X = SBox0[get_byte(3, C)] ^ SBox1[get_byte(2, C)] ^ + SBox2[get_byte(1, C)] ^ SBox3[get_byte(0, C)]; + Y = SBox0[get_byte(0, D)] ^ SBox1[get_byte(3, D)] ^ + SBox2[get_byte(2, D)] ^ SBox3[get_byte(1, D)]; + X += Y; + Y += X + round_key[37 - 2*j]; + X += round_key[36 - 2*j]; + + A = rotate_left(A, 1) ^ X; + B = rotate_right(B ^ Y, 1); + } - store_le(out, C, D, A, B); + C ^= round_key[0]; + D ^= round_key[1]; + A ^= round_key[2]; + B ^= round_key[3]; + + store_le(out, C, D, A, B); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/twofish/twofish.h b/src/block/twofish/twofish.h index 0640e32f8..87b9aa626 100644 --- a/src/block/twofish/twofish.h +++ b/src/block/twofish/twofish.h @@ -18,13 +18,15 @@ namespace Botan { class BOTAN_DLL Twofish : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw(); std::string name() const { return "Twofish"; } BlockCipher* clone() const { return new Twofish; } + Twofish() : BlockCipher(16, 16, 32, 8) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); static void rs_mul(byte[4], byte, u32bit); diff --git a/src/block/xtea/info.txt b/src/block/xtea/info.txt index 0120a3bce..1887e6673 100644 --- a/src/block/xtea/info.txt +++ b/src/block/xtea/info.txt @@ -1,10 +1,3 @@ realname "XTEA" define XTEA - -load_on auto - -<add> -xtea.cpp -xtea.h -</add> diff --git a/src/block/xtea/xtea.cpp b/src/block/xtea/xtea.cpp index 5047f6594..77543e1e8 100644 --- a/src/block/xtea/xtea.cpp +++ b/src/block/xtea/xtea.cpp @@ -7,40 +7,51 @@ #include <botan/xtea.h> #include <botan/loadstor.h> -#include <botan/parsing.h> namespace Botan { /* * XTEA Encryption */ -void XTEA::enc(const byte in[], byte out[]) const +void XTEA::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit L = load_be<u32bit>(in, 0), R = load_be<u32bit>(in, 1); - - for(u32bit j = 0; j != 32; ++j) + for(u32bit i = 0; i != blocks; ++i) { - L += (((R << 4) ^ (R >> 5)) + R) ^ EK[2*j]; - R += (((L << 4) ^ (L >> 5)) + L) ^ EK[2*j+1]; - } + u32bit L = load_be<u32bit>(in, 0), R = load_be<u32bit>(in, 1); + + for(u32bit j = 0; j != 32; ++j) + { + L += (((R << 4) ^ (R >> 5)) + R) ^ EK[2*j]; + R += (((L << 4) ^ (L >> 5)) + L) ^ EK[2*j+1]; + } - store_be(out, L, R); + store_be(out, L, R); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * XTEA Decryption */ -void XTEA::dec(const byte in[], byte out[]) const +void XTEA::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit L = load_be<u32bit>(in, 0), R = load_be<u32bit>(in, 1); - - for(u32bit j = 0; j != 32; ++j) + for(u32bit i = 0; i != blocks; ++i) { - R -= (((L << 4) ^ (L >> 5)) + L) ^ EK[63 - 2*j]; - L -= (((R << 4) ^ (R >> 5)) + R) ^ EK[62 - 2*j]; - } + u32bit L = load_be<u32bit>(in, 0), R = load_be<u32bit>(in, 1); + + for(u32bit j = 0; j != 32; ++j) + { + R -= (((L << 4) ^ (L >> 5)) + L) ^ EK[63 - 2*j]; + L -= (((R << 4) ^ (R >> 5)) + R) ^ EK[62 - 2*j]; + } - store_be(out, L, R); + store_be(out, L, R); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/xtea/xtea.h b/src/block/xtea/xtea.h index d9c6066cb..de265818d 100644 --- a/src/block/xtea/xtea.h +++ b/src/block/xtea/xtea.h @@ -18,13 +18,15 @@ namespace Botan { class BOTAN_DLL XTEA : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { EK.clear(); } std::string name() const { return "XTEA"; } BlockCipher* clone() const { return new XTEA; } + XTEA() : BlockCipher(8, 16) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); SecureBuffer<u32bit, 64> EK; }; diff --git a/src/build-data/arch/m68k.txt b/src/build-data/arch/m68k.txt index 27f246abc..759a3dac1 100644 --- a/src/build-data/arch/m68k.txt +++ b/src/build-data/arch/m68k.txt @@ -2,6 +2,11 @@ realname "Motorola 680x0" default_submodel 68020 +endian big + +# Except for Coldfire +#unaligned ok + <aliases> 680x0 68k diff --git a/src/build-data/arch/ppc.txt b/src/build-data/arch/ppc.txt index 16112f389..e2dfa6ea2 100644 --- a/src/build-data/arch/ppc.txt +++ b/src/build-data/arch/ppc.txt @@ -1,6 +1,7 @@ realname "PowerPC" endian big +unaligned ok default_submodel ppc604 diff --git a/src/build-data/arch/s390.txt b/src/build-data/arch/s390.txt index 392f51397..312b262c4 100644 --- a/src/build-data/arch/s390.txt +++ b/src/build-data/arch/s390.txt @@ -2,6 +2,9 @@ realname "S/390 31-bit" default_submodel s390 +endian big +unaligned ok + <submodels> s390 </submodels> diff --git a/src/build-data/arch/s390x.txt b/src/build-data/arch/s390x.txt index 49fb0bda7..9fe6bd615 100644 --- a/src/build-data/arch/s390x.txt +++ b/src/build-data/arch/s390x.txt @@ -2,6 +2,9 @@ realname "S/390 64-bit" default_submodel s390x +endian big +unaligned ok + <submodels> s390x </submodels> diff --git a/src/build-data/buildh.in b/src/build-data/buildh.in index e4ab0f44b..e0d8368ed 100644 --- a/src/build-data/buildh.in +++ b/src/build-data/buildh.in @@ -22,6 +22,18 @@ #define BOTAN_KARAT_SQR_THRESHOLD 32 #define BOTAN_PRIVATE_KEY_OP_BLINDING_BITS 64 +/* +* Toggles for parallel block cipher mode processing +* +* CBC and CFB can only use parallel processing in decryption mode +*/ +#define BOTAN_PARALLEL_BLOCKS_ECB 8 +#define BOTAN_PARALLEL_BLOCKS_CBC 8 +#define BOTAN_PARALLEL_BLOCKS_CFB 8 +#define BOTAN_PARALLEL_BLOCKS_CTR 8 +#define BOTAN_PARALLEL_BLOCKS_EAX 8 +#define BOTAN_PARALLEL_BLOCKS_XTS 8 + /* PK key consistency checking toggles */ #define BOTAN_PUBLIC_KEY_STRONG_CHECKS_ON_LOAD 1 #define BOTAN_PRIVATE_KEY_STRONG_CHECKS_ON_LOAD 1 diff --git a/src/build-data/cc/bcc.txt b/src/build-data/cc/bcc.txt index df09daff0..fe88c270e 100644 --- a/src/build-data/cc/bcc.txt +++ b/src/build-data/cc/bcc.txt @@ -1,5 +1,7 @@ realname "Borland C++" +macro_name "BORLAND" + binary_name "bcc32" compile_option "-c " diff --git a/src/build-data/cc/compaq.txt b/src/build-data/cc/compaq.txt index 66d3a5219..94075e888 100644 --- a/src/build-data/cc/compaq.txt +++ b/src/build-data/cc/compaq.txt @@ -1,5 +1,7 @@ realname "Compaq C++" +macro_name "COMPAQ" + binary_name "cxx" compile_option "-c " diff --git a/src/build-data/cc/ekopath.txt b/src/build-data/cc/ekopath.txt index ca2471059..38516e2f3 100644 --- a/src/build-data/cc/ekopath.txt +++ b/src/build-data/cc/ekopath.txt @@ -1,5 +1,7 @@ realname "PathScale EKOPath C++" +macro_name "PATHSCALE" + binary_name "pathCC" compile_option "-c " diff --git a/src/build-data/cc/gcc.txt b/src/build-data/cc/gcc.txt index 978ed6d58..9adef8cfb 100644 --- a/src/build-data/cc/gcc.txt +++ b/src/build-data/cc/gcc.txt @@ -1,5 +1,7 @@ realname "GNU C++" +macro_name "GCC" + binary_name "g++" compiler_has_tr1 yes @@ -14,10 +16,11 @@ lang_flags "-D_REENTRANT -ansi -Wno-long-long" warning_flags "-W -Wall" #warning_flags "-Wextra -Wall -Wstrict-aliasing -Wstrict-overflow=5 -Wcast-align -Wmissing-declarations -Wno-unused-parameter" -lib_opt_flags "-O2 -finline-functions" -check_opt_flags "-O2" +lib_opt_flags "-O2" +check_opt_flags "-O" shared_flags "-fPIC" debug_flags "-g" +no_debug_flags "-finline-functions" dll_import_flags "" dll_export_flags "" diff --git a/src/build-data/cc/hpcc.txt b/src/build-data/cc/hpcc.txt index 284e92ca6..9c0d4a784 100644 --- a/src/build-data/cc/hpcc.txt +++ b/src/build-data/cc/hpcc.txt @@ -1,5 +1,7 @@ realname "HP-UX C++" +macro_name "HP_ACC" + binary_name "aCC" compile_option "-c " diff --git a/src/build-data/cc/icc.txt b/src/build-data/cc/icc.txt index 7d8e9682f..9595714f6 100644 --- a/src/build-data/cc/icc.txt +++ b/src/build-data/cc/icc.txt @@ -1,5 +1,7 @@ realname "Intel C++" +macro_name "INTEL" + binary_name "icpc" compiler_has_tr1 yes diff --git a/src/build-data/cc/kai.txt b/src/build-data/cc/kai.txt index 8585e54e0..52ddba4ab 100644 --- a/src/build-data/cc/kai.txt +++ b/src/build-data/cc/kai.txt @@ -1,5 +1,7 @@ realname "KAI C++" +macro_name "KAI" + binary_name "KCC" compile_option "-c " diff --git a/src/build-data/cc/mipspro.txt b/src/build-data/cc/mipspro.txt index b75fc4fb3..a4cfbd1ee 100644 --- a/src/build-data/cc/mipspro.txt +++ b/src/build-data/cc/mipspro.txt @@ -1,5 +1,7 @@ realname "SGI MIPSPro C++" +macro_name "MIPSPRO" + binary_name "CC" compile_option "-c " diff --git a/src/build-data/cc/msvc.txt b/src/build-data/cc/msvc.txt index 68e4517f8..c19d93e2b 100644 --- a/src/build-data/cc/msvc.txt +++ b/src/build-data/cc/msvc.txt @@ -1,5 +1,7 @@ realname "Visual C++" +macro_name "MSVC" + binary_name "cl.exe" compile_option "/nologo /c " diff --git a/src/build-data/cc/open64.txt b/src/build-data/cc/open64.txt index b7c1e9e99..0157440cf 100644 --- a/src/build-data/cc/open64.txt +++ b/src/build-data/cc/open64.txt @@ -1,5 +1,7 @@ realname "Open64" +macro_name "OPEN64" + binary_name "openCC" compile_option "-c " diff --git a/src/build-data/cc/pgi.txt b/src/build-data/cc/pgi.txt index 35f466477..c4fdb9e70 100644 --- a/src/build-data/cc/pgi.txt +++ b/src/build-data/cc/pgi.txt @@ -1,5 +1,7 @@ realname "Portland Group C++" +macro_name "PORTLAND_GROUP" + binary_name "pgCC" compile_option "-c " diff --git a/src/build-data/cc/sgipro64.txt b/src/build-data/cc/sgipro64.txt index 28132ffcc..be91ac69a 100644 --- a/src/build-data/cc/sgipro64.txt +++ b/src/build-data/cc/sgipro64.txt @@ -1,5 +1,7 @@ realname "SGI Pro64" +macro_name "SGI_PRO64" + binary_name "sgiCC" compile_option "-c " diff --git a/src/build-data/cc/sunwspro.txt b/src/build-data/cc/sunwspro.txt index e1bc0b26f..9756f8538 100644 --- a/src/build-data/cc/sunwspro.txt +++ b/src/build-data/cc/sunwspro.txt @@ -1,5 +1,7 @@ realname "Sun Workshop Pro C++" +macro_name "SUN_WORKSHOP" + binary_name "CC" compile_option "-c " diff --git a/src/build-data/cc/xlc.txt b/src/build-data/cc/xlc.txt index 64b888421..6d06b4c43 100644 --- a/src/build-data/cc/xlc.txt +++ b/src/build-data/cc/xlc.txt @@ -1,5 +1,7 @@ realname "IBM XL C/C++" +macro_name "IBM_XLC" + binary_name "xlC" compile_option "-c " diff --git a/src/build-data/makefile/python.in b/src/build-data/makefile/python.in new file mode 100644 index 000000000..9658c70ce --- /dev/null +++ b/src/build-data/makefile/python.in @@ -0,0 +1,29 @@ +CXX = g++ + +PYTHON_ROOT = /usr/lib/python%{python_version}/config +PYTHON_INC = -I/usr/include/python%{python_version} +PYTHON_SITE_PACKAGE_DIR = /usr/lib/python%{python_version}/site-packages/ + +PYTHON_FLAGS = -Isrc/wrap/python -Os -fPIC -ftemplate-depth-255 -Wall -Wno-unused $(PYTHON_INC) + +PYTHON_OBJS = %{python_objs} + +BOTAN_PYTHON_MODDIR = build/botan-python + +all: $(BOTAN_PYTHON_MODDIR)/_botan.so + +%{python_build_cmds} + +$(BOTAN_PYTHON_MODDIR)/_botan.so: $(PYTHON_OBJS) + rm -rf $(BOTAN_PYTHON_MODDIR) + mkdir $(BOTAN_PYTHON_MODDIR) + cp src/wrap/python/*.py $(BOTAN_PYTHON_MODDIR) + $(CXX) -shared -o $@ $(PYTHON_OBJS) -L. -L$(PYTHON_ROOT) -lbotan -lboost_python -Wl,-rpath-link,. -Wl,-soname,$@ + +clean: + rm -f $(PYTHON_OBJS) $(BOTAN_PYTHON_MODDIR) + +install: + mkdir -p $(PYTHON_SITE_PACKAGE_DIR)/botan + cp $(BOTAN_PYTHON_MODDIR)/* $(PYTHON_SITE_PACKAGE_DIR)/botan + chmod -R u=rwX,go=rX $(PYTHON_SITE_PACKAGE_DIR)/botan diff --git a/src/build-data/makefile/unix.in b/src/build-data/makefile/unix.in index a48a5a17e..8e0e35b87 100644 --- a/src/build-data/makefile/unix.in +++ b/src/build-data/makefile/unix.in @@ -101,7 +101,7 @@ clean: distclean: clean $(RM_R) %{build_dir} $(RM_R) %{doc_src_dir}/doxygen %{doc_src_dir}/botan.doxy - $(RM) Makefile $(CONFIG_SCRIPT) $(PKGCONFIG) + $(RM) Makefile* $(CONFIG_SCRIPT) $(PKGCONFIG) install: $(LIBRARIES) $(ECHO) "Installing Botan into $(DESTDIR)... " diff --git a/src/build-data/makefile/unix_shr.in b/src/build-data/makefile/unix_shr.in index f718d1160..cfc8e3223 100644 --- a/src/build-data/makefile/unix_shr.in +++ b/src/build-data/makefile/unix_shr.in @@ -115,7 +115,7 @@ clean: distclean: clean $(RM_R) %{build_dir} $(RM_R) %{doc_src_dir}/doxygen %{doc_src_dir}/botan.doxy - $(RM) Makefile $(CONFIG_SCRIPT) $(PKGCONFIG) + $(RM) Makefile* $(CONFIG_SCRIPT) $(PKGCONFIG) install: $(LIBRARIES) $(ECHO) "Installing Botan into $(DESTDIR)... " diff --git a/src/build-data/os/hurd b/src/build-data/os/hurd new file mode 100644 index 000000000..ed56dad75 --- /dev/null +++ b/src/build-data/os/hurd @@ -0,0 +1,16 @@ +realname "Hurd" + +os_type unix + +<target_features> +posix_mlock +</target_features> + +# Is this correct? +<supports_shared> +all +</supports_shared> + +<aliases> +gnu +</aliases> diff --git a/src/cert/cvc/asn1_eac_tm.cpp b/src/cert/cvc/asn1_eac_tm.cpp index 05533b520..947b9e66d 100644 --- a/src/cert/cvc/asn1_eac_tm.cpp +++ b/src/cert/cvc/asn1_eac_tm.cpp @@ -11,53 +11,39 @@ #include <botan/ber_dec.h> #include <botan/charset.h> #include <botan/parsing.h> -#include <ctime> -#include <sstream> +#include <botan/rounding.h> +#include <botan/timer.h> namespace Botan { namespace { -/* -* Convert a time_t to a struct tm -*/ -std::tm get_tm(u64bit timer) - { - std::time_t time_val = static_cast<std::time_t>(timer); - - std::tm* tm_p = std::gmtime(&time_val); - if (tm_p == 0) - throw Encoding_Error("EAC_Time: gmtime could not encode " + - to_string(timer)); - return (*tm_p); - } SecureVector<byte> enc_two_digit(u32bit in) { SecureVector<byte> result; in %= 100; if (in < 10) - { result.append(0x00); - } else { - u32bit y_first_pos = (in - (in%10))/10; + u32bit y_first_pos = round_down(in, 10) / 10; result.append(static_cast<byte>(y_first_pos)); } - u32bit y_sec_pos = in%10; + + u32bit y_sec_pos = in % 10; result.append(static_cast<byte>(y_sec_pos)); return result; } + u32bit dec_two_digit(byte b1, byte b2) { u32bit upper = (u32bit)b1; u32bit lower = (u32bit)b2; - if (upper > 9 || lower > 9) - { - throw Invalid_Argument("u32bit dec_two_digit(byte b1, byte b2): value too large"); - } - return upper*10 + lower; + if(upper > 9 || lower > 9) + throw Invalid_Argument("CVC dec_two_digit value too large"); + + return upper*10 + lower; } } @@ -67,12 +53,11 @@ u32bit dec_two_digit(byte b1, byte b2) EAC_Time::EAC_Time(u64bit timer, ASN1_Tag t) :tag(t) { - std::tm time_info = get_tm(timer); + std::tm time_info = time_t_to_tm(timer); year = time_info.tm_year + 1900; month = time_info.tm_mon + 1; day = time_info.tm_mday; - } /* @@ -272,27 +257,15 @@ bool operator<(const EAC_Time& t1, const EAC_Time& t2) void EAC_Time::decode_from(BER_Decoder& source) { BER_Object obj = source.get_next_object(); - if (obj.type_tag != this->tag) - { - std::string message("decoding type mismatch for EAC_Time, tag is "); - std::stringstream ss; - std::string str_is; - ss << std::hex << obj.type_tag; - ss >> str_is; - message.append(str_is); - message.append(", while it should be "); - std::stringstream ss2; - std::string str_should; - ss2 << std::hex << this->tag; - ss2 >> str_should; - message.append(str_should); - throw Decoding_Error(message); - } - if (obj.value.size() != 6) + if(obj.type_tag != this->tag) + throw BER_Decoding_Error("Tag mismatch when decoding"); + + if(obj.value.size() != 6) { throw Decoding_Error("EAC_Time decoding failed"); } + try { u32bit tmp_year = dec_two_digit(obj.value[0], obj.value[1]); diff --git a/src/cert/cvc/cvc_ca.cpp b/src/cert/cvc/cvc_ca.cpp index 638d3f984..8ca8db0c2 100644 --- a/src/cert/cvc/cvc_ca.cpp +++ b/src/cert/cvc/cvc_ca.cpp @@ -1,7 +1,6 @@ #include <botan/cvc_ca.h> #include <botan/cvc_cert.h> #include <botan/der_enc.h> -#include <botan/util.h> #include <botan/oids.h> namespace Botan { diff --git a/src/cert/cvc/cvc_self.cpp b/src/cert/cvc/cvc_self.cpp index 91ea38724..777347a18 100644 --- a/src/cert/cvc/cvc_self.cpp +++ b/src/cert/cvc/cvc_self.cpp @@ -14,7 +14,7 @@ #include <botan/look_pk.h> #include <botan/cvc_req.h> #include <botan/cvc_ado.h> -#include <botan/util.h> +#include <botan/timer.h> #include <sstream> namespace Botan { diff --git a/src/cert/x509/crl_ent.cpp b/src/cert/x509/crl_ent.cpp index afea8cf6b..a8a989c24 100644 --- a/src/cert/x509/crl_ent.cpp +++ b/src/cert/x509/crl_ent.cpp @@ -11,7 +11,7 @@ #include <botan/ber_dec.h> #include <botan/bigint.h> #include <botan/oids.h> -#include <botan/util.h> +#include <botan/timer.h> namespace Botan { diff --git a/src/cert/x509/x509_ca.cpp b/src/cert/x509/x509_ca.cpp index 41e314724..f0eb9c3e5 100644 --- a/src/cert/x509/x509_ca.cpp +++ b/src/cert/x509/x509_ca.cpp @@ -13,7 +13,7 @@ #include <botan/bigint.h> #include <botan/parsing.h> #include <botan/oids.h> -#include <botan/util.h> +#include <botan/timer.h> #include <algorithm> #include <typeinfo> #include <iterator> diff --git a/src/cert/x509/x509opt.cpp b/src/cert/x509/x509opt.cpp index de9d589a3..03bcd20f4 100644 --- a/src/cert/x509/x509opt.cpp +++ b/src/cert/x509/x509opt.cpp @@ -6,10 +6,9 @@ */ #include <botan/x509self.h> -#include <botan/util.h> -#include <botan/parsing.h> #include <botan/oids.h> -#include <ctime> +#include <botan/parsing.h> +#include <botan/timer.h> namespace Botan { diff --git a/src/cert/x509/x509stor.cpp b/src/cert/x509/x509stor.cpp index cb61bc2d2..40801148c 100644 --- a/src/cert/x509/x509stor.cpp +++ b/src/cert/x509/x509stor.cpp @@ -10,7 +10,7 @@ #include <botan/pubkey.h> #include <botan/look_pk.h> #include <botan/oids.h> -#include <botan/util.h> +#include <botan/timer.h> #include <algorithm> #include <memory> diff --git a/src/codec/openpgp/openpgp.cpp b/src/codec/openpgp/openpgp.cpp index 7f9cf5f9c..bfba828af 100644 --- a/src/codec/openpgp/openpgp.cpp +++ b/src/codec/openpgp/openpgp.cpp @@ -7,6 +7,7 @@ #include <botan/openpgp.h> #include <botan/filters.h> +#include <botan/basefilt.h> #include <botan/charset.h> #include <botan/crc24.h> diff --git a/src/engine/def_engine/def_eng.h b/src/engine/def_engine/def_eng.h index 2d7145480..ba5bee8ef 100644 --- a/src/engine/def_engine/def_eng.h +++ b/src/engine/def_engine/def_eng.h @@ -78,6 +78,11 @@ class BOTAN_DLL Default_Engine : public Engine Algorithm_Factory&) const; }; +Keyed_Filter* get_cipher_mode(const BlockCipher* block_cipher, + Cipher_Dir direction, + const std::string& mode, + const std::string& padding); + } #endif diff --git a/src/engine/def_engine/def_mode.cpp b/src/engine/def_engine/def_mode.cpp index 2b093a0a3..0c7a1a2e2 100644 --- a/src/engine/def_engine/def_mode.cpp +++ b/src/engine/def_engine/def_mode.cpp @@ -51,22 +51,22 @@ namespace { /** * Get a block cipher padding method by name */ -BlockCipherModePaddingMethod* get_bc_pad(const std::string& algo_spec) +BlockCipherModePaddingMethod* get_bc_pad(const std::string& algo_spec, + const std::string& def_if_empty) { - SCAN_Name request(algo_spec); - #if defined(BOTAN_HAS_CIPHER_MODE_PADDING) - if(request.algo_name() == "PKCS7") + if(algo_spec == "NoPadding" || (algo_spec == "" && def_if_empty == "NoPadding")) + return new Null_Padding; + + if(algo_spec == "PKCS7" || (algo_spec == "" && def_if_empty == "PKCS7")) return new PKCS7_Padding; - if(request.algo_name() == "OneAndZeros") + if(algo_spec == "OneAndZeros") return new OneAndZeros_Padding; - if(request.algo_name() == "X9.23") + if(algo_spec == "X9.23") return new ANSI_X923_Padding; - if(request.algo_name() == "NoPadding") - return new Null_Padding; #endif throw Algorithm_Not_Found(algo_spec); @@ -74,58 +74,11 @@ BlockCipherModePaddingMethod* get_bc_pad(const std::string& algo_spec) } -/* -* Get a cipher object -*/ -Keyed_Filter* Default_Engine::get_cipher(const std::string& algo_spec, - Cipher_Dir direction, - Algorithm_Factory& af) +Keyed_Filter* get_cipher_mode(const BlockCipher* block_cipher, + Cipher_Dir direction, + const std::string& mode, + const std::string& padding) { - std::vector<std::string> algo_parts = split_on(algo_spec, '/'); - if(algo_parts.empty()) - throw Invalid_Algorithm_Name(algo_spec); - - const std::string cipher_name = algo_parts[0]; - - // check if it is a stream cipher first (easy case) - const StreamCipher* stream_cipher = af.prototype_stream_cipher(cipher_name); - if(stream_cipher) - return new StreamCipher_Filter(stream_cipher->clone()); - - const BlockCipher* block_cipher = af.prototype_block_cipher(cipher_name); - if(!block_cipher) - return 0; - - if(algo_parts.size() != 2 && algo_parts.size() != 3) - return 0; - - std::string mode = algo_parts[1]; - u32bit bits = 0; - - if(mode.find("CFB") != std::string::npos || - mode.find("EAX") != std::string::npos) - { - std::vector<std::string> algo_info = parse_algorithm_name(mode); - mode = algo_info[0]; - if(algo_info.size() == 1) - bits = 8*block_cipher->BLOCK_SIZE; - else if(algo_info.size() == 2) - bits = to_u32bit(algo_info[1]); - else - throw Invalid_Algorithm_Name(algo_spec); - } - - std::string padding; - if(algo_parts.size() == 3) - padding = algo_parts[2]; - else - padding = (mode == "CBC") ? "PKCS7" : "NoPadding"; - - if(mode == "ECB" && padding == "CTS") - return 0; - else if((mode != "CBC" && mode != "ECB") && padding != "NoPadding") - throw Invalid_Algorithm_Name(algo_spec); - #if defined(BOTAN_HAS_OFB) if(mode == "OFB") return new OFB(block_cipher->clone()); @@ -137,22 +90,14 @@ Keyed_Filter* Default_Engine::get_cipher(const std::string& algo_spec, #endif #if defined(BOTAN_HAS_ECB) - if(mode == "ECB") - { - if(direction == ENCRYPTION) - return new ECB_Encryption(block_cipher->clone(), get_bc_pad(padding)); - else - return new ECB_Decryption(block_cipher->clone(), get_bc_pad(padding)); - } -#endif - -#if defined(BOTAN_HAS_CFB) - if(mode == "CFB") + if(mode == "ECB" || mode == "") { if(direction == ENCRYPTION) - return new CFB_Encryption(block_cipher->clone(), bits); + return new ECB_Encryption(block_cipher->clone(), + get_bc_pad(padding, "NoPadding")); else - return new CFB_Decryption(block_cipher->clone(), bits); + return new ECB_Decryption(block_cipher->clone(), + get_bc_pad(padding, "NoPadding")); } #endif @@ -173,25 +118,15 @@ Keyed_Filter* Default_Engine::get_cipher(const std::string& algo_spec, #if defined(BOTAN_HAS_CBC) if(direction == ENCRYPTION) return new CBC_Encryption(block_cipher->clone(), - get_bc_pad(padding)); + get_bc_pad(padding, "PKCS7")); else return new CBC_Decryption(block_cipher->clone(), - get_bc_pad(padding)); + get_bc_pad(padding, "PKCS7")); #else return 0; #endif } -#if defined(BOTAN_HAS_EAX) - if(mode == "EAX") - { - if(direction == ENCRYPTION) - return new EAX_Encryption(block_cipher->clone(), bits); - else - return new EAX_Decryption(block_cipher->clone(), bits); - } -#endif - #if defined(BOTAN_HAS_XTS) if(mode == "XTS") { @@ -202,6 +137,86 @@ Keyed_Filter* Default_Engine::get_cipher(const std::string& algo_spec, } #endif + if(mode.find("CFB") != std::string::npos || + mode.find("EAX") != std::string::npos) + { + u32bit bits = 0; + + std::vector<std::string> algo_info = parse_algorithm_name(mode); + std::string mode_name = algo_info[0]; + if(algo_info.size() == 1) + bits = 8*block_cipher->BLOCK_SIZE; + else if(algo_info.size() == 2) + bits = to_u32bit(algo_info[1]); + else + return 0; + +#if defined(BOTAN_HAS_CFB) + if(mode_name == "CFB") + { + if(direction == ENCRYPTION) + return new CFB_Encryption(block_cipher->clone(), bits); + else + return new CFB_Decryption(block_cipher->clone(), bits); + } +#endif + +#if defined(BOTAN_HAS_EAX) + if(mode_name == "EAX") + { + if(direction == ENCRYPTION) + return new EAX_Encryption(block_cipher->clone(), bits); + else + return new EAX_Decryption(block_cipher->clone(), bits); + } +#endif + } + + return 0; + } + +/* +* Get a cipher object +*/ +Keyed_Filter* Default_Engine::get_cipher(const std::string& algo_spec, + Cipher_Dir direction, + Algorithm_Factory& af) + { + std::vector<std::string> algo_parts = split_on(algo_spec, '/'); + if(algo_parts.empty()) + throw Invalid_Algorithm_Name(algo_spec); + + const std::string cipher_name = algo_parts[0]; + + // check if it is a stream cipher first (easy case) + const StreamCipher* stream_cipher = af.prototype_stream_cipher(cipher_name); + if(stream_cipher) + return new StreamCipher_Filter(stream_cipher->clone()); + + const BlockCipher* block_cipher = af.prototype_block_cipher(cipher_name); + if(!block_cipher) + return 0; + + if(algo_parts.size() != 2 && algo_parts.size() != 3) + return 0; + + std::string mode = algo_parts[1]; + + std::string padding; + if(algo_parts.size() == 3) + padding = algo_parts[2]; + else + padding = (mode == "CBC") ? "PKCS7" : "NoPadding"; + + if(mode == "ECB" && padding == "CTS") + return 0; + else if((mode != "CBC" && mode != "ECB") && padding != "NoPadding") + throw Invalid_Algorithm_Name(algo_spec); + + Keyed_Filter* filt = get_cipher_mode(block_cipher, direction, mode, padding); + if(filt) + return filt; + throw Algorithm_Not_Found("get_mode: " + cipher_name + "/" + mode + "/" + padding); } diff --git a/src/engine/def_engine/lookup_hash.cpp b/src/engine/def_engine/lookup_hash.cpp index 58136fc5a..9b2018736 100644 --- a/src/engine/def_engine/lookup_hash.cpp +++ b/src/engine/def_engine/lookup_hash.cpp @@ -22,6 +22,10 @@ #include <botan/crc32.h> #endif +#if defined(BOTAN_HAS_BMW_512) + #include <botan/bmw_512.h> +#endif + #if defined(BOTAN_HAS_FORK_256) #include <botan/fork256.h> #endif @@ -103,6 +107,11 @@ Default_Engine::find_hash(const SCAN_Name& request, return new CRC32; #endif +#if defined(BOTAN_HAS_BMW_512) + if(request.algo_name() == "BMW-512") + return new BMW_512; +#endif + #if defined(BOTAN_HAS_FORK_256) if(request.algo_name() == "FORK-256") return new FORK_256; diff --git a/src/engine/openssl/ossl_bc.cpp b/src/engine/openssl/ossl_bc.cpp index 4d3761adb..9c85439ca 100644 --- a/src/engine/openssl/ossl_bc.cpp +++ b/src/engine/openssl/ossl_bc.cpp @@ -27,8 +27,8 @@ class EVP_BlockCipher : public BlockCipher ~EVP_BlockCipher(); private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; void key_schedule(const byte[], u32bit); std::string cipher_name; mutable EVP_CIPHER_CTX encrypt, decrypt; @@ -90,19 +90,21 @@ EVP_BlockCipher::~EVP_BlockCipher() /* * Encrypt a block */ -void EVP_BlockCipher::enc(const byte in[], byte out[]) const +void EVP_BlockCipher::encrypt_n(const byte in[], byte out[], + u32bit blocks) const { int out_len = 0; - EVP_EncryptUpdate(&encrypt, out, &out_len, in, BLOCK_SIZE); + EVP_EncryptUpdate(&encrypt, out, &out_len, in, blocks * BLOCK_SIZE); } /* * Decrypt a block */ -void EVP_BlockCipher::dec(const byte in[], byte out[]) const +void EVP_BlockCipher::decrypt_n(const byte in[], byte out[], + u32bit blocks) const { int out_len = 0; - EVP_DecryptUpdate(&decrypt, out, &out_len, in, BLOCK_SIZE); + EVP_DecryptUpdate(&decrypt, out, &out_len, in, blocks * BLOCK_SIZE); } /* @@ -174,7 +176,7 @@ OpenSSL_Engine::find_block_cipher(const SCAN_Name& request, if(request.algo_name() == NAME && request.arg_count() == 0) \ return new EVP_BlockCipher(EVP, NAME, MIN, MAX, MOD); -#if 0 +#if !defined(OPENSSL_NO_AES) /* Using OpenSSL's AES causes crashes inside EVP on x86-64 with OpenSSL 0.9.8g cause is unknown @@ -184,12 +186,36 @@ OpenSSL_Engine::find_block_cipher(const SCAN_Name& request, HANDLE_EVP_CIPHER("AES-256", EVP_aes_256_ecb()); #endif +#if !defined(OPENSSL_NO_DES) HANDLE_EVP_CIPHER("DES", EVP_des_ecb()); HANDLE_EVP_CIPHER_KEYLEN("TripleDES", EVP_des_ede3_ecb(), 16, 24, 8); +#endif +#if !defined(OPENSSL_NO_BF) HANDLE_EVP_CIPHER_KEYLEN("Blowfish", EVP_bf_ecb(), 1, 56, 1); +#endif + +#if !defined(OPENSSL_NO_CAST) HANDLE_EVP_CIPHER_KEYLEN("CAST-128", EVP_cast5_ecb(), 1, 16, 1); +#endif + +#if !defined(OPENSSL_NO_RC2) HANDLE_EVP_CIPHER_KEYLEN("RC2", EVP_rc2_ecb(), 1, 32, 1); +#endif + +#if !defined(OPENSSL_NO_RC5) + if(request.algo_name() == "RC5") + if(request.arg_as_u32bit(0, 12) == 12) + return new EVP_BlockCipher(EVP_rc5_32_12_16_ecb(), "RC5(12)", 1, 32, 1); +#endif + +#if !defined(OPENSSL_NO_IDEA) + HANDLE_EVP_CIPHER("IDEA", EVP_idea_ecb()); +#endif + +#if !defined(OPENSSL_NO_SEED) + HANDLE_EVP_CIPHER("SEED", EVP_seed_ecb()); +#endif #undef HANDLE_EVP_CIPHER #undef HANDLE_EVP_CIPHER_KEYLEN diff --git a/src/engine/openssl/ossl_md.cpp b/src/engine/openssl/ossl_md.cpp index 7c8fb678c..42975c8a3 100644 --- a/src/engine/openssl/ossl_md.cpp +++ b/src/engine/openssl/ossl_md.cpp @@ -95,27 +95,41 @@ EVP_HashFunction::~EVP_HashFunction() HashFunction* OpenSSL_Engine::find_hash(const SCAN_Name& request, Algorithm_Factory&) const { -#ifndef OPENSSL_NO_SHA +#if !defined(OPENSSL_NO_SHA) if(request.algo_name() == "SHA-160") return new EVP_HashFunction(EVP_sha1(), "SHA-160"); #endif -#ifndef OPENSSL_NO_MD2 +#if !defined(OPENSSL_NO_SHA256) + if(request.algo_name() == "SHA-224") + return new EVP_HashFunction(EVP_sha224(), "SHA-224"); + if(request.algo_name() == "SHA-256") + return new EVP_HashFunction(EVP_sha256(), "SHA-256"); +#endif + +#if !defined(OPENSSL_NO_SHA512) + if(request.algo_name() == "SHA-384") + return new EVP_HashFunction(EVP_sha384(), "SHA-384"); + if(request.algo_name() == "SHA-512") + return new EVP_HashFunction(EVP_sha512(), "SHA-512"); +#endif + +#if !defined(OPENSSL_NO_MD2) if(request.algo_name() == "MD2") return new EVP_HashFunction(EVP_md2(), "MD2"); #endif -#ifndef OPENSSL_NO_MD4 +#if !defined(OPENSSL_NO_MD4) if(request.algo_name() == "MD4") return new EVP_HashFunction(EVP_md4(), "MD4"); #endif -#ifndef OPENSSL_NO_MD5 +#if !defined(OPENSSL_NO_MD5) if(request.algo_name() == "MD5") return new EVP_HashFunction(EVP_md5(), "MD5"); #endif -#ifndef OPENSSL_NO_RIPEMD +#if !defined(OPENSSL_NO_RIPEMD) if(request.algo_name() == "RIPEMD-160") return new EVP_HashFunction(EVP_ripemd160(), "RIPEMD-160"); #endif diff --git a/src/engine/sse2_eng/eng_sse2.cpp b/src/engine/sse2_eng/eng_sse2.cpp index c738b3d96..07c625c7c 100644 --- a/src/engine/sse2_eng/eng_sse2.cpp +++ b/src/engine/sse2_eng/eng_sse2.cpp @@ -1,21 +1,45 @@ /** * SSE2 Assembly Engine -* (C) 1999-2008 Jack Lloyd +* (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ #include <botan/eng_sse2.h> +#include <botan/cpuid.h> #if defined(BOTAN_HAS_SHA1_SSE2) #include <botan/sha1_sse2.h> #endif +#if defined(BOTAN_HAS_SERPENT_SSE2) + #include <botan/serp_sse2.h> +#endif + namespace Botan { -HashFunction* SSE2_Assembler_Engine::find_hash(const SCAN_Name& request, - Algorithm_Factory&) const +BlockCipher* +SSE2_Assembler_Engine::find_block_cipher(const SCAN_Name& request, + Algorithm_Factory&) const + { + if(!CPUID::has_sse2()) + return 0; + +#if defined(BOTAN_HAS_SERPENT_SSE2) + if(request.algo_name() == "Serpent") + return new Serpent_SSE2; +#endif + + return 0; + } + +HashFunction* +SSE2_Assembler_Engine::find_hash(const SCAN_Name& request, + Algorithm_Factory&) const { + if(!CPUID::has_sse2()) + return 0; + #if defined(BOTAN_HAS_SHA1_SSE2) if(request.algo_name() == "SHA-160") return new SHA_160_SSE2; diff --git a/src/engine/sse2_eng/eng_sse2.h b/src/engine/sse2_eng/eng_sse2.h index 129697e8f..c6b0ce889 100644 --- a/src/engine/sse2_eng/eng_sse2.h +++ b/src/engine/sse2_eng/eng_sse2.h @@ -1,6 +1,6 @@ /** * SSE2 Assembly Engine -* (C) 1999-2008 Jack Lloyd +* (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -17,6 +17,9 @@ class BOTAN_DLL SSE2_Assembler_Engine : public Engine public: std::string provider_name() const { return "sse2"; } private: + BlockCipher* find_block_cipher(const SCAN_Name&, + Algorithm_Factory&) const; + HashFunction* find_hash(const SCAN_Name& reqeust, Algorithm_Factory&) const; }; diff --git a/src/engine/sse2_eng/info.txt b/src/engine/sse2_eng/info.txt index 6242c7fee..7508b9874 100644 --- a/src/engine/sse2_eng/info.txt +++ b/src/engine/sse2_eng/info.txt @@ -10,6 +10,14 @@ eng_sse2.h </add> <arch> -ia32 +pentium-m +pentium4 +prescott amd64 </arch> + +<cc> +gcc +icc +msvc +</cc> diff --git a/src/entropy/dev_random/info.txt b/src/entropy/dev_random/info.txt index fddb7ac06..5231b2901 100644 --- a/src/entropy/dev_random/info.txt +++ b/src/entropy/dev_random/info.txt @@ -18,6 +18,7 @@ darwin freebsd dragonfly hpux +hurd irix linux netbsd diff --git a/src/entropy/proc_walk/info.txt b/src/entropy/proc_walk/info.txt index db96ccdb8..b82929a73 100644 --- a/src/entropy/proc_walk/info.txt +++ b/src/entropy/proc_walk/info.txt @@ -17,6 +17,7 @@ darwin freebsd dragonfly hpux +hurd irix linux openbsd diff --git a/src/filters/algo_filt.cpp b/src/filters/algo_filt.cpp index 23f7a20cf..3268276a6 100644 --- a/src/filters/algo_filt.cpp +++ b/src/filters/algo_filt.cpp @@ -18,7 +18,7 @@ StreamCipher_Filter::StreamCipher_Filter(const std::string& sc_name) : buffer(DEFAULT_BUFFERSIZE) { Algorithm_Factory& af = global_state().algorithm_factory(); - base_ptr = cipher = af.make_stream_cipher(sc_name); + cipher = af.make_stream_cipher(sc_name); } /* @@ -27,7 +27,7 @@ StreamCipher_Filter::StreamCipher_Filter(const std::string& sc_name) : StreamCipher_Filter::StreamCipher_Filter(StreamCipher* stream_cipher) : buffer(DEFAULT_BUFFERSIZE) { - base_ptr = cipher = stream_cipher; + cipher = stream_cipher; } /* @@ -38,7 +38,7 @@ StreamCipher_Filter::StreamCipher_Filter(const std::string& sc_name, buffer(DEFAULT_BUFFERSIZE) { Algorithm_Factory& af = global_state().algorithm_factory(); - base_ptr = cipher = af.make_stream_cipher(sc_name); + cipher = af.make_stream_cipher(sc_name); cipher->set_key(key); } @@ -95,7 +95,7 @@ MAC_Filter::MAC_Filter(const std::string& mac_name, u32bit len) : OUTPUT_LENGTH(len) { Algorithm_Factory& af = global_state().algorithm_factory(); - base_ptr = mac = af.make_mac(mac_name); + mac = af.make_mac(mac_name); } /* @@ -105,7 +105,7 @@ MAC_Filter::MAC_Filter(const std::string& mac_name, const SymmetricKey& key, u32bit len) : OUTPUT_LENGTH(len) { Algorithm_Factory& af = global_state().algorithm_factory(); - base_ptr = mac = af.make_mac(mac_name); + mac = af.make_mac(mac_name); mac->set_key(key); } diff --git a/src/filters/basefilt.cpp b/src/filters/basefilt.cpp index 02dbd8a73..c91a5aa62 100644 --- a/src/filters/basefilt.cpp +++ b/src/filters/basefilt.cpp @@ -50,25 +50,4 @@ Fork::Fork(Filter* filters[], u32bit count) set_next(filters, count); } -/* -* Set the algorithm key -*/ -void Keyed_Filter::set_key(const SymmetricKey& key) - { - if(base_ptr) - base_ptr->set_key(key); - else - throw Invalid_State("Keyed_Filter::set_key: No base algorithm set"); - } - -/* -* Check if a keylength is valid -*/ -bool Keyed_Filter::valid_keylength(u32bit n) const - { - if(base_ptr) - return base_ptr->valid_keylength(n); - throw Invalid_State("Keyed_Filter::valid_keylength: No base algorithm set"); - } - } diff --git a/src/filters/basefilt.h b/src/filters/basefilt.h index 75625abb0..b1bcb1a00 100644 --- a/src/filters/basefilt.h +++ b/src/filters/basefilt.h @@ -9,11 +9,18 @@ #define BOTAN_BASEFILT_H__ #include <botan/filter.h> -#include <botan/sym_algo.h> namespace Botan { /** +* BitBucket is a filter which simply discards all inputs +*/ +struct BitBucket : public Filter + { + void write(const byte[], u32bit) {} + }; + +/** * This class represents Filter chains. A Filter chain is an ordered * concatenation of Filters, the input to a Chain sequentially passes * through all the Filters contained in the Chain. @@ -62,38 +69,6 @@ class BOTAN_DLL Fork : public Fanout_Filter Fork(Filter* filter_arr[], u32bit length); }; -/** -* This class represents keyed filters, i.e. filters that have to be -* fed with a key in order to function. -*/ -class BOTAN_DLL Keyed_Filter : public Filter - { - public: - - /** - * Set the key of this filter. - * @param key the key to set - */ - virtual void set_key(const SymmetricKey& key); - - /** - * Set the initialization vector of this filter. - * @param iv the initialization vector to set - */ - virtual void set_iv(const InitializationVector&) {} - - /** - * Check whether a key length is valid for this filter. - * @param length the key length to be checked for validity - * @return true if the key length is valid, false otherwise - */ - virtual bool valid_keylength(u32bit length) const; - - Keyed_Filter() { base_ptr = 0; } - protected: - SymmetricAlgorithm* base_ptr; - }; - } #endif diff --git a/src/filters/filters.h b/src/filters/filters.h index 725651f7d..964be0bd8 100644 --- a/src/filters/filters.h +++ b/src/filters/filters.h @@ -15,7 +15,9 @@ #include <botan/pipe.h> #include <botan/basefilt.h> +#include <botan/key_filt.h> #include <botan/data_snk.h> + #include <botan/scan_name.h> #if defined(BOTAN_HAS_BASE64_CODEC) @@ -36,6 +38,13 @@ class BOTAN_DLL StreamCipher_Filter : public Keyed_Filter public: /** + * Write input data + * @param input data + * @param input_len length of input in bytes + */ + void write(const byte input[], u32bit input_len); + + /** * Seek in the stream. * @param position the position to seek ahead */ @@ -53,7 +62,20 @@ class BOTAN_DLL StreamCipher_Filter : public Keyed_Filter * @param iv the initialization vector to set */ void set_iv(const InitializationVector& iv); - void write(const byte[], u32bit); + + /** + * Set the key of this filter. + * @param key the key to set + */ + void set_key(const SymmetricKey& key) { cipher->set_key(key); } + + /** + * Check whether a key length is valid for this filter. + * @param length the key length to be checked for validity + * @return true if the key length is valid, false otherwise + */ + bool valid_keylength(u32bit length) const + { return cipher->valid_keylength(length); } /** * Construct a stream cipher filter. @@ -126,6 +148,20 @@ class BOTAN_DLL MAC_Filter : public Keyed_Filter void end_msg(); /** + * Set the key of this filter. + * @param key the key to set + */ + void set_key(const SymmetricKey& key) { mac->set_key(key); } + + /** + * Check whether a key length is valid for this filter. + * @param length the key length to be checked for validity + * @return true if the key length is valid, false otherwise + */ + bool valid_keylength(u32bit length) const + { return mac->valid_keylength(length); } + + /** * Construct a MAC filter. The MAC key will be left empty. * @param mac the MAC to use * @param len the output length of this filter. Leave the default @@ -136,7 +172,7 @@ class BOTAN_DLL MAC_Filter : public Keyed_Filter MAC_Filter(MessageAuthenticationCode* mac_obj, u32bit out_len = 0) : OUTPUT_LENGTH(out_len) { - base_ptr = mac = mac_obj; + mac = mac_obj; } /** @@ -152,7 +188,7 @@ class BOTAN_DLL MAC_Filter : public Keyed_Filter const SymmetricKey& key, u32bit out_len = 0) : OUTPUT_LENGTH(out_len) { - base_ptr = mac = mac_obj; + mac = mac_obj; mac->set_key(key); } diff --git a/src/filters/info.txt b/src/filters/info.txt index 79a92a9c5..fb8108659 100644 --- a/src/filters/info.txt +++ b/src/filters/info.txt @@ -17,6 +17,7 @@ data_src.h filter.cpp filter.h filters.h +key_filt.h out_buf.cpp out_buf.h pbe.h diff --git a/src/filters/key_filt.h b/src/filters/key_filt.h new file mode 100644 index 000000000..36af91f88 --- /dev/null +++ b/src/filters/key_filt.h @@ -0,0 +1,45 @@ +/* +* Keyed_Filter +* (C) 1999-2007 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_KEYED_FILTER_H__ +#define BOTAN_KEYED_FILTER_H__ + +#include <botan/filter.h> +#include <botan/sym_algo.h> + +namespace Botan { + +/** +* This class represents keyed filters, i.e. filters that have to be +* fed with a key in order to function. +*/ +class BOTAN_DLL Keyed_Filter : public Filter + { + public: + /** + * Set the key of this filter. + * @param key the key to set + */ + virtual void set_key(const SymmetricKey& key) = 0; + + /** + * Set the initialization vector of this filter. + * @param iv the initialization vector to set + */ + virtual void set_iv(const InitializationVector&) {} + + /** + * Check whether a key length is valid for this filter. + * @param length the key length to be checked for validity + * @return true if the key length is valid, false otherwise + */ + virtual bool valid_keylength(u32bit length) const = 0; + }; + +} + +#endif diff --git a/src/hash/bmw/bmw_512.cpp b/src/hash/bmw/bmw_512.cpp new file mode 100644 index 000000000..ad3826351 --- /dev/null +++ b/src/hash/bmw/bmw_512.cpp @@ -0,0 +1,203 @@ +/* +* Blue Midnight Wish 512 (Round 2 tweaked) +* (C) 2009 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/bmw_512.h> +#include <botan/loadstor.h> +#include <botan/rotate.h> + +namespace Botan { + +namespace { + +inline u64bit S0(u64bit X) + { + return (X >> 1) ^ (X << 3) ^ rotate_left(X, 4) ^ rotate_left(X, 37); + } + +inline u64bit S1(u64bit X) + { + return (X >> 1) ^ (X << 2) ^ rotate_left(X, 13) ^ rotate_left(X, 43); + } + +inline u64bit S2(u64bit X) + { + return (X >> 2) ^ (X << 1) ^ rotate_left(X, 19) ^ rotate_left(X, 53); + } + +inline u64bit S3(u64bit X) + { + return (X >> 2) ^ (X << 2) ^ rotate_left(X, 28) ^ rotate_left(X, 59); + } + +inline u64bit S4(u64bit X) + { + return (X >> 1) ^ X; + } + +/** +* Blue Midnight Wish 512 compression function +*/ +void BMW_512_compress(u64bit H[16], const u64bit M[16], u64bit Q[32]) + { + const u32bit EXPAND_1_ROUNDS = 2; + + for(u32bit i = 0; i != 16; ++i) + Q[i] = H[i] ^ M[i]; + + Q[16] = Q[ 5] - Q[ 7] + Q[10] + Q[13] + Q[14]; + Q[17] = Q[ 6] - Q[ 8] + Q[11] + Q[14] - Q[15]; + Q[18] = Q[ 0] + Q[ 7] + Q[ 9] - Q[12] + Q[15]; + Q[19] = Q[ 0] - Q[ 1] + Q[ 8] - Q[10] + Q[13]; + Q[20] = Q[ 1] + Q[ 2] + Q[ 9] - Q[11] - Q[14]; + Q[21] = Q[ 3] - Q[ 2] + Q[10] - Q[12] + Q[15]; + Q[22] = Q[ 4] - Q[ 0] - Q[ 3] - Q[11] + Q[13]; + Q[23] = Q[ 1] - Q[ 4] - Q[ 5] - Q[12] - Q[14]; + Q[24] = Q[ 2] - Q[ 5] - Q[ 6] + Q[13] - Q[15]; + Q[25] = Q[ 0] - Q[ 3] + Q[ 6] - Q[ 7] + Q[14]; + Q[26] = Q[ 8] - Q[ 1] - Q[ 4] - Q[ 7] + Q[15]; + Q[27] = Q[ 8] - Q[ 0] - Q[ 2] - Q[ 5] + Q[ 9]; + Q[28] = Q[ 1] + Q[ 3] - Q[ 6] - Q[ 9] + Q[10]; + Q[29] = Q[ 2] + Q[ 4] + Q[ 7] + Q[10] + Q[11]; + Q[30] = Q[ 3] - Q[ 5] + Q[ 8] - Q[11] - Q[12]; + Q[31] = Q[12] - Q[ 4] - Q[ 6] - Q[ 9] + Q[13]; + + Q[ 0] = S0(Q[16]) + H[ 1]; + Q[ 1] = S1(Q[17]) + H[ 2]; + Q[ 2] = S2(Q[18]) + H[ 3]; + Q[ 3] = S3(Q[19]) + H[ 4]; + Q[ 4] = S4(Q[20]) + H[ 5]; + Q[ 5] = S0(Q[21]) + H[ 6]; + Q[ 6] = S1(Q[22]) + H[ 7]; + Q[ 7] = S2(Q[23]) + H[ 8]; + Q[ 8] = S3(Q[24]) + H[ 9]; + Q[ 9] = S4(Q[25]) + H[10]; + Q[10] = S0(Q[26]) + H[11]; + Q[11] = S1(Q[27]) + H[12]; + Q[12] = S2(Q[28]) + H[13]; + Q[13] = S3(Q[29]) + H[14]; + Q[14] = S4(Q[30]) + H[15]; + Q[15] = S0(Q[31]) + H[ 0]; + + for(u32bit i = 16; i != 16 + EXPAND_1_ROUNDS; ++i) + { + Q[i] = S1(Q[i-16]) + S2(Q[i-15]) + S3(Q[i-14]) + S0(Q[i-13]) + + S1(Q[i-12]) + S2(Q[i-11]) + S3(Q[i-10]) + S0(Q[i- 9]) + + S1(Q[i- 8]) + S2(Q[i- 7]) + S3(Q[i- 6]) + S0(Q[i- 5]) + + S1(Q[i- 4]) + S2(Q[i- 3]) + S3(Q[i- 2]) + S0(Q[i- 1]) + + ((rotate_left(M[(i-16) % 16], ((i-16)%16) + 1) + + rotate_left(M[(i-13) % 16], ((i-13)%16) + 1) - + rotate_left(M[(i- 6) % 16], ((i-6)%16) + 1) + + (0x0555555555555555 * i)) ^ H[(i-16+7)%16]); + } + + for(u32bit i = 16 + EXPAND_1_ROUNDS; i != 32; ++i) + { + Q[i] = Q[i-16] + rotate_left(Q[i-15], 5) + + Q[i-14] + rotate_left(Q[i-13], 11) + + Q[i-12] + rotate_left(Q[i-11], 27) + + Q[i-10] + rotate_left(Q[i- 9], 32) + + Q[i- 8] + rotate_left(Q[i- 7], 37) + + Q[i- 6] + rotate_left(Q[i- 5], 43) + + Q[i- 4] + rotate_left(Q[i- 3], 53) + + S4(Q[i - 2]) + ((Q[i-1] >> 2) ^ Q[i-1]) + + ((rotate_left(M[(i-16) % 16], ((i-16)%16 + 1)) + + rotate_left(M[(i-13) % 16], ((i-13)%16 + 1)) - + rotate_left(M[(i- 6) % 16], ((i-6)%16 + 1)) + + (0x0555555555555555 * i)) ^ H[(i-16+7)%16]); + } + + u64bit XL = Q[16] ^ Q[17] ^ Q[18] ^ Q[19] ^ + Q[20] ^ Q[21] ^ Q[22] ^ Q[23]; + + u64bit XH = Q[24] ^ Q[25] ^ Q[26] ^ Q[27] ^ + Q[28] ^ Q[29] ^ Q[30] ^ Q[31]; + + XH ^= XL; + + H[ 0] = ((XH << 5) ^ (Q[16] >> 5) ^ M[0]) + (XL ^ Q[24] ^ Q[0]); + H[ 1] = ((XH >> 7) ^ (Q[17] << 8) ^ M[1]) + (XL ^ Q[25] ^ Q[1]); + H[ 2] = ((XH >> 5) ^ (Q[18] << 5) ^ M[2]) + (XL ^ Q[26] ^ Q[2]); + H[ 3] = ((XH >> 1) ^ (Q[19] << 5) ^ M[3]) + (XL ^ Q[27] ^ Q[3]); + H[ 4] = ((XH >> 3) ^ (Q[20] ) ^ M[4]) + (XL ^ Q[28] ^ Q[4]); + H[ 5] = ((XH << 6) ^ (Q[21] >> 6) ^ M[5]) + (XL ^ Q[29] ^ Q[5]); + H[ 6] = ((XH >> 4) ^ (Q[22] << 6) ^ M[6]) + (XL ^ Q[30] ^ Q[6]); + H[ 7] = ((XH >> 11) ^ (Q[23] << 2) ^ M[7]) + (XL ^ Q[31] ^ Q[7]); + + H[ 8] = rotate_left(H[4], 9) + (XH ^ Q[24] ^ M[ 8]) + ((XL << 8) ^ Q[23] ^ Q[ 8]); + H[ 9] = rotate_left(H[5], 10) + (XH ^ Q[25] ^ M[ 9]) + ((XL >> 6) ^ Q[16] ^ Q[ 9]); + H[10] = rotate_left(H[6], 11) + (XH ^ Q[26] ^ M[10]) + ((XL << 6) ^ Q[17] ^ Q[10]); + H[11] = rotate_left(H[7], 12) + (XH ^ Q[27] ^ M[11]) + ((XL << 4) ^ Q[18] ^ Q[11]); + H[12] = rotate_left(H[0], 13) + (XH ^ Q[28] ^ M[12]) + ((XL >> 3) ^ Q[19] ^ Q[12]); + H[13] = rotate_left(H[1], 14) + (XH ^ Q[29] ^ M[13]) + ((XL >> 4) ^ Q[20] ^ Q[13]); + H[14] = rotate_left(H[2], 15) + (XH ^ Q[30] ^ M[14]) + ((XL >> 7) ^ Q[21] ^ Q[14]); + H[15] = rotate_left(H[3], 16) + (XH ^ Q[31] ^ M[15]) + ((XL >> 2) ^ Q[22] ^ Q[15]); + } + +} + +void BMW_512::compress_n(const byte input[], u32bit blocks) + { + for(u32bit i = 0; i != blocks; ++i) + { + for(u32bit j = 0; j != 16; ++j) + M[j] = load_le<u64bit>(input, j); + + BMW_512_compress(H, M, Q); + + input += HASH_BLOCK_SIZE; + } + } + +/* +* Copy out the digest +*/ +void BMW_512::copy_out(byte output[]) + { + u64bit final[16] = { + 0xAAAAAAAAAAAAAAA0, 0xAAAAAAAAAAAAAAA1, + 0xAAAAAAAAAAAAAAA2, 0xAAAAAAAAAAAAAAA3, + 0xAAAAAAAAAAAAAAA4, 0xAAAAAAAAAAAAAAA5, + 0xAAAAAAAAAAAAAAA6, 0xAAAAAAAAAAAAAAA7, + 0xAAAAAAAAAAAAAAA8, 0xAAAAAAAAAAAAAAA9, + 0xAAAAAAAAAAAAAAAA, 0xAAAAAAAAAAAAAAAB, + 0xAAAAAAAAAAAAAAAC, 0xAAAAAAAAAAAAAAAD, + 0xAAAAAAAAAAAAAAAE, 0xAAAAAAAAAAAAAAAF }; + + BMW_512_compress(final, H, Q); + + for(u32bit i = 0; i != OUTPUT_LENGTH; i += 8) + store_le(final[8 + i/8], output + i); + } + +/* +* Clear memory of sensitive data +*/ +void BMW_512::clear() throw() + { + MDx_HashFunction::clear(); + M.clear(); + Q.clear(); + + H[ 0] = 0x8081828384858687; + H[ 1] = 0x88898A8B8C8D8E8F; + H[ 2] = 0x9091929394959697; + H[ 3] = 0x98999A9B9C9D9E9F; + H[ 4] = 0xA0A1A2A3A4A5A6A7; + H[ 5] = 0xA8A9AAABACADAEAF; + H[ 6] = 0xB0B1B2B3B4B5B6B7; + H[ 7] = 0xB8B9BABBBCBDBEBF; + H[ 8] = 0xC0C1C2C3C4C5C6C7; + H[ 9] = 0xC8C9CACBCCCDCECF; + H[10] = 0xD0D1D2D3D4D5D6D7; + H[11] = 0xD8D9DADBDCDDDEDF; + H[12] = 0xE0E1E2E3E4E5E6E7; + H[13] = 0xE8E9EAEBECEDEEEF; + H[14] = 0xF0F1F2F3F4F5F6F7; + H[15] = 0xF8F9FAFBFCFDFEFF; + } + +} diff --git a/src/hash/bmw/bmw_512.h b/src/hash/bmw/bmw_512.h new file mode 100644 index 000000000..d1f2539e9 --- /dev/null +++ b/src/hash/bmw/bmw_512.h @@ -0,0 +1,32 @@ +/* +* Blue Midnight Wish 512 (Round 2 tweaked) +* (C) 2009 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_BMW_512_H__ +#define BOTAN_BMW_512_H__ + +#include <botan/mdx_hash.h> + +namespace Botan { + +class BMW_512 : public MDx_HashFunction + { + public: + void clear() throw(); + std::string name() const { return "BMW512"; } + HashFunction* clone() const { return new BMW_512; } + BMW_512() : MDx_HashFunction(64, 128, false, true) { clear(); } + private: + void compress_n(const byte input[], u32bit blocks); + void copy_out(byte output[]); + + SecureBuffer<u64bit, 16> H, M; + SecureBuffer<u64bit, 32> Q; + }; + +} + +#endif diff --git a/src/hash/bmw/info.txt b/src/hash/bmw/info.txt new file mode 100644 index 000000000..27e069c0a --- /dev/null +++ b/src/hash/bmw/info.txt @@ -0,0 +1,7 @@ +realname "Blue Midnight Wish" + +define BMW_512 + +<requires> +mdx_hash +</requires> diff --git a/src/hash/fork256/info.txt b/src/hash/fork256/info.txt index ae0c9f1a4..7c3c5bb94 100644 --- a/src/hash/fork256/info.txt +++ b/src/hash/fork256/info.txt @@ -2,13 +2,6 @@ realname "FORK-256" define FORK_256 -load_on auto - -<add> -fork256.cpp -fork256.h -</add> - <requires> mdx_hash </requires> diff --git a/src/hash/gost_3411/gost_3411.cpp b/src/hash/gost_3411/gost_3411.cpp index 3c7f5f92b..8f3982fca 100644 --- a/src/hash/gost_3411/gost_3411.cpp +++ b/src/hash/gost_3411/gost_3411.cpp @@ -1,6 +1,8 @@ /* * GOST 34.11 * (C) 2009 Jack Lloyd +* +* Distributed under the terms of the Botan license */ #include <botan/gost_3411.h> diff --git a/src/hash/gost_3411/gost_3411.h b/src/hash/gost_3411/gost_3411.h index c69555052..960adaa44 100644 --- a/src/hash/gost_3411/gost_3411.h +++ b/src/hash/gost_3411/gost_3411.h @@ -1,6 +1,8 @@ /** * GOST 34.11 * (C) 2009 Jack Lloyd +* +* Distributed under the terms of the Botan license */ #ifndef BOTAN_GOST_3411_H__ diff --git a/src/hash/gost_3411/info.txt b/src/hash/gost_3411/info.txt index 65b9475e1..353ceb3e5 100644 --- a/src/hash/gost_3411/info.txt +++ b/src/hash/gost_3411/info.txt @@ -2,13 +2,6 @@ realname "GOST 34.11" define GOST_34_11 -load_on auto - -<add> -gost_3411.cpp -gost_3411.h -</add> - <requires> gost_28147 </requires> diff --git a/src/hash/has160/info.txt b/src/hash/has160/info.txt index a945f3225..98cbc5155 100644 --- a/src/hash/has160/info.txt +++ b/src/hash/has160/info.txt @@ -2,13 +2,6 @@ realname "HAS-160" define HAS_160 -load_on auto - -<add> -has160.cpp -has160.h -</add> - <requires> mdx_hash </requires> diff --git a/src/hash/md2/info.txt b/src/hash/md2/info.txt index ff33e1eb3..4428584fd 100644 --- a/src/hash/md2/info.txt +++ b/src/hash/md2/info.txt @@ -1,10 +1,3 @@ realname "MD2" define MD2 - -load_on auto - -<add> -md2.cpp -md2.h -</add> diff --git a/src/hash/md4/info.txt b/src/hash/md4/info.txt index fc9cbe116..6aa4a5d59 100644 --- a/src/hash/md4/info.txt +++ b/src/hash/md4/info.txt @@ -2,13 +2,6 @@ realname "MD4" define MD4 -load_on auto - -<add> -md4.cpp -md4.h -</add> - <requires> mdx_hash </requires> diff --git a/src/hash/md4_ia32/info.txt b/src/hash/md4_ia32/info.txt index fee7dd1a8..217c3fc21 100644 --- a/src/hash/md4_ia32/info.txt +++ b/src/hash/md4_ia32/info.txt @@ -4,12 +4,6 @@ define MD4_IA32 load_on asm_ok -<add> -md4_ia32_imp.S -md4_ia32.cpp -md4_ia32.h -</add> - <arch> ia32 </arch> diff --git a/src/hash/md5/info.txt b/src/hash/md5/info.txt index 525a45ab5..14861d635 100644 --- a/src/hash/md5/info.txt +++ b/src/hash/md5/info.txt @@ -2,13 +2,6 @@ realname "MD5" define MD5 -load_on auto - -<add> -md5.cpp -md5.h -</add> - <requires> mdx_hash </requires> diff --git a/src/hash/md5_ia32/info.txt b/src/hash/md5_ia32/info.txt index ad9923b26..d298f2005 100644 --- a/src/hash/md5_ia32/info.txt +++ b/src/hash/md5_ia32/info.txt @@ -4,12 +4,6 @@ define MD5_IA32 load_on asm_ok -<add> -md5_ia32_imp.S -md5_ia32.cpp -md5_ia32.h -</add> - <arch> ia32 </arch> diff --git a/src/hash/mdx_hash/info.txt b/src/hash/mdx_hash/info.txt index 412c93350..ee4ccd6da 100644 --- a/src/hash/mdx_hash/info.txt +++ b/src/hash/mdx_hash/info.txt @@ -3,8 +3,3 @@ realname "MDx Hash Base" define MDX_HASH_FUNCTION load_on dep - -<add> -mdx_hash.cpp -mdx_hash.h -</add> diff --git a/src/hash/par_hash/info.txt b/src/hash/par_hash/info.txt index 45716aac8..029939cb5 100644 --- a/src/hash/par_hash/info.txt +++ b/src/hash/par_hash/info.txt @@ -1,10 +1,3 @@ realname "Parallel Hash" define PARALLEL_HASH - -load_on auto - -<add> -par_hash.cpp -par_hash.h -</add> diff --git a/src/hash/rmd128/info.txt b/src/hash/rmd128/info.txt index 402271da5..0a1ef2c74 100644 --- a/src/hash/rmd128/info.txt +++ b/src/hash/rmd128/info.txt @@ -2,13 +2,6 @@ realname "RIPEMD-128" define RIPEMD_128 -load_on auto - -<add> -rmd128.cpp -rmd128.h -</add> - <requires> mdx_hash </requires> diff --git a/src/hash/rmd160/info.txt b/src/hash/rmd160/info.txt index af4b5c230..225106afc 100644 --- a/src/hash/rmd160/info.txt +++ b/src/hash/rmd160/info.txt @@ -2,13 +2,6 @@ realname "RIPEMD-160" define RIPEMD_160 -load_on auto - -<add> -rmd160.cpp -rmd160.h -</add> - <requires> mdx_hash </requires> diff --git a/src/hash/sha1/info.txt b/src/hash/sha1/info.txt index a0ae30b4b..8915f9ebd 100644 --- a/src/hash/sha1/info.txt +++ b/src/hash/sha1/info.txt @@ -2,13 +2,6 @@ realname "SHA-1" define SHA1 -load_on auto - -<add> -sha160.cpp -sha160.h -</add> - <requires> mdx_hash </requires> diff --git a/src/hash/sha1_amd64/info.txt b/src/hash/sha1_amd64/info.txt index ddbc7d380..183658ac7 100644 --- a/src/hash/sha1_amd64/info.txt +++ b/src/hash/sha1_amd64/info.txt @@ -4,12 +4,6 @@ define SHA1_AMD64 load_on asm_ok -<add> -sha1_amd64_imp.S -sha1_amd64.cpp -sha1_amd64.h -</add> - <arch> amd64 </arch> diff --git a/src/hash/sha1_ia32/info.txt b/src/hash/sha1_ia32/info.txt index bfb321145..e7709454f 100644 --- a/src/hash/sha1_ia32/info.txt +++ b/src/hash/sha1_ia32/info.txt @@ -4,12 +4,6 @@ define SHA1_IA32 load_on asm_ok -<add> -sha1_ia32_imp.S -sha1_ia32.cpp -sha1_ia32.h -</add> - <arch> ia32 </arch> diff --git a/src/hash/sha1_sse2/info.txt b/src/hash/sha1_sse2/info.txt index b8d693b70..4a7a1b5e9 100644 --- a/src/hash/sha1_sse2/info.txt +++ b/src/hash/sha1_sse2/info.txt @@ -2,26 +2,6 @@ realname "SHA-1 (SSE2)" define SHA1_SSE2 -load_on auto - -<add> -sha1_sse2_imp.cpp -sha1_sse2.cpp -sha1_sse2.h -</add> - -<arch> -pentium-m -pentium4 -prescott -amd64 -</arch> - -<cc> -gcc -icc -</cc> - <requires> sha1 sse2_eng diff --git a/src/hash/sha1_sse2/sha1_sse2_imp.cpp b/src/hash/sha1_sse2/sha1_sse2_imp.cpp index 90a8dccd5..5ee222cca 100644 --- a/src/hash/sha1_sse2/sha1_sse2_imp.cpp +++ b/src/hash/sha1_sse2/sha1_sse2_imp.cpp @@ -1,27 +1,18 @@ -/* this code is public domain. - - * dean gaudet <[email protected]> - - * this code was inspired by this paper: - - * SHA: A Design for Parallel Architectures? - * Antoon Bosselaers, Ren�e Govaerts and Joos Vandewalle - * <http://www.esat.kuleuven.ac.be/~cosicart/pdf/AB-9700.pdf> - - * more information available on this implementation here: - - * http://arctic.org/~dean/crypto/sha1.html - - * version: 2 - */ +/* +* SHA-1 using SSE2 +* (C) 2009 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ /* - * Lightly modified for Botan, tested under GCC 4.1.1 and ICC 9.1 - * on a Linux/Core2 system. +* Based on public domain code by Dean Gaudet <[email protected]> +* http://arctic.org/~dean/crypto/sha1.html +*/ - */ #include <botan/sha1_sse2.h> -#include <xmmintrin.h> +#include <botan/rotate.h> +#include <emmintrin.h> namespace Botan { @@ -30,21 +21,13 @@ namespace { typedef union { u32bit u32[4]; __m128i u128; - } v4si __attribute__((aligned(16))); + } v4si; static const v4si K00_19 = { { 0x5a827999, 0x5a827999, 0x5a827999, 0x5a827999 } }; static const v4si K20_39 = { { 0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1 } }; static const v4si K40_59 = { { 0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc } }; static const v4si K60_79 = { { 0xca62c1d6, 0xca62c1d6, 0xca62c1d6, 0xca62c1d6 } }; -#define UNALIGNED 1 -#if UNALIGNED -#define load(p) _mm_loadu_si128(p) -#else -#define load(p) (*p) -#endif - - /* the first 16 bytes only need byte swapping @@ -57,19 +40,15 @@ and is overwritten with the swapped bytes __m128i r1, r2; \ \ r1 = (W); \ - if (1) { \ r1 = _mm_shufflehi_epi16(r1, _MM_SHUFFLE(2, 3, 0, 1)); \ r1 = _mm_shufflelo_epi16(r1, _MM_SHUFFLE(2, 3, 0, 1)); \ r2 = _mm_slli_epi16(r1, 8); \ r1 = _mm_srli_epi16(r1, 8); \ r1 = _mm_or_si128(r1, r2); \ (W) = r1; \ - } \ (prep).u128 = _mm_add_epi32(K00_19.u128, r1); \ } while(0) - - /* for each multiple of 4, t, we want to calculate this: @@ -115,45 +94,38 @@ W0 = W[t]..W[t+3] * efficeon, pentium-m, and opteron but shifts are available in * only one unit. */ -#define prep(prep, XW0, XW1, XW2, XW3, K) do { \ - __m128i r0, r1, r2, r3; \ - \ - /* load W[t-4] 16-byte aligned, and shift */ \ - r3 = _mm_srli_si128((XW3), 4); \ - r0 = (XW0); \ - /* get high 64-bits of XW0 into low 64-bits */ \ - r1 = _mm_shuffle_epi32((XW0), _MM_SHUFFLE(1,0,3,2)); \ - /* load high 64-bits of r1 */ \ - r1 = _mm_unpacklo_epi64(r1, (XW1)); \ - r2 = (XW2); \ - \ - r0 = _mm_xor_si128(r1, r0); \ - r2 = _mm_xor_si128(r3, r2); \ - r0 = _mm_xor_si128(r2, r0); \ - /* unrotated W[t]..W[t+2] in r0 ... still need W[t+3] */ \ - \ - r2 = _mm_slli_si128(r0, 12); \ - r1 = _mm_cmplt_epi32(r0, _mm_setzero_si128()); \ - r0 = _mm_add_epi32(r0, r0); /* shift left by 1 */ \ - r0 = _mm_sub_epi32(r0, r1); /* r0 has W[t]..W[t+2] */ \ - \ - r3 = _mm_srli_epi32(r2, 30); \ - r2 = _mm_slli_epi32(r2, 2); \ - \ - r0 = _mm_xor_si128(r0, r3); \ - r0 = _mm_xor_si128(r0, r2); /* r0 now has W[t+3] */ \ - \ - (XW0) = r0; \ - (prep).u128 = _mm_add_epi32(r0, (K).u128); \ - } while(0) - - -static inline u32bit rol(u32bit src, u32bit amt) - { - /* gcc and icc appear to turn this into a rotate */ - return (src << amt) | (src >> (32 - amt)); - } - +#define prep(prep, XW0, XW1, XW2, XW3, K) \ + do { \ + __m128i r0, r1, r2, r3; \ + \ + /* load W[t-4] 16-byte aligned, and shift */ \ + r3 = _mm_srli_si128((XW3), 4); \ + r0 = (XW0); \ + /* get high 64-bits of XW0 into low 64-bits */ \ + r1 = _mm_shuffle_epi32((XW0), _MM_SHUFFLE(1,0,3,2)); \ + /* load high 64-bits of r1 */ \ + r1 = _mm_unpacklo_epi64(r1, (XW1)); \ + r2 = (XW2); \ + \ + r0 = _mm_xor_si128(r1, r0); \ + r2 = _mm_xor_si128(r3, r2); \ + r0 = _mm_xor_si128(r2, r0); \ + /* unrotated W[t]..W[t+2] in r0 ... still need W[t+3] */ \ + \ + r2 = _mm_slli_si128(r0, 12); \ + r1 = _mm_cmplt_epi32(r0, _mm_setzero_si128()); \ + r0 = _mm_add_epi32(r0, r0); /* shift left by 1 */ \ + r0 = _mm_sub_epi32(r0, r1); /* r0 has W[t]..W[t+2] */ \ + \ + r3 = _mm_srli_epi32(r2, 30); \ + r2 = _mm_slli_epi32(r2, 2); \ + \ + r0 = _mm_xor_si128(r0, r3); \ + r0 = _mm_xor_si128(r0, r2); /* r0 now has W[t+3] */ \ + \ + (XW0) = r0; \ + (prep).u128 = _mm_add_epi32(r0, (K).u128); \ + } while(0) static inline u32bit f00_19(u32bit x, u32bit y, u32bit z) { @@ -184,11 +156,12 @@ static inline u32bit f60_79(u32bit x, u32bit y, u32bit z) return f20_39(x, y, z); } -#define step(nn_mm, xa, xb, xc, xd, xe, xt, input) do { \ - (xt) = (input) + f##nn_mm((xb), (xc), (xd)); \ - (xb) = rol((xb), 30); \ - (xt) += ((xe) + rol((xa), 5)); \ - } while(0) +#define step(nn_mm, xa, xb, xc, xd, xe, xt, input) \ + do { \ + (xt) = (input) + f##nn_mm((xb), (xc), (xd)); \ + (xb) = rotate_left((xb), 30); \ + (xt) += ((xe) + rotate_left((xa), 5)); \ + } while(0) } @@ -210,14 +183,14 @@ extern "C" void botan_sha1_sse2_compress(u32bit H[5], * steps ahead of the integer code. 12 steps ahead seems * to produce the best performance. -dean */ - W0 = load(&input[0]); + W0 = _mm_loadu_si128(&input[0]); prep00_15(prep0, W0); /* prepare for 00 through 03 */ - W1 = load(&input[1]); + W1 = _mm_loadu_si128(&input[1]); prep00_15(prep1, W1); /* prepare for 04 through 07 */ - W2 = load(&input[2]); + W2 = _mm_loadu_si128(&input[2]); prep00_15(prep2, W2); /* prepare for 08 through 11 */ - W3 = load(&input[3]); + W3 = _mm_loadu_si128(&input[3]); step(00_19, a, b, c, d, e, t, prep0.u32[0]); /* 00 */ step(00_19, t, a, b, c, d, e, prep0.u32[1]); /* 01 */ step(00_19, e, t, a, b, c, d, prep0.u32[2]); /* 02 */ diff --git a/src/hash/sha2/info.txt b/src/hash/sha2/info.txt index 9b92ff385..8cc50fa41 100644 --- a/src/hash/sha2/info.txt +++ b/src/hash/sha2/info.txt @@ -2,15 +2,6 @@ realname "SHA-2 (224, 256, 384, 512)" define SHA2 -load_on auto - -<add> -sha2_32.cpp -sha2_32.h -sha2_64.cpp -sha2_64.h -</add> - <requires> mdx_hash </requires> diff --git a/src/hash/skein/info.txt b/src/hash/skein/info.txt index bab8497c5..908033852 100644 --- a/src/hash/skein/info.txt +++ b/src/hash/skein/info.txt @@ -2,13 +2,6 @@ realname "Skein" define SKEIN_512 -load_on auto - -<add> -skein_512.cpp -skein_512.h -</add> - <requires> alloc </requires> diff --git a/src/hash/tiger/info.txt b/src/hash/tiger/info.txt index 7d4cd7177..92b5519c0 100644 --- a/src/hash/tiger/info.txt +++ b/src/hash/tiger/info.txt @@ -2,14 +2,6 @@ realname "Tiger" define TIGER -load_on auto - -<add> -tig_tab.cpp -tiger.cpp -tiger.h -</add> - <requires> mdx_hash </requires> diff --git a/src/hash/whirlpool/info.txt b/src/hash/whirlpool/info.txt index be55b5c3b..4fe4b2b25 100644 --- a/src/hash/whirlpool/info.txt +++ b/src/hash/whirlpool/info.txt @@ -2,14 +2,6 @@ realname "Whirlpool" define WHIRLPOOL -load_on auto - -<add> -whrl_tab.cpp -whrlpool.cpp -whrlpool.h -</add> - <requires> mdx_hash </requires> diff --git a/src/libstate/libstate.cpp b/src/libstate/libstate.cpp index 3275c6493..ca454458b 100644 --- a/src/libstate/libstate.cpp +++ b/src/libstate/libstate.cpp @@ -7,6 +7,7 @@ #include <botan/libstate.h> #include <botan/init.h> +#include <botan/selftest.h> #include <botan/engine.h> #include <botan/stl_util.h> #include <botan/mutex.h> @@ -212,7 +213,7 @@ std::string Library_State::deref_alias(const std::string& key) const /* * Set/Add an option */ -void Library_State::set_option(const std::string key, +void Library_State::set_option(const std::string& key, const std::string& value) { set("conf", key, value); @@ -302,6 +303,9 @@ void Library_State::initialize(bool thread_safe) engines.push_back(new Default_Engine); m_algorithm_factory = new Algorithm_Factory(engines, *mutex_factory); + + if(!passes_self_tests(algorithm_factory())) + throw Self_Test_Failure("Startup self tests failed"); } /* diff --git a/src/libstate/libstate.h b/src/libstate/libstate.h index 2493863a9..a0421953e 100644 --- a/src/libstate/libstate.h +++ b/src/libstate/libstate.h @@ -77,7 +77,7 @@ class BOTAN_DLL Library_State * @param key the key of the option to set * @param value the value to set */ - void set_option(const std::string key, const std::string& value); + void set_option(const std::string& key, const std::string& value); /** * Add a parameter value to the "alias" section. diff --git a/src/libstate/scan_name.cpp b/src/libstate/scan_name.cpp index ef771871d..224d2e509 100644 --- a/src/libstate/scan_name.cpp +++ b/src/libstate/scan_name.cpp @@ -1,6 +1,6 @@ /** -SCAN Name Abstraction -(C) 2008 Jack Lloyd +* SCAN Name Abstraction +* (C) 2008 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -14,28 +14,50 @@ namespace Botan { namespace { -std::vector<std::string> -parse_and_deref_aliases(const std::string& algo_spec) +std::string make_arg( + const std::vector<std::pair<u32bit, std::string> >& name, u32bit start) { - std::vector<std::string> parts = parse_algorithm_name(algo_spec); - std::vector<std::string> out; + std::string output = name[start].second; + u32bit level = name[start].first; - for(size_t i = 0; i != parts.size(); ++i) + u32bit paren_depth = 0; + + for(u32bit i = start + 1; i != name.size(); ++i) { - std::string part_i = global_state().deref_alias(parts[i]); + if(name[i].first <= name[start].first) + break; - if(i == 0 && part_i.find_first_of(",()") != std::string::npos) + if(name[i].first > level) { - std::vector<std::string> parts_i = parse_and_deref_aliases(part_i); - - for(size_t j = 0; j != parts_i.size(); ++j) - out.push_back(parts_i[j]); + output += '(' + name[i].second; + ++paren_depth; + } + else if(name[i].first < level) + { + output += ")," + name[i].second; + --paren_depth; } else - out.push_back(part_i); + { + if(output[output.size() - 1] != '(') + output += ","; + output += name[i].second; + } + + level = name[i].first; } - return out; + for(u32bit i = 0; i != paren_depth; ++i) + output += ')'; + + return output; + } + +std::pair<u32bit, std::string> +deref_aliases(const std::pair<u32bit, std::string>& in) + { + return std::make_pair(in.first, + global_state().deref_alias(in.second)); } } @@ -44,31 +66,101 @@ SCAN_Name::SCAN_Name(const std::string& algo_spec) { orig_algo_spec = algo_spec; - name = parse_and_deref_aliases(algo_spec); + std::vector<std::pair<u32bit, std::string> > name; + u32bit level = 0; + std::pair<u32bit, std::string> accum = std::make_pair(level, ""); + + for(u32bit i = 0; i != algo_spec.size(); ++i) + { + char c = algo_spec[i]; + + if(c == '/' || c == ',' || c == '(' || c == ')') + { + if(c == '(') + ++level; + else if(c == ')') + { + if(level == 0) + throw Decoding_Error("Bad SCAN name " + algo_spec); + --level; + } + + if(c == '/' && level > 0) + accum.second.push_back(c); + else + { + if(accum.second != "") + name.push_back(deref_aliases(accum)); + accum = std::make_pair(level, ""); + } + } + else + accum.second.push_back(c); + } + + if(accum.second != "") + name.push_back(deref_aliases(accum)); - if(name.size() == 0) + if(level != 0 || name.size() == 0) throw Decoding_Error("Bad SCAN name " + algo_spec); + + alg_name = name[0].second; + + bool in_modes = false; + + for(u32bit i = 1; i != name.size(); ++i) + { + if(name[i].first == 0) + { + mode_info.push_back(make_arg(name, i)); + in_modes = true; + } + else if(name[i].first == 1 && !in_modes) + args.push_back(make_arg(name, i)); + } + } + +std::string SCAN_Name::algo_name_and_args() const + { + std::string out; + + out = algo_name(); + + if(arg_count()) + { + out += '('; + for(u32bit i = 0; i != arg_count(); ++i) + { + out += arg(i); + if(i != arg_count() - 1) + out += ','; + } + out += ')'; + + } + + return out; } std::string SCAN_Name::arg(u32bit i) const { if(i >= arg_count()) throw std::range_error("SCAN_Name::argument"); - return name[i+1]; + return args[i]; } std::string SCAN_Name::arg(u32bit i, const std::string& def_value) const { if(i >= arg_count()) return def_value; - return name[i+1]; + return args[i]; } u32bit SCAN_Name::arg_as_u32bit(u32bit i, u32bit def_value) const { if(i >= arg_count()) return def_value; - return to_u32bit(name[i+1]); + return to_u32bit(args[i]); } } diff --git a/src/libstate/scan_name.h b/src/libstate/scan_name.h index 9e7af40d6..ced5f3e15 100644 --- a/src/libstate/scan_name.h +++ b/src/libstate/scan_name.h @@ -1,6 +1,6 @@ /** -SCAN Name Abstraction -(C) 2008 Jack Lloyd +* SCAN Name Abstraction +* (C) 2008 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -35,12 +35,17 @@ class SCAN_Name /** @return the algorithm name */ - std::string algo_name() const { return name[0]; } + std::string algo_name() const { return alg_name; } + + /** + @return the algorithm name plus any arguments + */ + std::string algo_name_and_args() const; /** @return the number of arguments */ - u32bit arg_count() const { return name.size() - 1; } + u32bit arg_count() const { return args.size(); } /** @return if the number of arguments is between lower and upper @@ -67,9 +72,24 @@ class SCAN_Name @return the ith argument as a u32bit, or the default value */ u32bit arg_as_u32bit(u32bit i, u32bit def_value) const; + + /** + @return the cipher mode (if any) + */ + std::string cipher_mode() const + { return (mode_info.size() >= 1) ? mode_info[0] : ""; } + + /** + @return the cipher mode padding (if any) + */ + std::string cipher_mode_pad() const + { return (mode_info.size() >= 2) ? mode_info[1] : ""; } + private: std::string orig_algo_spec; - std::vector<std::string> name; + std::string alg_name; + std::vector<std::string> args; + std::vector<std::string> mode_info; }; } diff --git a/src/mac/mac.cpp b/src/mac/mac.cpp index 96df25503..04b259647 100644 --- a/src/mac/mac.cpp +++ b/src/mac/mac.cpp @@ -1,6 +1,6 @@ /** -Message Authentication Code base class -(C) 1999-2008 Jack Lloyd +* Message Authentication Code base class +* (C) 1999-2008 Jack Lloyd * * Distributed under the terms of the Botan license */ diff --git a/src/math/bigint/bigint.cpp b/src/math/bigint/bigint.cpp index 926bedc02..63bdc3605 100644 --- a/src/math/bigint/bigint.cpp +++ b/src/math/bigint/bigint.cpp @@ -9,7 +9,7 @@ #include <botan/mp_core.h> #include <botan/loadstor.h> #include <botan/parsing.h> -#include <botan/util.h> +#include <botan/rounding.h> namespace Botan { diff --git a/src/math/gfpmath/curve_gfp.cpp b/src/math/gfpmath/curve_gfp.cpp index e12ade081..9a3ffd482 100644 --- a/src/math/gfpmath/curve_gfp.cpp +++ b/src/math/gfpmath/curve_gfp.cpp @@ -1,11 +1,11 @@ -/****** +/* * Elliptic curves over GF(p) * -* (C) 2007 Martin Doering -* Christoph Ludwig -* Falko Strenzke +* (C) 2007 Martin Doering, Christoph Ludwig, Falko Strenzke * 2008 Jack Lloyd -******/ +* +* Distributed under the terms of the Botan license +*/ #include <botan/curve_gfp.h> #include <botan/bigint.h> diff --git a/src/math/gfpmath/gfp_element.cpp b/src/math/gfpmath/gfp_element.cpp index b71809301..f9e0b09c9 100644 --- a/src/math/gfpmath/gfp_element.cpp +++ b/src/math/gfpmath/gfp_element.cpp @@ -1,13 +1,15 @@ -/****** - * Arithmetic for prime fields GF(p) (source file) - * - * (C) 2007 Martin Doering - * Christoph Ludwig - * Falko Strenzke - ******/ +/* +* Arithmetic for prime fields GF(p) +* +* (C) 2007 Martin Doering +* Christoph Ludwig +* Falko Strenzke +* +* Distributed under the terms of the Botan license +*/ #include <botan/gfp_element.h> #include <botan/numthry.h> @@ -15,8 +17,8 @@ #include <botan/mp_types.h> #include <botan/mp_asm.h> #include <botan/mp_asmi.h> -#include <assert.h> #include <ostream> +#include <assert.h> namespace Botan { diff --git a/src/math/gfpmath/gfp_element.h b/src/math/gfpmath/gfp_element.h index 4e0ee985b..18d9e51f9 100644 --- a/src/math/gfpmath/gfp_element.h +++ b/src/math/gfpmath/gfp_element.h @@ -1,13 +1,15 @@ -/****** - * Arithmetic for prime fields GF(p) (header file) - * - * (C) 2007 Martin Doering - * Christoph Ludwig - * Falko Strenzke - ******/ +/* +* Arithmetic for prime fields GF(p) +* +* (C) 2007 Martin Doering +* Christoph Ludwig +* Falko Strenzke +* +* Distributed under the terms of the Botan license +*/ #ifndef BOTAN_GFP_ELEMENT_H__ #define BOTAN_GFP_ELEMENT_H__ @@ -26,11 +28,11 @@ namespace Botan { -struct Illegal_Transformation : public Exception +struct BOTAN_DLL Illegal_Transformation : public Exception { Illegal_Transformation(const std::string& err = - "Requested transformation is not possible") - : Exception(err) {} + "Requested transformation is not possible") : + Exception(err) {} }; /** @@ -39,23 +41,6 @@ struct Illegal_Transformation : public Exception */ class BOTAN_DLL GFpElement { - private: - std::tr1::shared_ptr<GFpModulus> mp_mod; - mutable BigInt m_value; // ordinary residue or m-residue respectively - mutable BigInt workspace; - - // ***************************************** - // data members for montgomery multiplication - mutable bool m_use_montgm; - //mutable BigInt m_mres; - // this bool tells use whether the m_mres carries - // the actual value (in this case mValue doesn´t) - mutable bool m_is_trf; - - void ensure_montgm_precomp() const; - void trf_to_mres() const; - void trf_to_ordres() const; - public: /** construct an element of GF(p) with the given value. @@ -260,7 +245,22 @@ class BOTAN_DLL GFpElement * @param other The value to swap with */ void swap(GFpElement& other); + private: + void ensure_montgm_precomp() const; + void trf_to_mres() const; + void trf_to_ordres() const; + + std::tr1::shared_ptr<GFpModulus> mp_mod; + mutable BigInt m_value; // ordinary residue or m-residue respectively + mutable BigInt workspace; + // ***************************************** + // data members for montgomery multiplication + mutable bool m_use_montgm; + //mutable BigInt m_mres; + // this bool tells use whether the m_mres carries + // the actual value (in this case mValue doesn´t) + mutable bool m_is_trf; }; // relational operators diff --git a/src/math/gfpmath/gfp_modulus.h b/src/math/gfpmath/gfp_modulus.h index b5c085775..8e37e9a73 100644 --- a/src/math/gfpmath/gfp_modulus.h +++ b/src/math/gfpmath/gfp_modulus.h @@ -1,39 +1,33 @@ -/****** - * Modulus and related data for a specific - * implementation of GF(p) (header file) - * - * (C) 2008 Martin Döring - * Christoph Ludwig - * Falko Strenzke - ******/ +/* +* Modulus and related data for a specific implementation of GF(p) +* +* (C) 2008 Martin Döring +* <[email protected]> +* Christoph Ludwig +* <[email protected]> +* Falko Strenzke +* <[email protected]> +* +* Distributed under the terms of the Botan license +*/ #ifndef BOTAN_GFP_MODULUS_H__ #define BOTAN_GFP_MODULUS_H__ #include <botan/bigint.h> -namespace Botan -{ +namespace Botan { class BOTAN_DLL GFpElement; + /** -* This class represents a GFpElement modulus including the modulus related -* values necessary for the montgomery multiplication. -* -* Distributed under the terms of the Botan license +* This class represents a GFpElement modulus including the modulus +* related values necessary for the montgomery multiplication. */ class BOTAN_DLL GFpModulus { - friend class GFpElement; - private: - BigInt m_p; // the modulus itself - mutable BigInt m_p_dash; - mutable BigInt m_r; - mutable BigInt m_r_inv; public: + friend class GFpElement; /** * Construct a GF(P)-Modulus from a BigInt @@ -119,9 +113,14 @@ class BOTAN_DLL GFpModulus return m_p_dash; } // default cp-ctor, op= are fine + + private: + BigInt m_p; // the modulus itself + mutable BigInt m_p_dash; + mutable BigInt m_r; + mutable BigInt m_r_inv; }; } #endif - diff --git a/src/math/gfpmath/point_gfp.cpp b/src/math/gfpmath/point_gfp.cpp index 9139c3ef9..b67631f7b 100644 --- a/src/math/gfpmath/point_gfp.cpp +++ b/src/math/gfpmath/point_gfp.cpp @@ -1,12 +1,11 @@ -/****** -* Arithmetic for point groups of elliptic curves -* over GF(p) (source file) +/* +* Arithmetic for point groups of elliptic curves over GF(p) * -* (C) 2007 Martin Doering -* Christoph Ludwig -* Falko Strenzke +* (C) 2007 Martin Doering, Christoph Ludwig, Falko Strenzke * 2008 Jack Lloyd -******/ +* +* Distributed under the terms of the Botan license +*/ #include <botan/point_gfp.h> #include <botan/numthry.h> @@ -688,8 +687,6 @@ void PointGFp::turn_on_sp_red_mul() const * returns a point equivalent to *this but were * Z has value one, i.e. x and y correspond to * their values in affine coordinates -* -* Distributed under the terms of the Botan license */ PointGFp const PointGFp::get_z_to_one() const { diff --git a/src/math/gfpmath/point_gfp.h b/src/math/gfpmath/point_gfp.h index 771605efc..62b3bc7da 100644 --- a/src/math/gfpmath/point_gfp.h +++ b/src/math/gfpmath/point_gfp.h @@ -1,10 +1,8 @@ /* -* Arithmetic over GF(p) +* Arithmetic for point groups of elliptic curves over GF(p) * -* (C) 2007 Martin Doering -* Christoph Ludwig -* Falko Strenzke -* (C) 2008 Jack Lloyd +* (C) 2007 Martin Doering, Christoph Ludwig, Falko Strenzke +* 2008 Jack Lloyd * * Distributed under the terms of the Botan license */ diff --git a/src/math/numbertheory/mp_numth.cpp b/src/math/numbertheory/mp_numth.cpp index 45a398440..2cb36b8a3 100644 --- a/src/math/numbertheory/mp_numth.cpp +++ b/src/math/numbertheory/mp_numth.cpp @@ -7,7 +7,7 @@ #include <botan/numthry.h> #include <botan/mp_core.h> -#include <botan/util.h> +#include <botan/rounding.h> #include <algorithm> namespace Botan { diff --git a/src/modes/ctr/ctr.cpp b/src/modes/ctr/ctr.cpp index 9eb42ec5a..d458d7848 100644 --- a/src/modes/ctr/ctr.cpp +++ b/src/modes/ctr/ctr.cpp @@ -1,6 +1,6 @@ /* * CTR Mode -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -11,12 +11,21 @@ namespace Botan { +namespace { + +const u32bit PARALLEL_BLOCKS = BOTAN_PARALLEL_BLOCKS_CTR; + +} + /* * CTR-BE Constructor */ -CTR_BE::CTR_BE(BlockCipher* ciph) : - BlockCipherMode(ciph, "CTR-BE", ciph->BLOCK_SIZE, 1) +CTR_BE::CTR_BE(BlockCipher* ciph) : cipher(ciph) { + position = 0; + + counter.create(ciph->BLOCK_SIZE * PARALLEL_BLOCKS); + enc_buffer.create(ciph->BLOCK_SIZE * PARALLEL_BLOCKS); } /* @@ -24,39 +33,88 @@ CTR_BE::CTR_BE(BlockCipher* ciph) : */ CTR_BE::CTR_BE(BlockCipher* ciph, const SymmetricKey& key, const InitializationVector& iv) : - BlockCipherMode(ciph, "CTR-BE", ciph->BLOCK_SIZE, 1) + cipher(ciph) { - set_key(key); + position = 0; + + counter.create(ciph->BLOCK_SIZE * PARALLEL_BLOCKS); + enc_buffer.create(ciph->BLOCK_SIZE * PARALLEL_BLOCKS); + + cipher->set_key(key); set_iv(iv); } /* +* CTR_BE Destructor +*/ +CTR_BE::~CTR_BE() + { + delete cipher; + } + +/* +* Return the name of this type +*/ +std::string CTR_BE::name() const + { + return ("CTR-BE/" + cipher->name()); + } + +/* +* Set CTR-BE IV +*/ +void CTR_BE::set_iv(const InitializationVector& iv) + { + const u32bit BLOCK_SIZE = cipher->BLOCK_SIZE; + + if(iv.length() != BLOCK_SIZE) + throw Invalid_IV_Length(name(), iv.length()); + + enc_buffer.clear(); + position = 0; + + counter.copy(0, iv.begin(), iv.length()); + + for(u32bit i = 1; i != PARALLEL_BLOCKS; ++i) + { + counter.copy(i*BLOCK_SIZE, + counter.begin() + (i-1)*BLOCK_SIZE, BLOCK_SIZE); + + for(s32bit j = BLOCK_SIZE - 1; j >= 0; --j) + if(++counter[i*BLOCK_SIZE+j]) + break; + } + + cipher->encrypt_n(counter, enc_buffer, PARALLEL_BLOCKS); + } + +/* * CTR-BE Encryption/Decryption */ void CTR_BE::write(const byte input[], u32bit length) { - u32bit copied = std::min(BLOCK_SIZE - position, length); - xor_buf(buffer + position, input, copied); - send(buffer + position, copied); + u32bit copied = std::min(enc_buffer.size() - position, length); + xor_buf(enc_buffer + position, input, copied); + send(enc_buffer + position, copied); input += copied; length -= copied; position += copied; - if(position == BLOCK_SIZE) + if(position == enc_buffer.size()) increment_counter(); - while(length >= BLOCK_SIZE) + while(length >= enc_buffer.size()) { - xor_buf(buffer, input, BLOCK_SIZE); - send(buffer, BLOCK_SIZE); + xor_buf(enc_buffer, input, enc_buffer.size()); + send(enc_buffer, enc_buffer.size()); - input += BLOCK_SIZE; - length -= BLOCK_SIZE; + input += enc_buffer.size(); + length -= enc_buffer.size(); increment_counter(); } - xor_buf(buffer + position, input, length); - send(buffer + position, length); + xor_buf(enc_buffer + position, input, length); + send(enc_buffer + position, length); position += length; } @@ -65,10 +123,23 @@ void CTR_BE::write(const byte input[], u32bit length) */ void CTR_BE::increment_counter() { - for(s32bit j = BLOCK_SIZE - 1; j >= 0; --j) - if(++state[j]) - break; - cipher->encrypt(state, buffer); + for(u32bit i = 0; i != PARALLEL_BLOCKS; ++i) + { + byte* this_ctr = counter + i*cipher->BLOCK_SIZE; + + byte last_byte = this_ctr[cipher->BLOCK_SIZE-1]; + last_byte += PARALLEL_BLOCKS; + + if(this_ctr[cipher->BLOCK_SIZE-1] > last_byte) + for(s32bit j = cipher->BLOCK_SIZE - 2; j >= 0; --j) + if(++this_ctr[j]) + break; + + this_ctr[cipher->BLOCK_SIZE-1] = last_byte; + } + + cipher->encrypt_n(counter, enc_buffer, PARALLEL_BLOCKS); + position = 0; } diff --git a/src/modes/ctr/ctr.h b/src/modes/ctr/ctr.h index aa0db5761..1948ffe48 100644 --- a/src/modes/ctr/ctr.h +++ b/src/modes/ctr/ctr.h @@ -8,22 +8,37 @@ #ifndef BOTAN_COUNTER_MODE_H__ #define BOTAN_COUNTER_MODE_H__ -#include <botan/modebase.h> -#include <botan/modebase.h> +#include <botan/key_filt.h> +#include <botan/block_cipher.h> namespace Botan { /* * CTR-BE Mode */ -class BOTAN_DLL CTR_BE : public BlockCipherMode +class BOTAN_DLL CTR_BE : 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); } + CTR_BE(BlockCipher*); CTR_BE(BlockCipher*, const SymmetricKey&, const InitializationVector&); + + ~CTR_BE(); private: void write(const byte[], u32bit); void increment_counter(); + + BlockCipher* cipher; + SecureVector<byte> counter, enc_buffer; + u32bit position; }; } diff --git a/src/modes/eax/eax.h b/src/modes/eax/eax.h index 1bb2e510d..f569f2ede 100644 --- a/src/modes/eax/eax.h +++ b/src/modes/eax/eax.h @@ -8,7 +8,7 @@ #ifndef BOTAN_EAX_H__ #define BOTAN_EAX_H__ -#include <botan/basefilt.h> +#include <botan/key_filt.h> #include <botan/block_cipher.h> #include <botan/mac.h> diff --git a/src/modes/ecb/ecb.cpp b/src/modes/ecb/ecb.cpp index 8da0a4802..988a8b3f2 100644 --- a/src/modes/ecb/ecb.cpp +++ b/src/modes/ecb/ecb.cpp @@ -9,22 +9,60 @@ namespace Botan { +namespace { + +const u32bit PARALLEL_BLOCKS = BOTAN_PARALLEL_BLOCKS_ECB; + +} + /* -* Verify the IV is not set +* ECB_Encryption Constructor */ -bool ECB::valid_iv_size(u32bit iv_size) const +ECB_Encryption::ECB_Encryption(BlockCipher* ciph, + BlockCipherModePaddingMethod* pad) { - if(iv_size == 0) - return true; - return false; + cipher = ciph; + padder = pad; + + plaintext.create(cipher->BLOCK_SIZE); + ciphertext.create(cipher->BLOCK_SIZE * PARALLEL_BLOCKS); + + position = 0; + } + +/* +* ECB_Encryption Constructor +*/ +ECB_Encryption::ECB_Encryption(BlockCipher* ciph, + BlockCipherModePaddingMethod* pad, + const SymmetricKey& key) + { + cipher = ciph; + padder = pad; + + plaintext.create(cipher->BLOCK_SIZE); + ciphertext.create(cipher->BLOCK_SIZE * PARALLEL_BLOCKS); + + position = 0; + + cipher->set_key(key); + } + +/* +* ECB_Encryption Destructor +*/ +ECB_Encryption::~ECB_Encryption() + { + delete cipher; + delete padder; } /* * Return an ECB mode name */ -std::string ECB::name() const +std::string ECB_Encryption::name() const { - return (cipher->name() + "/" + mode_name + "/" + padder->name()); + return (cipher->name() + "/ECB/" + padder->name()); } /* @@ -32,23 +70,34 @@ std::string ECB::name() const */ void ECB_Encryption::write(const byte input[], u32bit length) { - buffer.copy(position, input, length); - if(position + length >= BLOCK_SIZE) + const u32bit BLOCK_SIZE = cipher->BLOCK_SIZE; + + if(position) { - cipher->encrypt(buffer); - send(buffer, BLOCK_SIZE); - input += (BLOCK_SIZE - position); - length -= (BLOCK_SIZE - position); - while(length >= BLOCK_SIZE) + plaintext.copy(position, input, length); + + if(position + length >= BLOCK_SIZE) { - cipher->encrypt(input, buffer); - send(buffer, BLOCK_SIZE); - input += BLOCK_SIZE; - length -= BLOCK_SIZE; + cipher->encrypt(plaintext, ciphertext); + send(ciphertext, BLOCK_SIZE); + input += (BLOCK_SIZE - position); + length -= (BLOCK_SIZE - position); + position = 0; } - buffer.copy(input, length); - position = 0; } + + while(length >= BLOCK_SIZE) + { + const u32bit to_proc = + std::min<u32bit>(length, ciphertext.size()) / BLOCK_SIZE; + + cipher->encrypt_n(input, ciphertext, to_proc); + send(ciphertext, to_proc * BLOCK_SIZE); + input += to_proc * BLOCK_SIZE; + length -= to_proc * BLOCK_SIZE; + } + + plaintext.copy(position, input, length); position += length; } @@ -57,6 +106,8 @@ void ECB_Encryption::write(const byte input[], u32bit length) */ void ECB_Encryption::end_msg() { + const u32bit BLOCK_SIZE = cipher->BLOCK_SIZE; + SecureVector<byte> padding(BLOCK_SIZE); padder->pad(padding, padding.size(), position); write(padding, padder->pad_bytes(BLOCK_SIZE, position)); @@ -65,27 +116,93 @@ void ECB_Encryption::end_msg() } /* +* ECB_Decryption Constructor +*/ +ECB_Decryption::ECB_Decryption(BlockCipher* ciph, + BlockCipherModePaddingMethod* pad) + { + cipher = ciph; + padder = pad; + + ciphertext.create(cipher->BLOCK_SIZE); + plaintext.create(cipher->BLOCK_SIZE * PARALLEL_BLOCKS); + + position = 0; + } + +/* +* ECB_Decryption Constructor +*/ +ECB_Decryption::ECB_Decryption(BlockCipher* ciph, + BlockCipherModePaddingMethod* pad, + const SymmetricKey& key) + { + cipher = ciph; + padder = pad; + + ciphertext.create(cipher->BLOCK_SIZE); + plaintext.create(cipher->BLOCK_SIZE * PARALLEL_BLOCKS); + + position = 0; + + cipher->set_key(key); + } + +/* +* ECB_Decryption Destructor +*/ +ECB_Decryption::~ECB_Decryption() + { + delete cipher; + delete padder; + } + +/* +* Return an ECB mode name +*/ +std::string ECB_Decryption::name() const + { + return (cipher->name() + "/ECB/" + padder->name()); + } + +/* * Decrypt in ECB mode */ void ECB_Decryption::write(const byte input[], u32bit length) { - buffer.copy(position, input, length); - if(position + length > BLOCK_SIZE) + const u32bit BLOCK_SIZE = cipher->BLOCK_SIZE; + + if(position) { - cipher->decrypt(buffer); - send(buffer, BLOCK_SIZE); - input += (BLOCK_SIZE - position); - length -= (BLOCK_SIZE - position); - while(length > BLOCK_SIZE) + ciphertext.copy(position, input, length); + + if(position + length > BLOCK_SIZE) { - cipher->decrypt(input, buffer); - send(buffer, BLOCK_SIZE); - input += BLOCK_SIZE; - length -= BLOCK_SIZE; + cipher->decrypt(ciphertext, plaintext); + send(plaintext, BLOCK_SIZE); + input += (BLOCK_SIZE - position); + length -= (BLOCK_SIZE - position); + position = 0; } - buffer.copy(input, length); - position = 0; } + + while(length > BLOCK_SIZE) + { + /* Always leave at least 1 byte left over, to ensure that (as long + as the input message actually is a multiple of the block size) + we will have the full final block left over in end_msg so as + to remove the padding + */ + const u32bit to_proc = + std::min<u32bit>(length - 1, plaintext.size()) / BLOCK_SIZE; + + cipher->decrypt_n(input, plaintext, to_proc); + send(plaintext, to_proc * BLOCK_SIZE); + input += to_proc * BLOCK_SIZE; + length -= to_proc * BLOCK_SIZE; + } + + ciphertext.copy(position, input, length); position += length; } @@ -94,11 +211,11 @@ void ECB_Decryption::write(const byte input[], u32bit length) */ void ECB_Decryption::end_msg() { - if(position != BLOCK_SIZE) + if(position != cipher->BLOCK_SIZE) throw Decoding_Error(name()); - cipher->decrypt(buffer); - send(buffer, padder->unpad(buffer, BLOCK_SIZE)); - state = buffer; + + cipher->decrypt(ciphertext); + send(ciphertext, padder->unpad(ciphertext, cipher->BLOCK_SIZE)); position = 0; } diff --git a/src/modes/ecb/ecb.h b/src/modes/ecb/ecb.h index 5230f9b14..ff9ea9635 100644 --- a/src/modes/ecb/ecb.h +++ b/src/modes/ecb/ecb.h @@ -1,6 +1,6 @@ /* * ECB Mode -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -8,64 +8,74 @@ #ifndef BOTAN_ECB_H__ #define BOTAN_ECB_H__ -#include <botan/modebase.h> -#include <botan/mode_pad.h> +#include <botan/basefilt.h> #include <botan/block_cipher.h> +#include <botan/mode_pad.h> -namespace Botan { - -/* -* ECB -*/ -class BOTAN_DLL ECB : public BlockCipherMode - { - protected: - ECB(BlockCipher* ciph, BlockCipherModePaddingMethod* pad) : - BlockCipherMode(ciph, "ECB", 0), padder(pad) {} - ~ECB() { delete padder; } +#include <botan/modebase.h> - std::string name() const; - BlockCipherModePaddingMethod* padder; - private: - bool valid_iv_size(u32bit) const; - }; +namespace Botan { /* * ECB Encryption */ -class BOTAN_DLL ECB_Encryption : public ECB +class BOTAN_DLL ECB_Encryption : public Keyed_Filter { public: + std::string name() const; + + void set_key(const SymmetricKey& key) { cipher->set_key(key); } + + bool valid_keylength(u32bit key_len) const + { return cipher->valid_keylength(key_len); } + ECB_Encryption(BlockCipher* ciph, - BlockCipherModePaddingMethod* pad) : - ECB(ciph, pad) {} + BlockCipherModePaddingMethod* pad); ECB_Encryption(BlockCipher* ciph, BlockCipherModePaddingMethod* pad, - const SymmetricKey& key) : - ECB(ciph, pad) { set_key(key); } + const SymmetricKey& key); + + ~ECB_Encryption(); private: void write(const byte[], u32bit); void end_msg(); + + BlockCipher* cipher; + BlockCipherModePaddingMethod* padder; + SecureVector<byte> plaintext, ciphertext; + u32bit position; }; /* * ECB Decryption */ -class BOTAN_DLL ECB_Decryption : public ECB +class BOTAN_DLL ECB_Decryption : public Keyed_Filter { public: + std::string name() const; + + void set_key(const SymmetricKey& key) { cipher->set_key(key); } + + bool valid_keylength(u32bit key_len) const + { return cipher->valid_keylength(key_len); } + ECB_Decryption(BlockCipher* ciph, - BlockCipherModePaddingMethod* pad) : - ECB(ciph, pad) {} + BlockCipherModePaddingMethod* pad); ECB_Decryption(BlockCipher* ciph, BlockCipherModePaddingMethod* pad, - const SymmetricKey& key) : - ECB(ciph, pad) { set_key(key); } + const SymmetricKey& key); + + ~ECB_Decryption(); private: void write(const byte[], u32bit); void end_msg(); + + BlockCipher* cipher; + BlockCipherModePaddingMethod* padder; + SecureVector<byte> plaintext, ciphertext; + u32bit position; }; } diff --git a/src/modes/mode_pad/mode_pad.cpp b/src/modes/mode_pad/mode_pad.cpp index b8badd7a7..2204c28b5 100644 --- a/src/modes/mode_pad/mode_pad.cpp +++ b/src/modes/mode_pad/mode_pad.cpp @@ -7,7 +7,6 @@ #include <botan/mode_pad.h> #include <botan/exceptn.h> -#include <botan/util.h> namespace Botan { diff --git a/src/modes/modebase.cpp b/src/modes/modebase.cpp index 8293acc54..b048862a4 100644 --- a/src/modes/modebase.cpp +++ b/src/modes/modebase.cpp @@ -19,7 +19,7 @@ BlockCipherMode::BlockCipherMode(BlockCipher* cipher_ptr, BLOCK_SIZE(cipher_ptr->BLOCK_SIZE), BUFFER_SIZE(buf_mult * BLOCK_SIZE), IV_METHOD(iv_meth), mode_name(cipher_mode_name) { - base_ptr = cipher = cipher_ptr; + cipher = cipher_ptr; buffer.create(BUFFER_SIZE); state.create(iv_size); position = 0; diff --git a/src/modes/modebase.h b/src/modes/modebase.h index 173fde58c..4a15524b6 100644 --- a/src/modes/modebase.h +++ b/src/modes/modebase.h @@ -8,7 +8,7 @@ #ifndef BOTAN_MODEBASE_H__ #define BOTAN_MODEBASE_H__ -#include <botan/basefilt.h> +#include <botan/key_filt.h> #include <botan/block_cipher.h> namespace Botan { @@ -21,12 +21,17 @@ 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: - void set_iv(const InitializationVector&); const u32bit BLOCK_SIZE, BUFFER_SIZE, IV_METHOD; const std::string mode_name; BlockCipher* cipher; diff --git a/src/modes/xts/xts.h b/src/modes/xts/xts.h index 01558175b..9badd3666 100644 --- a/src/modes/xts/xts.h +++ b/src/modes/xts/xts.h @@ -8,7 +8,7 @@ #ifndef BOTAN_XTS_H__ #define BOTAN_XTS_H__ -#include <botan/basefilt.h> +#include <botan/key_filt.h> #include <botan/block_cipher.h> namespace Botan { @@ -22,6 +22,9 @@ class BOTAN_DLL XTS_Encryption : public Keyed_Filter void set_key(const SymmetricKey& key); void set_iv(const InitializationVector& iv); + bool valid_keylength(u32bit key_len) const + { return cipher->valid_keylength(key_len); } + std::string name() const; XTS_Encryption(BlockCipher* ciph); @@ -52,6 +55,9 @@ class BOTAN_DLL XTS_Decryption : public Keyed_Filter void set_key(const SymmetricKey& key); void set_iv(const InitializationVector& iv); + bool valid_keylength(u32bit key_len) const + { return cipher->valid_keylength(key_len); } + std::string name() const; XTS_Decryption(BlockCipher* ciph); diff --git a/src/pubkey/dh/dh.cpp b/src/pubkey/dh/dh.cpp index 0c9d02f0e..149bc5882 100644 --- a/src/pubkey/dh/dh.cpp +++ b/src/pubkey/dh/dh.cpp @@ -7,7 +7,7 @@ #include <botan/dh.h> #include <botan/numthry.h> -#include <botan/util.h> +#include <botan/workfactor.h> namespace Botan { diff --git a/src/pubkey/dl_group/dl_group.cpp b/src/pubkey/dl_group/dl_group.cpp index 81c5d5e1d..13ea03016 100644 --- a/src/pubkey/dl_group/dl_group.cpp +++ b/src/pubkey/dl_group/dl_group.cpp @@ -12,7 +12,7 @@ #include <botan/der_enc.h> #include <botan/ber_dec.h> #include <botan/pipe.h> -#include <botan/util.h> +#include <botan/workfactor.h> #include <botan/pem.h> namespace Botan { diff --git a/src/pubkey/ec_dompar/ec_dompar.cpp b/src/pubkey/ec_dompar/ec_dompar.cpp index 6cfcc0619..0b5a6e681 100644 --- a/src/pubkey/ec_dompar/ec_dompar.cpp +++ b/src/pubkey/ec_dompar/ec_dompar.cpp @@ -1,3 +1,11 @@ +/* +* ECC Domain Parameters +* +* (C) 2007 Falko Strenzke, FlexSecure GmbH +* 2008 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ #include <botan/ec_dompar.h> #include <botan/pubkey_enums.h> diff --git a/src/pubkey/ec_dompar/ec_dompar.h b/src/pubkey/ec_dompar/ec_dompar.h index 47971d802..5ea599c9d 100644 --- a/src/pubkey/ec_dompar/ec_dompar.h +++ b/src/pubkey/ec_dompar/ec_dompar.h @@ -1,5 +1,6 @@ /* -* ECDSA Domain Parameters +* ECC Domain Parameters +* * (C) 2007 Falko Strenzke, FlexSecure GmbH * 2008 Jack Lloyd * diff --git a/src/pubkey/ecc_key/ecc_key.cpp b/src/pubkey/ecc_key/ecc_key.cpp index 615efecf1..677a5088e 100644 --- a/src/pubkey/ecc_key/ecc_key.cpp +++ b/src/pubkey/ecc_key/ecc_key.cpp @@ -10,7 +10,6 @@ #include <botan/ecc_key.h> #include <botan/x509_key.h> #include <botan/numthry.h> -#include <botan/util.h> #include <botan/der_enc.h> #include <botan/ber_dec.h> #include <botan/secmem.h> diff --git a/src/pubkey/ecdsa/ecdsa.cpp b/src/pubkey/ecdsa/ecdsa.cpp index 9640c6397..ea2c35a19 100644 --- a/src/pubkey/ecdsa/ecdsa.cpp +++ b/src/pubkey/ecdsa/ecdsa.cpp @@ -9,7 +9,6 @@ #include <botan/ecdsa.h> #include <botan/numthry.h> -#include <botan/util.h> #include <botan/der_enc.h> #include <botan/ber_dec.h> #include <botan/secmem.h> diff --git a/src/pubkey/eckaeg/eckaeg.cpp b/src/pubkey/eckaeg/eckaeg.cpp index b8ff75d89..dc6eb925b 100644 --- a/src/pubkey/eckaeg/eckaeg.cpp +++ b/src/pubkey/eckaeg/eckaeg.cpp @@ -9,7 +9,6 @@ #include <botan/eckaeg.h> #include <botan/numthry.h> -#include <botan/util.h> #include <botan/der_enc.h> #include <botan/ber_dec.h> #include <botan/secmem.h> diff --git a/src/pubkey/elgamal/elgamal.cpp b/src/pubkey/elgamal/elgamal.cpp index 1f79df57a..8c07c5735 100644 --- a/src/pubkey/elgamal/elgamal.cpp +++ b/src/pubkey/elgamal/elgamal.cpp @@ -9,7 +9,7 @@ #include <botan/numthry.h> #include <botan/keypair.h> #include <botan/look_pk.h> -#include <botan/util.h> +#include <botan/workfactor.h> namespace Botan { diff --git a/src/pubkey/info.txt b/src/pubkey/info.txt index ee8da5b9d..63af86c47 100644 --- a/src/pubkey/info.txt +++ b/src/pubkey/info.txt @@ -15,6 +15,8 @@ pubkey.cpp pubkey.h pubkey_enums.cpp pubkey_enums.h +workfactor.cpp +workfactor.h </add> <requires> diff --git a/src/pubkey/rsa/rsa.h b/src/pubkey/rsa/rsa.h index f07533a4f..0580fe8eb 100644 --- a/src/pubkey/rsa/rsa.h +++ b/src/pubkey/rsa/rsa.h @@ -28,7 +28,13 @@ class BOTAN_DLL RSA_PublicKey : public PK_Encrypting_Key, SecureVector<byte> verify(const byte[], u32bit) const; RSA_PublicKey() {} - RSA_PublicKey(const BigInt&, const BigInt&); + + /** + * Create a RSA_PublicKey + * @arg n the modulus + * @arg e the exponent + */ + RSA_PublicKey(const BigInt& n, const BigInt& e); protected: BigInt public_op(const BigInt&) const; }; diff --git a/src/utils/util.cpp b/src/pubkey/workfactor.cpp index 84dfd1a14..e40b7919c 100644 --- a/src/utils/util.cpp +++ b/src/pubkey/workfactor.cpp @@ -1,35 +1,17 @@ /* -* Utility Functions +* Public Key Work Factor Functions * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ -#include <botan/util.h> +#include <botan/workfactor.h> #include <algorithm> #include <cmath> namespace Botan { /* -* Round up n to multiple of align_to -*/ -u32bit round_up(u32bit n, u32bit align_to) - { - if(n % align_to || n == 0) - n += align_to - (n % align_to); - return n; - } - -/* -* Round down n to multiple of align_to -*/ -u32bit round_down(u32bit n, u32bit align_to) - { - return (n - (n % align_to)); - } - -/* * Choose the exponent size for a DL group */ u32bit dl_work_factor(u32bit bits) @@ -65,4 +47,5 @@ u32bit dl_work_factor(u32bit bits) #endif } + } diff --git a/src/pubkey/workfactor.h b/src/pubkey/workfactor.h new file mode 100644 index 000000000..653f697e3 --- /dev/null +++ b/src/pubkey/workfactor.h @@ -0,0 +1,22 @@ +/* +* Public Key Work Factor Functions +* (C) 1999-2007 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_WORKFACTOR_H__ +#define BOTAN_WORKFACTOR_H__ + +#include <botan/types.h> + +namespace Botan { + +/* +* Work Factor Estimates +*/ +BOTAN_DLL u32bit dl_work_factor(u32bit prime_group_size); + +} + +#endif diff --git a/src/rng/auto_rng/auto_rng.cpp b/src/rng/auto_rng/auto_rng.cpp index 8405170ad..f02a9249f 100644 --- a/src/rng/auto_rng/auto_rng.cpp +++ b/src/rng/auto_rng/auto_rng.cpp @@ -143,7 +143,7 @@ AutoSeeded_RNG::AutoSeeded_RNG(u32bit poll_bits) #endif if(!rng) - throw Algorithm_Not_Found("No usable RNG found enabled in build"); + throw Internal_Error("No usable RNG found enabled in build"); /* If X9.31 is available, use it to wrap the other RNG as a failsafe */ #if defined(BOTAN_HAS_X931_RNG) && defined(BOTAN_HAS_AES) diff --git a/src/rng/hmac_rng/hmac_rng.cpp b/src/rng/hmac_rng/hmac_rng.cpp index 113489db3..8444b1083 100644 --- a/src/rng/hmac_rng/hmac_rng.cpp +++ b/src/rng/hmac_rng/hmac_rng.cpp @@ -8,7 +8,6 @@ #include <botan/hmac_rng.h> #include <botan/loadstor.h> #include <botan/xor_buf.h> -#include <botan/util.h> #include <botan/stl_util.h> #include <algorithm> diff --git a/src/rng/randpool/randpool.cpp b/src/rng/randpool/randpool.cpp index 77a5228c6..fe83f4361 100644 --- a/src/rng/randpool/randpool.cpp +++ b/src/rng/randpool/randpool.cpp @@ -8,7 +8,7 @@ #include <botan/randpool.h> #include <botan/loadstor.h> #include <botan/xor_buf.h> -#include <botan/util.h> +#include <botan/timer.h> #include <botan/stl_util.h> #include <algorithm> diff --git a/src/selftest/info.txt b/src/selftest/info.txt index 323a610a6..c4b61bb99 100644 --- a/src/selftest/info.txt +++ b/src/selftest/info.txt @@ -11,11 +11,6 @@ selftest.h <requires> algo_factory -cbc -cfb -ctr -ecb filters -hmac -ofb +def_engine </requires> diff --git a/src/selftest/selftest.cpp b/src/selftest/selftest.cpp index d644e866e..660be36e4 100644 --- a/src/selftest/selftest.cpp +++ b/src/selftest/selftest.cpp @@ -7,12 +7,8 @@ #include <botan/selftest.h> #include <botan/filters.h> -#include <botan/ecb.h> -#include <botan/cbc.h> -#include <botan/cfb.h> -#include <botan/ofb.h> -#include <botan/ctr.h> -#include <botan/hmac.h> +#include <botan/def_eng.h> +#include <botan/stl_util.h> namespace Botan { @@ -21,23 +17,143 @@ namespace { /* * Perform a Known Answer Test */ -void do_kat(const std::string& in, const std::string& out, - const std::string& algo_name, Filter* filter) +bool test_filter_kat(Filter* filter, + const std::string& input, + const std::string& output) { - if(out.length()) + Pipe pipe(new Hex_Decoder, filter, new Hex_Encoder); + pipe.process_msg(input); + + return (output == pipe.read_all_as_string()); + } + +} + +/* +* Run a set of KATs +*/ +std::map<std::string, bool> +algorithm_kat(const SCAN_Name& algo_name, + const std::map<std::string, std::string>& vars, + Algorithm_Factory& af) + { + const std::string& algo = algo_name.algo_name_and_args(); + + std::vector<std::string> providers = af.providers_of(algo); + std::map<std::string, bool> all_results; + + if(providers.empty()) // no providers, nothing to do + return all_results; + + const std::string input = search_map(vars, std::string("input")); + const std::string output = search_map(vars, std::string("output")); + const std::string key = search_map(vars, std::string("key")); + const std::string iv = search_map(vars, std::string("iv")); + + for(u32bit i = 0; i != providers.size(); ++i) { - Pipe pipe(new Hex_Decoder, filter, new Hex_Encoder); - pipe.process_msg(in); + const std::string provider = providers[i]; - if(out != pipe.read_all_as_string()) - throw Self_Test_Failure(algo_name + " startup test"); + if(const HashFunction* proto = + af.prototype_hash_function(algo, provider)) + { + Filter* filt = new Hash_Filter(proto->clone()); + all_results[provider] = test_filter_kat(filt, input, output); + } + else if(const MessageAuthenticationCode* proto = + af.prototype_mac(algo, provider)) + { + Keyed_Filter* filt = new MAC_Filter(proto->clone(), key); + all_results[provider] = test_filter_kat(filt, input, output); + } + else if(const StreamCipher* proto = + af.prototype_stream_cipher(algo, provider)) + { + Keyed_Filter* filt = new StreamCipher_Filter(proto->clone()); + filt->set_key(key); + filt->set_iv(iv); + + all_results[provider] = test_filter_kat(filt, input, output); + } + else if(const BlockCipher* proto = + af.prototype_block_cipher(algo, provider)) + { + Keyed_Filter* enc = get_cipher_mode(proto, ENCRYPTION, + algo_name.cipher_mode(), + algo_name.cipher_mode_pad()); + + Keyed_Filter* dec = get_cipher_mode(proto, DECRYPTION, + algo_name.cipher_mode(), + algo_name.cipher_mode_pad()); + + if(!enc || !dec) + { + delete enc; + delete dec; + continue; + } + + enc->set_key(key); + enc->set_iv(iv); + + dec->set_key(key); + dec->set_iv(iv); + + bool enc_ok = test_filter_kat(enc, input, output); + bool dec_ok = test_filter_kat(dec, output, input); + + all_results[provider] = enc_ok && dec_ok; + } } + + return all_results; + } + +namespace { + +void verify_results(const std::string& algo, + const std::map<std::string, bool>& results) + { + for(std::map<std::string, bool>::const_iterator i = results.begin(); + i != results.end(); ++i) + { + if(!i->second) + throw Self_Test_Failure(algo + " self-test failed, provider "+ + i->first); + } + } + +void hash_test(Algorithm_Factory& af, + const std::string& name, + const std::string& in, + const std::string& out) + { + std::map<std::string, std::string> vars; + vars["input"] = in; + vars["output"] = out; + + verify_results(name, algorithm_kat(name, vars, af)); + } + +void mac_test(Algorithm_Factory& af, + const std::string& name, + const std::string& in, + const std::string& out, + const std::string& key) + { + std::map<std::string, std::string> vars; + vars["input"] = in; + vars["output"] = out; + vars["key"] = key; + + verify_results(name, algorithm_kat(name, vars, af)); } /* * Perform a KAT for a cipher */ -void cipher_kat(const BlockCipher* proto, +void cipher_kat(Algorithm_Factory& af, + const std::string& algo, const std::string& key_str, const std::string& iv_str, const std::string& in, @@ -50,27 +166,28 @@ void cipher_kat(const BlockCipher* proto, SymmetricKey key(key_str); InitializationVector iv(iv_str); - std::string name = proto->name(); + std::map<std::string, std::string> vars; + vars["key"] = key_str; + vars["iv"] = iv_str; + vars["input"] = in; + + std::map<std::string, bool> results; - do_kat(in, ecb_out, name + "/ECB", - new ECB_Encryption(proto->clone(), new Null_Padding, key)); - do_kat(ecb_out, in, name + "/ECB", - new ECB_Decryption(proto->clone(), new Null_Padding, key)); + vars["output"] = ecb_out; + verify_results(algo + "/ECB", algorithm_kat(algo + "/ECB", vars, af)); - do_kat(in, cbc_out, name + "/CBC", - new CBC_Encryption(proto->clone(), new Null_Padding, key, iv)); - do_kat(cbc_out, in, name + "/CBC", - new CBC_Decryption(proto->clone(), new Null_Padding, key, iv)); + vars["output"] = cbc_out; + verify_results(algo + "/CBC", + algorithm_kat(algo + "/CBC/NoPadding", vars, af)); - do_kat(in, cfb_out, name + "/CFB", - new CFB_Encryption(proto->clone(), key, iv)); - do_kat(cfb_out, in, name + "/CFB", - new CFB_Decryption(proto->clone(), key, iv)); + vars["output"] = cfb_out; + verify_results(algo + "/CFB", algorithm_kat(algo + "/CFB", vars, af)); - do_kat(in, ofb_out, name + "/OFB", new OFB(proto->clone(), key, iv)); + vars["output"] = ofb_out; + verify_results(algo + "/OFB", algorithm_kat(algo + "/OFB", vars, af)); - do_kat(in, ctr_out, name + "/CTR-BE", - new CTR_BE(proto->clone(), key, iv)); + vars["output"] = ctr_out; + verify_results(algo + "/CTR", algorithm_kat(algo + "/CTR-BE", vars, af)); } } @@ -82,9 +199,7 @@ bool passes_self_tests(Algorithm_Factory& af) { try { - if(const BlockCipher* proto = af.prototype_block_cipher("DES")) - { - cipher_kat(proto, + cipher_kat(af, "DES", "0123456789ABCDEF", "1234567890ABCDEF", "4E6F77206973207468652074696D6520666F7220616C6C20", "3FA40E8A984D48156A271787AB8883F9893D51EC4B563B53", @@ -92,11 +207,8 @@ bool passes_self_tests(Algorithm_Factory& af) "F3096249C7F46E51A69E839B1A92F78403467133898EA622", "F3096249C7F46E5135F24A242EEB3D3F3D6D5BE3255AF8C3", "F3096249C7F46E51163A8CA0FFC94C27FA2F80F480B86F75"); - } - if(const BlockCipher* proto = af.prototype_block_cipher("TripleDES")) - { - cipher_kat(proto, + cipher_kat(af, "TripleDES", "385D7189A5C3D485E1370AA5D408082B5CCCCB5E19F2D90E", "C141B5FCCD28DC8A", "6E1BD7C6120947A464A6AAB293A0F89A563D8D40D3461B68", @@ -105,75 +217,63 @@ bool passes_self_tests(Algorithm_Factory& af) "E26BA806A59B0330DE40CA38E77A3E494BE2B212F6DD624B", "E26BA806A59B03307DE2BCC25A08BA40A8BA335F5D604C62", "E26BA806A59B03303C62C2EFF32D3ACDD5D5F35EBCC53371"); - } - - if(const BlockCipher* proto = af.prototype_block_cipher("AES")) - { - cipher_kat(proto, - "2B7E151628AED2A6ABF7158809CF4F3C", - "000102030405060708090A0B0C0D0E0F", - "6BC1BEE22E409F96E93D7E117393172A" - "AE2D8A571E03AC9C9EB76FAC45AF8E51", - "3AD77BB40D7A3660A89ECAF32466EF97" - "F5D3D58503B9699DE785895A96FDBAAF", - "7649ABAC8119B246CEE98E9B12E9197D" - "5086CB9B507219EE95DB113A917678B2", - "3B3FD92EB72DAD20333449F8E83CFB4A" - "C8A64537A0B3A93FCDE3CDAD9F1CE58B", - "3B3FD92EB72DAD20333449F8E83CFB4A" - "7789508D16918F03F53C52DAC54ED825", - "3B3FD92EB72DAD20333449F8E83CFB4A" - "010C041999E03F36448624483E582D0E"); - } - - if(const HashFunction* proto = af.prototype_hash_function("SHA-1")) - { - do_kat("", "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709", - proto->name(), new Hash_Filter(proto->clone())); - - do_kat("616263", "A9993E364706816ABA3E25717850C26C9CD0D89D", - proto->name(), new Hash_Filter(proto->clone())); - - do_kat("6162636462636465636465666465666765666768666768696768696A" + + cipher_kat(af, "AES-128", + "2B7E151628AED2A6ABF7158809CF4F3C", + "000102030405060708090A0B0C0D0E0F", + "6BC1BEE22E409F96E93D7E117393172A" + "AE2D8A571E03AC9C9EB76FAC45AF8E51", + "3AD77BB40D7A3660A89ECAF32466EF97" + "F5D3D58503B9699DE785895A96FDBAAF", + "7649ABAC8119B246CEE98E9B12E9197D" + "5086CB9B507219EE95DB113A917678B2", + "3B3FD92EB72DAD20333449F8E83CFB4A" + "C8A64537A0B3A93FCDE3CDAD9F1CE58B", + "3B3FD92EB72DAD20333449F8E83CFB4A" + "7789508D16918F03F53C52DAC54ED825", + "3B3FD92EB72DAD20333449F8E83CFB4A" + "010C041999E03F36448624483E582D0E"); + + hash_test(af, "SHA-1", + "", "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709"); + + hash_test(af, "SHA-1", + "616263", "A9993E364706816ABA3E25717850C26C9CD0D89D"); + + hash_test(af, "SHA-1", + "6162636462636465636465666465666765666768666768696768696A" "68696A6B696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F7071", - "84983E441C3BD26EBAAE4AA1F95129E5E54670F1", - proto->name(), new Hash_Filter(proto->clone())); - - do_kat("4869205468657265", - "B617318655057264E28BC0B6FB378C8EF146BE00", - "HMAC(" + proto->name() + ")", - new MAC_Filter(new HMAC(proto->clone()), - SymmetricKey("0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B"))); - } - - if(const HashFunction* proto = af.prototype_hash_function("SHA-256")) - { - do_kat("", - "E3B0C44298FC1C149AFBF4C8996FB924" - "27AE41E4649B934CA495991B7852B855", - proto->name(), new Hash_Filter(proto->clone())); - - do_kat("616263", - "BA7816BF8F01CFEA414140DE5DAE2223" - "B00361A396177A9CB410FF61F20015AD", - proto->name(), new Hash_Filter(proto->clone())); - - do_kat("6162636462636465636465666465666765666768666768696768696A" + "84983E441C3BD26EBAAE4AA1F95129E5E54670F1"); + + mac_test(af, "HMAC(SHA-1)", + "4869205468657265", + "B617318655057264E28BC0B6FB378C8EF146BE00", + "0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B"); + + hash_test(af, "SHA-256", + "", + "E3B0C44298FC1C149AFBF4C8996FB924" + "27AE41E4649B934CA495991B7852B855"); + + hash_test(af, "SHA-256", + "616263", + "BA7816BF8F01CFEA414140DE5DAE2223" + "B00361A396177A9CB410FF61F20015AD"); + + hash_test(af, "SHA-256", + "6162636462636465636465666465666765666768666768696768696A" "68696A6B696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F7071", "248D6A61D20638B8E5C026930C3E6039" - "A33CE45964FF2167F6ECEDD419DB06C1", - proto->name(), new Hash_Filter(proto->clone())); - - do_kat("4869205468657265", - "198A607EB44BFBC69903A0F1CF2BBDC5" - "BA0AA3F3D9AE3C1C7A3B1696A0B68CF7", - "HMAC(" + proto->name() + ")", - new MAC_Filter(new HMAC(proto->clone()), - SymmetricKey("0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B" - "0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B"))); - } + "A33CE45964FF2167F6ECEDD419DB06C1"); + + mac_test(af, "HMAC(SHA-256)", + "4869205468657265", + "198A607EB44BFBC69903A0F1CF2BBDC5" + "BA0AA3F3D9AE3C1C7A3B1696A0B68CF7", + "0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B" + "0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B"); } - catch(std::exception) + catch(Self_Test_Failure) { return false; } diff --git a/src/selftest/selftest.h b/src/selftest/selftest.h index 9e36d2298..4cb6e23d7 100644 --- a/src/selftest/selftest.h +++ b/src/selftest/selftest.h @@ -9,6 +9,9 @@ #define BOTAN_SELF_TESTS_H__ #include <botan/algo_factory.h> +#include <botan/scan_name.h> +#include <map> +#include <string> namespace Botan { @@ -17,6 +20,11 @@ namespace Botan { */ BOTAN_DLL bool passes_self_tests(Algorithm_Factory& af); +BOTAN_DLL std::map<std::string, bool> +algorithm_kat(const SCAN_Name& algo_name, + const std::map<std::string, std::string>& vars, + Algorithm_Factory& af); + } #endif diff --git a/src/stream/salsa20/salsa20.cpp b/src/stream/salsa20/salsa20.cpp index 75137798c..9c7c811f0 100644 --- a/src/stream/salsa20/salsa20.cpp +++ b/src/stream/salsa20/salsa20.cpp @@ -6,10 +6,8 @@ */ #include <botan/salsa20.h> -#include <botan/mem_ops.h> #include <botan/xor_buf.h> #include <botan/loadstor.h> -#include <botan/parsing.h> namespace Botan { diff --git a/src/stream/turing/turing.cpp b/src/stream/turing/turing.cpp index b988568c3..1e2203480 100644 --- a/src/stream/turing/turing.cpp +++ b/src/stream/turing/turing.cpp @@ -218,25 +218,6 @@ u32bit Turing::fixedS(u32bit W) } /* -* Generate the expanded Turing Sbox tables -*/ -void Turing::gen_sbox(MemoryRegion<u32bit>& S, u32bit which, - const MemoryRegion<u32bit>& K) - { - for(u32bit j = 0; j != 256; ++j) - { - u32bit W = 0, C = j; - - for(u32bit k = 0; k < K.size(); ++k) - { - C = SBOX[get_byte(which, K[k]) ^ C]; - W ^= rotate_left(Q_BOX[C], k + 8*which); - } - S[j] = (W & rotate_right(0x00FFFFFF, 8*which)) | (C << (24 - 8*which)); - } - } - -/* * Turing Key Schedule */ void Turing::key_schedule(const byte key[], u32bit length) @@ -250,10 +231,31 @@ void Turing::key_schedule(const byte key[], u32bit length) PHT(K); - gen_sbox(S0, 0, K); - gen_sbox(S1, 1, K); - gen_sbox(S2, 2, K); - gen_sbox(S3, 3, K); + for(u32bit i = 0; i != 256; ++i) + { + u32bit W0 = 0, C0 = i; + u32bit W1 = 0, C1 = i; + u32bit W2 = 0, C2 = i; + u32bit W3 = 0, C3 = i; + + for(u32bit j = 0; j < K.size(); ++j) + { + C0 = SBOX[get_byte(0, K[j]) ^ C0]; + C1 = SBOX[get_byte(1, K[j]) ^ C1]; + C2 = SBOX[get_byte(2, K[j]) ^ C2]; + C3 = SBOX[get_byte(3, K[j]) ^ C3]; + + W0 ^= rotate_left(Q_BOX[C0], j); + W1 ^= rotate_left(Q_BOX[C1], j + 8); + W2 ^= rotate_left(Q_BOX[C2], j + 16); + W3 ^= rotate_left(Q_BOX[C3], j + 24); + } + + S0[i] = (W0 & 0x00FFFFFF) | (C0 << 24); + S1[i] = (W1 & 0xFF00FFFF) | (C1 << 16); + S2[i] = (W2 & 0xFFFF00FF) | (C2 << 8); + S3[i] = (W3 & 0xFFFFFF00) | C3; + } resync(0, 0); } diff --git a/src/stream/turing/turing.h b/src/stream/turing/turing.h index d48c1d8a8..455d3c612 100644 --- a/src/stream/turing/turing.h +++ b/src/stream/turing/turing.h @@ -29,8 +29,6 @@ class BOTAN_DLL Turing : public StreamCipher void generate(); static u32bit fixedS(u32bit); - static void gen_sbox(MemoryRegion<u32bit>&, u32bit, - const MemoryRegion<u32bit>&); static const u32bit Q_BOX[256]; static const byte SBOX[256]; diff --git a/src/timer/gettimeofday/tm_unix.cpp b/src/timer/gettimeofday/tm_unix.cpp index e32df7166..9d8ac4a04 100644 --- a/src/timer/gettimeofday/tm_unix.cpp +++ b/src/timer/gettimeofday/tm_unix.cpp @@ -6,7 +6,6 @@ */ #include <botan/tm_unix.h> -#include <botan/util.h> #include <sys/time.h> namespace Botan { diff --git a/src/timer/posix_rt/tm_posix.cpp b/src/timer/posix_rt/tm_posix.cpp index d356384ab..96182025c 100644 --- a/src/timer/posix_rt/tm_posix.cpp +++ b/src/timer/posix_rt/tm_posix.cpp @@ -6,7 +6,6 @@ */ #include <botan/tm_posix.h> -#include <botan/util.h> #ifndef _POSIX_C_SOURCE #define _POSIX_C_SOURCE 199309 diff --git a/src/timer/timer.cpp b/src/timer/timer.cpp index 035c217f9..16d7dc368 100644 --- a/src/timer/timer.cpp +++ b/src/timer/timer.cpp @@ -7,7 +7,6 @@ #include <botan/timer.h> #include <botan/loadstor.h> -#include <botan/util.h> #include <ctime> namespace Botan { @@ -20,6 +19,19 @@ u64bit system_time() return static_cast<u64bit>(std::time(0)); } +/* +* Convert a time_t to a struct tm +*/ +std::tm time_t_to_tm(u64bit timer) + { + std::time_t time_val = static_cast<std::time_t>(timer); + + 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); + } + /** * Read the clock and return the output */ diff --git a/src/timer/timer.h b/src/timer/timer.h index b6e8ef448..603027f6d 100644 --- a/src/timer/timer.h +++ b/src/timer/timer.h @@ -9,9 +9,17 @@ #define BOTAN_TIMERS_H__ #include <botan/rng.h> +#include <ctime> namespace Botan { +/* +* Time Access/Conversion Functions +*/ +BOTAN_DLL u64bit system_time(); + +BOTAN_DLL std::tm time_t_to_tm(u64bit); + /** * Timer Interface */ diff --git a/src/tss/info.txt b/src/tss/info.txt new file mode 100644 index 000000000..af4e0b930 --- /dev/null +++ b/src/tss/info.txt @@ -0,0 +1,8 @@ +realname "Threshold Secret Sharing" + +<requires> +hash +rng +filters +hex +</requires> diff --git a/src/tss/tss.cpp b/src/tss/tss.cpp new file mode 100644 index 000000000..3bd799727 --- /dev/null +++ b/src/tss/tss.cpp @@ -0,0 +1,263 @@ +/* +* RTSS (threshold secret sharing) +* (C) 2009 Jack Lloyd <[email protected]> +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/tss.h> +#include <botan/loadstor.h> +#include <botan/pipe.h> +#include <botan/hex.h> +#include <botan/sha2_32.h> +#include <botan/sha160.h> +#include <memory> + +namespace Botan { + +namespace { + +/** +Table for GF(2^8) arithmetic (exponentials) +*/ +const byte EXP[256] = { +0x01, 0x03, 0x05, 0x0F, 0x11, 0x33, 0x55, 0xFF, 0x1A, 0x2E, 0x72, +0x96, 0xA1, 0xF8, 0x13, 0x35, 0x5F, 0xE1, 0x38, 0x48, 0xD8, 0x73, +0x95, 0xA4, 0xF7, 0x02, 0x06, 0x0A, 0x1E, 0x22, 0x66, 0xAA, 0xE5, +0x34, 0x5C, 0xE4, 0x37, 0x59, 0xEB, 0x26, 0x6A, 0xBE, 0xD9, 0x70, +0x90, 0xAB, 0xE6, 0x31, 0x53, 0xF5, 0x04, 0x0C, 0x14, 0x3C, 0x44, +0xCC, 0x4F, 0xD1, 0x68, 0xB8, 0xD3, 0x6E, 0xB2, 0xCD, 0x4C, 0xD4, +0x67, 0xA9, 0xE0, 0x3B, 0x4D, 0xD7, 0x62, 0xA6, 0xF1, 0x08, 0x18, +0x28, 0x78, 0x88, 0x83, 0x9E, 0xB9, 0xD0, 0x6B, 0xBD, 0xDC, 0x7F, +0x81, 0x98, 0xB3, 0xCE, 0x49, 0xDB, 0x76, 0x9A, 0xB5, 0xC4, 0x57, +0xF9, 0x10, 0x30, 0x50, 0xF0, 0x0B, 0x1D, 0x27, 0x69, 0xBB, 0xD6, +0x61, 0xA3, 0xFE, 0x19, 0x2B, 0x7D, 0x87, 0x92, 0xAD, 0xEC, 0x2F, +0x71, 0x93, 0xAE, 0xE9, 0x20, 0x60, 0xA0, 0xFB, 0x16, 0x3A, 0x4E, +0xD2, 0x6D, 0xB7, 0xC2, 0x5D, 0xE7, 0x32, 0x56, 0xFA, 0x15, 0x3F, +0x41, 0xC3, 0x5E, 0xE2, 0x3D, 0x47, 0xC9, 0x40, 0xC0, 0x5B, 0xED, +0x2C, 0x74, 0x9C, 0xBF, 0xDA, 0x75, 0x9F, 0xBA, 0xD5, 0x64, 0xAC, +0xEF, 0x2A, 0x7E, 0x82, 0x9D, 0xBC, 0xDF, 0x7A, 0x8E, 0x89, 0x80, +0x9B, 0xB6, 0xC1, 0x58, 0xE8, 0x23, 0x65, 0xAF, 0xEA, 0x25, 0x6F, +0xB1, 0xC8, 0x43, 0xC5, 0x54, 0xFC, 0x1F, 0x21, 0x63, 0xA5, 0xF4, +0x07, 0x09, 0x1B, 0x2D, 0x77, 0x99, 0xB0, 0xCB, 0x46, 0xCA, 0x45, +0xCF, 0x4A, 0xDE, 0x79, 0x8B, 0x86, 0x91, 0xA8, 0xE3, 0x3E, 0x42, +0xC6, 0x51, 0xF3, 0x0E, 0x12, 0x36, 0x5A, 0xEE, 0x29, 0x7B, 0x8D, +0x8C, 0x8F, 0x8A, 0x85, 0x94, 0xA7, 0xF2, 0x0D, 0x17, 0x39, 0x4B, +0xDD, 0x7C, 0x84, 0x97, 0xA2, 0xFD, 0x1C, 0x24, 0x6C, 0xB4, 0xC7, +0x52, 0xF6, 0x01 }; + +/** +Table for GF(2^8) arithmetic (logarithms) +*/ +const byte LOG[] = { +0x90, 0x00, 0x19, 0x01, 0x32, 0x02, 0x1A, 0xC6, 0x4B, 0xC7, 0x1B, +0x68, 0x33, 0xEE, 0xDF, 0x03, 0x64, 0x04, 0xE0, 0x0E, 0x34, 0x8D, +0x81, 0xEF, 0x4C, 0x71, 0x08, 0xC8, 0xF8, 0x69, 0x1C, 0xC1, 0x7D, +0xC2, 0x1D, 0xB5, 0xF9, 0xB9, 0x27, 0x6A, 0x4D, 0xE4, 0xA6, 0x72, +0x9A, 0xC9, 0x09, 0x78, 0x65, 0x2F, 0x8A, 0x05, 0x21, 0x0F, 0xE1, +0x24, 0x12, 0xF0, 0x82, 0x45, 0x35, 0x93, 0xDA, 0x8E, 0x96, 0x8F, +0xDB, 0xBD, 0x36, 0xD0, 0xCE, 0x94, 0x13, 0x5C, 0xD2, 0xF1, 0x40, +0x46, 0x83, 0x38, 0x66, 0xDD, 0xFD, 0x30, 0xBF, 0x06, 0x8B, 0x62, +0xB3, 0x25, 0xE2, 0x98, 0x22, 0x88, 0x91, 0x10, 0x7E, 0x6E, 0x48, +0xC3, 0xA3, 0xB6, 0x1E, 0x42, 0x3A, 0x6B, 0x28, 0x54, 0xFA, 0x85, +0x3D, 0xBA, 0x2B, 0x79, 0x0A, 0x15, 0x9B, 0x9F, 0x5E, 0xCA, 0x4E, +0xD4, 0xAC, 0xE5, 0xF3, 0x73, 0xA7, 0x57, 0xAF, 0x58, 0xA8, 0x50, +0xF4, 0xEA, 0xD6, 0x74, 0x4F, 0xAE, 0xE9, 0xD5, 0xE7, 0xE6, 0xAD, +0xE8, 0x2C, 0xD7, 0x75, 0x7A, 0xEB, 0x16, 0x0B, 0xF5, 0x59, 0xCB, +0x5F, 0xB0, 0x9C, 0xA9, 0x51, 0xA0, 0x7F, 0x0C, 0xF6, 0x6F, 0x17, +0xC4, 0x49, 0xEC, 0xD8, 0x43, 0x1F, 0x2D, 0xA4, 0x76, 0x7B, 0xB7, +0xCC, 0xBB, 0x3E, 0x5A, 0xFB, 0x60, 0xB1, 0x86, 0x3B, 0x52, 0xA1, +0x6C, 0xAA, 0x55, 0x29, 0x9D, 0x97, 0xB2, 0x87, 0x90, 0x61, 0xBE, +0xDC, 0xFC, 0xBC, 0x95, 0xCF, 0xCD, 0x37, 0x3F, 0x5B, 0xD1, 0x53, +0x39, 0x84, 0x3C, 0x41, 0xA2, 0x6D, 0x47, 0x14, 0x2A, 0x9E, 0x5D, +0x56, 0xF2, 0xD3, 0xAB, 0x44, 0x11, 0x92, 0xD9, 0x23, 0x20, 0x2E, +0x89, 0xB4, 0x7C, 0xB8, 0x26, 0x77, 0x99, 0xE3, 0xA5, 0x67, 0x4A, +0xED, 0xDE, 0xC5, 0x31, 0xFE, 0x18, 0x0D, 0x63, 0x8C, 0x80, 0xC0, +0xF7, 0x70, 0x07 }; + +byte gfp_mul(byte x, byte y) + { + if(x == 0 || y == 0) + return 0; + return EXP[(LOG[x] + LOG[y]) % 255]; + } + +byte rtss_hash_id(const std::string& hash_name) + { + if(hash_name == "SHA-160") + return 1; + else if(hash_name == "SHA-256") + return 2; + else + throw Invalid_Argument("RTSS only supports SHA-1 and SHA-256"); + } + +HashFunction* get_rtss_hash_by_id(byte id) + { + if(id == 1) + return new SHA_160; + else if(id == 2) + return new SHA_256; + else + throw Decoding_Error("Bad RTSS hash identifier"); + } + +} + +RTSS_Share::RTSS_Share(const std::string& hex_input) + { + Pipe pipe(new Hex_Decoder); + pipe.process_msg(hex_input); + contents = pipe.read_all(); + } + +byte RTSS_Share::share_id() const + { + if(!initialized()) + throw Invalid_State("RTSS_Share::share_id not initialized"); + + return contents[20]; + } + +std::string RTSS_Share::to_string() const + { + Pipe pipe(new Hex_Encoder); + pipe.process_msg(contents); + return pipe.read_all_as_string(); + } + +std::vector<RTSS_Share> +RTSS_Share::split(byte M, byte N, + const byte S[], u16bit S_len, + const byte identifier[16], + RandomNumberGenerator& rng) + { + if(M == 0 || N == 0 || M > N) + throw Encoding_Error("RTSS_Share::split: M == 0 or N == 0 or M > N"); + + SHA_256 hash; // always use SHA-256 when generating shares + + std::vector<RTSS_Share> shares(N); + + // Create RTSS header in each share + for(byte i = 0; i != N; ++i) + { + shares[i].contents.append(identifier, 16); + shares[i].contents.append(rtss_hash_id(hash.name())); + shares[i].contents.append(M); + shares[i].contents.append(get_byte(0, S_len)); + shares[i].contents.append(get_byte(1, S_len)); + } + + // Choose sequential values for X starting from 1 + for(byte i = 0; i != N; ++i) + shares[i].contents.append(i+1); + + // secret = S || H(S) + SecureVector<byte> secret(S, S_len); + secret.append(hash.process(S, S_len)); + + for(size_t i = 0; i != secret.size(); ++i) + { + std::vector<byte> coefficients(M-1); + rng.randomize(&coefficients[0], coefficients.size()); + + for(byte j = 0; j != N; ++j) + { + const byte X = j + 1; + + byte sum = secret[i]; + byte X_i = X; + + for(size_t k = 0; k != coefficients.size(); ++k) + { + sum ^= gfp_mul(X_i, coefficients[k]); + X_i = gfp_mul(X_i, X); + } + + shares[j].contents.append(sum); + } + } + + return shares; + } + +SecureVector<byte> +RTSS_Share::reconstruct(const std::vector<RTSS_Share>& shares) + { + const u32bit RTSS_HEADER_SIZE = 20; + + for(size_t i = 0; i != shares.size(); ++i) + { + if(shares[i].size() != shares[0].size()) + throw Decoding_Error("Different sized RTSS shares detected"); + if(shares[i].share_id() == 0) + throw Decoding_Error("Invalid (id = 0) RTSS share detected"); + if(shares[i].size() < RTSS_HEADER_SIZE) + throw Decoding_Error("Missing or malformed RTSS header"); + + if(!same_mem(shares[0].contents.begin(), + shares[i].contents.begin(), RTSS_HEADER_SIZE)) + throw Decoding_Error("Different RTSS headers detected"); + } + + if(shares.size() < shares[0].contents[17]) + throw Decoding_Error("Insufficient shares to do TSS reconstruction"); + + u16bit secret_len = make_u16bit(shares[0].contents[18], + shares[0].contents[19]); + + byte hash_id = shares[0].contents[16]; + + std::auto_ptr<HashFunction> hash(get_rtss_hash_by_id(hash_id)); + + if(shares[0].size() != secret_len + hash->OUTPUT_LENGTH + RTSS_HEADER_SIZE + 1) + throw Decoding_Error("Bad RTSS length field in header"); + + std::vector<byte> V(shares.size()); + SecureVector<byte> secret; + + for(size_t i = RTSS_HEADER_SIZE + 1; i != shares[0].size(); ++i) + { + for(size_t j = 0; j != V.size(); ++j) + V[j] = shares[j].contents[i]; + + byte r = 0; + for(size_t k = 0; k != shares.size(); ++k) + { + // L_i function: + byte r2 = 1; + for(size_t l = 0; l != shares.size(); ++l) + { + if(k == l) + continue; + + byte share_k = shares[k].share_id(); + byte share_l = shares[l].share_id(); + + if(share_k == share_l) + throw Decoding_Error("Duplicate shares found in RTSS recovery"); + + byte div = EXP[(255 + LOG[share_l] - LOG[share_k ^ share_l]) % 255]; + + r2 = gfp_mul(r2, div); + } + + r ^= gfp_mul(V[k], r2); + } + secret.append(r); + } + + if(secret.size() != secret_len + hash->OUTPUT_LENGTH) + throw Decoding_Error("Bad length in RTSS output"); + + hash->update(secret, secret_len); + SecureVector<byte> hash_check = hash->final(); + + if(!same_mem(hash_check.begin(), secret + secret_len, hash->OUTPUT_LENGTH)) + throw Decoding_Error("RTSS hash check failed"); + + return SecureVector<byte>(secret, secret_len); + } + +} diff --git a/src/tss/tss.h b/src/tss/tss.h new file mode 100644 index 000000000..0b26bfdcb --- /dev/null +++ b/src/tss/tss.h @@ -0,0 +1,55 @@ +/* +* RTSS (threshold secret sharing) +* (C) 2009 Jack Lloyd <[email protected]> +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_RTSS_H__ +#define BOTAN_RTSS_H__ + +#include <botan/secmem.h> +#include <botan/hash.h> +#include <botan/rng.h> +#include <vector> + +namespace Botan { + +class RTSS_Share + { + public: + /** + * @arg M the number of shares needed to reconstruct + * @arg N the number of shares generated + * @arg secret the secret to split + * @arg secret_len the length of the secret + * @arg identifier the 16 byte share identifier + * @arg rng the random number generator to use + */ + static std::vector<RTSS_Share> + split(byte M, byte N, + const byte secret[], u16bit secret_len, + const byte identifier[16], + RandomNumberGenerator& rng); + + /** + * @arg shares the list of shares + */ + static SecureVector<byte> + reconstruct(const std::vector<RTSS_Share>& shares); + + RTSS_Share() {} + RTSS_Share(const std::string&); + + std::string to_string() const; + byte share_id() const; + + u32bit size() const { return contents.size(); } + bool initialized() const { return contents.size(); } + private: + SecureVector<byte> contents; + }; + +} + +#endif diff --git a/src/utils/asm_amd64/info.txt b/src/utils/asm_amd64/info.txt index 19035b545..6fa4d1de5 100644 --- a/src/utils/asm_amd64/info.txt +++ b/src/utils/asm_amd64/info.txt @@ -14,3 +14,7 @@ amd64 gcc icc </cc> + +<requires> +amd64_eng +</requires> diff --git a/src/utils/asm_ia32/info.txt b/src/utils/asm_ia32/info.txt index 4340c35aa..8485d33b9 100644 --- a/src/utils/asm_ia32/info.txt +++ b/src/utils/asm_ia32/info.txt @@ -14,3 +14,7 @@ ia32 gcc icc </cc> + +<requires> +ia32_eng +</requires> diff --git a/src/utils/cpuid.cpp b/src/utils/cpuid.cpp new file mode 100644 index 000000000..ae82bdac8 --- /dev/null +++ b/src/utils/cpuid.cpp @@ -0,0 +1,98 @@ +/** +* Runtime CPU detection +* (C) 2009 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/cpuid.h> +#include <botan/types.h> +#include <botan/loadstor.h> +#include <botan/mem_ops.h> + +#if defined(BOTAN_TARGET_ARCH_IS_X86) || defined(BOTAN_TARGET_ARCH_IS_AMD64) + +#if defined(BOTAN_BUILD_COMPILER_IS_MSVC) + + #include <intrin.h> + #define CALL_CPUID(type, out) do { __cpuid(out, type) } while(0) + +#elif defined(BOTAN_BUILD_COMPILER_IS_ICC) + + #include <ia32intrin.h> + #define CALL_CPUID(type, out) do { __cpuid(out, type) } while(0); + +#elif defined(BOTAN_BUILD_COMPILER_IS_GCC) + + #include <cpuid.h> + #define CALL_CPUID(type, out) \ + do { __get_cpuid(type, out, out+1, out+2, out+3); } while(0); + +#endif + +#else + // In all other cases, just zeroize the supposed cpuid output + #define CALL_CPUID(type, out) out[0] = out[1] = out[2] = out[3] = 0; +#endif + +namespace Botan { + +namespace { + +u32bit get_x86_cache_line_size() + { + const u32bit INTEL_CPUID[3] = { 0x756E6547, 0x6C65746E, 0x49656E69 }; + const u32bit AMD_CPUID[3] = { 0x68747541, 0x444D4163, 0x69746E65 }; + + u32bit cpuid[4] = { 0 }; + CALL_CPUID(0, cpuid); + + if(same_mem(cpuid + 1, INTEL_CPUID, 3)) + { + CALL_CPUID(1, cpuid); + return 8 * get_byte(2, cpuid[1]); + } + else if(same_mem(cpuid + 1, AMD_CPUID, 3)) + { + CALL_CPUID(0x80000005, cpuid); + return get_byte(3, cpuid[2]); + } + else + return 32; // default cache line guess + } + +} + +/* +* Call the x86 CPUID instruction and return the contents of ecx and +* edx, which contain the feature masks. +*/ +u64bit CPUID::x86_processor_flags() + { + static u64bit proc_flags = 0; + + if(proc_flags) + return proc_flags; + + u32bit cpuid[4] = { 0 }; + CALL_CPUID(1, cpuid); + + // Set the FPU bit on to force caching in proc_flags + proc_flags = ((u64bit)cpuid[2] << 32) | cpuid[3] | 1; + + return proc_flags; + } + +u32bit CPUID::cache_line_size() + { + static u32bit cl_size = 0; + + if(cl_size) + return cl_size; + + cl_size = get_x86_cache_line_size(); + + return cl_size; + } + +} diff --git a/src/utils/cpuid.h b/src/utils/cpuid.h new file mode 100644 index 000000000..0b210768a --- /dev/null +++ b/src/utils/cpuid.h @@ -0,0 +1,74 @@ +/** +* Runtime CPU detection +* (C) 2009 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_CPUID_H__ +#define BOTAN_CPUID_H__ + +#include <botan/types.h> + +namespace Botan { + +class CPUID + { + public: + enum CPUID_bits { + CPUID_RDTSC_BIT = 4, + CPUID_SSE2_BIT = 26, + CPUID_SSSE3_BIT = 41, + CPUID_SSE41_BIT = 51, + CPUID_SSE42_BIT = 52, + CPUID_INTEL_AES_BIT = 57, + }; + + /** + * Return a best guess of the cache line size + */ + static u32bit cache_line_size(); + + /** + * Check if the processor supports RDTSC + */ + static bool has_rdtsc() + { return ((x86_processor_flags() >> CPUID_RDTSC_BIT) & 1); } + + /** + * Check if the processor supports SSE2 + */ + static bool has_sse2() + { return ((x86_processor_flags() >> CPUID_SSE2_BIT) & 1); } + + /** + * Check if the processor supports SSSE3 + */ + static bool has_ssse3() + { return ((x86_processor_flags() >> CPUID_SSSE3_BIT) & 1); } + + /** + * Check if the processor supports SSE4.1 + */ + static bool has_sse41() + { return ((x86_processor_flags() >> CPUID_SSE41_BIT) & 1); } + + /** + * Check if the processor supports SSE4.2 + */ + static bool has_sse42() + { return ((x86_processor_flags() >> CPUID_SSE42_BIT) & 1); } + + /** + * Check if the processor supports Intel AES instructions + */ + static bool has_intel_aes() + { return ((x86_processor_flags() >> CPUID_INTEL_AES_BIT) & 1); } + + private: + static u64bit x86_processor_flags(); + }; + +} + +#endif diff --git a/src/utils/info.txt b/src/utils/info.txt index ab50b88ad..6380fd6c2 100644 --- a/src/utils/info.txt +++ b/src/utils/info.txt @@ -7,27 +7,3 @@ load_on always <libs> tru64 -> rt </libs> - -<add> -bit_ops.h -bswap.h -charset.cpp -charset.h -exceptn.cpp -exceptn.h -loadstor.h -mem_ops.h -mlock.cpp -parsing.cpp -parsing.h -rotate.h -stl_util.h -types.h -ui.cpp -ui.h -util.cpp -util.h -version.cpp -version.h -xor_buf.h -</add> diff --git a/src/utils/loadstor.h b/src/utils/loadstor.h index 77ed1554e..8c64deaee 100644 --- a/src/utils/loadstor.h +++ b/src/utils/loadstor.h @@ -12,6 +12,7 @@ #include <botan/types.h> #include <botan/bswap.h> #include <botan/rotate.h> +#include <botan/prefetch.h> #if BOTAN_TARGET_UNALIGNED_LOADSTOR_OK diff --git a/src/utils/mlock.cpp b/src/utils/mlock.cpp index 9bb062da5..6453d8a30 100644 --- a/src/utils/mlock.cpp +++ b/src/utils/mlock.cpp @@ -5,7 +5,7 @@ * Distributed under the terms of the Botan license */ -#include <botan/util.h> +#include <botan/mlock.h> #if defined(BOTAN_TARGET_OS_HAS_POSIX_MLOCK) #include <sys/types.h> diff --git a/src/utils/mlock.h b/src/utils/mlock.h new file mode 100644 index 000000000..0811e8190 --- /dev/null +++ b/src/utils/mlock.h @@ -0,0 +1,32 @@ +/* +* Memory Locking Functions +* (C) 1999-2007 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_MLOCK_H__ +#define BOTAN_MLOCK_H__ + +#include <botan/types.h> + +namespace Botan { + +/** +* Lock memory into RAM if possible +* @param addr the start of the memory block +* @param length the length of the memory block in bytes +* @returns true if successful, false otherwise +*/ +BOTAN_DLL bool lock_mem(void* addr, u32bit length); + +/** +* Unlock memory locked with lock_mem() +* @param addr the start of the memory block +* @param length the length of the memory block in bytes +*/ +BOTAN_DLL void unlock_mem(void* addr, u32bit length); + +} + +#endif diff --git a/src/utils/parsing.cpp b/src/utils/parsing.cpp index bdb9e79dc..58a8e0b38 100644 --- a/src/utils/parsing.cpp +++ b/src/utils/parsing.cpp @@ -23,6 +23,9 @@ u32bit to_u32bit(const std::string& number) { const u32bit OVERFLOW_MARK = 0xFFFFFFFF / 10; + if(*j == ' ') + continue; + byte digit = Charset::char2digit(*j); if((n > OVERFLOW_MARK) || (n == OVERFLOW_MARK && digit > 5)) diff --git a/src/utils/prefetch.h b/src/utils/prefetch.h new file mode 100644 index 000000000..7afdbda0a --- /dev/null +++ b/src/utils/prefetch.h @@ -0,0 +1,43 @@ +/* +* Prefetching Operations +* (C) 2009 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_PREFETCH_H__ +#define BOTAN_PREFETCH_H__ + +#include <botan/cpuid.h> + +namespace Botan { + +namespace PREFETCH { + +template<typename T> +inline void readonly(const T* addr, u32bit length) + { +#if defined(__GNUG__) + const u32bit Ts_per_cache_line = CPUID::cache_line_size() / sizeof(T); + + for(u32bit i = 0; i <= length; i += Ts_per_cache_line) + __builtin_prefetch(addr + i, 0); +#endif + } + +template<typename T> +inline void readwrite(const T* addr, u32bit length) + { +#if defined(__GNUG__) + const u32bit Ts_per_cache_line = CPUID::cache_line_size() / sizeof(T); + + for(u32bit i = 0; i <= length; i += Ts_per_cache_line) + __builtin_prefetch(addr + i, 0); +#endif + } + +} + +} + +#endif diff --git a/src/utils/rounding.h b/src/utils/rounding.h new file mode 100644 index 000000000..11ab90b8d --- /dev/null +++ b/src/utils/rounding.h @@ -0,0 +1,35 @@ +/* +* Integer Rounding Functions +* (C) 1999-2007 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_ROUNDING_H__ +#define BOTAN_ROUNDING_H__ + +#include <botan/types.h> + +namespace Botan { + +/* +* Round up n to multiple of align_to +*/ +inline u32bit round_up(u32bit n, u32bit align_to) + { + if(n % align_to || n == 0) + n += align_to - (n % align_to); + return n; + } + +/* +* Round down n to multiple of align_to +*/ +inline u32bit round_down(u32bit n, u32bit align_to) + { + return (n - (n % align_to)); + } + +} + +#endif diff --git a/src/utils/util.h b/src/utils/util.h deleted file mode 100644 index ac7867390..000000000 --- a/src/utils/util.h +++ /dev/null @@ -1,39 +0,0 @@ -/* -* Utility Functions -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_UTIL_H__ -#define BOTAN_UTIL_H__ - -#include <botan/types.h> - -namespace Botan { - -/* -* Time Access Functions -*/ -BOTAN_DLL u64bit system_time(); - -/* -* Memory Locking Functions -*/ -BOTAN_DLL bool lock_mem(void*, u32bit); -BOTAN_DLL void unlock_mem(void*, u32bit); - -/* -* Misc Utility Functions -*/ -BOTAN_DLL u32bit round_up(u32bit, u32bit); -BOTAN_DLL u32bit round_down(u32bit, u32bit); - -/* -* Work Factor Estimates -*/ -BOTAN_DLL u32bit dl_work_factor(u32bit); - -} - -#endif diff --git a/src/wrap/perl-xs/Botan.pm b/src/wrap/perl-xs/Botan.pm new file mode 100644 index 000000000..ac4ad91fb --- /dev/null +++ b/src/wrap/perl-xs/Botan.pm @@ -0,0 +1,117 @@ +package Botan; + +use strict; +use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $AUTOLOAD); + +require DynaLoader; +require AutoLoader; +use Carp; + +@ISA = qw(DynaLoader); +$VERSION = '0.01'; + +@EXPORT_OK = qw( + NONE + IGNORE_WS + FULL_CHECK +); + +%EXPORT_TAGS = ( + 'all' => [ @EXPORT_OK ], + 'decoder_checking' => [ qw( + NONE + IGNORE_WS + FULL_CHECK + )], + +); + + +sub AUTOLOAD +{ + # This AUTOLOAD is used to 'autoload' constants from the constant() + # XS function. If a constant is not found then control is passed + # to the AUTOLOAD in AutoLoader. + + my $constname = $AUTOLOAD; + $constname =~ s/.*:://; + croak '& not defined' if $constname eq 'constant'; +# my $val = constant($constname, @_ ? $_[0] : 0); + my $val = constant($constname); + if ($! != 0) { + if ( $! =~ /Invalid/ ) + { + $AutoLoader::AUTOLOAD = $AUTOLOAD; + goto &AutoLoader::AUTOLOAD; + } + else + { + croak "Your vendor has not defined Botan symbol $constname"; + } + } + no strict 'refs'; + *$AUTOLOAD = sub { $val }; + goto &$AUTOLOAD; +} + + +bootstrap Botan $VERSION; + +# to setup inheritance... + +package Botan::Filter; +use vars qw(@ISA); +@ISA = qw(); + +package Botan::Chain; +use vars qw(@ISA); +@ISA = qw( Botan::Filter ); + +package Botan::Fork; +use vars qw(@ISA); +@ISA = qw( Botan::Filter ); + +package Botan::Hex_Encoder; +use vars qw(@ISA); +@ISA = qw( Botan::Filter ); + +package Botan::Hex_Decoder; +use vars qw(@ISA); +@ISA = qw( Botan::Filter ); + +package Botan::Base64_Decoder; +use vars qw(@ISA); +@ISA = qw( Botan::Filter ); + +package Botan::Base64_Encoder; +use vars qw(@ISA); +@ISA = qw( Botan::Filter ); + + +package Botan; + +1; +__END__ + +=head1 NAME + +Botan - Perl extension for access to Botan ... + +=head1 SYNOPSIS + + use Botan; + blah blah blah + +=head1 DESCRIPTION + +Blah blah blah. + +=head1 AUTHOR + +Vaclav Ovsik <[email protected]> + +=head1 SEE ALSO + +Bla + +=cut diff --git a/src/wrap/perl-xs/Botan.xs b/src/wrap/perl-xs/Botan.xs new file mode 100644 index 000000000..ded129d2e --- /dev/null +++ b/src/wrap/perl-xs/Botan.xs @@ -0,0 +1,829 @@ +#ifdef __cplusplus +extern "C" { +#endif + +#include "EXTERN.h" +#include "perl.h" +#include "XSUB.h" + +#ifdef __cplusplus +} +#endif + +#include <botan/asn1_obj.h> +#include <botan/asn1_oid.h> +#include <botan/base64.h> +#include <botan/basefilt.h> +#include <botan/hex.h> +#include <botan/init.h> +#include <botan/oids.h> +#include <botan/x509cert.h> +#include <botan/x509_ext.h> + + +/* xsubpp converts ':' to '_' in typemap. We create our types without ':' */ + +typedef Botan::ASN1_String Botan__ASN1_String; +typedef Botan::AlgorithmIdentifier Botan__AlgorithmIdentifier; +typedef Botan::AlternativeName Botan__AlternativeName; +typedef Botan::Attribute Botan__Attribute; +typedef Botan::Base64_Decoder Botan__Base64_Decoder; +typedef Botan::Base64_Encoder Botan__Base64_Encoder; +typedef Botan::Chain Botan__Chain; +typedef Botan::Certificate_Extension Botan__Extension; +typedef Botan::Filter Botan__Filter; +typedef Botan::Fork Botan__Fork; +typedef Botan::Hex_Decoder Botan__Hex_Decoder; +typedef Botan::Hex_Encoder Botan__Hex_Encoder; +typedef Botan::OID Botan__OID; +typedef Botan::Pipe Botan__Pipe; +typedef Botan::X509_Certificate Botan__X509_Certificate; +typedef Botan::X509_DN Botan__X509_DN; +typedef Botan::X509_Time Botan__X509_Time; +typedef Botan::u32bit Botan__u32bit; + + +/* Types to keep track of destruction C++ objects passed + * into other objects... + * An Botan object is deleted by his parent object into which is passed, + * e.g. some Filter is deleted when his Pipe is destructed. We must + * track this and not to delete object again in Perls destructor. + */ + +class ObjectInfo +{ +private: + I32 d_signature; + bool d_del; +public: + static I32 const SIGNVAL = 0x696a626f; + ObjectInfo() : d_signature(SIGNVAL), + d_del(true) {}; + ~ObjectInfo() {}; + void set_delete(bool del = true) { d_del = del; }; + void set_delete_no() { set_delete(false); }; + void set_delete_yes() { set_delete(true); }; + bool should_delete() const { return d_del; }; +}; + +/* Constant object in initial state - template */ + +ObjectInfo const oi_init; + + +/* Botan library initializer ... */ + +Botan::LibraryInitializer botan_init; + + + +/*============================================================================*/ + +MODULE = Botan PACKAGE = Botan + +PROTOTYPES: ENABLE + +void +constant(char *name) + CODE: + using namespace Botan; + errno = 0; + switch (name[0]) + { + case 'F': + if ( strEQ(name, "FULL_CHECK") ) + XSRETURN_IV( FULL_CHECK ); // Decoder_Checking enum + break; + case 'I': + if ( strEQ(name, "IGNORE_WS") ) + XSRETURN_IV( IGNORE_WS ); // Decoder_Checking enum + break; + case 'N': + if ( strEQ(name, "NONE") ) + XSRETURN_IV( NONE ); // Decoder_Checking enum + break; + } + errno = EINVAL; + XSRETURN_UNDEF; + + +# =========================== Botan::Chain ========================== + +MODULE = Botan PACKAGE = Botan::Chain + +Botan__Chain * +Botan__Chain::new(f1 = 0, f2 = 0, f3 = 0, f4 = 0) + Botan__Filter *f1; + Botan__Filter *f2; + Botan__Filter *f3; + Botan__Filter *f4; + PREINIT: + ObjectInfo *f1_oi; + ObjectInfo *f2_oi; + ObjectInfo *f3_oi; + ObjectInfo *f4_oi; + CODE: + try { + RETVAL = new Botan__Chain(f1, f2, f3, f4); + if ( f1 ) f1_oi->set_delete_no(); + if ( f2 ) f2_oi->set_delete_no(); + if ( f3 ) f3_oi->set_delete_no(); + if ( f4 ) f4_oi->set_delete_no(); + } + catch (const std::exception &e) { + croak(e.what()); + } + OUTPUT: + RETVAL + +void +Botan__Chain::DESTROY() + PREINIT: + ObjectInfo *THIS_oi; + CODE: + if ( THIS_oi->should_delete() ) + try { + delete THIS; + } + catch (const std::exception &e) { + croak(e.what()); + } + + +# =========================== Botan::Fork ========================== + +MODULE = Botan PACKAGE = Botan::Fork + +Botan__Fork * +Botan__Fork::new(f1 = 0, f2 = 0, f3 = 0, f4 = 0) + Botan__Filter *f1; + Botan__Filter *f2; + Botan__Filter *f3; + Botan__Filter *f4; + PREINIT: + ObjectInfo *f1_oi; + ObjectInfo *f2_oi; + ObjectInfo *f3_oi; + ObjectInfo *f4_oi; + CODE: + try { + RETVAL = new Botan__Fork(f1, f2, f3, f4); + if ( f1 ) f1_oi->set_delete_no(); + if ( f2 ) f2_oi->set_delete_no(); + if ( f3 ) f3_oi->set_delete_no(); + if ( f4 ) f4_oi->set_delete_no(); + } + catch (const std::exception &e) { + croak(e.what()); + } + OUTPUT: + RETVAL + +void +Botan__Fork::DESTROY() + PREINIT: + ObjectInfo *THIS_oi; + CODE: + if ( THIS_oi->should_delete() ) + try { + delete THIS; + } + catch (const std::exception &e) { + croak(e.what()); + } + + +# ============================ Botan::Base64_Decoder ============================ + +MODULE = Botan PACKAGE = Botan::Base64_Decoder + +Botan__Base64_Decoder * +Botan__Base64_Decoder::new(checking = Botan::NONE) + int checking; + CODE: + try { + using namespace Botan; + RETVAL = new Base64_Decoder((Decoder_Checking)checking); + } + catch (const std::exception &e) { + croak(e.what()); + } + OUTPUT: + RETVAL + +void +Botan__Base64_Decoder::DESTROY() + PREINIT: + ObjectInfo *THIS_oi; + CODE: + if ( THIS_oi->should_delete() ) + try { + delete THIS; + } + catch (const std::exception &e) { + croak(e.what()); + } + + +# =========================== Botan::Base64_Encoder ========================== + +MODULE = Botan PACKAGE = Botan::Base64_Encoder + +Botan__Base64_Encoder * +Botan__Base64_Encoder::new(breaks = false, length = 72) + bool breaks; + Botan__u32bit length; + CODE: + try { + RETVAL = new Botan__Base64_Encoder(breaks, length); + } + catch (const std::exception &e) { + croak(e.what()); + } + OUTPUT: + RETVAL + +void +Botan__Base64_Encoder::DESTROY() + PREINIT: + ObjectInfo *THIS_oi; + CODE: + if ( THIS_oi->should_delete() ) + try { + delete THIS; + } + catch (const std::exception &e) { + croak(e.what()); + } + + +# ============================ Botan::Hex_Decoder ============================ + +MODULE = Botan PACKAGE = Botan::Hex_Decoder + +Botan__Hex_Decoder * +Botan__Hex_Decoder::new(checking = Botan::NONE) + int checking; + CODE: + try { + using namespace Botan; + RETVAL = new Hex_Decoder((Decoder_Checking)checking); + } + catch (const std::exception &e) { + croak(e.what()); + } + OUTPUT: + RETVAL + +void +Botan__Hex_Decoder::DESTROY() + PREINIT: + ObjectInfo *THIS_oi; + CODE: + if ( THIS_oi->should_delete() ) + try { + delete THIS; + } + catch (const std::exception &e) { + croak(e.what()); + } + + +# ============================ Botan::Hex_Encoder ============================ + +MODULE = Botan PACKAGE = Botan::Hex_Encoder + +Botan__Hex_Encoder * +Botan__Hex_Encoder::new(breaks = false, length = 72, lcase = false) + bool breaks; + Botan__u32bit length; + bool lcase; + CODE: + try { + using Botan::Hex_Encoder; + RETVAL = new Hex_Encoder(breaks, length, + lcase ? Hex_Encoder::Lowercase : Hex_Encoder::Uppercase); + } + catch (const std::exception &e) { + croak(e.what()); + } + OUTPUT: + RETVAL + +void +Botan__Hex_Encoder::DESTROY() + PREINIT: + ObjectInfo *THIS_oi; + CODE: + if ( THIS_oi->should_delete() ) + try { + delete THIS; + } + catch (const std::exception &e) { + croak(e.what()); + } + + +# ================================ Botan::OID ================================ + +MODULE = Botan PACKAGE = Botan::OID + +Botan__OID * +Botan__OID::new(s) + char *s; + CODE: + try { + RETVAL = new Botan__OID(s); + } + catch (const std::exception &e) { + croak(e.what()); + } + OUTPUT: + RETVAL + +void +Botan__OID::DESTROY() + CODE: + try { + delete THIS; + } + catch (const std::exception &e) { + croak(e.what()); + } + +char * +Botan__OID::as_string() + CODE: + try { + RETVAL = const_cast<char *>(THIS->as_string().c_str()); + } + catch (const std::exception &e) { + croak(e.what()); + } + OUTPUT: + RETVAL + + +# ================================ Botan::OIDS ================================ + +MODULE = Botan PACKAGE = Botan::OIDS + +void +add_oid(oid, name) + Botan__OID *oid; + char *name; + CODE: + try { + Botan::OIDS::add_oid(*oid, name); + } + catch (const std::exception &e) { + croak(e.what()); + } + +char * +lookup_by_oid(oid) + Botan__OID *oid; + CODE: + try { + RETVAL = const_cast<char *>(Botan::OIDS::lookup(*oid).c_str()); + } + catch (const std::exception &e) { + croak(e.what()); + } + OUTPUT: + RETVAL + +Botan__OID * +lookup_by_name(name) + char *name; + CODE: + try { + RETVAL = new Botan__OID(Botan::OIDS::lookup(name)); + } + catch (const std::exception &e) { + croak(e.what()); + } + char const * CLASS = "Botan::OID"; + OUTPUT: + RETVAL + +int +have_oid(name) + char *name; + CODE: + try { + RETVAL = Botan::OIDS::have_oid(name); + } + catch (const std::exception &e) { + croak(e.what()); + } + OUTPUT: + RETVAL + + +# ================================ Botan::Pipe ================================ + +MODULE = Botan PACKAGE = Botan::Pipe + +Botan__Pipe * +Botan__Pipe::new(...) + CODE: + for (I32 i = 1; i < items; i++) + { + if ( !sv_isobject(ST(i)) || (SvTYPE(SvRV(ST(i))) != SVt_PVMG) ) + croak("Botan::Pipe::new() -- arg %u is not " + "a blessed SV reference", i +1); + if ( !sv_derived_from(ST(i), "Botan::Filter") ) + croak("Botan::Pipe::new() -- arg %u is not " + "an object derived from Botan::Filter", i +1); + MAGIC *mg = mg_find(SvRV(ST(i)), '~'); + if ( mg == 0 + || mg->mg_len != sizeof(ObjectInfo) + || *(I32 *)(mg->mg_ptr) != ObjectInfo::SIGNVAL ) + croak("Botan::Pipe::new() -- arg %u has no " + "valid private magic data (ObjectInfo)", i +1); + } + try { + RETVAL = new Botan__Pipe(); + for (I32 i = 1; i < items; i++) + { + SV *osv = (SV *)SvRV(ST(i)); + ObjectInfo *oi = (ObjectInfo *)(mg_find(osv, '~')->mg_ptr); + RETVAL->append((Botan__Filter *)(SvIV(osv))); + oi->set_delete_no(); + } + } + catch (const std::exception &e) { + croak(e.what()); + } + OUTPUT: + RETVAL + +void +Botan__Pipe::DESTROY() + PREINIT: + ObjectInfo *THIS_oi; + CODE: + try { + delete THIS; + } + catch (const std::exception &e) { + croak(e.what()); + } + +void +Botan__Pipe::write(s) + SV *s; + PREINIT: + ObjectInfo *THIS_oi; + CODE: + STRLEN len; + char *ptr = SvPV(s, len); + try { + THIS->write((unsigned char *)ptr, len); + } + catch (const std::exception &e) { + croak(e.what()); + } + +void +Botan__Pipe::process_msg(s) + SV *s; + PREINIT: + ObjectInfo *THIS_oi; + CODE: + STRLEN len; + char *ptr = SvPV(s, len); + try { + THIS->process_msg((unsigned char *)ptr, len); + } + catch (const std::exception &e) { + croak(e.what()); + } + +Botan__u32bit +Botan__Pipe::remaining(msgno = Botan::Pipe::DEFAULT_MESSAGE) + Botan__u32bit msgno; + PREINIT: + ObjectInfo *THIS_oi; + CODE: + try { + RETVAL = THIS->remaining(msgno); + } + catch (const std::exception &e) { + croak(e.what()); + } + OUTPUT: + RETVAL + +SV * +Botan__Pipe::read(len = 0xFFFFFFFF, msgno = Botan::Pipe::DEFAULT_MESSAGE) + Botan__u32bit len; + Botan__u32bit msgno; + PREINIT: + ObjectInfo *THIS_oi; + CODE: + try { + if ( len > THIS->remaining(msgno) ) + len = THIS->remaining(msgno); + RETVAL = NEWSV(0, len); + SvPOK_on(RETVAL); + if ( len > 0 ) + SvCUR_set(RETVAL, THIS->read((unsigned char *)SvPVX(RETVAL), + len, msgno)); + } + catch (const std::exception &e) { + croak(e.what()); + } + OUTPUT: + RETVAL + +SV * +Botan__Pipe::peek(len = 0xFFFFFFFF, offset = 0, \ + msgno = Botan::Pipe::DEFAULT_MESSAGE) + Botan__u32bit len; + Botan__u32bit offset; + Botan__u32bit msgno; + PREINIT: + ObjectInfo *THIS_oi; + CODE: + try { + if ( len > THIS->remaining(msgno) ) + len = THIS->remaining(msgno); + RETVAL = NEWSV(0, len); + SvPOK_on(RETVAL); + if ( len > 0 ) + SvCUR_set(RETVAL, THIS->peek((unsigned char *)SvPVX(RETVAL), + len, offset, msgno)); + } + catch (const std::exception &e) { + croak(e.what()); + } + OUTPUT: + RETVAL + +Botan__u32bit +Botan__Pipe::default_msg() + PREINIT: + ObjectInfo *THIS_oi; + CODE: + try { + RETVAL = THIS->default_msg(); + } + catch (const std::exception &e) { + croak(e.what()); + } + OUTPUT: + RETVAL + +void +Botan__Pipe::set_default_msg(msgno) + Botan__u32bit msgno; + PREINIT: + ObjectInfo *THIS_oi; + CODE: + try { + THIS->set_default_msg(msgno); + } + catch (const std::exception &e) { + croak(e.what()); + } + +Botan__u32bit +Botan__Pipe::message_count() + PREINIT: + ObjectInfo *THIS_oi; + CODE: + try { + RETVAL = THIS->message_count(); + } + catch (const std::exception &e) { + croak(e.what()); + } + OUTPUT: + RETVAL + +bool +Botan__Pipe::end_of_data() + PREINIT: + ObjectInfo *THIS_oi; + CODE: + try { + RETVAL = THIS->end_of_data(); + } + catch (const std::exception &e) { + croak(e.what()); + } + OUTPUT: + RETVAL + +void +Botan__Pipe::start_msg() + PREINIT: + ObjectInfo *THIS_oi; + CODE: + try { + THIS->start_msg(); + } + catch (const std::exception &e) { + croak(e.what()); + } + +void +Botan__Pipe::end_msg() + PREINIT: + ObjectInfo *THIS_oi; + CODE: + try { + THIS->end_msg(); + } + catch (const std::exception &e) { + croak(e.what()); + } + +void +Botan__Pipe::reset() + PREINIT: + ObjectInfo *THIS_oi; + CODE: + try { + THIS->reset(); + } + catch (const std::exception &e) { + croak(e.what()); + } + + +# ========================== Botan::X509_Certificate ========================== + +MODULE = Botan PACKAGE = Botan::X509_Certificate + +Botan__X509_Certificate * +Botan__X509_Certificate::new(char *fn) + CODE: + try { + RETVAL = new Botan__X509_Certificate(fn); + } + catch (const std::exception &e) { + croak(e.what()); + } + OUTPUT: + RETVAL + +void +Botan__X509_Certificate::DESTROY() + CODE: + try { + delete THIS; + } + catch (const std::exception &e) { + croak(e.what()); + } + +unsigned int +Botan__X509_Certificate::x509_version() + CODE: + try { + RETVAL = THIS->x509_version(); + } + catch (const std::exception &e) { + croak(e.what()); + } + OUTPUT: + RETVAL + +char * +Botan__X509_Certificate::start_time() + CODE: + try { + RETVAL = const_cast<char *>(THIS->start_time().c_str()); + } + catch (const std::exception &e) { + croak(e.what()); + } + OUTPUT: + RETVAL + +char * +Botan__X509_Certificate::end_time() + CODE: + try { + RETVAL = const_cast<char *>(THIS->end_time().c_str()); + } + catch (const std::exception &e) { + croak(e.what()); + } + OUTPUT: + RETVAL + +char * +Botan__X509_Certificate::subject_info(char *info) + CODE: + try { + std::vector<std::string> s = THIS->subject_info(info); + + if(s.size() > 0) + RETVAL = const_cast<char *>(s[0].c_str()); + else + RETVAL = "err"; + } + catch (const std::exception &e) { + croak(e.what()); + } + OUTPUT: + RETVAL + +char * +Botan__X509_Certificate::issuer_info(char *info) + CODE: + try { + std::vector<std::string> s = THIS->subject_info(info); + + if(s.size() > 0) + RETVAL = const_cast<char *>(s[0].c_str()); + else + RETVAL = "err"; + } + catch (const std::exception &e) { + croak(e.what()); + } + OUTPUT: + RETVAL + +Botan__X509_DN * +Botan__X509_Certificate::subject_dn() + CODE: + try { + RETVAL = new Botan__X509_DN(THIS->subject_dn()); + } + catch (const std::exception &e) { + croak(e.what()); + } + char const * CLASS = "Botan::X509_DN"; + OUTPUT: + RETVAL + +Botan__X509_DN * +Botan__X509_Certificate::issuer_dn() + CODE: + try { + RETVAL = new Botan__X509_DN(THIS->issuer_dn()); + } + catch (const std::exception &e) { + croak(e.what()); + } + char const * CLASS = "Botan::X509_DN"; + OUTPUT: + RETVAL + + +# ============================== Botan::X509_DN ============================== + +MODULE = Botan PACKAGE = Botan::X509_DN + +Botan__X509_DN * +Botan__X509_DN::new() + CODE: + try { + RETVAL = new Botan__X509_DN(); + } + catch (const std::exception &e) { + croak(e.what()); + } + OUTPUT: + RETVAL + +void +Botan__X509_DN::DESTROY() + CODE: + try { + delete THIS; + } + catch (const std::exception &e) { + croak(e.what()); + } + +AV * +Botan__X509_DN::get_attributes() + CODE: + try { + using namespace std; + using namespace Botan; + + typedef multimap<OID, string>::const_iterator rdn_iter; + + multimap<OID, string> const &atrmmap = THIS->get_attributes(); + RETVAL = newAV(); + for(rdn_iter i = atrmmap.begin(); i != atrmmap.end(); i++) + { + string const &atr = i->first.as_string(); + string const &val = i->second; + av_push(RETVAL, newSVpvn(atr.c_str(), atr.length())); + av_push(RETVAL, newSVpvn(val.c_str(), val.length())); + } + } + catch (const std::exception &e) { + croak(e.what()); + } + OUTPUT: + RETVAL diff --git a/src/wrap/perl-xs/Changes b/src/wrap/perl-xs/Changes new file mode 100644 index 000000000..5f32b0c63 --- /dev/null +++ b/src/wrap/perl-xs/Changes @@ -0,0 +1,4 @@ +Revision history for Perl extension to Botan. + +0.01 Fri, 20 Feb 2004 15:10:50 +0100 + - first version diff --git a/src/wrap/perl-xs/MANIFEST b/src/wrap/perl-xs/MANIFEST new file mode 100644 index 000000000..b9d8454d6 --- /dev/null +++ b/src/wrap/perl-xs/MANIFEST @@ -0,0 +1,15 @@ +Botan.pm +Botan.xs +Changes +MANIFEST +Makefile.PL +data/ca.cert.der +data/ca.cert.pem +t/base64.t +t/filt.t +t/hex.t +t/oid.t +t/pipe.t +t/testutl.pl +t/x509cert.t +typemap diff --git a/src/wrap/perl-xs/Makefile.PL b/src/wrap/perl-xs/Makefile.PL new file mode 100644 index 000000000..46317e72b --- /dev/null +++ b/src/wrap/perl-xs/Makefile.PL @@ -0,0 +1,29 @@ +use ExtUtils::MakeMaker; + +my ($cc, $cflags, $lids); +if ( $^O eq 'MSWin32' ) +{ +# $cflags = ''; +# $libs = ':nosearch -lgdi32 -llibeay32'; +} +else +{ + $cc = 'g++'; + $cflags = '-Wno-write-strings -fexceptions ' . qx( botan-config --cflags ); + $libs = qx( botan-config --libs ); +} + +WriteMakefile( + 'NAME' => 'Botan', + 'DISTNAME' => 'Botan-XS', + 'VERSION_FROM' => 'Botan.pm', # finds $VERSION + 'XSOPT' => '-C++', + 'CC' => $cc, + 'LD' => '$(CC)', + 'CCFLAGS' => $cflags, + 'LIBS' => [ $libs ], + 'OPTIMIZE' => '-g', +# 'clean' => { +# 'FILES' => 'neco.p12 rnd', +# }, +); diff --git a/src/wrap/perl-xs/data/ca.cert.der b/src/wrap/perl-xs/data/ca.cert.der Binary files differnew file mode 100644 index 000000000..d6ed8aeaf --- /dev/null +++ b/src/wrap/perl-xs/data/ca.cert.der diff --git a/src/wrap/perl-xs/data/ca.cert.pem b/src/wrap/perl-xs/data/ca.cert.pem new file mode 100644 index 000000000..012913b26 --- /dev/null +++ b/src/wrap/perl-xs/data/ca.cert.pem @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICxDCCAi2gAwIBAgIBEjANBgkqhkiG9w0BAQUFADBSMQswCQYDVQQGEwJDWjER +MA8GA1UEChMISUNaIGEucy4xGDAWBgNVBAMTD1Rlc3QgcHJpbWFyeSBDQTEWMBQG +CSqGSIb3DQEJARYHY2FAaS5jejAeFw0wMDA4MjAyMTQ4MDBaFw0wMjA4MTAyMTQ4 +MDBaME8xCzAJBgNVBAYTAkNaMREwDwYDVQQKEwhJQ1ogYS5zLjEVMBMGA1UEAxMM +VGVzdCBzaWduIENBMRYwFAYJKoZIhvcNAQkBFgdjYUBpLmN6MIGfMA0GCSqGSIb3 +DQEBAQUAA4GNADCBiQKBgQCo2GReNqwU0/8bZZua5hgYaVHvD9QAmfILNXD25jRk +C8lqe5m/GzbmftSUso5HyUy1t+qzvRDTmxK8uRn0P00Mqj9gjwF8PGQvZE/FrDF7 +rta9GCcH4n2GfQ0iexlhRZW44AfOD4HCgq38Z0bzBclsvUslBWe1AT+S5+chZ5Wb +UwIDAQABo4GsMIGpMAwGA1UdEwQFMAMBAf8wHQYDVR0OBBYEFLXqc1b1DOfGehii +k4Z+/ih9BYZmMHoGA1UdIwRzMHGAFL7x2ToS4RDAbDJu4fHnzzGjfGmgoVakVDBS +MQswCQYDVQQGEwJDWjERMA8GA1UEChMISUNaIGEucy4xGDAWBgNVBAMTD1Rlc3Qg +cHJpbWFyeSBDQTEWMBQGCSqGSIb3DQEJARYHY2FAaS5jeoIBADANBgkqhkiG9w0B +AQUFAAOBgQAKD9ku9kKXUGhSw8KuWJXTnEsIUzDtgmREBEUOtEvGfU45vogWN7ZL +9fQZ1deywN4RJ4T5ZTTcCTPodOdG+IXLJ+uPn/m9iQ/D86c3GKS3yx4JNAn5PH1m +qLsMYVjbFD2uREZQsqbg3RT6L1D8+oK0pN379u3bD6oJx/qa7+F4Jg== +-----END CERTIFICATE----- diff --git a/src/wrap/perl-xs/t/base64.t b/src/wrap/perl-xs/t/base64.t new file mode 100644 index 000000000..f0973e13e --- /dev/null +++ b/src/wrap/perl-xs/t/base64.t @@ -0,0 +1,273 @@ +# vim: set ft=perl: +# Before `make install' is performed this script should be runnable with +# `make test'. After `make install' it should work as `perl test.pl' + +######################### We start with some black magic to print on failure. + +# Change 1..1 below to 1..last_test_to_print . +# (It may become useful if the test is moved to ./t subdirectory.) + +BEGIN { $| = 1; print "1..24\n"; } +END { print "not ok 1\n" unless $loaded; } + +require 't/testutl.pl'; +use Botan; + +$loaded = 1; +print "ok 1\n"; + +######################### End of black magic. + +# Insert your test code below (better if it prints "ok 13" +# (correspondingly "not ok 13") depending on the success of chunk 13 +# of the test code): + +use strict; + +# Data prep + +my $botan_lic_b64_garbage = <<'EOF'; +Q29weXJpZ2h0IChDKSAxOTk5LTIwMDQgVGhlIEJvdGFuIFByb2plY3QuIEFsbCBy__� +aWdodHMgcmVzZXJ2ZWQuCgpSZWRpc3RyaWJ1dGlvbiBhbmQgdXNlIGluIHNvdXJj$$*: +ZSBhbmQgYmluYXJ5IGZvcm1zLCBmb3IgYW55IHVzZSwgd2l0aCBvciB3aXRob3V0!@#$%^&*( +Cm1vZGlmaWNhdGlvbiwgaXMgcGVybWl0dGVkIHByb3ZpZGVkIHRoYXQgdGhlIGZv[\] +bGxvd2luZyBjb25kaXRpb25zIGFyZSBtZXQ6CgoxLiBSZWRpc3RyaWJ1dGlvbnMg'~` +b2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3ZlIGNvcHlyaWdodCBu() +b3RpY2UsIHRoaXMKbGlzdCBvZiBjb25kaXRpb25zLCBhbmQgdGhlIGZvbGxvd2lu +ZyBkaXNjbGFpbWVyLgoKMi4gUmVkaXN0cmlidXRpb25zIGluIGJpbmFyeSBmb3Jt +IG11c3QgcmVwcm9kdWNlIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLAp0aGlz +IGxpc3Qgb2YgY29uZGl0aW9ucywgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1l +ciBpbiB0aGUgZG9jdW1lbnRhdGlvbgphbmQvb3Igb3RoZXIgbWF0ZXJpYWxzIHBy_,^ +b3ZpZGVkIHdpdGggdGhlIGRpc3RyaWJ1dGlvbi4KClRISVMgU09GVFdBUkUgSVMg{|}~~~~~ +UFJPVklERUQgQlkgVEhFIEFVVEhPUihTKSAiQVMgSVMiIEFORCBBTlkgRVhQUkVT~~~~~~~~ +UyBPUiBJTVBMSUVECldBUlJBTlRJRVMsIElOQ0xVRElORywgQlVUIE5PVCBMSU1J__:; +VEVEIFRPLCBUSEUgSU1QTElFRCBXQVJSQU5USUVTIE9GCk1FUkNIQU5UQUJJTElU +WSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UsIEFSRSBESVND +TEFJTUVELgoKSU4gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUihTKSBPUiBDT05U +UklCVVRPUihTKSBCRSBMSUFCTEUgRk9SIEFOWSBESVJFQ1QsCklORElSRUNULCBJ +TkNJREVOVEFMLCBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwg +REFNQUdFUyAoSU5DTFVESU5HLApCVVQgTk9UIExJTUlURUQgVE8sIFBST0NVUkVN +RU5UIE9GIFNVQlNUSVRVVEUgR09PRFMgT1IgU0VSVklDRVM7IExPU1MgT0YgVVNF +LApEQVRBLCBPUiBQUk9GSVRTOyBPUiBCVVNJTkVTUyBJTlRFUlJVUFRJT04pIEhP +V0VWRVIgQ0FVU0VEIEFORCBPTiBBTlkgVEhFT1JZIE9GCkxJQUJJTElUWSwgV0hF +VEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSwgT1IgVE9SVCAoSU5D +TFVESU5HIE5FR0xJR0VOQ0UKT1IgT1RIRVJXSVNFKSBBUklTSU5HIElOIEFOWSBX +QVkgT1VUIE9GIFRIRSBVU0UgT0YgVEhJUyBTT0ZUV0FSRSwgRVZFTiBJRgpBRFZJ +U0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRiBTVUNIIERBTUFHRS4K +EOF + +my $botan_lic_b64_ws = $botan_lic_b64_garbage; +$botan_lic_b64_ws =~ s/[^A-Za-z0-9+\/= \n]//g; + +my $botan_lic_b64 = $botan_lic_b64_ws; +$botan_lic_b64 =~ s/[ \n]//g; + + +my $botan_lic = <<'EOF'; +Copyright (C) 1999-2004 The Botan Project. All rights reserved. + +Redistribution and use in source and binary forms, for any use, with or without +modification, is permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions, and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions, and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. + +IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTOR(S) BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +EOF + + +# Decoder... + +my $f; + +eval { $f = Botan::Base64_Decoder->new(&Botan::NONE); }; +print "not " if $@ || !defined $f; +print "ok 2\n"; + +my $dec; +eval { $dec = Botan::Pipe->new($f); }; +print "not " if $@ || !defined $dec; +print "ok 3\n"; + +eval { $f = Botan::Base64_Decoder->new(&Botan::IGNORE_WS); }; +print "not " if $@ || !defined $f; +print "ok 4\n"; + +my $dec_is; +eval { $dec_is = Botan::Pipe->new($f); }; +print "not " if $@ || !defined $dec_is; +print "ok 5\n"; + +eval { $f = Botan::Base64_Decoder->new(&Botan::FULL_CHECK); }; +print "not " if $@ || !defined $f; +print "ok 6\n"; + +my $dec_fc; +eval { $dec_fc = Botan::Pipe->new($f); }; +print "not " if $@ || !defined $dec_fc; +print "ok 7\n"; + + +# Testing clean base64 input + +my $data; + +undef $data; +eval { + $dec->process_msg($botan_lic_b64); + $data = $dec->read(); +}; + +print "not " if $@ || $data ne $botan_lic; +print "ok 8\n"; + +undef $data; +eval { + $dec_is->process_msg($botan_lic_b64); + $data = $dec_is->read(); +}; + +print "not " if $@ || $data ne $botan_lic; +print "ok 9\n"; + +undef $data; +eval { + $dec_fc->process_msg($botan_lic_b64); + $data = $dec_fc->read(); +}; + +print "not " if $@ || $data ne $botan_lic; +print "ok 10\n"; + + +# Testing base64 input with whitespaces + +undef $data; +eval { + $dec->process_msg($botan_lic_b64_ws); + $dec->set_default_msg(1); + $data = $dec->read(); +}; + +print "not " if $@ || $data ne $botan_lic; +print "ok 11\n"; + +undef $data; +eval { + $dec_is->process_msg($botan_lic_b64_ws); + $dec_is->set_default_msg(1); + $data = $dec_is->read(); +}; + +print "not " if $@ || $data ne $botan_lic; +print "ok 12\n"; + +undef $data; +eval { + $dec_fc->process_msg($botan_lic_b64_ws); + $dec_fc->set_default_msg(1); + $data = $dec_fc->read(); +}; + +print "not " unless $@ && !defined $data; +print "ok 13\n"; + + +# Testing base64 input with garbage + +undef $data; +eval { + $dec->process_msg($botan_lic_b64_garbage); + $dec->set_default_msg(2); + $data = $dec->read(); +}; + +print "not " if $@ || $data ne $botan_lic; +print "ok 14\n"; + +undef $data; +eval { + $dec_is->process_msg($botan_lic_b64_garbage); + $dec_is->set_default_msg(2); + $data = $dec_is->read(); +}; + +print "not " unless $@ && !defined $data; +print "ok 15\n"; + +undef $data; +eval { + $dec_fc->process_msg($botan_lic_b64_garbage); + $dec_fc->set_default_msg(2); + $data = $dec_fc->read(); +}; + +print "not " unless $@ && !defined $data; +print "ok 16\n"; + + +# Encoder... + +eval { $f = Botan::Base64_Encoder->new(); }; +print "not " if $@ || !defined $f; +print "ok 17\n"; + +my $enc; +eval { $enc = Botan::Pipe->new($f); }; +print "not " if $@ || !defined $enc; +print "ok 18\n"; + +eval { $f = Botan::Base64_Encoder->new(1, 5); }; +print "not " if $@ || !defined $f; +print "ok 19\n"; + +my $enc2; +eval { $enc2 = Botan::Pipe->new($f); }; +print "not " if $@ || !defined $enc2; +print "ok 20\n"; + +undef $data; +eval { + $enc->process_msg("Hello\n"); + $data = $enc->read(); +}; +print "not " if $@ || $data ne "SGVsbG8K"; +print "ok 21\n"; + +undef $data; +eval { + $enc2->process_msg("Hello\n"); + $data = $enc2->read(); +}; +print "not " if $@ || $data ne "SGVsb\nG8K\n"; +print "ok 22\n"; + + +# Encoder with decoder... + +my $p; +eval { + $p = Botan::Pipe->new( + Botan::Base64_Encoder->new(), + Botan::Base64_Decoder->new(), + ); +}; +print "not " if $@ || !defined $p; +print "ok 23\n"; + +print "not " unless random_message_ok($p); +print "ok 24\n"; diff --git a/src/wrap/perl-xs/t/filt.t b/src/wrap/perl-xs/t/filt.t new file mode 100644 index 000000000..2a7b4c8ba --- /dev/null +++ b/src/wrap/perl-xs/t/filt.t @@ -0,0 +1,56 @@ +# vim: set ft=perl: +# Before `make install' is performed this script should be runnable with +# `make test'. After `make install' it should work as `perl test.pl' + +######################### We start with some black magic to print on failure. + +# Change 1..1 below to 1..last_test_to_print . +# (It may become useful if the test is moved to ./t subdirectory.) + +BEGIN { $| = 1; print "1..5\n"; } +END { print "not ok 1\n" unless $loaded; } + +use Botan; + +$loaded = 1; +print "ok 1\n"; + +######################### End of black magic. + +# Insert your test code below (better if it prints "ok 13" +# (correspondingly "not ok 13") depending on the success of chunk 13 +# of the test code): + +use strict; + +my $pipe = Botan::Pipe->new(Botan::Hex_Encoder->new()); + +print "not " unless $pipe; +print "ok 2\n"; + +$pipe->process_msg('FOO'); + +print "not " if $pipe->read() ne '464F4F'; +print "ok 3\n"; + +$pipe = Botan::Pipe->new(Botan::Hex_Encoder->new(0, 0, 1)); + +print "not " unless $pipe; +print "ok 4\n"; + +$pipe->process_msg('FOO'); + +print "not " if $pipe->read() ne '464f4f'; +print "ok 5\n"; + + + + + + +#my $pipe = Botan::Pipe->new(Botan::Base64_Encoder->new()); +#$pipe->process_msg('FOO'); +# +#print "not " if $pipe->read() ne 'Rk9P'; +#print "ok 4\n"; + diff --git a/src/wrap/perl-xs/t/hex.t b/src/wrap/perl-xs/t/hex.t new file mode 100644 index 000000000..6f447b25c --- /dev/null +++ b/src/wrap/perl-xs/t/hex.t @@ -0,0 +1,256 @@ +# vim: set ft=perl: +# Before `make install' is performed this script should be runnable with +# `make test'. After `make install' it should work as `perl test.pl' + +######################### We start with some black magic to print on failure. + +# Change 1..1 below to 1..last_test_to_print . +# (It may become useful if the test is moved to ./t subdirectory.) + +BEGIN { $| = 1; print "1..24\n"; } +END { print "not ok 1\n" unless $loaded; } + +require 't/testutl.pl'; +use Botan; + +$loaded = 1; +print "ok 1\n"; + +######################### End of black magic. + +# Insert your test code below (better if it prints "ok 13" +# (correspondingly "not ok 13") depending on the success of chunk 13 +# of the test code): + +use strict; + +# Data prep + +my ($hex, $hex_ws, $hex_garbage); +while ( $_ = <DATA> ) +{ + $hex_garbage .= $_; + s/[^[:xdigit:][:space:]]//g; + $hex_ws .= $_; + s/[^[:xdigit:]]//g; + $hex .= $_; +} +my $data_test = pack("H*", $hex); + +# Decoder... + +my $f; + +eval { $f = Botan::Hex_Decoder->new(&Botan::NONE); }; +print "not " if $@ || !defined $f; +print "ok 2\n"; + +my $dec; +eval { $dec = Botan::Pipe->new($f); }; +print "not " if $@ || !defined $dec; +print "ok 3\n"; + +eval { $f = Botan::Hex_Decoder->new(&Botan::IGNORE_WS); }; +print "not " if $@ || !defined $f; +print "ok 4\n"; + +my $dec_is; +eval { $dec_is = Botan::Pipe->new($f); }; +print "not " if $@ || !defined $dec_is; +print "ok 5\n"; + +eval { $f = Botan::Hex_Decoder->new(&Botan::FULL_CHECK); }; +print "not " if $@ || !defined $f; +print "ok 6\n"; + +my $dec_fc; +eval { $dec_fc = Botan::Pipe->new($f); }; +print "not " if $@ || !defined $dec_fc; +print "ok 7\n"; + + +# Testing clean hexadecimal input + +my $data; + +undef $data; +eval { + $dec->process_msg($hex); + $data = $dec->read(); +}; + +print "not " if $@ || $data ne $data_test; +print "ok 8\n"; + +undef $data; +eval { + $dec_is->process_msg($hex); + $data = $dec_is->read(); +}; + +print "not " if $@ || $data ne $data_test; +print "ok 9\n"; + +undef $data; +eval { + $dec_fc->process_msg($hex); + $data = $dec_fc->read(); +}; + +print "not " if $@ || $data ne $data_test; +print "ok 10\n"; + + +# Testing hexadecimal input with whitespaces + +undef $data; +eval { + $dec->process_msg($hex_ws); + $dec->set_default_msg(1); + $data = $dec->read(); +}; + +print "not " if $@ || $data ne $data_test; +print "ok 11\n"; + +undef $data; +eval { + $dec_is->process_msg($hex_ws); + $dec_is->set_default_msg(1); + $data = $dec_is->read(); +}; + +print "not " if $@ || $data ne $data_test; +print "ok 12\n"; + +undef $data; +eval { + $dec_fc->process_msg($hex_ws); + $dec_fc->set_default_msg(1); + $data = $dec_fc->read(); +}; + +print "not " unless $@ && !defined $data; +print "ok 13\n"; + + +# Testing hexadecimal input with garbage + +undef $data; +eval { + $dec->process_msg($hex_garbage); + $dec->set_default_msg(2); + $data = $dec->read(); +}; + +print "not " if $@ || $data ne $data_test; +print "ok 14\n"; + +undef $data; +eval { + $dec_is->process_msg($hex_garbage); + $dec_is->set_default_msg(2); + $data = $dec_is->read(); +}; + +print "not " unless $@ && !defined $data; +print "ok 15\n"; + +undef $data; +eval { + $dec_fc->process_msg($hex_garbage); + $dec_fc->set_default_msg(2); + $data = $dec_fc->read(); +}; + +print "not " unless $@ && !defined $data; +print "ok 16\n"; + + +# Encoder... + +eval { $f = Botan::Hex_Encoder->new(); }; +print "not " if $@ || !defined $f; +print "ok 17\n"; + +my $enc; +eval { $enc = Botan::Pipe->new($f); }; +print "not " if $@ || !defined $enc; +print "ok 18\n"; + +eval { $f = Botan::Hex_Encoder->new(1, 5, 1); }; +print "not " if $@ || !defined $f; +print "ok 19\n"; + +my $enc2; +eval { $enc2 = Botan::Pipe->new($f); }; +print "not " if $@ || !defined $enc2; +print "ok 20\n"; + +undef $data; +eval { + $enc->process_msg("Hello\n"); + $data = $enc->read(); +}; +print "not " if $@ || $data ne "48656C6C6F0A"; +print "ok 21\n"; + +undef $data; +eval { + $enc2->process_msg("Hello\n"); + $data = $enc2->read(); +}; +print "not " if $@ || $data ne "48656\nc6c6f\n0a\n"; +print "ok 22\n"; + + +# Encoder with decoder... + +my $p; +eval { + $p = Botan::Pipe->new( + Botan::Hex_Encoder->new(), + Botan::Hex_Decoder->new(), + ); +}; +print "not " if $@ || !defined $p; +print "ok 23\n"; + +print "not " unless random_message_ok($p); +print "ok 24\n"; + + + +__DATA__ +cb13 4a4d 7522 1fd3 c6f6 7786 d04b 3043 ..JMu"....w..K.. +4552 4bcf 4d2b 9d71 0cfe 4d6a 1caf bcfd .RK.M+.q..Mj.... +8f91 6151 ff85 e900 7e6a bafc 15e9 ae51 ...Q....~j.....Q +b14b 7210 bb40 5958 2b82 d49e b808 68a5 .Kr..@YX+.....h. +7945 9dec f686 9b98 989e 826d 8088 6ee7 y..........m..n. +d066 1eac 8c34 c461 bb54 7726 87ab d681 .........Tw&.... +a0be 52e5 1128 0cf2 759e cb2d e690 4ed9 ..R..(..u..-..N. +7e88 bda7 2523 4a0f 185a 02b1 f898 fc41 ~...%#J..Z...... +dd48 fa87 945d 7611 b8c9 a50a 2de2 b670 .H...]v.....-..p +0056 c8be 2cbb e7d0 1e70 4a3d 79f0 dce9 .V..,....pJ=y... +b57f 154b 2b3a db73 f086 de11 9f3e 1641 ...K+:.s.....>.. +3a28 8b9b bb0f 682b 80db b791 89e0 62c0 :(....h+........ +7204 db97 5432 2eb0 a04e f38e 809f 7223 r...T....N....r# +912e e552 1452 6dd2 e09f dd06 c715 7c1a ...R.Rm.......|. +fe3d d6cc b6d0 a17a 27d7 4327 4e43 8af3 .=.....z'..'N... +6eb5 e9f8 bfe9 34c3 6636 8243 358f 966d n..............m +7d87 d17b 5c37 6acb 4972 f4ec 6806 bbde }..{\.j.Ir..h... +2689 a019 a9e2 4101 7fe2 de72 bc03 eb5e &..........r...^ +b699 2d6b f8cd a08e 6e01 edfc a81a 94b6 ..-k....n....... +9073 15fb efb2 c8d9 9f85 6633 85f1 e9d0 .s.............. +20ce 578b ab9d 2e51 b947 69bf fba5 82c6 .W....Q.Gi..... +2ed0 dd36 d679 a399 7db3 8a0d cdef 0eda .....y..}....... +e761 e7f1 5b17 3f67 0c83 215a eddf 9d2a ....[.?g..!Z...* +5e70 0a77 c92e 94e1 a82b fd7c f10a 894f ^p.w.....+.|...O +2955 f0e8 7398 f409 2040 b797 da03 a5a6 )U..s... @...... +7ba4 c3c9 2659 b9f7 6a56 e17a b481 983f {...&Y..jV.z...? +00ed 3cc8 5a22 ad5c b6e0 3566 d717 35a6 ..<.Z".\........ +1523 4104 de63 477e fd24 68e5 e816 98df .#....G~.$h..... +1747 417e db72 a76a be5b b9dc 3dfb 2d05 .G.~.r.j.[..=.-. +d27f e597 eafc 9a29 15c5 792d 9c88 9aea .......)..y-.... +485e e431 96c3 7723 da6d 28b2 477a fd12 H^....w#.m(.Gz.. +e645 5dcd 7d5a d8b4 7acc 10b2 b41a e11d ..].}Z..z....... diff --git a/src/wrap/perl-xs/t/oid.t b/src/wrap/perl-xs/t/oid.t new file mode 100644 index 000000000..66204541f --- /dev/null +++ b/src/wrap/perl-xs/t/oid.t @@ -0,0 +1,45 @@ +# vim: set ft=perl: +# Before `make install' is performed this script should be runnable with +# `make test'. After `make install' it should work as `perl test.pl' + +######################### We start with some black magic to print on failure. + +# Change 1..1 below to 1..last_test_to_print . +# (It may become useful if the test is moved to ./t subdirectory.) + +BEGIN { $| = 1; print "1..6\n"; } +END { print "not ok 1\n" unless $loaded; } + +use Botan; + +$loaded = 1; +print "ok 1\n"; + +######################### End of black magic. + +# Insert your test code below (better if it prints "ok 13" +# (correspondingly "not ok 13") depending on the success of chunk 13 +# of the test code): + +use strict; + +print "not " unless Botan::OIDS::have_oid('X520.CommonName'); +print "ok 2\n"; + +my $oid_c = Botan::OID->new('2.5.4.3'); +print "not " if Botan::OIDS::lookup_by_oid($oid_c) ne 'X520.CommonName'; +print "ok 3\n"; + +my $oid_x = Botan::OIDS::lookup_by_name('X520.CommonName'); +print "not " if $oid_x->as_string() ne '2.5.4.3'; +print "ok 4\n"; + +my $oid_foo_num = '1.2.3.4.5.6.7.8.9.10.11.12.13.14.15'; +my $oid_foo = Botan::OID->new($oid_foo_num); +print "not " if Botan::OIDS::lookup_by_oid($oid_foo) ne $oid_foo_num; +print "ok 5\n"; + +Botan::OIDS::add_oid($oid_foo, 'Zito.Foo'); + +print "not " if Botan::OIDS::lookup_by_oid($oid_foo) ne 'Zito.Foo'; +print "ok 6\n"; diff --git a/src/wrap/perl-xs/t/pipe.t b/src/wrap/perl-xs/t/pipe.t new file mode 100644 index 000000000..f850d8519 --- /dev/null +++ b/src/wrap/perl-xs/t/pipe.t @@ -0,0 +1,98 @@ +# vim: set ft=perl: +# Before `make install' is performed this script should be runnable with +# `make test'. After `make install' it should work as `perl test.pl' + +######################### We start with some black magic to print on failure. + +# Change 1..1 below to 1..last_test_to_print . +# (It may become useful if the test is moved to ./t subdirectory.) + +BEGIN { $| = 1; print "1..20\n"; } +END { print "not ok 1\n" unless $loaded; } + +use Botan; + +$loaded = 1; +print "ok 1\n"; + +######################### End of black magic. + +# Insert your test code below (better if it prints "ok 13" +# (correspondingly "not ok 13") depending on the success of chunk 13 +# of the test code): + +use strict; + +my $pipe = Botan::Pipe->new(); + +print "not " unless $pipe; +print "ok 2\n"; + +$pipe->start_msg(); +$pipe->write('Hello world'); +$pipe->end_msg(); + +print "not " if $pipe->message_count() != 1; +print "ok 3\n"; + +print "not " if $pipe->remaining() != 11; +print "ok 4\n"; + +print "not " if $pipe->end_of_data(); +print "ok 5\n"; + +print "not " if $pipe->read() ne 'Hello world'; +print "ok 6\n"; + +print "not " if $pipe->remaining() != 0; +print "ok 7\n"; + +print "not " unless $pipe->end_of_data(); +print "ok 8\n"; + +$pipe->process_msg('Hello world'); + +print "not " if $pipe->message_count() != 2; +print "ok 9\n"; + +my $msg_num = $pipe->message_count() -1; + +print "not " if $pipe->read(5, $msg_num) ne 'Hello'; +print "ok 10\n"; + +print "not " if $pipe->read(6, $msg_num) ne ' world'; +print "ok 11\n"; + +print "not " if $pipe->remaining() != 0; +print "ok 12\n"; + +print "not " unless $pipe->end_of_data(); +print "ok 13\n"; + +$pipe->process_msg("The\0string\0with\0null\0chars\0"); +$msg_num = $pipe->message_count() -1; + +print "not " if $pipe->read(80, $msg_num) ne "The\0string\0with\0null\0chars\0"; +print "ok 14\n"; + +$pipe->process_msg('FOO BAR'); +$pipe->set_default_msg($pipe->message_count() -1); + +print "not " if $pipe->peek(3) ne 'FOO'; +print "ok 15\n"; + +print "not " if $pipe->peek(3, 4) ne 'BAR'; +print "ok 16\n"; + +print "not " if $pipe->peek() ne 'FOO BAR'; +print "ok 17\n"; + +print "not " if $pipe->read() ne 'FOO BAR'; +print "ok 18\n"; + +print "not " if $pipe->remaining() != 0; +print "ok 19\n"; + +print "not " unless $pipe->end_of_data(); +print "ok 20\n"; + diff --git a/src/wrap/perl-xs/t/testutl.pl b/src/wrap/perl-xs/t/testutl.pl new file mode 100644 index 000000000..add6f6a45 --- /dev/null +++ b/src/wrap/perl-xs/t/testutl.pl @@ -0,0 +1,26 @@ +#!/usr/bin/perl + +sub random_message_ok +{ + my ($pipe, $iter, $chunkmax) = @_; + $iter = 100 unless defined $iter; + $chunkmax = 300 unless defined $chunkmax; + eval { + my $input = ''; + $pipe->start_msg(); + for(my $i = 0; $i < $iter; $i++) + { + my $chunk = ''; + my $chunklen = int(rand($chunkmax)); + $chunk .= pack("C", int(rand(256))) while $chunklen--; + $input .= $chunk; + $pipe->write($chunk); + } + $pipe->end_msg(); + my $msg_num = $pipe->message_count() -1; + my $output = $pipe->read(0xFFFFFFFF, $msg_num); + return $input eq $output; + }; +} + +1; diff --git a/src/wrap/perl-xs/t/x509cert.t b/src/wrap/perl-xs/t/x509cert.t new file mode 100644 index 000000000..2a943aeac --- /dev/null +++ b/src/wrap/perl-xs/t/x509cert.t @@ -0,0 +1,42 @@ +# vim: set ft=perl: +# Before `make install' is performed this script should be runnable with +# `make test'. After `make install' it should work as `perl test.pl' + +######################### We start with some black magic to print on failure. + +# Change 1..1 below to 1..last_test_to_print . +# (It may become useful if the test is moved to ./t subdirectory.) + +BEGIN { $| = 1; print "1..4\n"; } +END { print "not ok 1\n" unless $loaded; } + +use Botan; + +$loaded = 1; +print "ok 1\n"; + +######################### End of black magic. + +# Insert your test code below (better if it prints "ok 13" +# (correspondingly "not ok 13") depending on the success of chunk 13 +# of the test code): + +use strict; + +my $cert = Botan::X509_Certificate->new('data/ca.cert.der'); + +print "not " if $cert->x509_version() != 3; +print "ok 2\n"; + +print "not " if $cert->start_time() ne '2000/8/20 21:48:00 UTC'; +print "ok 3\n"; + +print "not " if $cert->end_time() ne '2002/8/10 21:48:00 UTC'; +print "ok 4\n"; + +#my $subject = $cert->subject_dn()->get_attributes(); +#print STDERR "subject=", join(',', @{$subject}), "\n"; +# +#my $issuer = $cert->issuer_dn()->get_attributes(); +#print STDERR "issuer=", join(',', @{$issuer}), "\n"; +# diff --git a/src/wrap/perl-xs/typemap b/src/wrap/perl-xs/typemap new file mode 100644 index 000000000..d7403d40d --- /dev/null +++ b/src/wrap/perl-xs/typemap @@ -0,0 +1,62 @@ +TYPEMAP + +Botan__ASN1_String * O_OBJECT +Botan__AlgorithmIdentifier * O_OBJECT +Botan__AlternativeName * O_OBJECT +Botan__Attribute * O_OBJECT +Botan__Base64_Decoder * O_EXTOBJECT +Botan__Base64_Encoder * O_EXTOBJECT +Botan__Chain * O_EXTOBJECT +Botan__Extension * O_OBJECT +Botan__Filter * O_EXTOBJECT +Botan__Fork * O_EXTOBJECT +Botan__Hex_Decoder * O_EXTOBJECT +Botan__Hex_Encoder * O_EXTOBJECT +Botan__OID * O_OBJECT +Botan__Pipe * O_OBJECT +Botan__X509_Certificate * O_OBJECT +Botan__X509_DN * O_OBJECT +Botan__X509_Time * O_OBJECT +Botan__u32bit T_UV + + +###################################################################### +OUTPUT + +# The Perl object is blessed into 'CLASS', which should be a +# char* having the name of the package for the blessing. +O_OBJECT + sv_setref_pv($arg, CLASS, (void*)$var); + +O_EXTOBJECT + sv_setref_pv($arg, CLASS, (void*)$var); + sv_magic(SvRV($arg), 0, '~', (char *)&oi_init, sizeof(oi_init)); + + +###################################################################### +INPUT + +O_OBJECT + if ( sv_isobject($arg) && (SvTYPE(SvRV($arg)) == SVt_PVMG) ) + $var = ($type)SvIV((SV*)SvRV( $arg )); + else + croak(\"${Package}::$func_name() -- \" + \"$var is not a blessed SV reference\"); + +# The pointer variable "ObjectInfo *${var}_oi;" must be declared +# in PREINIT section. I don't know how to emit this declaration safely here. +O_EXTOBJECT + if ( sv_isobject($arg) && (SvTYPE(SvRV($arg)) == SVt_PVMG) ) + $var = ($type)SvIV((SV*)SvRV($arg)); + else + croak(\"${Package}::$func_name() -- \" + \"$var is not a blessed SV reference\"); + { + MAGIC *mg = mg_find(SvRV($arg), '~'); + if ( mg == 0 + || mg->mg_len != sizeof(ObjectInfo) + || *(I32 *)(mg->mg_ptr) != ObjectInfo::SIGNVAL ) + croak(\"${Package}::$func_name() -- \" + \"private magic data for $var invalid\"); + ${var}_oi = (ObjectInfo *)(mg->mg_ptr); + } diff --git a/src/wrap/python/__init__.py b/src/wrap/python/__init__.py new file mode 100644 index 000000000..2df9a456f --- /dev/null +++ b/src/wrap/python/__init__.py @@ -0,0 +1,4 @@ +from _botan import * + +# Initialize the library when the module is imported +init = LibraryInitializer() diff --git a/src/wrap/python/core.cpp b/src/wrap/python/core.cpp new file mode 100644 index 000000000..fe26e16ee --- /dev/null +++ b/src/wrap/python/core.cpp @@ -0,0 +1,216 @@ +/* +* Boost.Python module definition +* (C) 1999-2007 Jack Lloyd +*/ + +#include <botan/init.h> +#include <botan/pipe.h> +#include <botan/lookup.h> +#include <botan/cryptobox.h> +#include <botan/pbkdf2.h> +#include <botan/hmac.h> +using namespace Botan; + +#include "python_botan.h" + +class Py_Cipher + { + public: + Py_Cipher(std::string algo_name, std::string direction, + std::string key); + + std::string cipher_noiv(const std::string& text); + + std::string cipher(const std::string& text, + const std::string& iv); + + std::string name() const { return algo_name; } + private: + std::string algo_name; + Keyed_Filter* filter; + Pipe pipe; + }; + +std::string Py_Cipher::cipher(const std::string& input, + const std::string& iv_str) + { + if(iv_str.size()) + { + const byte* iv_bytes = reinterpret_cast<const byte*>(iv_str.data()); + u32bit iv_len = iv_str.size(); + filter->set_iv(InitializationVector(iv_bytes, iv_len)); + } + + pipe.process_msg(input); + return pipe.read_all_as_string(Pipe::LAST_MESSAGE); + } + +// For IV-less algorithms +std::string Py_Cipher::cipher_noiv(const std::string& input) + { + pipe.process_msg(input); + return pipe.read_all_as_string(Pipe::LAST_MESSAGE); + } + +Py_Cipher::Py_Cipher(std::string algo_name, + std::string direction, + std::string key_str) + { + const byte* key_bytes = reinterpret_cast<const byte*>(key_str.data()); + u32bit key_len = key_str.size(); + + Cipher_Dir dir; + + if(direction == "encrypt") + dir = ENCRYPTION; + else if(direction == "decrypt") + dir = DECRYPTION; + else + throw std::invalid_argument("Bad cipher direction " + direction); + + filter = get_cipher(algo_name, dir); + filter->set_key(SymmetricKey(key_bytes, key_len)); + pipe.append(filter); + } + +class Py_HashFunction + { + public: + Py_HashFunction(const std::string& algo_name) + { + hash = get_hash(algo_name); + } + + ~Py_HashFunction() { delete hash; } + + void update(const std::string& input) + { + hash->update(input); + } + + std::string final() + { + std::string out(output_length(), 0); + hash->final(reinterpret_cast<byte*>(&out[0])); + return out; + } + + std::string name() const + { + return hash->name(); + } + + u32bit output_length() const + { + return hash->OUTPUT_LENGTH; + } + + private: + HashFunction* hash; + }; + +class Py_MAC + { + public: + + Py_MAC(const std::string& name, const std::string& key_str) + { + mac = get_mac(name); + + mac->set_key(reinterpret_cast<const byte*>(key_str.data()), + key_str.size()); + } + + ~Py_MAC() { delete mac; } + + u32bit output_length() const { return mac->OUTPUT_LENGTH; } + + std::string name() const { return mac->name(); } + + void update(const std::string& in) { mac->update(in); } + + std::string final() + { + std::string out(output_length(), 0); + mac->final(reinterpret_cast<byte*>(&out[0])); + return out; + } + private: + MessageAuthenticationCode* mac; + }; + +std::string cryptobox_encrypt(const std::string& in, + const std::string& passphrase, + Python_RandomNumberGenerator& rng) + { + const byte* in_bytes = reinterpret_cast<const byte*>(in.data()); + + return CryptoBox::encrypt(in_bytes, in.size(), + passphrase, rng.get_underlying_rng()); + } + +std::string cryptobox_decrypt(const std::string& in, + const std::string& passphrase) + { + const byte* in_bytes = reinterpret_cast<const byte*>(in.data()); + + return CryptoBox::decrypt(in_bytes, in.size(), + passphrase); + } + +std::string python_pbkdf2(const std::string& passphrase, + const std::string& salt, + u32bit iterations, + u32bit output_size, + const std::string& hash_fn) + { + PKCS5_PBKDF2 pbkdf2(new HMAC(get_hash(hash_fn))); + + pbkdf2.set_iterations(iterations); + pbkdf2.change_salt(reinterpret_cast<const byte*>(salt.data()), salt.size()); + + return make_string(pbkdf2.derive_key(output_size, passphrase).bits_of()); + } + +BOOST_PYTHON_MODULE(_botan) + { + python::class_<LibraryInitializer>("LibraryInitializer") + .def(python::init< python::optional<std::string> >()); + + python::class_<Python_RandomNumberGenerator>("RandomNumberGenerator") + .def(python::init<>()) + .def("__str__", &Python_RandomNumberGenerator::name) + .def("name", &Python_RandomNumberGenerator::name) + .def("reseed", &Python_RandomNumberGenerator::reseed) + .def("add_entropy", &Python_RandomNumberGenerator::add_entropy) + .def("gen_random_byte", &Python_RandomNumberGenerator::gen_random_byte) + .def("gen_random", &Python_RandomNumberGenerator::gen_random); + + python::class_<Py_Cipher, boost::noncopyable> + ("Cipher", python::init<std::string, std::string, std::string>()) + .def("name", &Py_Cipher::name) + .def("cipher", &Py_Cipher::cipher) + .def("cipher", &Py_Cipher::cipher_noiv); + + python::class_<Py_HashFunction, boost::noncopyable> + ("HashFunction", python::init<std::string>()) + .def("update", &Py_HashFunction::update) + .def("final", &Py_HashFunction::final) + .def("name", &Py_HashFunction::name) + .def("output_length", &Py_HashFunction::output_length); + + python::class_<Py_MAC, boost::noncopyable> + ("MAC", python::init<std::string, std::string>()) + .def("update", &Py_MAC::update) + .def("final", &Py_MAC::final) + .def("name", &Py_MAC::name) + .def("output_length", &Py_MAC::output_length); + + python::def("cryptobox_encrypt", cryptobox_encrypt); + python::def("cryptobox_decrypt", cryptobox_decrypt); + python::def("pbkdf2", python_pbkdf2); + + export_filters(); + export_rsa(); + export_x509(); + } diff --git a/src/wrap/python/filter.cpp b/src/wrap/python/filter.cpp new file mode 100644 index 000000000..a678af9e5 --- /dev/null +++ b/src/wrap/python/filter.cpp @@ -0,0 +1,178 @@ +/************************************************* +* Boost.Python module definition * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#include <boost/python.hpp> +using namespace boost::python; + +#include <botan/pipe.h> +#include <botan/lookup.h> +using namespace Botan; + +class Py_Filter : public Filter + { + public: + virtual void write_str(const std::string&) = 0; + + void write(const byte data[], u32bit length) + { + write_str(std::string((const char*)data, length)); + } + + void send_str(const std::string& str) + { + printf("Py_Filter::send_str\n"); + send((const byte*)str.data(), str.length()); + } + }; + +class FilterWrapper : public Py_Filter, public wrapper<Py_Filter> + { + public: + void start_msg() + { + printf("wrapper start_msg\n"); + if(override start_msg = this->get_override("start_msg")) + start_msg(); + } + + void end_msg() + { + printf("wrapper end_msg\n"); + if(override end_msg = this->get_override("end_msg")) + end_msg(); + } + + void default_start_msg() {} + void default_end_msg() {} + + virtual void write_str(const std::string& str) + { + printf("wrapper write\n"); + this->get_override("write")(str); + } + }; + +Filter* return_or_raise(Filter* filter, const std::string& name) + { + if(filter) + return filter; + throw Invalid_Argument("Filter " + name + " could not be found"); + } + +Filter* make_filter1(const std::string& name) + { + Filter* filter = 0; + + if(have_hash(name)) filter = new Hash_Filter(name); + else if(name == "Hex_Encoder") filter = new Hex_Encoder; + else if(name == "Hex_Decoder") filter = new Hex_Decoder; + else if(name == "Base64_Encoder") filter = new Base64_Encoder; + else if(name == "Base64_Decoder") filter = new Base64_Decoder; + + return return_or_raise(filter, name); + } + +Filter* make_filter2(const std::string& name, + const SymmetricKey& key) + { + Filter* filter = 0; + + if(have_mac(name)) + filter = new MAC_Filter(name, key); + else if(have_stream_cipher(name)) + filter = new StreamCipher_Filter(name, key); + + return return_or_raise(filter, name); + } + +// FIXME: add new wrapper for Keyed_Filter here +Filter* make_filter3(const std::string& name, + const SymmetricKey& key, + Cipher_Dir direction) + { + return return_or_raise( + get_cipher(name, key, direction), + name); + } + +Filter* make_filter4(const std::string& name, + const SymmetricKey& key, + const InitializationVector& iv, + Cipher_Dir direction) + { + return return_or_raise( + get_cipher(name, key, iv, direction), + name); + } + +void append_filter(Pipe& pipe, std::auto_ptr<Filter> filter) + { + pipe.append(filter.get()); + filter.release(); + } + +void prepend_filter(Pipe& pipe, std::auto_ptr<Filter> filter) + { + pipe.prepend(filter.get()); + filter.release(); + } + +void do_send(std::auto_ptr<FilterWrapper> filter, const std::string& data) + { + printf("Sending %s to %p\n", data.c_str(), filter.get()); + filter->send_str(data); + } + +BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(rallas_ovls, read_all_as_string, 0, 1) + +void export_filters() + { + class_<Filter, std::auto_ptr<Filter>, boost::noncopyable> + ("__Internal_FilterObj", no_init); + + def("make_filter", make_filter1, + return_value_policy<manage_new_object>()); + def("make_filter", make_filter2, + return_value_policy<manage_new_object>()); + def("make_filter", make_filter3, + return_value_policy<manage_new_object>()); + def("make_filter", make_filter4, + return_value_policy<manage_new_object>()); + + // This might not work - Pipe will delete the filter, but Python + // might have allocated the space with malloc() or who-knows-what -> bad + class_<FilterWrapper, std::auto_ptr<FilterWrapper>, + bases<Filter>, boost::noncopyable> + ("FilterObj") + .def("write", pure_virtual(&Py_Filter::write_str)) + .def("send", &do_send) + .def("start_msg", &Filter::start_msg, &FilterWrapper::default_start_msg) + .def("end_msg", &Filter::end_msg, &FilterWrapper::default_end_msg); + + implicitly_convertible<std::auto_ptr<FilterWrapper>, + std::auto_ptr<Filter> >(); + + void (Pipe::*pipe_write_str)(const std::string&) = &Pipe::write; + void (Pipe::*pipe_process_str)(const std::string&) = &Pipe::process_msg; + + class_<Pipe, boost::noncopyable>("PipeObj") + .def(init<>()) + /* + .def_readonly("LAST_MESSAGE", &Pipe::LAST_MESSAGE) + .def_readonly("DEFAULT_MESSAGE", &Pipe::DEFAULT_MESSAGE) + */ + .add_property("default_msg", &Pipe::default_msg, &Pipe::set_default_msg) + .add_property("msg_count", &Pipe::message_count) + .def("append", append_filter) + .def("prepend", prepend_filter) + .def("reset", &Pipe::reset) + .def("pop", &Pipe::pop) + .def("end_of_data", &Pipe::end_of_data) + .def("start_msg", &Pipe::start_msg) + .def("end_msg", &Pipe::end_msg) + .def("write", pipe_write_str) + .def("process_msg", pipe_process_str) + .def("read_all", &Pipe::read_all_as_string, rallas_ovls()); + } diff --git a/src/wrap/python/python_botan.h b/src/wrap/python/python_botan.h new file mode 100644 index 000000000..646c2e2c1 --- /dev/null +++ b/src/wrap/python/python_botan.h @@ -0,0 +1,79 @@ + +#ifndef BOTAN_BOOST_PYTHON_COMMON_H__ +#define BOTAN_BOOST_PYTHON_COMMON_H__ + +#include <botan/exceptn.h> +#include <botan/parsing.h> +#include <botan/secmem.h> +using namespace Botan; + +#include <boost/python.hpp> +namespace python = boost::python; + +extern void export_filters(); +extern void export_rsa(); +extern void export_x509(); + +class Bad_Size : public Exception + { + public: + Bad_Size(u32bit got, u32bit expected) : + Exception("Bad size detected in Python/C++ conversion layer: got " + + to_string(got) + " bytes, expected " + to_string(expected)) + {} + }; + +inline std::string make_string(const byte input[], u32bit length) + { + return std::string((const char*)input, length); + } + +inline std::string make_string(const MemoryRegion<byte>& in) + { + return make_string(in.begin(), in.size()); + } + +inline void string2binary(const std::string& from, byte to[], u32bit expected) + { + if(from.size() != expected) + throw Bad_Size(from.size(), expected); + std::memcpy(to, from.data(), expected); + } + +template<typename T> +inline python::object get_owner(T* me) + { + return python::object( + python::handle<>( + python::borrowed(python::detail::wrapper_base_::get_owner(*me)))); + } + +class Python_RandomNumberGenerator + { + public: + Python_RandomNumberGenerator() + { rng = RandomNumberGenerator::make_rng(); } + ~Python_RandomNumberGenerator() { delete rng; } + + std::string name() const { return rng->name(); } + + void reseed() { rng->reseed(192); } + + int gen_random_byte() { return rng->next_byte(); } + + std::string gen_random(int n) + { + std::string s(n, 0); + rng->randomize(reinterpret_cast<byte*>(&s[0]), n); + return s; + } + + void add_entropy(const std::string& in) + { rng->add_entropy(reinterpret_cast<const byte*>(in.c_str()), in.length()); } + + RandomNumberGenerator& get_underlying_rng() { return *rng; } + private: + RandomNumberGenerator* rng; + }; + +#endif diff --git a/src/wrap/python/rsa.cpp b/src/wrap/python/rsa.cpp new file mode 100644 index 000000000..900c3f93d --- /dev/null +++ b/src/wrap/python/rsa.cpp @@ -0,0 +1,187 @@ +/* +* Boost.Python module definition +* (C) 1999-2007 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/rsa.h> +#include <botan/look_pk.h> +#include <botan/pubkey.h> +#include <botan/x509_key.h> +using namespace Botan; + +#include "python_botan.h" +#include <sstream> + +std::string bigint2str(const BigInt& n) + { + std::ostringstream out; + out << n; + return out.str(); + } + +class Py_RSA_PrivateKey + { + public: + Py_RSA_PrivateKey(std::string pem_str, + Python_RandomNumberGenerator& rng, + std::string pass); + + Py_RSA_PrivateKey(u32bit bits, Python_RandomNumberGenerator& rng); + ~Py_RSA_PrivateKey() { delete rsa_key; } + + std::string to_string() const + { + return PKCS8::PEM_encode(*rsa_key); + } + + std::string get_N() const { return bigint2str(get_bigint_N()); } + std::string get_E() const { return bigint2str(get_bigint_E()); } + + const BigInt& get_bigint_N() const { return rsa_key->get_n(); } + const BigInt& get_bigint_E() const { return rsa_key->get_e(); } + + std::string decrypt(const std::string& in, + const std::string& padding); + + std::string sign(const std::string& in, + const std::string& padding, + Python_RandomNumberGenerator& rng); + private: + RSA_PrivateKey* rsa_key; + }; + +std::string Py_RSA_PrivateKey::decrypt(const std::string& in, + const std::string& padding) + { + std::auto_ptr<PK_Decryptor> enc(get_pk_decryptor(*rsa_key, padding)); + + const byte* in_bytes = reinterpret_cast<const byte*>(in.data()); + + return make_string(enc->decrypt(in_bytes, in.size())); + } + +std::string Py_RSA_PrivateKey::sign(const std::string& in, + const std::string& padding, + Python_RandomNumberGenerator& rng) + { + std::auto_ptr<PK_Signer> sign(get_pk_signer(*rsa_key, padding)); + const byte* in_bytes = reinterpret_cast<const byte*>(in.data()); + sign->update(in_bytes, in.size()); + return make_string(sign->signature(rng.get_underlying_rng())); + } + +Py_RSA_PrivateKey::Py_RSA_PrivateKey(u32bit bits, + Python_RandomNumberGenerator& rng) + { + rsa_key = new RSA_PrivateKey(rng.get_underlying_rng(), bits); + } + +Py_RSA_PrivateKey::Py_RSA_PrivateKey(std::string pem_str, + Python_RandomNumberGenerator& rng, + std::string passphrase) + { + DataSource_Memory in(pem_str); + + Private_Key* pkcs8_key = + PKCS8::load_key(in, + rng.get_underlying_rng(), + passphrase); + + rsa_key = dynamic_cast<RSA_PrivateKey*>(pkcs8_key); + + if(!rsa_key) + throw std::invalid_argument("Key is not an RSA key"); + } + +class Py_RSA_PublicKey + { + public: + Py_RSA_PublicKey(std::string pem_str); + Py_RSA_PublicKey(const Py_RSA_PrivateKey&); + ~Py_RSA_PublicKey() { delete rsa_key; } + + std::string get_N() const { return bigint2str(get_bigint_N()); } + std::string get_E() const { return bigint2str(get_bigint_E()); } + + const BigInt& get_bigint_N() const { return rsa_key->get_n(); } + const BigInt& get_bigint_E() const { return rsa_key->get_e(); } + + std::string to_string() const + { + return X509::PEM_encode(*rsa_key); + } + + std::string encrypt(const std::string& in, + const std::string& padding, + Python_RandomNumberGenerator& rng); + + bool verify(const std::string& in, + const std::string& padding, + const std::string& signature); + private: + RSA_PublicKey* rsa_key; + }; + +Py_RSA_PublicKey::Py_RSA_PublicKey(const Py_RSA_PrivateKey& priv) + { + rsa_key = new RSA_PublicKey(priv.get_bigint_N(), priv.get_bigint_E()); + } + +Py_RSA_PublicKey::Py_RSA_PublicKey(std::string pem_str) + { + DataSource_Memory in(pem_str); + Public_Key* x509_key = X509::load_key(in); + + rsa_key = dynamic_cast<RSA_PublicKey*>(x509_key); + + if(!rsa_key) + throw std::invalid_argument("Key is not an RSA key"); + } + +std::string Py_RSA_PublicKey::encrypt(const std::string& in, + const std::string& padding, + Python_RandomNumberGenerator& rng) + { + std::auto_ptr<PK_Encryptor> enc(get_pk_encryptor(*rsa_key, padding)); + + const byte* in_bytes = reinterpret_cast<const byte*>(in.data()); + + return make_string(enc->encrypt(in_bytes, in.size(), + rng.get_underlying_rng())); + } + +bool Py_RSA_PublicKey::verify(const std::string& in, + const std::string& signature, + const std::string& padding) + { + std::auto_ptr<PK_Verifier> ver(get_pk_verifier(*rsa_key, padding)); + + const byte* in_bytes = reinterpret_cast<const byte*>(in.data()); + const byte* sig_bytes = reinterpret_cast<const byte*>(signature.data()); + + ver->update(in_bytes, in.size()); + return ver->check_signature(sig_bytes, signature.size()); + } + +void export_rsa() + { + python::class_<Py_RSA_PublicKey> + ("RSA_PublicKey", python::init<std::string>()) + .def(python::init<const Py_RSA_PrivateKey&>()) + .def("to_string", &Py_RSA_PublicKey::to_string) + .def("encrypt", &Py_RSA_PublicKey::encrypt) + .def("verify", &Py_RSA_PublicKey::verify) + .def("get_N", &Py_RSA_PublicKey::get_N) + .def("get_E", &Py_RSA_PublicKey::get_E); + + python::class_<Py_RSA_PrivateKey> + ("RSA_PrivateKey", python::init<std::string, Python_RandomNumberGenerator&, std::string>()) + .def(python::init<u32bit, Python_RandomNumberGenerator&>()) + .def("to_string", &Py_RSA_PrivateKey::to_string) + .def("decrypt", &Py_RSA_PrivateKey::decrypt) + .def("sign", &Py_RSA_PrivateKey::sign) + .def("get_N", &Py_RSA_PrivateKey::get_N) + .def("get_E", &Py_RSA_PrivateKey::get_E); + } diff --git a/src/wrap/python/x509.cpp b/src/wrap/python/x509.cpp new file mode 100644 index 000000000..90c2bba1c --- /dev/null +++ b/src/wrap/python/x509.cpp @@ -0,0 +1,140 @@ +/************************************************* +* Boost.Python module definition * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#include <botan/oids.h> +#include <botan/pipe.h> +#include <botan/filters.h> +#include <botan/x509cert.h> +#include <botan/x509_crl.h> +#include <botan/x509stor.h> +using namespace Botan; + +#include <boost/python.hpp> +namespace python = boost::python; + +template<typename T> +class vector_to_list + { + public: + static PyObject* convert(const std::vector<T>& in) + { + python::list out; + typename std::vector<T>::const_iterator i = in.begin(); + while(i != in.end()) + { + out.append(*i); + ++i; + } + return python::incref(out.ptr()); + } + + vector_to_list() + { + python::to_python_converter<std::vector<T>, vector_to_list<T> >(); + } + }; + +template<typename T> +class memvec_to_hexstr + { + public: + static PyObject* convert(const T& in) + { + Pipe pipe(new Hex_Encoder); + pipe.process_msg(in); + std::string result = pipe.read_all_as_string(); + return python::incref(python::str(result).ptr()); + } + + memvec_to_hexstr() + { + python::to_python_converter<T, memvec_to_hexstr<T> >(); + } + }; + +class X509_Store_Search_Wrap : public X509_Store::Search_Func, + public python::wrapper<X509_Store::Search_Func> + { + public: + bool match(const X509_Certificate& cert) const + { + return this->get_override("match")(cert); + } + }; + +BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(add_cert_ols, add_cert, 1, 2) +BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(validate_cert_ols, validate_cert, 1, 2) + +void export_x509() + { + vector_to_list<std::string>(); + vector_to_list<X509_Certificate>(); + memvec_to_hexstr<MemoryVector<byte> >(); + + python::class_<X509_Certificate> + ("X509_Certificate", python::init<std::string>()) + .def(python::self == python::self) + .def(python::self != python::self) + .add_property("version", &X509_Certificate::x509_version) + .add_property("is_CA", &X509_Certificate::is_CA_cert) + .add_property("self_signed", &X509_Certificate::is_self_signed) + .add_property("pathlimit", &X509_Certificate::path_limit) + .add_property("as_pem", &X509_Object::PEM_encode) + .def("start_time", &X509_Certificate::start_time) + .def("end_time", &X509_Certificate::end_time) + .def("subject_info", &X509_Certificate::subject_info) + .def("issuer_info", &X509_Certificate::issuer_info) + .def("ex_constraints", &X509_Certificate::ex_constraints) + .def("policies", &X509_Certificate::policies) + .def("subject_key_id", &X509_Certificate::subject_key_id) + .def("authority_key_id", &X509_Certificate::authority_key_id); + + python::class_<X509_CRL> + ("X509_CRL", python::init<std::string>()) + .add_property("as_pem", &X509_Object::PEM_encode); + + python::enum_<X509_Code>("verify_result") + .value("verified", VERIFIED) + .value("unknown_x509_error", UNKNOWN_X509_ERROR) + .value("cannot_establish_trust", CANNOT_ESTABLISH_TRUST) + .value("cert_chain_too_long", CERT_CHAIN_TOO_LONG) + .value("signature_error", SIGNATURE_ERROR) + .value("policy_error", POLICY_ERROR) + .value("invalid_usage", INVALID_USAGE) + .value("cert_format_error", CERT_FORMAT_ERROR) + .value("cert_issuer_not_found", CERT_ISSUER_NOT_FOUND) + .value("cert_not_yet_valid", CERT_NOT_YET_VALID) + .value("cert_has_expired", CERT_HAS_EXPIRED) + .value("cert_is_revoked", CERT_IS_REVOKED) + .value("crl_format_error", CRL_FORMAT_ERROR) + .value("crl_issuer_not_found", CRL_ISSUER_NOT_FOUND) + .value("crl_not_yet_valid", CRL_NOT_YET_VALID) + .value("crl_has_expired", CRL_HAS_EXPIRED) + .value("ca_cert_cannot_sign", CA_CERT_CANNOT_SIGN) + .value("ca_cert_not_for_cert_issuer", CA_CERT_NOT_FOR_CERT_ISSUER) + .value("ca_cert_not_for_crl_issuer", CA_CERT_NOT_FOR_CRL_ISSUER); + + python::enum_<X509_Store::Cert_Usage>("cert_usage") + .value("any", X509_Store::ANY) + .value("tls_server", X509_Store::TLS_SERVER) + .value("tls_client", X509_Store::TLS_CLIENT) + .value("code_signing", X509_Store::CODE_SIGNING) + .value("email_protection", X509_Store::EMAIL_PROTECTION) + .value("time_stamping", X509_Store::TIME_STAMPING) + .value("crl_signing", X509_Store::CRL_SIGNING); + + { + python::scope in_class = + python::class_<X509_Store>("X509_Store") + .def("add_cert", &X509_Store::add_cert, add_cert_ols()) + .def("validate", &X509_Store::validate_cert, validate_cert_ols()) + .def("get_certs", &X509_Store::get_certs) + .def("add_crl", &X509_Store::add_crl); + + python::class_<X509_Store_Search_Wrap, boost::noncopyable> + ("Search_Func") + .def("match", python::pure_virtual(&X509_Store::Search_Func::match)); + } + } |