/* * Botan 1.10.2 Amalgamation * (C) 1999-2011 Jack Lloyd and others * * Distributed under the terms of the Botan license */ #include "botan.h" #include #ifdef Q_OS_WIN #ifndef NOMINMAX #define NOMINMAX #endif #endif namespace Botan { /** * Represents a DLL or shared object */ class Dynamically_Loaded_Library { public: /** * Load a DLL (or fail with an exception) * @param lib_name name or path to a library * * If you don't use a full path, the search order will be defined * by whatever the system linker does by default. Always using fully * qualified pathnames can help prevent code injection attacks (eg * via manipulation of LD_LIBRARY_PATH on Linux) */ Dynamically_Loaded_Library(const std::string& lib_name); /** * Unload the DLL * @warning Any pointers returned by resolve()/resolve_symbol() * should not be used after this destructor runs. */ ~Dynamically_Loaded_Library(); /** * Load a symbol (or fail with an exception) * @param symbol names the symbol to load * @return address of the loaded symbol */ void* resolve_symbol(const std::string& symbol); /** * Convenience function for casting symbol to the right type * @param symbol names the symbol to load * @return address of the loaded symbol */ template T resolve(const std::string& symbol) { #if defined(__GNUC__) && __GNUC__ < 4 return (T)(resolve_symbol(symbol)); #else return reinterpret_cast(resolve_symbol(symbol)); #endif } private: Dynamically_Loaded_Library(const Dynamically_Loaded_Library&); Dynamically_Loaded_Library& operator=(const Dynamically_Loaded_Library&); std::string lib_name; void* lib; }; } #ifdef Q_OS_WIN namespace Botan { /** * Win32 Entropy Source */ class Win32_EntropySource : public EntropySource { public: std::string name() const { return "Win32 Statistics"; } void poll(Entropy_Accumulator& accum); }; } #endif namespace Botan { /** * Fake SIMD, using plain scalar operations * Often still faster than iterative on superscalar machines */ class SIMD_Scalar { public: static bool enabled() { return true; } SIMD_Scalar(const u32bit B[4]) { R0 = B[0]; R1 = B[1]; R2 = B[2]; R3 = B[3]; } SIMD_Scalar(u32bit B0, u32bit B1, u32bit B2, u32bit B3) { R0 = B0; R1 = B1; R2 = B2; R3 = B3; } SIMD_Scalar(u32bit B) { R0 = B; R1 = B; R2 = B; R3 = B; } static SIMD_Scalar load_le(const void* in) { const byte* in_b = static_cast(in); return SIMD_Scalar(Botan::load_le(in_b, 0), Botan::load_le(in_b, 1), Botan::load_le(in_b, 2), Botan::load_le(in_b, 3)); } static SIMD_Scalar load_be(const void* in) { const byte* in_b = static_cast(in); return SIMD_Scalar(Botan::load_be(in_b, 0), Botan::load_be(in_b, 1), Botan::load_be(in_b, 2), Botan::load_be(in_b, 3)); } void store_le(byte out[]) const { Botan::store_le(out, R0, R1, R2, R3); } void store_be(byte out[]) const { Botan::store_be(out, R0, R1, R2, R3); } void rotate_left(size_t rot) { R0 = Botan::rotate_left(R0, rot); R1 = Botan::rotate_left(R1, rot); R2 = Botan::rotate_left(R2, rot); R3 = Botan::rotate_left(R3, rot); } void rotate_right(size_t rot) { R0 = Botan::rotate_right(R0, rot); R1 = Botan::rotate_right(R1, rot); R2 = Botan::rotate_right(R2, rot); R3 = Botan::rotate_right(R3, rot); } void operator+=(const SIMD_Scalar& other) { R0 += other.R0; R1 += other.R1; R2 += other.R2; R3 += other.R3; } SIMD_Scalar operator+(const SIMD_Scalar& other) const { return SIMD_Scalar(R0 + other.R0, R1 + other.R1, R2 + other.R2, R3 + other.R3); } void operator-=(const SIMD_Scalar& other) { R0 -= other.R0; R1 -= other.R1; R2 -= other.R2; R3 -= other.R3; } SIMD_Scalar operator-(const SIMD_Scalar& other) const { return SIMD_Scalar(R0 - other.R0, R1 - other.R1, R2 - other.R2, R3 - other.R3); } void operator^=(const SIMD_Scalar& other) { R0 ^= other.R0; R1 ^= other.R1; R2 ^= other.R2; R3 ^= other.R3; } SIMD_Scalar operator^(const SIMD_Scalar& other) const { return SIMD_Scalar(R0 ^ other.R0, R1 ^ other.R1, R2 ^ other.R2, R3 ^ other.R3); } void operator|=(const SIMD_Scalar& other) { R0 |= other.R0; R1 |= other.R1; R2 |= other.R2; R3 |= other.R3; } SIMD_Scalar operator&(const SIMD_Scalar& other) { return SIMD_Scalar(R0 & other.R0, R1 & other.R1, R2 & other.R2, R3 & other.R3); } void operator&=(const SIMD_Scalar& other) { R0 &= other.R0; R1 &= other.R1; R2 &= other.R2; R3 &= other.R3; } SIMD_Scalar operator<<(size_t shift) const { return SIMD_Scalar(R0 << shift, R1 << shift, R2 << shift, R3 << shift); } SIMD_Scalar operator>>(size_t shift) const { return SIMD_Scalar(R0 >> shift, R1 >> shift, R2 >> shift, R3 >> shift); } SIMD_Scalar operator~() const { return SIMD_Scalar(~R0, ~R1, ~R2, ~R3); } // (~reg) & other SIMD_Scalar andc(const SIMD_Scalar& other) { return SIMD_Scalar(~R0 & other.R0, ~R1 & other.R1, ~R2 & other.R2, ~R3 & other.R3); } SIMD_Scalar bswap() const { return SIMD_Scalar(reverse_bytes(R0), reverse_bytes(R1), reverse_bytes(R2), reverse_bytes(R3)); } static void transpose(SIMD_Scalar& B0, SIMD_Scalar& B1, SIMD_Scalar& B2, SIMD_Scalar& B3) { SIMD_Scalar T0(B0.R0, B1.R0, B2.R0, B3.R0); SIMD_Scalar T1(B0.R1, B1.R1, B2.R1, B3.R1); SIMD_Scalar T2(B0.R2, B1.R2, B2.R2, B3.R2); SIMD_Scalar T3(B0.R3, B1.R3, B2.R3, B3.R3); B0 = T0; B1 = T1; B2 = T2; B3 = T3; } private: u32bit R0, R1, R2, R3; }; } namespace Botan { /** * XOR arrays. Postcondition out[i] = in[i] ^ out[i] forall i = 0...length * @param out the input/output buffer * @param in the read-only input buffer * @param length the length of the buffers */ inline void xor_buf(byte out[], const byte in[], size_t length) { while(length >= 8) { #if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK *reinterpret_cast(out) ^= *reinterpret_cast(in); #else out[0] ^= in[0]; out[1] ^= in[1]; out[2] ^= in[2]; out[3] ^= in[3]; out[4] ^= in[4]; out[5] ^= in[5]; out[6] ^= in[6]; out[7] ^= in[7]; #endif out += 8; in += 8; length -= 8; } for(size_t i = 0; i != length; ++i) out[i] ^= in[i]; } /** * XOR arrays. Postcondition out[i] = in[i] ^ in2[i] forall i = 0...length * @param out the output buffer * @param in the first input buffer * @param in2 the second output buffer * @param length the length of the three buffers */ inline void xor_buf(byte out[], const byte in[], const byte in2[], size_t length) { while(length >= 8) { #if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK *reinterpret_cast(out) = *reinterpret_cast(in) ^ *reinterpret_cast(in2); #else out[0] = in[0] ^ in2[0]; out[1] = in[1] ^ in2[1]; out[2] = in[2] ^ in2[2]; out[3] = in[3] ^ in2[3]; out[4] = in[4] ^ in2[4]; out[5] = in[5] ^ in2[5]; out[6] = in[6] ^ in2[6]; out[7] = in[7] ^ in2[7]; #endif in += 8; in2 += 8; out += 8; length -= 8; } for(size_t i = 0; i != length; ++i) out[i] = in[i] ^ in2[i]; } } namespace Botan { /** * Mutex Base Class */ class Mutex { public: /** * Lock the mutex */ virtual void lock() = 0; /** * Unlock the mutex */ virtual void unlock() = 0; virtual ~Mutex() {} }; /** * Mutex Factory */ class Mutex_Factory { public: /** * @return newly allocated mutex */ virtual Mutex* make() = 0; virtual ~Mutex_Factory() {} }; /** * Mutex Holding Class for RAII */ class Mutex_Holder { public: /** * Hold onto a mutex until we leave scope * @param m the mutex to lock */ Mutex_Holder(Mutex* m) : mux(m) { if(!mux) throw Invalid_Argument("Mutex_Holder: Argument was NULL"); mux->lock(); } ~Mutex_Holder() { mux->unlock(); } private: Mutex* mux; }; } namespace Botan { /** * Copy-on-Predicate Algorithm * @param current the first iterator value * @param end the final iterator value * @param dest an output iterator * @param copy_p the predicate */ template OutputIterator copy_if(InputIterator current, InputIterator end, OutputIterator dest, Predicate copy_p) { while(current != end) { if(copy_p(*current)) *dest++ = *current; ++current; } return dest; } /** * Searching through a std::map * @param mapping the map to search * @param key is what to look for * @param null_result is the value to return if key is not in mapping * @return mapping[key] or null_result */ template inline V search_map(const std::map& mapping, const K& key, const V& null_result = V()) { typename std::map::const_iterator i = mapping.find(key); if(i == mapping.end()) return null_result; return i->second; } /** * Function adaptor for delete operation */ template class del_fun : public std::unary_function { public: void operator()(T* ptr) { delete ptr; } }; /** * Delete the second half of a pair of objects */ template void delete2nd(Pair& pair) { delete pair.second; } /** * Insert a key/value pair into a multimap */ template void multimap_insert(std::multimap& multimap, const K& key, const V& value) { #if defined(BOTAN_BUILD_COMPILER_IS_SUN_STUDIO) // Work around a strange bug in Sun Studio multimap.insert(std::make_pair(key, value)); #else multimap.insert(std::make_pair(key, value)); #endif } } namespace Botan { /** * @param prov_name a provider name * @return weight for this provider */ size_t static_provider_weight(const std::string& prov_name); /** * Algorithm_Cache (used by Algorithm_Factory) */ template class Algorithm_Cache { public: /** * @param algo_spec names the requested algorithm * @param pref_provider suggests a preferred provider * @return prototype object, or NULL */ const T* get(const std::string& algo_spec, const std::string& pref_provider); /** * Add a new algorithm implementation to the cache * @param algo the algorithm prototype object * @param requested_name how this name will be requested * @param provider_name is the name of the provider of this prototype */ void add(T* algo, const std::string& requested_name, const std::string& provider_name); /** * Set the preferred provider * @param algo_spec names the algorithm * @param provider names the preferred provider */ void set_preferred_provider(const std::string& algo_spec, const std::string& provider); /** * Return the list of providers of this algorithm * @param algo_name names the algorithm * @return list of providers of this algorithm */ std::vector providers_of(const std::string& algo_name); /** * Clear the cache */ void clear_cache(); /** * Constructor * @param m a mutex to serialize internal access */ Algorithm_Cache(Mutex* m) : mutex(m) {} ~Algorithm_Cache() { clear_cache(); delete mutex; } private: typedef typename std::map >::iterator algorithms_iterator; typedef typename std::map::iterator provider_iterator; algorithms_iterator find_algorithm(const std::string& algo_spec); Mutex* mutex; std::map aliases; std::map pref_providers; std::map > algorithms; }; /* * Look for an algorithm implementation in the cache, also checking aliases * Assumes object lock is held */ template typename Algorithm_Cache::algorithms_iterator Algorithm_Cache::find_algorithm(const std::string& algo_spec) { algorithms_iterator algo = algorithms.find(algo_spec); // Not found? Check if a known alias if(algo == algorithms.end()) { std::map::const_iterator alias = aliases.find(algo_spec); if(alias != aliases.end()) algo = algorithms.find(alias->second); } return algo; } /* * Look for an algorithm implementation by a particular provider */ template const T* Algorithm_Cache::get(const std::string& algo_spec, const std::string& requested_provider) { Mutex_Holder lock(mutex); algorithms_iterator algo = find_algorithm(algo_spec); if(algo == algorithms.end()) // algo not found at all (no providers) return 0; // If a provider is requested specifically, return it or fail entirely if(requested_provider != "") { provider_iterator prov = algo->second.find(requested_provider); if(prov != algo->second.end()) return prov->second; return 0; } const T* prototype = 0; std::string prototype_provider; size_t prototype_prov_weight = 0; const std::string pref_provider = search_map(pref_providers, algo_spec); for(provider_iterator i = algo->second.begin(); i != algo->second.end(); ++i) { const std::string prov_name = i->first; const size_t prov_weight = static_provider_weight(prov_name); // preferred prov exists, return immediately if(prov_name == pref_provider) return i->second; if(prototype == 0 || prov_weight > prototype_prov_weight) { prototype = i->second; prototype_provider = i->first; prototype_prov_weight = prov_weight; } } return prototype; } /* * Add an implementation to the cache */ template void Algorithm_Cache::add(T* algo, const std::string& requested_name, const std::string& provider) { if(!algo) return; Mutex_Holder lock(mutex); if(algo->name() != requested_name && aliases.find(requested_name) == aliases.end()) { aliases[requested_name] = algo->name(); } if(!algorithms[algo->name()][provider]) algorithms[algo->name()][provider] = algo; else delete algo; } /* * Find the providers of this algo (if any) */ template std::vector Algorithm_Cache::providers_of(const std::string& algo_name) { Mutex_Holder lock(mutex); std::vector providers; algorithms_iterator algo = find_algorithm(algo_name); if(algo != algorithms.end()) { provider_iterator provider = algo->second.begin(); while(provider != algo->second.end()) { providers.push_back(provider->first); ++provider; } } return providers; } /* * Set the preferred provider for an algorithm */ template void Algorithm_Cache::set_preferred_provider(const std::string& algo_spec, const std::string& provider) { Mutex_Holder lock(mutex); pref_providers[algo_spec] = provider; } /* * Clear out the cache */ template void Algorithm_Cache::clear_cache() { algorithms_iterator algo = algorithms.begin(); while(algo != algorithms.end()) { provider_iterator provider = algo->second.begin(); while(provider != algo->second.end()) { delete provider->second; ++provider; } ++algo; } algorithms.clear(); } } namespace Botan { /** * Round up * @param n an integer * @param align_to the alignment boundary * @return n rounded up to a multiple of align_to */ template inline T round_up(T n, T align_to) { if(n % align_to || n == 0) n += align_to - (n % align_to); return n; } /** * Round down * @param n an integer * @param align_to the alignment boundary * @return n rounded down to a multiple of align_to */ template inline T round_down(T n, T align_to) { return (n - (n % align_to)); } } namespace Botan { /** * Engine for implementations that use some kind of SIMD */ class SIMD_Engine : public Engine { public: std::string provider_name() const { return "simd"; } BlockCipher* find_block_cipher(const SCAN_Name&, Algorithm_Factory&) const; HashFunction* find_hash(const SCAN_Name& request, Algorithm_Factory&) const; }; } namespace Botan { /** * File Tree Walking Entropy Source */ class FTW_EntropySource : public EntropySource { public: std::string name() const { return "Proc Walker"; } void poll(Entropy_Accumulator& accum); FTW_EntropySource(const std::string& root_dir); ~FTW_EntropySource(); private: std::string path; class File_Descriptor_Source* dir; }; } namespace Botan { /** * Entropy source using high resolution timers * * @note Any results from timers are marked as not contributing entropy * to the poll, as a local attacker could observe them directly. */ class High_Resolution_Timestamp : public EntropySource { public: std::string name() const { return "High Resolution Timestamp"; } void poll(Entropy_Accumulator& accum); }; } #ifdef Q_OS_WIN namespace Botan { /** * Win32 Mutex Factory */ class Win32_Mutex_Factory : public Mutex_Factory { public: Mutex* make(); }; } #endif namespace Botan { /** * Power of 2 test. T should be an unsigned integer type * @param arg an integer value * @return true iff arg is 2^n for some n > 0 */ template inline bool power_of_2(T arg) { return ((arg != 0 && arg != 1) && ((arg & (arg-1)) == 0)); } /** * Return the index of the highest set bit * T is an unsigned integer type * @param n an integer value * @return index of the highest set bit in n */ template inline size_t high_bit(T n) { for(size_t i = 8*sizeof(T); i > 0; --i) if((n >> (i - 1)) & 0x01) return i; return 0; } /** * Return the index of the lowest set bit * T is an unsigned integer type * @param n an integer value * @return index of the lowest set bit in n */ template inline size_t low_bit(T n) { for(size_t i = 0; i != 8*sizeof(T); ++i) if((n >> i) & 0x01) return (i + 1); return 0; } /** * Return the number of significant bytes in n * @param n an integer value * @return number of significant bytes in n */ template inline size_t significant_bytes(T n) { for(size_t i = 0; i != sizeof(T); ++i) if(get_byte(i, n)) return sizeof(T)-i; return 0; } /** * Compute Hamming weights * @param n an integer value * @return number of bits in n set to 1 */ template inline size_t hamming_weight(T n) { const byte NIBBLE_WEIGHTS[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 }; size_t weight = 0; for(size_t i = 0; i != 2*sizeof(T); ++i) weight += NIBBLE_WEIGHTS[(n >> (4*i)) & 0x0F]; return weight; } /** * Count the trailing zero bits in n * @param n an integer value * @return maximum x st 2^x divides n */ template inline size_t ctz(T n) { for(size_t i = 0; i != 8*sizeof(T); ++i) if((n >> i) & 0x01) return i; return 8*sizeof(T); } } namespace Botan { /** * Estimate work factor for discrete logarithm * @param prime_group_size size of the group in bits * @return estimated security level for this group */ size_t dl_work_factor(size_t prime_group_size); } namespace Botan { /** * No-Op Mutex Factory */ class Noop_Mutex_Factory : public Mutex_Factory { public: Mutex* make(); }; } namespace Botan { /** * Pooling Allocator */ class Pooling_Allocator : public Allocator { public: void* allocate(size_t); void deallocate(void*, size_t); void destroy(); /** * @param mutex used for internal locking */ Pooling_Allocator(Mutex* mutex); ~Pooling_Allocator(); private: void get_more_core(size_t); byte* allocate_blocks(size_t); virtual void* alloc_block(size_t) = 0; virtual void dealloc_block(void*, size_t) = 0; class Memory_Block { public: Memory_Block(void*); static size_t bitmap_size() { return BITMAP_SIZE; } static size_t block_size() { return BLOCK_SIZE; } bool contains(void*, size_t) const; byte* alloc(size_t); void free(void*, size_t); bool operator<(const Memory_Block& other) const { if(buffer < other.buffer && other.buffer < buffer_end) return false; return (buffer < other.buffer); } private: typedef u64bit bitmap_type; static const size_t BITMAP_SIZE = 8 * sizeof(bitmap_type); static const size_t BLOCK_SIZE = 64; bitmap_type bitmap; byte* buffer, *buffer_end; }; std::vector blocks; std::vector::iterator last_used; std::vector > allocated; Mutex* mutex; }; } namespace Botan { /** * Allocator using malloc */ class Malloc_Allocator : public Allocator { public: void* allocate(size_t); void deallocate(void*, size_t); std::string type() const { return "malloc"; } }; /** * Allocator using malloc plus locking */ class Locking_Allocator : public Pooling_Allocator { public: /** * @param mutex used for internal locking */ Locking_Allocator(Mutex* mutex) : Pooling_Allocator(mutex) {} std::string type() const { return "locking"; } private: void* alloc_block(size_t); void dealloc_block(void*, size_t); }; } namespace Botan { /** * Fixed Window Exponentiator */ class Fixed_Window_Exponentiator : public Modular_Exponentiator { public: void set_exponent(const BigInt&); void set_base(const BigInt&); BigInt execute() const; Modular_Exponentiator* copy() const { return new Fixed_Window_Exponentiator(*this); } Fixed_Window_Exponentiator(const BigInt&, Power_Mod::Usage_Hints); private: Modular_Reducer reducer; BigInt exp; size_t window_bits; std::vector g; Power_Mod::Usage_Hints hints; }; /** * Montgomery Exponentiator */ class Montgomery_Exponentiator : public Modular_Exponentiator { public: void set_exponent(const BigInt&); void set_base(const BigInt&); BigInt execute() const; Modular_Exponentiator* copy() const { return new Montgomery_Exponentiator(*this); } Montgomery_Exponentiator(const BigInt&, Power_Mod::Usage_Hints); private: BigInt exp, modulus; BigInt R2, R_mod; std::vector g; word mod_prime; size_t mod_words, exp_bits, window_bits; Power_Mod::Usage_Hints hints; }; } #if (BOTAN_MP_WORD_BITS != 32) #error The mp_x86_32 module requires that BOTAN_MP_WORD_BITS == 32 #endif #ifdef Q_OS_UNIX namespace Botan { extern "C" { /* * Helper Macros for x86 Assembly */ #define ASM(x) x "\n\t" /* * Word Multiply */ inline word word_madd2(word a, word b, word* c) { asm( ASM("mull %[b]") ASM("addl %[c],%[a]") ASM("adcl $0,%[carry]") : [a]"=a"(a), [b]"=rm"(b), [carry]"=&d"(*c) : "0"(a), "1"(b), [c]"g"(*c) : "cc"); return a; } /* * Word Multiply/Add */ inline word word_madd3(word a, word b, word c, word* d) { asm( ASM("mull %[b]") ASM("addl %[c],%[a]") ASM("adcl $0,%[carry]") ASM("addl %[d],%[a]") ASM("adcl $0,%[carry]") : [a]"=a"(a), [b]"=rm"(b), [carry]"=&d"(*d) : "0"(a), "1"(b), [c]"g"(c), [d]"g"(*d) : "cc"); return a; } } } #endif namespace Botan { /** * Unix Program Info */ struct Unix_Program { /** * @param n is the name and arguments of what we are going run * @param p is the priority level (lower prio numbers get polled first) */ Unix_Program(const char* n, size_t p) { name_and_args = n; priority = p; working = true; } /** * The name and arguments for this command */ std::string name_and_args; /** * Priority: we scan from low to high */ size_t priority; /** * Does this source seem to be working? */ bool working; }; /** * Command Output DataSource */ class DataSource_Command : public DataSource { public: size_t read(byte[], size_t); size_t peek(byte[], size_t, size_t) const; bool end_of_data() const; std::string id() const; int fd() const; DataSource_Command(const std::string&, const std::vector& paths); ~DataSource_Command(); private: void create_pipe(const std::vector&); void shutdown_pipe(); const size_t MAX_BLOCK_USECS, KILL_WAIT; std::vector arg_list; struct pipe_wrapper* pipe; }; } namespace Botan { /** * Allocator that uses memory maps backed by disk. We zeroize the map * upon deallocation. If swap occurs, the VM will swap to the shared * file backing rather than to a swap device, which means we know where * it is and can zap it later. */ class MemoryMapping_Allocator : public Pooling_Allocator { public: /** * @param mutex used for internal locking */ MemoryMapping_Allocator(Mutex* mutex) : Pooling_Allocator(mutex) {} std::string type() const { return "mmap"; } private: void* alloc_block(size_t); void dealloc_block(void*, size_t); }; } #if defined(BOTAN_HAS_SIMD_SSE2) namespace Botan { typedef SIMD_SSE2 SIMD_32; } #elif defined(BOTAN_HAS_SIMD_ALTIVEC) namespace Botan { typedef SIMD_Altivec SIMD_32; } #elif defined(BOTAN_HAS_SIMD_SCALAR) namespace Botan { typedef SIMD_Scalar SIMD_32; } #else #error "No SIMD module defined" #endif namespace Botan { /** * Entropy source reading from kernel devices like /dev/random */ class Device_EntropySource : public EntropySource { public: std::string name() const { return "RNG Device Reader"; } void poll(Entropy_Accumulator& accum); Device_EntropySource(const std::vector& fsnames); ~Device_EntropySource(); private: /** A class handling reading from a Unix character device */ class Device_Reader { public: typedef int fd_type; // Does not own fd, a transient class Device_Reader(fd_type device_fd) : fd(device_fd) {} void close(); size_t get(byte out[], size_t length, size_t ms_wait_time); static fd_type open(const std::string& pathname); private: fd_type fd; }; std::vector devices; }; } namespace Botan { void assertion_failure(const char* expr_str, const char* msg, const char* func, const char* file, int line); #define BOTAN_ASSERT(expr, msg) \ do { \ if(!(expr)) \ Botan::assertion_failure(#expr, \ msg, \ BOTAN_ASSERT_FUNCTION, \ __FILE__, \ __LINE__); \ } while(0) #define BOTAN_ASSERT_EQUAL(value1, value2, msg) \ do { \ if(value1 != value2) \ Botan::assertion_failure(#value1 " == " #value2, \ msg, \ BOTAN_ASSERT_FUNCTION, \ __FILE__, \ __LINE__); \ } while(0) /* * Unfortunately getting the function name from the preprocessor * isn't standard in C++98 (C++0x uses C99's __func__) */ #if defined(BOTAN_BUILD_COMPILER_IS_GCC) || \ defined(BOTAN_BUILD_COMPILER_IS_CLANG) || \ defined(BOTAN_BUILD_COMPILER_IS_INTEL) #define BOTAN_ASSERT_FUNCTION __PRETTY_FUNCTION__ #elif defined(BOTAN_BUILD_COMPILER_IS_MSVC) #define BOTAN_ASSERT_FUNCTION __FUNCTION__ #else #define BOTAN_ASSERT_FUNCTION ((const char*)0) #endif } namespace Botan { /* * The size of the word type, in bits */ const size_t MP_WORD_BITS = BOTAN_MP_WORD_BITS; extern "C" { /* * Addition/Subtraction Operations */ void bigint_add2(word x[], size_t x_size, const word y[], size_t y_size); void bigint_add3(word z[], const word x[], size_t x_size, const word y[], size_t y_size); word bigint_add2_nc(word x[], size_t x_size, const word y[], size_t y_size); word bigint_add3_nc(word z[], const word x[], size_t x_size, const word y[], size_t y_size); word bigint_sub2(word x[], size_t x_size, const word y[], size_t y_size); /** * x = y - x; assumes y >= x */ void bigint_sub2_rev(word x[], const word y[], size_t y_size); word bigint_sub3(word z[], const word x[], size_t x_size, const word y[], size_t y_size); /* * Shift Operations */ void bigint_shl1(word x[], size_t x_size, size_t word_shift, size_t bit_shift); void bigint_shr1(word x[], size_t x_size, size_t word_shift, size_t bit_shift); void bigint_shl2(word y[], const word x[], size_t x_size, size_t word_shift, size_t bit_shift); void bigint_shr2(word y[], const word x[], size_t x_size, size_t word_shift, size_t bit_shift); /* * Simple O(N^2) Multiplication and Squaring */ void bigint_simple_mul(word z[], const word x[], size_t x_size, const word y[], size_t y_size); void bigint_simple_sqr(word z[], const word x[], size_t x_size); /* * Linear Multiply */ void bigint_linmul2(word x[], size_t x_size, word y); void bigint_linmul3(word z[], const word x[], size_t x_size, word y); /** * Montgomery Reduction * @param z integer to reduce (also output in first p_size+1 words) * @param z_size size of z (should be >= 2*p_size+1) * @param p modulus * @param p_size size of p * @param p_dash Montgomery value * @param workspace array of at least 2*(p_size+1) words */ void bigint_monty_redc(word z[], size_t z_size, const word p[], size_t p_size, word p_dash, word workspace[]); /* * Montgomery Multiplication */ void bigint_monty_mul(word z[], size_t z_size, const word x[], size_t x_size, size_t x_sw, const word y[], size_t y_size, size_t y_sw, const word p[], size_t p_size, word p_dash, word workspace[]); /* * Montgomery Squaring */ void bigint_monty_sqr(word z[], size_t z_size, const word x[], size_t x_size, size_t x_sw, const word p[], size_t p_size, word p_dash, word workspace[]); /* * Division operation */ size_t bigint_divcore(word q, word y2, word y1, word x3, word x2, word x1); /** * Compare x and y */ s32bit bigint_cmp(const word x[], size_t x_size, const word y[], size_t y_size); /** * Compute ((n1<& path); private: static std::vector get_default_sources(); void fast_poll(Entropy_Accumulator& accum); const std::vector PATH; std::vector sources; }; } namespace Botan { /** * EGD Entropy Source */ class EGD_EntropySource : public EntropySource { public: std::string name() const { return "EGD/PRNGD"; } void poll(Entropy_Accumulator& accum); EGD_EntropySource(const std::vector&); ~EGD_EntropySource(); private: class EGD_Socket { public: EGD_Socket(const std::string& path); void close(); size_t read(byte outbuf[], size_t length); private: static int open_socket(const std::string& path); std::string socket_path; int m_fd; // cached fd }; std::vector sockets; }; } #endif namespace Botan { Public_Key* make_public_key(const AlgorithmIdentifier& alg_id, const MemoryRegion& key_bits); Private_Key* make_private_key(const AlgorithmIdentifier& alg_id, const MemoryRegion& key_bits, RandomNumberGenerator& rng); } namespace Botan { /** * Container of output buffers for Pipe */ class Output_Buffers { public: size_t read(byte[], size_t, Pipe::message_id); size_t peek(byte[], size_t, size_t, Pipe::message_id) const; size_t remaining(Pipe::message_id) const; void add(class SecureQueue*); void retire(); Pipe::message_id message_count() const; Output_Buffers(); ~Output_Buffers(); private: class SecureQueue* get(Pipe::message_id) const; std::deque buffers; Pipe::message_id offset; }; } namespace Botan { /** * Check if we can at least potentially lock memory */ bool has_mlock(); /** * 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 */ bool lock_mem(void* addr, size_t 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 */ void unlock_mem(void* addr, size_t length); } #ifdef Q_OS_WIN #if (BOTAN_MP_WORD_BITS == 8) typedef Botan::u16bit dword; #elif (BOTAN_MP_WORD_BITS == 16) typedef Botan::u32bit dword; #elif (BOTAN_MP_WORD_BITS == 32) typedef Botan::u64bit dword; #elif (BOTAN_MP_WORD_BITS == 64) #error BOTAN_MP_WORD_BITS can be 64 only with assembly support #else #error BOTAN_MP_WORD_BITS must be 8, 16, 32, or 64 #endif namespace Botan { extern "C" { /* * Word Multiply/Add */ inline word word_madd2(word a, word b, word* c) { dword z = (dword)a * b + *c; *c = (word)(z >> BOTAN_MP_WORD_BITS); return (word)z; } /* * Word Multiply/Add */ inline word word_madd3(word a, word b, word c, word* d) { dword z = (dword)a * b + c + *d; *d = (word)(z >> BOTAN_MP_WORD_BITS); return (word)z; } } /** * Win32 CAPI Entropy Source */ class Win32_CAPI_EntropySource : public EntropySource { public: std::string name() const { return "Win32 CryptoGenRandom"; } void poll(Entropy_Accumulator& accum); /** * Win32_Capi_Entropysource Constructor * @param provs list of providers, separated by ':' */ Win32_CAPI_EntropySource(const std::string& provs = ""); private: std::vector prov_types; }; } #endif namespace Botan { template inline void prefetch_readonly(const T* addr, size_t length) { #if defined(__GNUG__) const size_t Ts_per_cache_line = CPUID::cache_line_size() / sizeof(T); for(size_t i = 0; i <= length; i += Ts_per_cache_line) __builtin_prefetch(addr + i, 0); #endif } template inline void prefetch_readwrite(const T* addr, size_t length) { #if defined(__GNUG__) const size_t Ts_per_cache_line = CPUID::cache_line_size() / sizeof(T); for(size_t i = 0; i <= length; i += Ts_per_cache_line) __builtin_prefetch(addr + i, 1); #endif } } namespace Botan { const u64bit Camellia_SBOX1[256] = { 0x7070700070000070ULL, 0x8282820082000082ULL, 0x2C2C2C002C00002CULL, 0xECECEC00EC0000ECULL, 0xB3B3B300B30000B3ULL, 0x2727270027000027ULL, 0xC0C0C000C00000C0ULL, 0xE5E5E500E50000E5ULL, 0xE4E4E400E40000E4ULL, 0x8585850085000085ULL, 0x5757570057000057ULL, 0x3535350035000035ULL, 0xEAEAEA00EA0000EAULL, 0x0C0C0C000C00000CULL, 0xAEAEAE00AE0000AEULL, 0x4141410041000041ULL, 0x2323230023000023ULL, 0xEFEFEF00EF0000EFULL, 0x6B6B6B006B00006BULL, 0x9393930093000093ULL, 0x4545450045000045ULL, 0x1919190019000019ULL, 0xA5A5A500A50000A5ULL, 0x2121210021000021ULL, 0xEDEDED00ED0000EDULL, 0x0E0E0E000E00000EULL, 0x4F4F4F004F00004FULL, 0x4E4E4E004E00004EULL, 0x1D1D1D001D00001DULL, 0x6565650065000065ULL, 0x9292920092000092ULL, 0xBDBDBD00BD0000BDULL, 0x8686860086000086ULL, 0xB8B8B800B80000B8ULL, 0xAFAFAF00AF0000AFULL, 0x8F8F8F008F00008FULL, 0x7C7C7C007C00007CULL, 0xEBEBEB00EB0000EBULL, 0x1F1F1F001F00001FULL, 0xCECECE00CE0000CEULL, 0x3E3E3E003E00003EULL, 0x3030300030000030ULL, 0xDCDCDC00DC0000DCULL, 0x5F5F5F005F00005FULL, 0x5E5E5E005E00005EULL, 0xC5C5C500C50000C5ULL, 0x0B0B0B000B00000BULL, 0x1A1A1A001A00001AULL, 0xA6A6A600A60000A6ULL, 0xE1E1E100E10000E1ULL, 0x3939390039000039ULL, 0xCACACA00CA0000CAULL, 0xD5D5D500D50000D5ULL, 0x4747470047000047ULL, 0x5D5D5D005D00005DULL, 0x3D3D3D003D00003DULL, 0xD9D9D900D90000D9ULL, 0x0101010001000001ULL, 0x5A5A5A005A00005AULL, 0xD6D6D600D60000D6ULL, 0x5151510051000051ULL, 0x5656560056000056ULL, 0x6C6C6C006C00006CULL, 0x4D4D4D004D00004DULL, 0x8B8B8B008B00008BULL, 0x0D0D0D000D00000DULL, 0x9A9A9A009A00009AULL, 0x6666660066000066ULL, 0xFBFBFB00FB0000FBULL, 0xCCCCCC00CC0000CCULL, 0xB0B0B000B00000B0ULL, 0x2D2D2D002D00002DULL, 0x7474740074000074ULL, 0x1212120012000012ULL, 0x2B2B2B002B00002BULL, 0x2020200020000020ULL, 0xF0F0F000F00000F0ULL, 0xB1B1B100B10000B1ULL, 0x8484840084000084ULL, 0x9999990099000099ULL, 0xDFDFDF00DF0000DFULL, 0x4C4C4C004C00004CULL, 0xCBCBCB00CB0000CBULL, 0xC2C2C200C20000C2ULL, 0x3434340034000034ULL, 0x7E7E7E007E00007EULL, 0x7676760076000076ULL, 0x0505050005000005ULL, 0x6D6D6D006D00006DULL, 0xB7B7B700B70000B7ULL, 0xA9A9A900A90000A9ULL, 0x3131310031000031ULL, 0xD1D1D100D10000D1ULL, 0x1717170017000017ULL, 0x0404040004000004ULL, 0xD7D7D700D70000D7ULL, 0x1414140014000014ULL, 0x5858580058000058ULL, 0x3A3A3A003A00003AULL, 0x6161610061000061ULL, 0xDEDEDE00DE0000DEULL, 0x1B1B1B001B00001BULL, 0x1111110011000011ULL, 0x1C1C1C001C00001CULL, 0x3232320032000032ULL, 0x0F0F0F000F00000FULL, 0x9C9C9C009C00009CULL, 0x1616160016000016ULL, 0x5353530053000053ULL, 0x1818180018000018ULL, 0xF2F2F200F20000F2ULL, 0x2222220022000022ULL, 0xFEFEFE00FE0000FEULL, 0x4444440044000044ULL, 0xCFCFCF00CF0000CFULL, 0xB2B2B200B20000B2ULL, 0xC3C3C300C30000C3ULL, 0xB5B5B500B50000B5ULL, 0x7A7A7A007A00007AULL, 0x9191910091000091ULL, 0x2424240024000024ULL, 0x0808080008000008ULL, 0xE8E8E800E80000E8ULL, 0xA8A8A800A80000A8ULL, 0x6060600060000060ULL, 0xFCFCFC00FC0000FCULL, 0x6969690069000069ULL, 0x5050500050000050ULL, 0xAAAAAA00AA0000AAULL, 0xD0D0D000D00000D0ULL, 0xA0A0A000A00000A0ULL, 0x7D7D7D007D00007DULL, 0xA1A1A100A10000A1ULL, 0x8989890089000089ULL, 0x6262620062000062ULL, 0x9797970097000097ULL, 0x5454540054000054ULL, 0x5B5B5B005B00005BULL, 0x1E1E1E001E00001EULL, 0x9595950095000095ULL, 0xE0E0E000E00000E0ULL, 0xFFFFFF00FF0000FFULL, 0x6464640064000064ULL, 0xD2D2D200D20000D2ULL, 0x1010100010000010ULL, 0xC4C4C400C40000C4ULL, 0x0000000000000000ULL, 0x4848480048000048ULL, 0xA3A3A300A30000A3ULL, 0xF7F7F700F70000F7ULL, 0x7575750075000075ULL, 0xDBDBDB00DB0000DBULL, 0x8A8A8A008A00008AULL, 0x0303030003000003ULL, 0xE6E6E600E60000E6ULL, 0xDADADA00DA0000DAULL, 0x0909090009000009ULL, 0x3F3F3F003F00003FULL, 0xDDDDDD00DD0000DDULL, 0x9494940094000094ULL, 0x8787870087000087ULL, 0x5C5C5C005C00005CULL, 0x8383830083000083ULL, 0x0202020002000002ULL, 0xCDCDCD00CD0000CDULL, 0x4A4A4A004A00004AULL, 0x9090900090000090ULL, 0x3333330033000033ULL, 0x7373730073000073ULL, 0x6767670067000067ULL, 0xF6F6F600F60000F6ULL, 0xF3F3F300F30000F3ULL, 0x9D9D9D009D00009DULL, 0x7F7F7F007F00007FULL, 0xBFBFBF00BF0000BFULL, 0xE2E2E200E20000E2ULL, 0x5252520052000052ULL, 0x9B9B9B009B00009BULL, 0xD8D8D800D80000D8ULL, 0x2626260026000026ULL, 0xC8C8C800C80000C8ULL, 0x3737370037000037ULL, 0xC6C6C600C60000C6ULL, 0x3B3B3B003B00003BULL, 0x8181810081000081ULL, 0x9696960096000096ULL, 0x6F6F6F006F00006FULL, 0x4B4B4B004B00004BULL, 0x1313130013000013ULL, 0xBEBEBE00BE0000BEULL, 0x6363630063000063ULL, 0x2E2E2E002E00002EULL, 0xE9E9E900E90000E9ULL, 0x7979790079000079ULL, 0xA7A7A700A70000A7ULL, 0x8C8C8C008C00008CULL, 0x9F9F9F009F00009FULL, 0x6E6E6E006E00006EULL, 0xBCBCBC00BC0000BCULL, 0x8E8E8E008E00008EULL, 0x2929290029000029ULL, 0xF5F5F500F50000F5ULL, 0xF9F9F900F90000F9ULL, 0xB6B6B600B60000B6ULL, 0x2F2F2F002F00002FULL, 0xFDFDFD00FD0000FDULL, 0xB4B4B400B40000B4ULL, 0x5959590059000059ULL, 0x7878780078000078ULL, 0x9898980098000098ULL, 0x0606060006000006ULL, 0x6A6A6A006A00006AULL, 0xE7E7E700E70000E7ULL, 0x4646460046000046ULL, 0x7171710071000071ULL, 0xBABABA00BA0000BAULL, 0xD4D4D400D40000D4ULL, 0x2525250025000025ULL, 0xABABAB00AB0000ABULL, 0x4242420042000042ULL, 0x8888880088000088ULL, 0xA2A2A200A20000A2ULL, 0x8D8D8D008D00008DULL, 0xFAFAFA00FA0000FAULL, 0x7272720072000072ULL, 0x0707070007000007ULL, 0xB9B9B900B90000B9ULL, 0x5555550055000055ULL, 0xF8F8F800F80000F8ULL, 0xEEEEEE00EE0000EEULL, 0xACACAC00AC0000ACULL, 0x0A0A0A000A00000AULL, 0x3636360036000036ULL, 0x4949490049000049ULL, 0x2A2A2A002A00002AULL, 0x6868680068000068ULL, 0x3C3C3C003C00003CULL, 0x3838380038000038ULL, 0xF1F1F100F10000F1ULL, 0xA4A4A400A40000A4ULL, 0x4040400040000040ULL, 0x2828280028000028ULL, 0xD3D3D300D30000D3ULL, 0x7B7B7B007B00007BULL, 0xBBBBBB00BB0000BBULL, 0xC9C9C900C90000C9ULL, 0x4343430043000043ULL, 0xC1C1C100C10000C1ULL, 0x1515150015000015ULL, 0xE3E3E300E30000E3ULL, 0xADADAD00AD0000ADULL, 0xF4F4F400F40000F4ULL, 0x7777770077000077ULL, 0xC7C7C700C70000C7ULL, 0x8080800080000080ULL, 0x9E9E9E009E00009EULL }; const u64bit Camellia_SBOX2[256] = { 0x00E0E0E0E0E00000ULL, 0x0005050505050000ULL, 0x0058585858580000ULL, 0x00D9D9D9D9D90000ULL, 0x0067676767670000ULL, 0x004E4E4E4E4E0000ULL, 0x0081818181810000ULL, 0x00CBCBCBCBCB0000ULL, 0x00C9C9C9C9C90000ULL, 0x000B0B0B0B0B0000ULL, 0x00AEAEAEAEAE0000ULL, 0x006A6A6A6A6A0000ULL, 0x00D5D5D5D5D50000ULL, 0x0018181818180000ULL, 0x005D5D5D5D5D0000ULL, 0x0082828282820000ULL, 0x0046464646460000ULL, 0x00DFDFDFDFDF0000ULL, 0x00D6D6D6D6D60000ULL, 0x0027272727270000ULL, 0x008A8A8A8A8A0000ULL, 0x0032323232320000ULL, 0x004B4B4B4B4B0000ULL, 0x0042424242420000ULL, 0x00DBDBDBDBDB0000ULL, 0x001C1C1C1C1C0000ULL, 0x009E9E9E9E9E0000ULL, 0x009C9C9C9C9C0000ULL, 0x003A3A3A3A3A0000ULL, 0x00CACACACACA0000ULL, 0x0025252525250000ULL, 0x007B7B7B7B7B0000ULL, 0x000D0D0D0D0D0000ULL, 0x0071717171710000ULL, 0x005F5F5F5F5F0000ULL, 0x001F1F1F1F1F0000ULL, 0x00F8F8F8F8F80000ULL, 0x00D7D7D7D7D70000ULL, 0x003E3E3E3E3E0000ULL, 0x009D9D9D9D9D0000ULL, 0x007C7C7C7C7C0000ULL, 0x0060606060600000ULL, 0x00B9B9B9B9B90000ULL, 0x00BEBEBEBEBE0000ULL, 0x00BCBCBCBCBC0000ULL, 0x008B8B8B8B8B0000ULL, 0x0016161616160000ULL, 0x0034343434340000ULL, 0x004D4D4D4D4D0000ULL, 0x00C3C3C3C3C30000ULL, 0x0072727272720000ULL, 0x0095959595950000ULL, 0x00ABABABABAB0000ULL, 0x008E8E8E8E8E0000ULL, 0x00BABABABABA0000ULL, 0x007A7A7A7A7A0000ULL, 0x00B3B3B3B3B30000ULL, 0x0002020202020000ULL, 0x00B4B4B4B4B40000ULL, 0x00ADADADADAD0000ULL, 0x00A2A2A2A2A20000ULL, 0x00ACACACACAC0000ULL, 0x00D8D8D8D8D80000ULL, 0x009A9A9A9A9A0000ULL, 0x0017171717170000ULL, 0x001A1A1A1A1A0000ULL, 0x0035353535350000ULL, 0x00CCCCCCCCCC0000ULL, 0x00F7F7F7F7F70000ULL, 0x0099999999990000ULL, 0x0061616161610000ULL, 0x005A5A5A5A5A0000ULL, 0x00E8E8E8E8E80000ULL, 0x0024242424240000ULL, 0x0056565656560000ULL, 0x0040404040400000ULL, 0x00E1E1E1E1E10000ULL, 0x0063636363630000ULL, 0x0009090909090000ULL, 0x0033333333330000ULL, 0x00BFBFBFBFBF0000ULL, 0x0098989898980000ULL, 0x0097979797970000ULL, 0x0085858585850000ULL, 0x0068686868680000ULL, 0x00FCFCFCFCFC0000ULL, 0x00ECECECECEC0000ULL, 0x000A0A0A0A0A0000ULL, 0x00DADADADADA0000ULL, 0x006F6F6F6F6F0000ULL, 0x0053535353530000ULL, 0x0062626262620000ULL, 0x00A3A3A3A3A30000ULL, 0x002E2E2E2E2E0000ULL, 0x0008080808080000ULL, 0x00AFAFAFAFAF0000ULL, 0x0028282828280000ULL, 0x00B0B0B0B0B00000ULL, 0x0074747474740000ULL, 0x00C2C2C2C2C20000ULL, 0x00BDBDBDBDBD0000ULL, 0x0036363636360000ULL, 0x0022222222220000ULL, 0x0038383838380000ULL, 0x0064646464640000ULL, 0x001E1E1E1E1E0000ULL, 0x0039393939390000ULL, 0x002C2C2C2C2C0000ULL, 0x00A6A6A6A6A60000ULL, 0x0030303030300000ULL, 0x00E5E5E5E5E50000ULL, 0x0044444444440000ULL, 0x00FDFDFDFDFD0000ULL, 0x0088888888880000ULL, 0x009F9F9F9F9F0000ULL, 0x0065656565650000ULL, 0x0087878787870000ULL, 0x006B6B6B6B6B0000ULL, 0x00F4F4F4F4F40000ULL, 0x0023232323230000ULL, 0x0048484848480000ULL, 0x0010101010100000ULL, 0x00D1D1D1D1D10000ULL, 0x0051515151510000ULL, 0x00C0C0C0C0C00000ULL, 0x00F9F9F9F9F90000ULL, 0x00D2D2D2D2D20000ULL, 0x00A0A0A0A0A00000ULL, 0x0055555555550000ULL, 0x00A1A1A1A1A10000ULL, 0x0041414141410000ULL, 0x00FAFAFAFAFA0000ULL, 0x0043434343430000ULL, 0x0013131313130000ULL, 0x00C4C4C4C4C40000ULL, 0x002F2F2F2F2F0000ULL, 0x00A8A8A8A8A80000ULL, 0x00B6B6B6B6B60000ULL, 0x003C3C3C3C3C0000ULL, 0x002B2B2B2B2B0000ULL, 0x00C1C1C1C1C10000ULL, 0x00FFFFFFFFFF0000ULL, 0x00C8C8C8C8C80000ULL, 0x00A5A5A5A5A50000ULL, 0x0020202020200000ULL, 0x0089898989890000ULL, 0x0000000000000000ULL, 0x0090909090900000ULL, 0x0047474747470000ULL, 0x00EFEFEFEFEF0000ULL, 0x00EAEAEAEAEA0000ULL, 0x00B7B7B7B7B70000ULL, 0x0015151515150000ULL, 0x0006060606060000ULL, 0x00CDCDCDCDCD0000ULL, 0x00B5B5B5B5B50000ULL, 0x0012121212120000ULL, 0x007E7E7E7E7E0000ULL, 0x00BBBBBBBBBB0000ULL, 0x0029292929290000ULL, 0x000F0F0F0F0F0000ULL, 0x00B8B8B8B8B80000ULL, 0x0007070707070000ULL, 0x0004040404040000ULL, 0x009B9B9B9B9B0000ULL, 0x0094949494940000ULL, 0x0021212121210000ULL, 0x0066666666660000ULL, 0x00E6E6E6E6E60000ULL, 0x00CECECECECE0000ULL, 0x00EDEDEDEDED0000ULL, 0x00E7E7E7E7E70000ULL, 0x003B3B3B3B3B0000ULL, 0x00FEFEFEFEFE0000ULL, 0x007F7F7F7F7F0000ULL, 0x00C5C5C5C5C50000ULL, 0x00A4A4A4A4A40000ULL, 0x0037373737370000ULL, 0x00B1B1B1B1B10000ULL, 0x004C4C4C4C4C0000ULL, 0x0091919191910000ULL, 0x006E6E6E6E6E0000ULL, 0x008D8D8D8D8D0000ULL, 0x0076767676760000ULL, 0x0003030303030000ULL, 0x002D2D2D2D2D0000ULL, 0x00DEDEDEDEDE0000ULL, 0x0096969696960000ULL, 0x0026262626260000ULL, 0x007D7D7D7D7D0000ULL, 0x00C6C6C6C6C60000ULL, 0x005C5C5C5C5C0000ULL, 0x00D3D3D3D3D30000ULL, 0x00F2F2F2F2F20000ULL, 0x004F4F4F4F4F0000ULL, 0x0019191919190000ULL, 0x003F3F3F3F3F0000ULL, 0x00DCDCDCDCDC0000ULL, 0x0079797979790000ULL, 0x001D1D1D1D1D0000ULL, 0x0052525252520000ULL, 0x00EBEBEBEBEB0000ULL, 0x00F3F3F3F3F30000ULL, 0x006D6D6D6D6D0000ULL, 0x005E5E5E5E5E0000ULL, 0x00FBFBFBFBFB0000ULL, 0x0069696969690000ULL, 0x00B2B2B2B2B20000ULL, 0x00F0F0F0F0F00000ULL, 0x0031313131310000ULL, 0x000C0C0C0C0C0000ULL, 0x00D4D4D4D4D40000ULL, 0x00CFCFCFCFCF0000ULL, 0x008C8C8C8C8C0000ULL, 0x00E2E2E2E2E20000ULL, 0x0075757575750000ULL, 0x00A9A9A9A9A90000ULL, 0x004A4A4A4A4A0000ULL, 0x0057575757570000ULL, 0x0084848484840000ULL, 0x0011111111110000ULL, 0x0045454545450000ULL, 0x001B1B1B1B1B0000ULL, 0x00F5F5F5F5F50000ULL, 0x00E4E4E4E4E40000ULL, 0x000E0E0E0E0E0000ULL, 0x0073737373730000ULL, 0x00AAAAAAAAAA0000ULL, 0x00F1F1F1F1F10000ULL, 0x00DDDDDDDDDD0000ULL, 0x0059595959590000ULL, 0x0014141414140000ULL, 0x006C6C6C6C6C0000ULL, 0x0092929292920000ULL, 0x0054545454540000ULL, 0x00D0D0D0D0D00000ULL, 0x0078787878780000ULL, 0x0070707070700000ULL, 0x00E3E3E3E3E30000ULL, 0x0049494949490000ULL, 0x0080808080800000ULL, 0x0050505050500000ULL, 0x00A7A7A7A7A70000ULL, 0x00F6F6F6F6F60000ULL, 0x0077777777770000ULL, 0x0093939393930000ULL, 0x0086868686860000ULL, 0x0083838383830000ULL, 0x002A2A2A2A2A0000ULL, 0x00C7C7C7C7C70000ULL, 0x005B5B5B5B5B0000ULL, 0x00E9E9E9E9E90000ULL, 0x00EEEEEEEEEE0000ULL, 0x008F8F8F8F8F0000ULL, 0x0001010101010000ULL, 0x003D3D3D3D3D0000ULL }; const u64bit Camellia_SBOX3[256] = { 0x3800383800383800ULL, 0x4100414100414100ULL, 0x1600161600161600ULL, 0x7600767600767600ULL, 0xD900D9D900D9D900ULL, 0x9300939300939300ULL, 0x6000606000606000ULL, 0xF200F2F200F2F200ULL, 0x7200727200727200ULL, 0xC200C2C200C2C200ULL, 0xAB00ABAB00ABAB00ULL, 0x9A009A9A009A9A00ULL, 0x7500757500757500ULL, 0x0600060600060600ULL, 0x5700575700575700ULL, 0xA000A0A000A0A000ULL, 0x9100919100919100ULL, 0xF700F7F700F7F700ULL, 0xB500B5B500B5B500ULL, 0xC900C9C900C9C900ULL, 0xA200A2A200A2A200ULL, 0x8C008C8C008C8C00ULL, 0xD200D2D200D2D200ULL, 0x9000909000909000ULL, 0xF600F6F600F6F600ULL, 0x0700070700070700ULL, 0xA700A7A700A7A700ULL, 0x2700272700272700ULL, 0x8E008E8E008E8E00ULL, 0xB200B2B200B2B200ULL, 0x4900494900494900ULL, 0xDE00DEDE00DEDE00ULL, 0x4300434300434300ULL, 0x5C005C5C005C5C00ULL, 0xD700D7D700D7D700ULL, 0xC700C7C700C7C700ULL, 0x3E003E3E003E3E00ULL, 0xF500F5F500F5F500ULL, 0x8F008F8F008F8F00ULL, 0x6700676700676700ULL, 0x1F001F1F001F1F00ULL, 0x1800181800181800ULL, 0x6E006E6E006E6E00ULL, 0xAF00AFAF00AFAF00ULL, 0x2F002F2F002F2F00ULL, 0xE200E2E200E2E200ULL, 0x8500858500858500ULL, 0x0D000D0D000D0D00ULL, 0x5300535300535300ULL, 0xF000F0F000F0F000ULL, 0x9C009C9C009C9C00ULL, 0x6500656500656500ULL, 0xEA00EAEA00EAEA00ULL, 0xA300A3A300A3A300ULL, 0xAE00AEAE00AEAE00ULL, 0x9E009E9E009E9E00ULL, 0xEC00ECEC00ECEC00ULL, 0x8000808000808000ULL, 0x2D002D2D002D2D00ULL, 0x6B006B6B006B6B00ULL, 0xA800A8A800A8A800ULL, 0x2B002B2B002B2B00ULL, 0x3600363600363600ULL, 0xA600A6A600A6A600ULL, 0xC500C5C500C5C500ULL, 0x8600868600868600ULL, 0x4D004D4D004D4D00ULL, 0x3300333300333300ULL, 0xFD00FDFD00FDFD00ULL, 0x6600666600666600ULL, 0x5800585800585800ULL, 0x9600969600969600ULL, 0x3A003A3A003A3A00ULL, 0x0900090900090900ULL, 0x9500959500959500ULL, 0x1000101000101000ULL, 0x7800787800787800ULL, 0xD800D8D800D8D800ULL, 0x4200424200424200ULL, 0xCC00CCCC00CCCC00ULL, 0xEF00EFEF00EFEF00ULL, 0x2600262600262600ULL, 0xE500E5E500E5E500ULL, 0x6100616100616100ULL, 0x1A001A1A001A1A00ULL, 0x3F003F3F003F3F00ULL, 0x3B003B3B003B3B00ULL, 0x8200828200828200ULL, 0xB600B6B600B6B600ULL, 0xDB00DBDB00DBDB00ULL, 0xD400D4D400D4D400ULL, 0x9800989800989800ULL, 0xE800E8E800E8E800ULL, 0x8B008B8B008B8B00ULL, 0x0200020200020200ULL, 0xEB00EBEB00EBEB00ULL, 0x0A000A0A000A0A00ULL, 0x2C002C2C002C2C00ULL, 0x1D001D1D001D1D00ULL, 0xB000B0B000B0B000ULL, 0x6F006F6F006F6F00ULL, 0x8D008D8D008D8D00ULL, 0x8800888800888800ULL, 0x0E000E0E000E0E00ULL, 0x1900191900191900ULL, 0x8700878700878700ULL, 0x4E004E4E004E4E00ULL, 0x0B000B0B000B0B00ULL, 0xA900A9A900A9A900ULL, 0x0C000C0C000C0C00ULL, 0x7900797900797900ULL, 0x1100111100111100ULL, 0x7F007F7F007F7F00ULL, 0x2200222200222200ULL, 0xE700E7E700E7E700ULL, 0x5900595900595900ULL, 0xE100E1E100E1E100ULL, 0xDA00DADA00DADA00ULL, 0x3D003D3D003D3D00ULL, 0xC800C8C800C8C800ULL, 0x1200121200121200ULL, 0x0400040400040400ULL, 0x7400747400747400ULL, 0x5400545400545400ULL, 0x3000303000303000ULL, 0x7E007E7E007E7E00ULL, 0xB400B4B400B4B400ULL, 0x2800282800282800ULL, 0x5500555500555500ULL, 0x6800686800686800ULL, 0x5000505000505000ULL, 0xBE00BEBE00BEBE00ULL, 0xD000D0D000D0D000ULL, 0xC400C4C400C4C400ULL, 0x3100313100313100ULL, 0xCB00CBCB00CBCB00ULL, 0x2A002A2A002A2A00ULL, 0xAD00ADAD00ADAD00ULL, 0x0F000F0F000F0F00ULL, 0xCA00CACA00CACA00ULL, 0x7000707000707000ULL, 0xFF00FFFF00FFFF00ULL, 0x3200323200323200ULL, 0x6900696900696900ULL, 0x0800080800080800ULL, 0x6200626200626200ULL, 0x0000000000000000ULL, 0x2400242400242400ULL, 0xD100D1D100D1D100ULL, 0xFB00FBFB00FBFB00ULL, 0xBA00BABA00BABA00ULL, 0xED00EDED00EDED00ULL, 0x4500454500454500ULL, 0x8100818100818100ULL, 0x7300737300737300ULL, 0x6D006D6D006D6D00ULL, 0x8400848400848400ULL, 0x9F009F9F009F9F00ULL, 0xEE00EEEE00EEEE00ULL, 0x4A004A4A004A4A00ULL, 0xC300C3C300C3C300ULL, 0x2E002E2E002E2E00ULL, 0xC100C1C100C1C100ULL, 0x0100010100010100ULL, 0xE600E6E600E6E600ULL, 0x2500252500252500ULL, 0x4800484800484800ULL, 0x9900999900999900ULL, 0xB900B9B900B9B900ULL, 0xB300B3B300B3B300ULL, 0x7B007B7B007B7B00ULL, 0xF900F9F900F9F900ULL, 0xCE00CECE00CECE00ULL, 0xBF00BFBF00BFBF00ULL, 0xDF00DFDF00DFDF00ULL, 0x7100717100717100ULL, 0x2900292900292900ULL, 0xCD00CDCD00CDCD00ULL, 0x6C006C6C006C6C00ULL, 0x1300131300131300ULL, 0x6400646400646400ULL, 0x9B009B9B009B9B00ULL, 0x6300636300636300ULL, 0x9D009D9D009D9D00ULL, 0xC000C0C000C0C000ULL, 0x4B004B4B004B4B00ULL, 0xB700B7B700B7B700ULL, 0xA500A5A500A5A500ULL, 0x8900898900898900ULL, 0x5F005F5F005F5F00ULL, 0xB100B1B100B1B100ULL, 0x1700171700171700ULL, 0xF400F4F400F4F400ULL, 0xBC00BCBC00BCBC00ULL, 0xD300D3D300D3D300ULL, 0x4600464600464600ULL, 0xCF00CFCF00CFCF00ULL, 0x3700373700373700ULL, 0x5E005E5E005E5E00ULL, 0x4700474700474700ULL, 0x9400949400949400ULL, 0xFA00FAFA00FAFA00ULL, 0xFC00FCFC00FCFC00ULL, 0x5B005B5B005B5B00ULL, 0x9700979700979700ULL, 0xFE00FEFE00FEFE00ULL, 0x5A005A5A005A5A00ULL, 0xAC00ACAC00ACAC00ULL, 0x3C003C3C003C3C00ULL, 0x4C004C4C004C4C00ULL, 0x0300030300030300ULL, 0x3500353500353500ULL, 0xF300F3F300F3F300ULL, 0x2300232300232300ULL, 0xB800B8B800B8B800ULL, 0x5D005D5D005D5D00ULL, 0x6A006A6A006A6A00ULL, 0x9200929200929200ULL, 0xD500D5D500D5D500ULL, 0x2100212100212100ULL, 0x4400444400444400ULL, 0x5100515100515100ULL, 0xC600C6C600C6C600ULL, 0x7D007D7D007D7D00ULL, 0x3900393900393900ULL, 0x8300838300838300ULL, 0xDC00DCDC00DCDC00ULL, 0xAA00AAAA00AAAA00ULL, 0x7C007C7C007C7C00ULL, 0x7700777700777700ULL, 0x5600565600565600ULL, 0x0500050500050500ULL, 0x1B001B1B001B1B00ULL, 0xA400A4A400A4A400ULL, 0x1500151500151500ULL, 0x3400343400343400ULL, 0x1E001E1E001E1E00ULL, 0x1C001C1C001C1C00ULL, 0xF800F8F800F8F800ULL, 0x5200525200525200ULL, 0x2000202000202000ULL, 0x1400141400141400ULL, 0xE900E9E900E9E900ULL, 0xBD00BDBD00BDBD00ULL, 0xDD00DDDD00DDDD00ULL, 0xE400E4E400E4E400ULL, 0xA100A1A100A1A100ULL, 0xE000E0E000E0E000ULL, 0x8A008A8A008A8A00ULL, 0xF100F1F100F1F100ULL, 0xD600D6D600D6D600ULL, 0x7A007A7A007A7A00ULL, 0xBB00BBBB00BBBB00ULL, 0xE300E3E300E3E300ULL, 0x4000404000404000ULL, 0x4F004F4F004F4F00ULL }; const u64bit Camellia_SBOX4[256] = { 0x7070007000007070ULL, 0x2C2C002C00002C2CULL, 0xB3B300B30000B3B3ULL, 0xC0C000C00000C0C0ULL, 0xE4E400E40000E4E4ULL, 0x5757005700005757ULL, 0xEAEA00EA0000EAEAULL, 0xAEAE00AE0000AEAEULL, 0x2323002300002323ULL, 0x6B6B006B00006B6BULL, 0x4545004500004545ULL, 0xA5A500A50000A5A5ULL, 0xEDED00ED0000EDEDULL, 0x4F4F004F00004F4FULL, 0x1D1D001D00001D1DULL, 0x9292009200009292ULL, 0x8686008600008686ULL, 0xAFAF00AF0000AFAFULL, 0x7C7C007C00007C7CULL, 0x1F1F001F00001F1FULL, 0x3E3E003E00003E3EULL, 0xDCDC00DC0000DCDCULL, 0x5E5E005E00005E5EULL, 0x0B0B000B00000B0BULL, 0xA6A600A60000A6A6ULL, 0x3939003900003939ULL, 0xD5D500D50000D5D5ULL, 0x5D5D005D00005D5DULL, 0xD9D900D90000D9D9ULL, 0x5A5A005A00005A5AULL, 0x5151005100005151ULL, 0x6C6C006C00006C6CULL, 0x8B8B008B00008B8BULL, 0x9A9A009A00009A9AULL, 0xFBFB00FB0000FBFBULL, 0xB0B000B00000B0B0ULL, 0x7474007400007474ULL, 0x2B2B002B00002B2BULL, 0xF0F000F00000F0F0ULL, 0x8484008400008484ULL, 0xDFDF00DF0000DFDFULL, 0xCBCB00CB0000CBCBULL, 0x3434003400003434ULL, 0x7676007600007676ULL, 0x6D6D006D00006D6DULL, 0xA9A900A90000A9A9ULL, 0xD1D100D10000D1D1ULL, 0x0404000400000404ULL, 0x1414001400001414ULL, 0x3A3A003A00003A3AULL, 0xDEDE00DE0000DEDEULL, 0x1111001100001111ULL, 0x3232003200003232ULL, 0x9C9C009C00009C9CULL, 0x5353005300005353ULL, 0xF2F200F20000F2F2ULL, 0xFEFE00FE0000FEFEULL, 0xCFCF00CF0000CFCFULL, 0xC3C300C30000C3C3ULL, 0x7A7A007A00007A7AULL, 0x2424002400002424ULL, 0xE8E800E80000E8E8ULL, 0x6060006000006060ULL, 0x6969006900006969ULL, 0xAAAA00AA0000AAAAULL, 0xA0A000A00000A0A0ULL, 0xA1A100A10000A1A1ULL, 0x6262006200006262ULL, 0x5454005400005454ULL, 0x1E1E001E00001E1EULL, 0xE0E000E00000E0E0ULL, 0x6464006400006464ULL, 0x1010001000001010ULL, 0x0000000000000000ULL, 0xA3A300A30000A3A3ULL, 0x7575007500007575ULL, 0x8A8A008A00008A8AULL, 0xE6E600E60000E6E6ULL, 0x0909000900000909ULL, 0xDDDD00DD0000DDDDULL, 0x8787008700008787ULL, 0x8383008300008383ULL, 0xCDCD00CD0000CDCDULL, 0x9090009000009090ULL, 0x7373007300007373ULL, 0xF6F600F60000F6F6ULL, 0x9D9D009D00009D9DULL, 0xBFBF00BF0000BFBFULL, 0x5252005200005252ULL, 0xD8D800D80000D8D8ULL, 0xC8C800C80000C8C8ULL, 0xC6C600C60000C6C6ULL, 0x8181008100008181ULL, 0x6F6F006F00006F6FULL, 0x1313001300001313ULL, 0x6363006300006363ULL, 0xE9E900E90000E9E9ULL, 0xA7A700A70000A7A7ULL, 0x9F9F009F00009F9FULL, 0xBCBC00BC0000BCBCULL, 0x2929002900002929ULL, 0xF9F900F90000F9F9ULL, 0x2F2F002F00002F2FULL, 0xB4B400B40000B4B4ULL, 0x7878007800007878ULL, 0x0606000600000606ULL, 0xE7E700E70000E7E7ULL, 0x7171007100007171ULL, 0xD4D400D40000D4D4ULL, 0xABAB00AB0000ABABULL, 0x8888008800008888ULL, 0x8D8D008D00008D8DULL, 0x7272007200007272ULL, 0xB9B900B90000B9B9ULL, 0xF8F800F80000F8F8ULL, 0xACAC00AC0000ACACULL, 0x3636003600003636ULL, 0x2A2A002A00002A2AULL, 0x3C3C003C00003C3CULL, 0xF1F100F10000F1F1ULL, 0x4040004000004040ULL, 0xD3D300D30000D3D3ULL, 0xBBBB00BB0000BBBBULL, 0x4343004300004343ULL, 0x1515001500001515ULL, 0xADAD00AD0000ADADULL, 0x7777007700007777ULL, 0x8080008000008080ULL, 0x8282008200008282ULL, 0xECEC00EC0000ECECULL, 0x2727002700002727ULL, 0xE5E500E50000E5E5ULL, 0x8585008500008585ULL, 0x3535003500003535ULL, 0x0C0C000C00000C0CULL, 0x4141004100004141ULL, 0xEFEF00EF0000EFEFULL, 0x9393009300009393ULL, 0x1919001900001919ULL, 0x2121002100002121ULL, 0x0E0E000E00000E0EULL, 0x4E4E004E00004E4EULL, 0x6565006500006565ULL, 0xBDBD00BD0000BDBDULL, 0xB8B800B80000B8B8ULL, 0x8F8F008F00008F8FULL, 0xEBEB00EB0000EBEBULL, 0xCECE00CE0000CECEULL, 0x3030003000003030ULL, 0x5F5F005F00005F5FULL, 0xC5C500C50000C5C5ULL, 0x1A1A001A00001A1AULL, 0xE1E100E10000E1E1ULL, 0xCACA00CA0000CACAULL, 0x4747004700004747ULL, 0x3D3D003D00003D3DULL, 0x0101000100000101ULL, 0xD6D600D60000D6D6ULL, 0x5656005600005656ULL, 0x4D4D004D00004D4DULL, 0x0D0D000D00000D0DULL, 0x6666006600006666ULL, 0xCCCC00CC0000CCCCULL, 0x2D2D002D00002D2DULL, 0x1212001200001212ULL, 0x2020002000002020ULL, 0xB1B100B10000B1B1ULL, 0x9999009900009999ULL, 0x4C4C004C00004C4CULL, 0xC2C200C20000C2C2ULL, 0x7E7E007E00007E7EULL, 0x0505000500000505ULL, 0xB7B700B70000B7B7ULL, 0x3131003100003131ULL, 0x1717001700001717ULL, 0xD7D700D70000D7D7ULL, 0x5858005800005858ULL, 0x6161006100006161ULL, 0x1B1B001B00001B1BULL, 0x1C1C001C00001C1CULL, 0x0F0F000F00000F0FULL, 0x1616001600001616ULL, 0x1818001800001818ULL, 0x2222002200002222ULL, 0x4444004400004444ULL, 0xB2B200B20000B2B2ULL, 0xB5B500B50000B5B5ULL, 0x9191009100009191ULL, 0x0808000800000808ULL, 0xA8A800A80000A8A8ULL, 0xFCFC00FC0000FCFCULL, 0x5050005000005050ULL, 0xD0D000D00000D0D0ULL, 0x7D7D007D00007D7DULL, 0x8989008900008989ULL, 0x9797009700009797ULL, 0x5B5B005B00005B5BULL, 0x9595009500009595ULL, 0xFFFF00FF0000FFFFULL, 0xD2D200D20000D2D2ULL, 0xC4C400C40000C4C4ULL, 0x4848004800004848ULL, 0xF7F700F70000F7F7ULL, 0xDBDB00DB0000DBDBULL, 0x0303000300000303ULL, 0xDADA00DA0000DADAULL, 0x3F3F003F00003F3FULL, 0x9494009400009494ULL, 0x5C5C005C00005C5CULL, 0x0202000200000202ULL, 0x4A4A004A00004A4AULL, 0x3333003300003333ULL, 0x6767006700006767ULL, 0xF3F300F30000F3F3ULL, 0x7F7F007F00007F7FULL, 0xE2E200E20000E2E2ULL, 0x9B9B009B00009B9BULL, 0x2626002600002626ULL, 0x3737003700003737ULL, 0x3B3B003B00003B3BULL, 0x9696009600009696ULL, 0x4B4B004B00004B4BULL, 0xBEBE00BE0000BEBEULL, 0x2E2E002E00002E2EULL, 0x7979007900007979ULL, 0x8C8C008C00008C8CULL, 0x6E6E006E00006E6EULL, 0x8E8E008E00008E8EULL, 0xF5F500F50000F5F5ULL, 0xB6B600B60000B6B6ULL, 0xFDFD00FD0000FDFDULL, 0x5959005900005959ULL, 0x9898009800009898ULL, 0x6A6A006A00006A6AULL, 0x4646004600004646ULL, 0xBABA00BA0000BABAULL, 0x2525002500002525ULL, 0x4242004200004242ULL, 0xA2A200A20000A2A2ULL, 0xFAFA00FA0000FAFAULL, 0x0707000700000707ULL, 0x5555005500005555ULL, 0xEEEE00EE0000EEEEULL, 0x0A0A000A00000A0AULL, 0x4949004900004949ULL, 0x6868006800006868ULL, 0x3838003800003838ULL, 0xA4A400A40000A4A4ULL, 0x2828002800002828ULL, 0x7B7B007B00007B7BULL, 0xC9C900C90000C9C9ULL, 0xC1C100C10000C1C1ULL, 0xE3E300E30000E3E3ULL, 0xF4F400F40000F4F4ULL, 0xC7C700C70000C7C7ULL, 0x9E9E009E00009E9EULL }; const u64bit Camellia_SBOX5[256] = { 0x00E0E0E000E0E0E0ULL, 0x0005050500050505ULL, 0x0058585800585858ULL, 0x00D9D9D900D9D9D9ULL, 0x0067676700676767ULL, 0x004E4E4E004E4E4EULL, 0x0081818100818181ULL, 0x00CBCBCB00CBCBCBULL, 0x00C9C9C900C9C9C9ULL, 0x000B0B0B000B0B0BULL, 0x00AEAEAE00AEAEAEULL, 0x006A6A6A006A6A6AULL, 0x00D5D5D500D5D5D5ULL, 0x0018181800181818ULL, 0x005D5D5D005D5D5DULL, 0x0082828200828282ULL, 0x0046464600464646ULL, 0x00DFDFDF00DFDFDFULL, 0x00D6D6D600D6D6D6ULL, 0x0027272700272727ULL, 0x008A8A8A008A8A8AULL, 0x0032323200323232ULL, 0x004B4B4B004B4B4BULL, 0x0042424200424242ULL, 0x00DBDBDB00DBDBDBULL, 0x001C1C1C001C1C1CULL, 0x009E9E9E009E9E9EULL, 0x009C9C9C009C9C9CULL, 0x003A3A3A003A3A3AULL, 0x00CACACA00CACACAULL, 0x0025252500252525ULL, 0x007B7B7B007B7B7BULL, 0x000D0D0D000D0D0DULL, 0x0071717100717171ULL, 0x005F5F5F005F5F5FULL, 0x001F1F1F001F1F1FULL, 0x00F8F8F800F8F8F8ULL, 0x00D7D7D700D7D7D7ULL, 0x003E3E3E003E3E3EULL, 0x009D9D9D009D9D9DULL, 0x007C7C7C007C7C7CULL, 0x0060606000606060ULL, 0x00B9B9B900B9B9B9ULL, 0x00BEBEBE00BEBEBEULL, 0x00BCBCBC00BCBCBCULL, 0x008B8B8B008B8B8BULL, 0x0016161600161616ULL, 0x0034343400343434ULL, 0x004D4D4D004D4D4DULL, 0x00C3C3C300C3C3C3ULL, 0x0072727200727272ULL, 0x0095959500959595ULL, 0x00ABABAB00ABABABULL, 0x008E8E8E008E8E8EULL, 0x00BABABA00BABABAULL, 0x007A7A7A007A7A7AULL, 0x00B3B3B300B3B3B3ULL, 0x0002020200020202ULL, 0x00B4B4B400B4B4B4ULL, 0x00ADADAD00ADADADULL, 0x00A2A2A200A2A2A2ULL, 0x00ACACAC00ACACACULL, 0x00D8D8D800D8D8D8ULL, 0x009A9A9A009A9A9AULL, 0x0017171700171717ULL, 0x001A1A1A001A1A1AULL, 0x0035353500353535ULL, 0x00CCCCCC00CCCCCCULL, 0x00F7F7F700F7F7F7ULL, 0x0099999900999999ULL, 0x0061616100616161ULL, 0x005A5A5A005A5A5AULL, 0x00E8E8E800E8E8E8ULL, 0x0024242400242424ULL, 0x0056565600565656ULL, 0x0040404000404040ULL, 0x00E1E1E100E1E1E1ULL, 0x0063636300636363ULL, 0x0009090900090909ULL, 0x0033333300333333ULL, 0x00BFBFBF00BFBFBFULL, 0x0098989800989898ULL, 0x0097979700979797ULL, 0x0085858500858585ULL, 0x0068686800686868ULL, 0x00FCFCFC00FCFCFCULL, 0x00ECECEC00ECECECULL, 0x000A0A0A000A0A0AULL, 0x00DADADA00DADADAULL, 0x006F6F6F006F6F6FULL, 0x0053535300535353ULL, 0x0062626200626262ULL, 0x00A3A3A300A3A3A3ULL, 0x002E2E2E002E2E2EULL, 0x0008080800080808ULL, 0x00AFAFAF00AFAFAFULL, 0x0028282800282828ULL, 0x00B0B0B000B0B0B0ULL, 0x0074747400747474ULL, 0x00C2C2C200C2C2C2ULL, 0x00BDBDBD00BDBDBDULL, 0x0036363600363636ULL, 0x0022222200222222ULL, 0x0038383800383838ULL, 0x0064646400646464ULL, 0x001E1E1E001E1E1EULL, 0x0039393900393939ULL, 0x002C2C2C002C2C2CULL, 0x00A6A6A600A6A6A6ULL, 0x0030303000303030ULL, 0x00E5E5E500E5E5E5ULL, 0x0044444400444444ULL, 0x00FDFDFD00FDFDFDULL, 0x0088888800888888ULL, 0x009F9F9F009F9F9FULL, 0x0065656500656565ULL, 0x0087878700878787ULL, 0x006B6B6B006B6B6BULL, 0x00F4F4F400F4F4F4ULL, 0x0023232300232323ULL, 0x0048484800484848ULL, 0x0010101000101010ULL, 0x00D1D1D100D1D1D1ULL, 0x0051515100515151ULL, 0x00C0C0C000C0C0C0ULL, 0x00F9F9F900F9F9F9ULL, 0x00D2D2D200D2D2D2ULL, 0x00A0A0A000A0A0A0ULL, 0x0055555500555555ULL, 0x00A1A1A100A1A1A1ULL, 0x0041414100414141ULL, 0x00FAFAFA00FAFAFAULL, 0x0043434300434343ULL, 0x0013131300131313ULL, 0x00C4C4C400C4C4C4ULL, 0x002F2F2F002F2F2FULL, 0x00A8A8A800A8A8A8ULL, 0x00B6B6B600B6B6B6ULL, 0x003C3C3C003C3C3CULL, 0x002B2B2B002B2B2BULL, 0x00C1C1C100C1C1C1ULL, 0x00FFFFFF00FFFFFFULL, 0x00C8C8C800C8C8C8ULL, 0x00A5A5A500A5A5A5ULL, 0x0020202000202020ULL, 0x0089898900898989ULL, 0x0000000000000000ULL, 0x0090909000909090ULL, 0x0047474700474747ULL, 0x00EFEFEF00EFEFEFULL, 0x00EAEAEA00EAEAEAULL, 0x00B7B7B700B7B7B7ULL, 0x0015151500151515ULL, 0x0006060600060606ULL, 0x00CDCDCD00CDCDCDULL, 0x00B5B5B500B5B5B5ULL, 0x0012121200121212ULL, 0x007E7E7E007E7E7EULL, 0x00BBBBBB00BBBBBBULL, 0x0029292900292929ULL, 0x000F0F0F000F0F0FULL, 0x00B8B8B800B8B8B8ULL, 0x0007070700070707ULL, 0x0004040400040404ULL, 0x009B9B9B009B9B9BULL, 0x0094949400949494ULL, 0x0021212100212121ULL, 0x0066666600666666ULL, 0x00E6E6E600E6E6E6ULL, 0x00CECECE00CECECEULL, 0x00EDEDED00EDEDEDULL, 0x00E7E7E700E7E7E7ULL, 0x003B3B3B003B3B3BULL, 0x00FEFEFE00FEFEFEULL, 0x007F7F7F007F7F7FULL, 0x00C5C5C500C5C5C5ULL, 0x00A4A4A400A4A4A4ULL, 0x0037373700373737ULL, 0x00B1B1B100B1B1B1ULL, 0x004C4C4C004C4C4CULL, 0x0091919100919191ULL, 0x006E6E6E006E6E6EULL, 0x008D8D8D008D8D8DULL, 0x0076767600767676ULL, 0x0003030300030303ULL, 0x002D2D2D002D2D2DULL, 0x00DEDEDE00DEDEDEULL, 0x0096969600969696ULL, 0x0026262600262626ULL, 0x007D7D7D007D7D7DULL, 0x00C6C6C600C6C6C6ULL, 0x005C5C5C005C5C5CULL, 0x00D3D3D300D3D3D3ULL, 0x00F2F2F200F2F2F2ULL, 0x004F4F4F004F4F4FULL, 0x0019191900191919ULL, 0x003F3F3F003F3F3FULL, 0x00DCDCDC00DCDCDCULL, 0x0079797900797979ULL, 0x001D1D1D001D1D1DULL, 0x0052525200525252ULL, 0x00EBEBEB00EBEBEBULL, 0x00F3F3F300F3F3F3ULL, 0x006D6D6D006D6D6DULL, 0x005E5E5E005E5E5EULL, 0x00FBFBFB00FBFBFBULL, 0x0069696900696969ULL, 0x00B2B2B200B2B2B2ULL, 0x00F0F0F000F0F0F0ULL, 0x0031313100313131ULL, 0x000C0C0C000C0C0CULL, 0x00D4D4D400D4D4D4ULL, 0x00CFCFCF00CFCFCFULL, 0x008C8C8C008C8C8CULL, 0x00E2E2E200E2E2E2ULL, 0x0075757500757575ULL, 0x00A9A9A900A9A9A9ULL, 0x004A4A4A004A4A4AULL, 0x0057575700575757ULL, 0x0084848400848484ULL, 0x0011111100111111ULL, 0x0045454500454545ULL, 0x001B1B1B001B1B1BULL, 0x00F5F5F500F5F5F5ULL, 0x00E4E4E400E4E4E4ULL, 0x000E0E0E000E0E0EULL, 0x0073737300737373ULL, 0x00AAAAAA00AAAAAAULL, 0x00F1F1F100F1F1F1ULL, 0x00DDDDDD00DDDDDDULL, 0x0059595900595959ULL, 0x0014141400141414ULL, 0x006C6C6C006C6C6CULL, 0x0092929200929292ULL, 0x0054545400545454ULL, 0x00D0D0D000D0D0D0ULL, 0x0078787800787878ULL, 0x0070707000707070ULL, 0x00E3E3E300E3E3E3ULL, 0x0049494900494949ULL, 0x0080808000808080ULL, 0x0050505000505050ULL, 0x00A7A7A700A7A7A7ULL, 0x00F6F6F600F6F6F6ULL, 0x0077777700777777ULL, 0x0093939300939393ULL, 0x0086868600868686ULL, 0x0083838300838383ULL, 0x002A2A2A002A2A2AULL, 0x00C7C7C700C7C7C7ULL, 0x005B5B5B005B5B5BULL, 0x00E9E9E900E9E9E9ULL, 0x00EEEEEE00EEEEEEULL, 0x008F8F8F008F8F8FULL, 0x0001010100010101ULL, 0x003D3D3D003D3D3DULL }; const u64bit Camellia_SBOX6[256] = { 0x3800383838003838ULL, 0x4100414141004141ULL, 0x1600161616001616ULL, 0x7600767676007676ULL, 0xD900D9D9D900D9D9ULL, 0x9300939393009393ULL, 0x6000606060006060ULL, 0xF200F2F2F200F2F2ULL, 0x7200727272007272ULL, 0xC200C2C2C200C2C2ULL, 0xAB00ABABAB00ABABULL, 0x9A009A9A9A009A9AULL, 0x7500757575007575ULL, 0x0600060606000606ULL, 0x5700575757005757ULL, 0xA000A0A0A000A0A0ULL, 0x9100919191009191ULL, 0xF700F7F7F700F7F7ULL, 0xB500B5B5B500B5B5ULL, 0xC900C9C9C900C9C9ULL, 0xA200A2A2A200A2A2ULL, 0x8C008C8C8C008C8CULL, 0xD200D2D2D200D2D2ULL, 0x9000909090009090ULL, 0xF600F6F6F600F6F6ULL, 0x0700070707000707ULL, 0xA700A7A7A700A7A7ULL, 0x2700272727002727ULL, 0x8E008E8E8E008E8EULL, 0xB200B2B2B200B2B2ULL, 0x4900494949004949ULL, 0xDE00DEDEDE00DEDEULL, 0x4300434343004343ULL, 0x5C005C5C5C005C5CULL, 0xD700D7D7D700D7D7ULL, 0xC700C7C7C700C7C7ULL, 0x3E003E3E3E003E3EULL, 0xF500F5F5F500F5F5ULL, 0x8F008F8F8F008F8FULL, 0x6700676767006767ULL, 0x1F001F1F1F001F1FULL, 0x1800181818001818ULL, 0x6E006E6E6E006E6EULL, 0xAF00AFAFAF00AFAFULL, 0x2F002F2F2F002F2FULL, 0xE200E2E2E200E2E2ULL, 0x8500858585008585ULL, 0x0D000D0D0D000D0DULL, 0x5300535353005353ULL, 0xF000F0F0F000F0F0ULL, 0x9C009C9C9C009C9CULL, 0x6500656565006565ULL, 0xEA00EAEAEA00EAEAULL, 0xA300A3A3A300A3A3ULL, 0xAE00AEAEAE00AEAEULL, 0x9E009E9E9E009E9EULL, 0xEC00ECECEC00ECECULL, 0x8000808080008080ULL, 0x2D002D2D2D002D2DULL, 0x6B006B6B6B006B6BULL, 0xA800A8A8A800A8A8ULL, 0x2B002B2B2B002B2BULL, 0x3600363636003636ULL, 0xA600A6A6A600A6A6ULL, 0xC500C5C5C500C5C5ULL, 0x8600868686008686ULL, 0x4D004D4D4D004D4DULL, 0x3300333333003333ULL, 0xFD00FDFDFD00FDFDULL, 0x6600666666006666ULL, 0x5800585858005858ULL, 0x9600969696009696ULL, 0x3A003A3A3A003A3AULL, 0x0900090909000909ULL, 0x9500959595009595ULL, 0x1000101010001010ULL, 0x7800787878007878ULL, 0xD800D8D8D800D8D8ULL, 0x4200424242004242ULL, 0xCC00CCCCCC00CCCCULL, 0xEF00EFEFEF00EFEFULL, 0x2600262626002626ULL, 0xE500E5E5E500E5E5ULL, 0x6100616161006161ULL, 0x1A001A1A1A001A1AULL, 0x3F003F3F3F003F3FULL, 0x3B003B3B3B003B3BULL, 0x8200828282008282ULL, 0xB600B6B6B600B6B6ULL, 0xDB00DBDBDB00DBDBULL, 0xD400D4D4D400D4D4ULL, 0x9800989898009898ULL, 0xE800E8E8E800E8E8ULL, 0x8B008B8B8B008B8BULL, 0x0200020202000202ULL, 0xEB00EBEBEB00EBEBULL, 0x0A000A0A0A000A0AULL, 0x2C002C2C2C002C2CULL, 0x1D001D1D1D001D1DULL, 0xB000B0B0B000B0B0ULL, 0x6F006F6F6F006F6FULL, 0x8D008D8D8D008D8DULL, 0x8800888888008888ULL, 0x0E000E0E0E000E0EULL, 0x1900191919001919ULL, 0x8700878787008787ULL, 0x4E004E4E4E004E4EULL, 0x0B000B0B0B000B0BULL, 0xA900A9A9A900A9A9ULL, 0x0C000C0C0C000C0CULL, 0x7900797979007979ULL, 0x1100111111001111ULL, 0x7F007F7F7F007F7FULL, 0x2200222222002222ULL, 0xE700E7E7E700E7E7ULL, 0x5900595959005959ULL, 0xE100E1E1E100E1E1ULL, 0xDA00DADADA00DADAULL, 0x3D003D3D3D003D3DULL, 0xC800C8C8C800C8C8ULL, 0x1200121212001212ULL, 0x0400040404000404ULL, 0x7400747474007474ULL, 0x5400545454005454ULL, 0x3000303030003030ULL, 0x7E007E7E7E007E7EULL, 0xB400B4B4B400B4B4ULL, 0x2800282828002828ULL, 0x5500555555005555ULL, 0x6800686868006868ULL, 0x5000505050005050ULL, 0xBE00BEBEBE00BEBEULL, 0xD000D0D0D000D0D0ULL, 0xC400C4C4C400C4C4ULL, 0x3100313131003131ULL, 0xCB00CBCBCB00CBCBULL, 0x2A002A2A2A002A2AULL, 0xAD00ADADAD00ADADULL, 0x0F000F0F0F000F0FULL, 0xCA00CACACA00CACAULL, 0x7000707070007070ULL, 0xFF00FFFFFF00FFFFULL, 0x3200323232003232ULL, 0x6900696969006969ULL, 0x0800080808000808ULL, 0x6200626262006262ULL, 0x0000000000000000ULL, 0x2400242424002424ULL, 0xD100D1D1D100D1D1ULL, 0xFB00FBFBFB00FBFBULL, 0xBA00BABABA00BABAULL, 0xED00EDEDED00EDEDULL, 0x4500454545004545ULL, 0x8100818181008181ULL, 0x7300737373007373ULL, 0x6D006D6D6D006D6DULL, 0x8400848484008484ULL, 0x9F009F9F9F009F9FULL, 0xEE00EEEEEE00EEEEULL, 0x4A004A4A4A004A4AULL, 0xC300C3C3C300C3C3ULL, 0x2E002E2E2E002E2EULL, 0xC100C1C1C100C1C1ULL, 0x0100010101000101ULL, 0xE600E6E6E600E6E6ULL, 0x2500252525002525ULL, 0x4800484848004848ULL, 0x9900999999009999ULL, 0xB900B9B9B900B9B9ULL, 0xB300B3B3B300B3B3ULL, 0x7B007B7B7B007B7BULL, 0xF900F9F9F900F9F9ULL, 0xCE00CECECE00CECEULL, 0xBF00BFBFBF00BFBFULL, 0xDF00DFDFDF00DFDFULL, 0x7100717171007171ULL, 0x2900292929002929ULL, 0xCD00CDCDCD00CDCDULL, 0x6C006C6C6C006C6CULL, 0x1300131313001313ULL, 0x6400646464006464ULL, 0x9B009B9B9B009B9BULL, 0x6300636363006363ULL, 0x9D009D9D9D009D9DULL, 0xC000C0C0C000C0C0ULL, 0x4B004B4B4B004B4BULL, 0xB700B7B7B700B7B7ULL, 0xA500A5A5A500A5A5ULL, 0x8900898989008989ULL, 0x5F005F5F5F005F5FULL, 0xB100B1B1B100B1B1ULL, 0x1700171717001717ULL, 0xF400F4F4F400F4F4ULL, 0xBC00BCBCBC00BCBCULL, 0xD300D3D3D300D3D3ULL, 0x4600464646004646ULL, 0xCF00CFCFCF00CFCFULL, 0x3700373737003737ULL, 0x5E005E5E5E005E5EULL, 0x4700474747004747ULL, 0x9400949494009494ULL, 0xFA00FAFAFA00FAFAULL, 0xFC00FCFCFC00FCFCULL, 0x5B005B5B5B005B5BULL, 0x9700979797009797ULL, 0xFE00FEFEFE00FEFEULL, 0x5A005A5A5A005A5AULL, 0xAC00ACACAC00ACACULL, 0x3C003C3C3C003C3CULL, 0x4C004C4C4C004C4CULL, 0x0300030303000303ULL, 0x3500353535003535ULL, 0xF300F3F3F300F3F3ULL, 0x2300232323002323ULL, 0xB800B8B8B800B8B8ULL, 0x5D005D5D5D005D5DULL, 0x6A006A6A6A006A6AULL, 0x9200929292009292ULL, 0xD500D5D5D500D5D5ULL, 0x2100212121002121ULL, 0x4400444444004444ULL, 0x5100515151005151ULL, 0xC600C6C6C600C6C6ULL, 0x7D007D7D7D007D7DULL, 0x3900393939003939ULL, 0x8300838383008383ULL, 0xDC00DCDCDC00DCDCULL, 0xAA00AAAAAA00AAAAULL, 0x7C007C7C7C007C7CULL, 0x7700777777007777ULL, 0x5600565656005656ULL, 0x0500050505000505ULL, 0x1B001B1B1B001B1BULL, 0xA400A4A4A400A4A4ULL, 0x1500151515001515ULL, 0x3400343434003434ULL, 0x1E001E1E1E001E1EULL, 0x1C001C1C1C001C1CULL, 0xF800F8F8F800F8F8ULL, 0x5200525252005252ULL, 0x2000202020002020ULL, 0x1400141414001414ULL, 0xE900E9E9E900E9E9ULL, 0xBD00BDBDBD00BDBDULL, 0xDD00DDDDDD00DDDDULL, 0xE400E4E4E400E4E4ULL, 0xA100A1A1A100A1A1ULL, 0xE000E0E0E000E0E0ULL, 0x8A008A8A8A008A8AULL, 0xF100F1F1F100F1F1ULL, 0xD600D6D6D600D6D6ULL, 0x7A007A7A7A007A7AULL, 0xBB00BBBBBB00BBBBULL, 0xE300E3E3E300E3E3ULL, 0x4000404040004040ULL, 0x4F004F4F4F004F4FULL }; const u64bit Camellia_SBOX7[256] = { 0x7070007070700070ULL, 0x2C2C002C2C2C002CULL, 0xB3B300B3B3B300B3ULL, 0xC0C000C0C0C000C0ULL, 0xE4E400E4E4E400E4ULL, 0x5757005757570057ULL, 0xEAEA00EAEAEA00EAULL, 0xAEAE00AEAEAE00AEULL, 0x2323002323230023ULL, 0x6B6B006B6B6B006BULL, 0x4545004545450045ULL, 0xA5A500A5A5A500A5ULL, 0xEDED00EDEDED00EDULL, 0x4F4F004F4F4F004FULL, 0x1D1D001D1D1D001DULL, 0x9292009292920092ULL, 0x8686008686860086ULL, 0xAFAF00AFAFAF00AFULL, 0x7C7C007C7C7C007CULL, 0x1F1F001F1F1F001FULL, 0x3E3E003E3E3E003EULL, 0xDCDC00DCDCDC00DCULL, 0x5E5E005E5E5E005EULL, 0x0B0B000B0B0B000BULL, 0xA6A600A6A6A600A6ULL, 0x3939003939390039ULL, 0xD5D500D5D5D500D5ULL, 0x5D5D005D5D5D005DULL, 0xD9D900D9D9D900D9ULL, 0x5A5A005A5A5A005AULL, 0x5151005151510051ULL, 0x6C6C006C6C6C006CULL, 0x8B8B008B8B8B008BULL, 0x9A9A009A9A9A009AULL, 0xFBFB00FBFBFB00FBULL, 0xB0B000B0B0B000B0ULL, 0x7474007474740074ULL, 0x2B2B002B2B2B002BULL, 0xF0F000F0F0F000F0ULL, 0x8484008484840084ULL, 0xDFDF00DFDFDF00DFULL, 0xCBCB00CBCBCB00CBULL, 0x3434003434340034ULL, 0x7676007676760076ULL, 0x6D6D006D6D6D006DULL, 0xA9A900A9A9A900A9ULL, 0xD1D100D1D1D100D1ULL, 0x0404000404040004ULL, 0x1414001414140014ULL, 0x3A3A003A3A3A003AULL, 0xDEDE00DEDEDE00DEULL, 0x1111001111110011ULL, 0x3232003232320032ULL, 0x9C9C009C9C9C009CULL, 0x5353005353530053ULL, 0xF2F200F2F2F200F2ULL, 0xFEFE00FEFEFE00FEULL, 0xCFCF00CFCFCF00CFULL, 0xC3C300C3C3C300C3ULL, 0x7A7A007A7A7A007AULL, 0x2424002424240024ULL, 0xE8E800E8E8E800E8ULL, 0x6060006060600060ULL, 0x6969006969690069ULL, 0xAAAA00AAAAAA00AAULL, 0xA0A000A0A0A000A0ULL, 0xA1A100A1A1A100A1ULL, 0x6262006262620062ULL, 0x5454005454540054ULL, 0x1E1E001E1E1E001EULL, 0xE0E000E0E0E000E0ULL, 0x6464006464640064ULL, 0x1010001010100010ULL, 0x0000000000000000ULL, 0xA3A300A3A3A300A3ULL, 0x7575007575750075ULL, 0x8A8A008A8A8A008AULL, 0xE6E600E6E6E600E6ULL, 0x0909000909090009ULL, 0xDDDD00DDDDDD00DDULL, 0x8787008787870087ULL, 0x8383008383830083ULL, 0xCDCD00CDCDCD00CDULL, 0x9090009090900090ULL, 0x7373007373730073ULL, 0xF6F600F6F6F600F6ULL, 0x9D9D009D9D9D009DULL, 0xBFBF00BFBFBF00BFULL, 0x5252005252520052ULL, 0xD8D800D8D8D800D8ULL, 0xC8C800C8C8C800C8ULL, 0xC6C600C6C6C600C6ULL, 0x8181008181810081ULL, 0x6F6F006F6F6F006FULL, 0x1313001313130013ULL, 0x6363006363630063ULL, 0xE9E900E9E9E900E9ULL, 0xA7A700A7A7A700A7ULL, 0x9F9F009F9F9F009FULL, 0xBCBC00BCBCBC00BCULL, 0x2929002929290029ULL, 0xF9F900F9F9F900F9ULL, 0x2F2F002F2F2F002FULL, 0xB4B400B4B4B400B4ULL, 0x7878007878780078ULL, 0x0606000606060006ULL, 0xE7E700E7E7E700E7ULL, 0x7171007171710071ULL, 0xD4D400D4D4D400D4ULL, 0xABAB00ABABAB00ABULL, 0x8888008888880088ULL, 0x8D8D008D8D8D008DULL, 0x7272007272720072ULL, 0xB9B900B9B9B900B9ULL, 0xF8F800F8F8F800F8ULL, 0xACAC00ACACAC00ACULL, 0x3636003636360036ULL, 0x2A2A002A2A2A002AULL, 0x3C3C003C3C3C003CULL, 0xF1F100F1F1F100F1ULL, 0x4040004040400040ULL, 0xD3D300D3D3D300D3ULL, 0xBBBB00BBBBBB00BBULL, 0x4343004343430043ULL, 0x1515001515150015ULL, 0xADAD00ADADAD00ADULL, 0x7777007777770077ULL, 0x8080008080800080ULL, 0x8282008282820082ULL, 0xECEC00ECECEC00ECULL, 0x2727002727270027ULL, 0xE5E500E5E5E500E5ULL, 0x8585008585850085ULL, 0x3535003535350035ULL, 0x0C0C000C0C0C000CULL, 0x4141004141410041ULL, 0xEFEF00EFEFEF00EFULL, 0x9393009393930093ULL, 0x1919001919190019ULL, 0x2121002121210021ULL, 0x0E0E000E0E0E000EULL, 0x4E4E004E4E4E004EULL, 0x6565006565650065ULL, 0xBDBD00BDBDBD00BDULL, 0xB8B800B8B8B800B8ULL, 0x8F8F008F8F8F008FULL, 0xEBEB00EBEBEB00EBULL, 0xCECE00CECECE00CEULL, 0x3030003030300030ULL, 0x5F5F005F5F5F005FULL, 0xC5C500C5C5C500C5ULL, 0x1A1A001A1A1A001AULL, 0xE1E100E1E1E100E1ULL, 0xCACA00CACACA00CAULL, 0x4747004747470047ULL, 0x3D3D003D3D3D003DULL, 0x0101000101010001ULL, 0xD6D600D6D6D600D6ULL, 0x5656005656560056ULL, 0x4D4D004D4D4D004DULL, 0x0D0D000D0D0D000DULL, 0x6666006666660066ULL, 0xCCCC00CCCCCC00CCULL, 0x2D2D002D2D2D002DULL, 0x1212001212120012ULL, 0x2020002020200020ULL, 0xB1B100B1B1B100B1ULL, 0x9999009999990099ULL, 0x4C4C004C4C4C004CULL, 0xC2C200C2C2C200C2ULL, 0x7E7E007E7E7E007EULL, 0x0505000505050005ULL, 0xB7B700B7B7B700B7ULL, 0x3131003131310031ULL, 0x1717001717170017ULL, 0xD7D700D7D7D700D7ULL, 0x5858005858580058ULL, 0x6161006161610061ULL, 0x1B1B001B1B1B001BULL, 0x1C1C001C1C1C001CULL, 0x0F0F000F0F0F000FULL, 0x1616001616160016ULL, 0x1818001818180018ULL, 0x2222002222220022ULL, 0x4444004444440044ULL, 0xB2B200B2B2B200B2ULL, 0xB5B500B5B5B500B5ULL, 0x9191009191910091ULL, 0x0808000808080008ULL, 0xA8A800A8A8A800A8ULL, 0xFCFC00FCFCFC00FCULL, 0x5050005050500050ULL, 0xD0D000D0D0D000D0ULL, 0x7D7D007D7D7D007DULL, 0x8989008989890089ULL, 0x9797009797970097ULL, 0x5B5B005B5B5B005BULL, 0x9595009595950095ULL, 0xFFFF00FFFFFF00FFULL, 0xD2D200D2D2D200D2ULL, 0xC4C400C4C4C400C4ULL, 0x4848004848480048ULL, 0xF7F700F7F7F700F7ULL, 0xDBDB00DBDBDB00DBULL, 0x0303000303030003ULL, 0xDADA00DADADA00DAULL, 0x3F3F003F3F3F003FULL, 0x9494009494940094ULL, 0x5C5C005C5C5C005CULL, 0x0202000202020002ULL, 0x4A4A004A4A4A004AULL, 0x3333003333330033ULL, 0x6767006767670067ULL, 0xF3F300F3F3F300F3ULL, 0x7F7F007F7F7F007FULL, 0xE2E200E2E2E200E2ULL, 0x9B9B009B9B9B009BULL, 0x2626002626260026ULL, 0x3737003737370037ULL, 0x3B3B003B3B3B003BULL, 0x9696009696960096ULL, 0x4B4B004B4B4B004BULL, 0xBEBE00BEBEBE00BEULL, 0x2E2E002E2E2E002EULL, 0x7979007979790079ULL, 0x8C8C008C8C8C008CULL, 0x6E6E006E6E6E006EULL, 0x8E8E008E8E8E008EULL, 0xF5F500F5F5F500F5ULL, 0xB6B600B6B6B600B6ULL, 0xFDFD00FDFDFD00FDULL, 0x5959005959590059ULL, 0x9898009898980098ULL, 0x6A6A006A6A6A006AULL, 0x4646004646460046ULL, 0xBABA00BABABA00BAULL, 0x2525002525250025ULL, 0x4242004242420042ULL, 0xA2A200A2A2A200A2ULL, 0xFAFA00FAFAFA00FAULL, 0x0707000707070007ULL, 0x5555005555550055ULL, 0xEEEE00EEEEEE00EEULL, 0x0A0A000A0A0A000AULL, 0x4949004949490049ULL, 0x6868006868680068ULL, 0x3838003838380038ULL, 0xA4A400A4A4A400A4ULL, 0x2828002828280028ULL, 0x7B7B007B7B7B007BULL, 0xC9C900C9C9C900C9ULL, 0xC1C100C1C1C100C1ULL, 0xE3E300E3E3E300E3ULL, 0xF4F400F4F4F400F4ULL, 0xC7C700C7C7C700C7ULL, 0x9E9E009E9E9E009EULL }; const u64bit Camellia_SBOX8[256] = { 0x7070700070707000ULL, 0x8282820082828200ULL, 0x2C2C2C002C2C2C00ULL, 0xECECEC00ECECEC00ULL, 0xB3B3B300B3B3B300ULL, 0x2727270027272700ULL, 0xC0C0C000C0C0C000ULL, 0xE5E5E500E5E5E500ULL, 0xE4E4E400E4E4E400ULL, 0x8585850085858500ULL, 0x5757570057575700ULL, 0x3535350035353500ULL, 0xEAEAEA00EAEAEA00ULL, 0x0C0C0C000C0C0C00ULL, 0xAEAEAE00AEAEAE00ULL, 0x4141410041414100ULL, 0x2323230023232300ULL, 0xEFEFEF00EFEFEF00ULL, 0x6B6B6B006B6B6B00ULL, 0x9393930093939300ULL, 0x4545450045454500ULL, 0x1919190019191900ULL, 0xA5A5A500A5A5A500ULL, 0x2121210021212100ULL, 0xEDEDED00EDEDED00ULL, 0x0E0E0E000E0E0E00ULL, 0x4F4F4F004F4F4F00ULL, 0x4E4E4E004E4E4E00ULL, 0x1D1D1D001D1D1D00ULL, 0x6565650065656500ULL, 0x9292920092929200ULL, 0xBDBDBD00BDBDBD00ULL, 0x8686860086868600ULL, 0xB8B8B800B8B8B800ULL, 0xAFAFAF00AFAFAF00ULL, 0x8F8F8F008F8F8F00ULL, 0x7C7C7C007C7C7C00ULL, 0xEBEBEB00EBEBEB00ULL, 0x1F1F1F001F1F1F00ULL, 0xCECECE00CECECE00ULL, 0x3E3E3E003E3E3E00ULL, 0x3030300030303000ULL, 0xDCDCDC00DCDCDC00ULL, 0x5F5F5F005F5F5F00ULL, 0x5E5E5E005E5E5E00ULL, 0xC5C5C500C5C5C500ULL, 0x0B0B0B000B0B0B00ULL, 0x1A1A1A001A1A1A00ULL, 0xA6A6A600A6A6A600ULL, 0xE1E1E100E1E1E100ULL, 0x3939390039393900ULL, 0xCACACA00CACACA00ULL, 0xD5D5D500D5D5D500ULL, 0x4747470047474700ULL, 0x5D5D5D005D5D5D00ULL, 0x3D3D3D003D3D3D00ULL, 0xD9D9D900D9D9D900ULL, 0x0101010001010100ULL, 0x5A5A5A005A5A5A00ULL, 0xD6D6D600D6D6D600ULL, 0x5151510051515100ULL, 0x5656560056565600ULL, 0x6C6C6C006C6C6C00ULL, 0x4D4D4D004D4D4D00ULL, 0x8B8B8B008B8B8B00ULL, 0x0D0D0D000D0D0D00ULL, 0x9A9A9A009A9A9A00ULL, 0x6666660066666600ULL, 0xFBFBFB00FBFBFB00ULL, 0xCCCCCC00CCCCCC00ULL, 0xB0B0B000B0B0B000ULL, 0x2D2D2D002D2D2D00ULL, 0x7474740074747400ULL, 0x1212120012121200ULL, 0x2B2B2B002B2B2B00ULL, 0x2020200020202000ULL, 0xF0F0F000F0F0F000ULL, 0xB1B1B100B1B1B100ULL, 0x8484840084848400ULL, 0x9999990099999900ULL, 0xDFDFDF00DFDFDF00ULL, 0x4C4C4C004C4C4C00ULL, 0xCBCBCB00CBCBCB00ULL, 0xC2C2C200C2C2C200ULL, 0x3434340034343400ULL, 0x7E7E7E007E7E7E00ULL, 0x7676760076767600ULL, 0x0505050005050500ULL, 0x6D6D6D006D6D6D00ULL, 0xB7B7B700B7B7B700ULL, 0xA9A9A900A9A9A900ULL, 0x3131310031313100ULL, 0xD1D1D100D1D1D100ULL, 0x1717170017171700ULL, 0x0404040004040400ULL, 0xD7D7D700D7D7D700ULL, 0x1414140014141400ULL, 0x5858580058585800ULL, 0x3A3A3A003A3A3A00ULL, 0x6161610061616100ULL, 0xDEDEDE00DEDEDE00ULL, 0x1B1B1B001B1B1B00ULL, 0x1111110011111100ULL, 0x1C1C1C001C1C1C00ULL, 0x3232320032323200ULL, 0x0F0F0F000F0F0F00ULL, 0x9C9C9C009C9C9C00ULL, 0x1616160016161600ULL, 0x5353530053535300ULL, 0x1818180018181800ULL, 0xF2F2F200F2F2F200ULL, 0x2222220022222200ULL, 0xFEFEFE00FEFEFE00ULL, 0x4444440044444400ULL, 0xCFCFCF00CFCFCF00ULL, 0xB2B2B200B2B2B200ULL, 0xC3C3C300C3C3C300ULL, 0xB5B5B500B5B5B500ULL, 0x7A7A7A007A7A7A00ULL, 0x9191910091919100ULL, 0x2424240024242400ULL, 0x0808080008080800ULL, 0xE8E8E800E8E8E800ULL, 0xA8A8A800A8A8A800ULL, 0x6060600060606000ULL, 0xFCFCFC00FCFCFC00ULL, 0x6969690069696900ULL, 0x5050500050505000ULL, 0xAAAAAA00AAAAAA00ULL, 0xD0D0D000D0D0D000ULL, 0xA0A0A000A0A0A000ULL, 0x7D7D7D007D7D7D00ULL, 0xA1A1A100A1A1A100ULL, 0x8989890089898900ULL, 0x6262620062626200ULL, 0x9797970097979700ULL, 0x5454540054545400ULL, 0x5B5B5B005B5B5B00ULL, 0x1E1E1E001E1E1E00ULL, 0x9595950095959500ULL, 0xE0E0E000E0E0E000ULL, 0xFFFFFF00FFFFFF00ULL, 0x6464640064646400ULL, 0xD2D2D200D2D2D200ULL, 0x1010100010101000ULL, 0xC4C4C400C4C4C400ULL, 0x0000000000000000ULL, 0x4848480048484800ULL, 0xA3A3A300A3A3A300ULL, 0xF7F7F700F7F7F700ULL, 0x7575750075757500ULL, 0xDBDBDB00DBDBDB00ULL, 0x8A8A8A008A8A8A00ULL, 0x0303030003030300ULL, 0xE6E6E600E6E6E600ULL, 0xDADADA00DADADA00ULL, 0x0909090009090900ULL, 0x3F3F3F003F3F3F00ULL, 0xDDDDDD00DDDDDD00ULL, 0x9494940094949400ULL, 0x8787870087878700ULL, 0x5C5C5C005C5C5C00ULL, 0x8383830083838300ULL, 0x0202020002020200ULL, 0xCDCDCD00CDCDCD00ULL, 0x4A4A4A004A4A4A00ULL, 0x9090900090909000ULL, 0x3333330033333300ULL, 0x7373730073737300ULL, 0x6767670067676700ULL, 0xF6F6F600F6F6F600ULL, 0xF3F3F300F3F3F300ULL, 0x9D9D9D009D9D9D00ULL, 0x7F7F7F007F7F7F00ULL, 0xBFBFBF00BFBFBF00ULL, 0xE2E2E200E2E2E200ULL, 0x5252520052525200ULL, 0x9B9B9B009B9B9B00ULL, 0xD8D8D800D8D8D800ULL, 0x2626260026262600ULL, 0xC8C8C800C8C8C800ULL, 0x3737370037373700ULL, 0xC6C6C600C6C6C600ULL, 0x3B3B3B003B3B3B00ULL, 0x8181810081818100ULL, 0x9696960096969600ULL, 0x6F6F6F006F6F6F00ULL, 0x4B4B4B004B4B4B00ULL, 0x1313130013131300ULL, 0xBEBEBE00BEBEBE00ULL, 0x6363630063636300ULL, 0x2E2E2E002E2E2E00ULL, 0xE9E9E900E9E9E900ULL, 0x7979790079797900ULL, 0xA7A7A700A7A7A700ULL, 0x8C8C8C008C8C8C00ULL, 0x9F9F9F009F9F9F00ULL, 0x6E6E6E006E6E6E00ULL, 0xBCBCBC00BCBCBC00ULL, 0x8E8E8E008E8E8E00ULL, 0x2929290029292900ULL, 0xF5F5F500F5F5F500ULL, 0xF9F9F900F9F9F900ULL, 0xB6B6B600B6B6B600ULL, 0x2F2F2F002F2F2F00ULL, 0xFDFDFD00FDFDFD00ULL, 0xB4B4B400B4B4B400ULL, 0x5959590059595900ULL, 0x7878780078787800ULL, 0x9898980098989800ULL, 0x0606060006060600ULL, 0x6A6A6A006A6A6A00ULL, 0xE7E7E700E7E7E700ULL, 0x4646460046464600ULL, 0x7171710071717100ULL, 0xBABABA00BABABA00ULL, 0xD4D4D400D4D4D400ULL, 0x2525250025252500ULL, 0xABABAB00ABABAB00ULL, 0x4242420042424200ULL, 0x8888880088888800ULL, 0xA2A2A200A2A2A200ULL, 0x8D8D8D008D8D8D00ULL, 0xFAFAFA00FAFAFA00ULL, 0x7272720072727200ULL, 0x0707070007070700ULL, 0xB9B9B900B9B9B900ULL, 0x5555550055555500ULL, 0xF8F8F800F8F8F800ULL, 0xEEEEEE00EEEEEE00ULL, 0xACACAC00ACACAC00ULL, 0x0A0A0A000A0A0A00ULL, 0x3636360036363600ULL, 0x4949490049494900ULL, 0x2A2A2A002A2A2A00ULL, 0x6868680068686800ULL, 0x3C3C3C003C3C3C00ULL, 0x3838380038383800ULL, 0xF1F1F100F1F1F100ULL, 0xA4A4A400A4A4A400ULL, 0x4040400040404000ULL, 0x2828280028282800ULL, 0xD3D3D300D3D3D300ULL, 0x7B7B7B007B7B7B00ULL, 0xBBBBBB00BBBBBB00ULL, 0xC9C9C900C9C9C900ULL, 0x4343430043434300ULL, 0xC1C1C100C1C1C100ULL, 0x1515150015151500ULL, 0xE3E3E300E3E3E300ULL, 0xADADAD00ADADAD00ULL, 0xF4F4F400F4F4F400ULL, 0x7777770077777700ULL, 0xC7C7C700C7C7C700ULL, 0x8080800080808000ULL, 0x9E9E9E009E9E9E00ULL }; } namespace Botan { extern "C" { #ifdef Q_OS_UNIX /* * Helper Macros for x86 Assembly */ #ifndef ASM #define ASM(x) x "\n\t" #endif #define ADDSUB2_OP(OPERATION, INDEX) \ ASM("movl 4*" #INDEX "(%[y]), %[carry]") \ ASM(OPERATION " %[carry], 4*" #INDEX "(%[x])") \ #define ADDSUB3_OP(OPERATION, INDEX) \ ASM("movl 4*" #INDEX "(%[x]), %[carry]") \ ASM(OPERATION " 4*" #INDEX "(%[y]), %[carry]") \ ASM("movl %[carry], 4*" #INDEX "(%[z])") \ #define LINMUL_OP(WRITE_TO, INDEX) \ ASM("movl 4*" #INDEX "(%[x]),%%eax") \ ASM("mull %[y]") \ ASM("addl %[carry],%%eax") \ ASM("adcl $0,%%edx") \ ASM("movl %%edx,%[carry]") \ ASM("movl %%eax, 4*" #INDEX "(%[" WRITE_TO "])") #define MULADD_OP(IGNORED, INDEX) \ ASM("movl 4*" #INDEX "(%[x]),%%eax") \ ASM("mull %[y]") \ ASM("addl %[carry],%%eax") \ ASM("adcl $0,%%edx") \ ASM("addl 4*" #INDEX "(%[z]),%%eax") \ ASM("adcl $0,%%edx") \ ASM("movl %%edx,%[carry]") \ ASM("movl %%eax, 4*" #INDEX " (%[z])") #define DO_8_TIMES(MACRO, ARG) \ MACRO(ARG, 0) \ MACRO(ARG, 1) \ MACRO(ARG, 2) \ MACRO(ARG, 3) \ MACRO(ARG, 4) \ MACRO(ARG, 5) \ MACRO(ARG, 6) \ MACRO(ARG, 7) #define ADD_OR_SUBTRACT(CORE_CODE) \ ASM("rorl %[carry]") \ CORE_CODE \ ASM("sbbl %[carry],%[carry]") \ ASM("negl %[carry]") /* * Word Addition */ inline word word_add(word x, word y, word* carry) { asm( ADD_OR_SUBTRACT(ASM("adcl %[y],%[x]")) : [x]"=r"(x), [carry]"=r"(*carry) : "0"(x), [y]"rm"(y), "1"(*carry) : "cc"); return x; } /* * Eight Word Block Addition, Two Argument */ inline word word8_add2(word x[8], const word y[8], word carry) { asm( ADD_OR_SUBTRACT(DO_8_TIMES(ADDSUB2_OP, "adcl")) : [carry]"=r"(carry) : [x]"r"(x), [y]"r"(y), "0"(carry) : "cc", "memory"); return carry; } /* * Eight Word Block Addition, Three Argument */ inline word word8_add3(word z[8], const word x[8], const word y[8], word carry) { asm( ADD_OR_SUBTRACT(DO_8_TIMES(ADDSUB3_OP, "adcl")) : [carry]"=r"(carry) : [x]"r"(x), [y]"r"(y), [z]"r"(z), "0"(carry) : "cc", "memory"); return carry; } /* * Word Subtraction */ inline word word_sub(word x, word y, word* carry) { asm( ADD_OR_SUBTRACT(ASM("sbbl %[y],%[x]")) : [x]"=r"(x), [carry]"=r"(*carry) : "0"(x), [y]"rm"(y), "1"(*carry) : "cc"); return x; } /* * Eight Word Block Subtraction, Two Argument */ inline word word8_sub2(word x[8], const word y[8], word carry) { asm( ADD_OR_SUBTRACT(DO_8_TIMES(ADDSUB2_OP, "sbbl")) : [carry]"=r"(carry) : [x]"r"(x), [y]"r"(y), "0"(carry) : "cc", "memory"); return carry; } /* * Eight Word Block Subtraction, Two Argument */ inline word word8_sub2_rev(word x[8], const word y[8], word carry) { asm( ADD_OR_SUBTRACT(DO_8_TIMES(ADDSUB3_OP, "sbbl")) : [carry]"=r"(carry) : [x]"r"(y), [y]"r"(x), [z]"r"(x), "0"(carry) : "cc", "memory"); return carry; } /* * Eight Word Block Subtraction, Three Argument */ inline word word8_sub3(word z[8], const word x[8], const word y[8], word carry) { asm( ADD_OR_SUBTRACT(DO_8_TIMES(ADDSUB3_OP, "sbbl")) : [carry]"=r"(carry) : [x]"r"(x), [y]"r"(y), [z]"r"(z), "0"(carry) : "cc", "memory"); return carry; } /* * Eight Word Block Linear Multiplication */ inline word word8_linmul2(word x[8], word y, word carry) { asm( DO_8_TIMES(LINMUL_OP, "x") : [carry]"=r"(carry) : [x]"r"(x), [y]"rm"(y), "0"(carry) : "cc", "%eax", "%edx"); return carry; } /* * Eight Word Block Linear Multiplication */ inline word word8_linmul3(word z[8], const word x[8], word y, word carry) { asm( DO_8_TIMES(LINMUL_OP, "z") : [carry]"=r"(carry) : [z]"r"(z), [x]"r"(x), [y]"rm"(y), "0"(carry) : "cc", "%eax", "%edx"); return carry; } /* * Eight Word Block Multiply/Add */ inline word word8_madd3(word z[8], const word x[8], word y, word carry) { asm( DO_8_TIMES(MULADD_OP, "") : [carry]"=r"(carry) : [z]"r"(z), [x]"r"(x), [y]"rm"(y), "0"(carry) : "cc", "%eax", "%edx"); return carry; } /* * Multiply-Add Accumulator */ inline void word3_muladd(word* w2, word* w1, word* w0, word x, word y) { asm( ASM("mull %[y]") ASM("addl %[x],%[w0]") ASM("adcl %[y],%[w1]") ASM("adcl $0,%[w2]") : [w0]"=r"(*w0), [w1]"=r"(*w1), [w2]"=r"(*w2) : [x]"a"(x), [y]"d"(y), "0"(*w0), "1"(*w1), "2"(*w2) : "cc"); } /* * Multiply-Add Accumulator */ inline void word3_muladd_2(word* w2, word* w1, word* w0, word x, word y) { asm( ASM("mull %[y]") ASM("addl %[x],%[w0]") ASM("adcl %[y],%[w1]") ASM("adcl $0,%[w2]") ASM("addl %[x],%[w0]") ASM("adcl %[y],%[w1]") ASM("adcl $0,%[w2]") : [w0]"=r"(*w0), [w1]"=r"(*w1), [w2]"=r"(*w2) : [x]"a"(x), [y]"d"(y), "0"(*w0), "1"(*w1), "2"(*w2) : "cc"); } #else /* * Word Addition */ inline word word_add(word x, word y, word* carry) { word z = x + y; word c1 = (z < x); z += *carry; *carry = c1 | (z < *carry); return z; } /* * Eight Word Block Addition, Two Argument */ inline word word8_add2(word x[8], const word y[8], word carry) { x[0] = word_add(x[0], y[0], &carry); x[1] = word_add(x[1], y[1], &carry); x[2] = word_add(x[2], y[2], &carry); x[3] = word_add(x[3], y[3], &carry); x[4] = word_add(x[4], y[4], &carry); x[5] = word_add(x[5], y[5], &carry); x[6] = word_add(x[6], y[6], &carry); x[7] = word_add(x[7], y[7], &carry); return carry; } /* * Eight Word Block Addition, Three Argument */ inline word word8_add3(word z[8], const word x[8], const word y[8], word carry) { z[0] = word_add(x[0], y[0], &carry); z[1] = word_add(x[1], y[1], &carry); z[2] = word_add(x[2], y[2], &carry); z[3] = word_add(x[3], y[3], &carry); z[4] = word_add(x[4], y[4], &carry); z[5] = word_add(x[5], y[5], &carry); z[6] = word_add(x[6], y[6], &carry); z[7] = word_add(x[7], y[7], &carry); return carry; } /* * Word Subtraction */ inline word word_sub(word x, word y, word* carry) { word t0 = x - y; word c1 = (t0 > x); word z = t0 - *carry; *carry = c1 | (z > t0); return z; } /* * Eight Word Block Subtraction, Two Argument */ inline word word8_sub2(word x[8], const word y[8], word carry) { x[0] = word_sub(x[0], y[0], &carry); x[1] = word_sub(x[1], y[1], &carry); x[2] = word_sub(x[2], y[2], &carry); x[3] = word_sub(x[3], y[3], &carry); x[4] = word_sub(x[4], y[4], &carry); x[5] = word_sub(x[5], y[5], &carry); x[6] = word_sub(x[6], y[6], &carry); x[7] = word_sub(x[7], y[7], &carry); return carry; } /* * Eight Word Block Subtraction, Two Argument */ inline word word8_sub2_rev(word x[8], const word y[8], word carry) { x[0] = word_sub(y[0], x[0], &carry); x[1] = word_sub(y[1], x[1], &carry); x[2] = word_sub(y[2], x[2], &carry); x[3] = word_sub(y[3], x[3], &carry); x[4] = word_sub(y[4], x[4], &carry); x[5] = word_sub(y[5], x[5], &carry); x[6] = word_sub(y[6], x[6], &carry); x[7] = word_sub(y[7], x[7], &carry); return carry; } /* * Eight Word Block Subtraction, Three Argument */ inline word word8_sub3(word z[8], const word x[8], const word y[8], word carry) { z[0] = word_sub(x[0], y[0], &carry); z[1] = word_sub(x[1], y[1], &carry); z[2] = word_sub(x[2], y[2], &carry); z[3] = word_sub(x[3], y[3], &carry); z[4] = word_sub(x[4], y[4], &carry); z[5] = word_sub(x[5], y[5], &carry); z[6] = word_sub(x[6], y[6], &carry); z[7] = word_sub(x[7], y[7], &carry); return carry; } /* * Eight Word Block Linear Multiplication */ inline word word8_linmul2(word x[8], word y, word carry) { x[0] = word_madd2(x[0], y, &carry); x[1] = word_madd2(x[1], y, &carry); x[2] = word_madd2(x[2], y, &carry); x[3] = word_madd2(x[3], y, &carry); x[4] = word_madd2(x[4], y, &carry); x[5] = word_madd2(x[5], y, &carry); x[6] = word_madd2(x[6], y, &carry); x[7] = word_madd2(x[7], y, &carry); return carry; } /* * Eight Word Block Linear Multiplication */ inline word word8_linmul3(word z[8], const word x[8], word y, word carry) { z[0] = word_madd2(x[0], y, &carry); z[1] = word_madd2(x[1], y, &carry); z[2] = word_madd2(x[2], y, &carry); z[3] = word_madd2(x[3], y, &carry); z[4] = word_madd2(x[4], y, &carry); z[5] = word_madd2(x[5], y, &carry); z[6] = word_madd2(x[6], y, &carry); z[7] = word_madd2(x[7], y, &carry); return carry; } /* * Eight Word Block Multiply/Add */ inline word word8_madd3(word z[8], const word x[8], word y, word carry) { z[0] = word_madd3(x[0], y, z[0], &carry); z[1] = word_madd3(x[1], y, z[1], &carry); z[2] = word_madd3(x[2], y, z[2], &carry); z[3] = word_madd3(x[3], y, z[3], &carry); z[4] = word_madd3(x[4], y, z[4], &carry); z[5] = word_madd3(x[5], y, z[5], &carry); z[6] = word_madd3(x[6], y, z[6], &carry); z[7] = word_madd3(x[7], y, z[7], &carry); return carry; } /* * Multiply-Add Accumulator */ inline void word3_muladd(word* w2, word* w1, word* w0, word a, word b) { word carry = *w0; *w0 = word_madd2(a, b, &carry); *w1 += carry; *w2 += (*w1 < carry) ? 1 : 0; } /* * Multiply-Add Accumulator */ inline void word3_muladd_2(word* w2, word* w1, word* w0, word a, word b) { word carry = 0; a = word_madd2(a, b, &carry); b = carry; word top = (b >> (BOTAN_MP_WORD_BITS-1)); b <<= 1; b |= (a >> (BOTAN_MP_WORD_BITS-1)); a <<= 1; carry = 0; *w0 = word_add(*w0, a, &carry); *w1 = word_add(*w1, b, &carry); *w2 = word_add(*w2, top, &carry); } #endif } } /* * OctetString * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ #include namespace Botan { /* * Create an OctetString from RNG output */ OctetString::OctetString(RandomNumberGenerator& rng, size_t length) { bits = rng.random_vec(length); } /* * Create an OctetString from a hex string */ void OctetString::change(const std::string& hex_string) { bits.resize(1 + hex_string.length() / 2); bits.resize(hex_decode(&bits[0], hex_string)); } /* * Create an OctetString from a byte string */ void OctetString::change(const byte in[], size_t n) { bits.resize(n); bits.copy(in, n); } /* * Set the parity of each key byte to odd */ void OctetString::set_odd_parity() { const byte ODD_PARITY[256] = { 0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x07, 0x07, 0x08, 0x08, 0x0B, 0x0B, 0x0D, 0x0D, 0x0E, 0x0E, 0x10, 0x10, 0x13, 0x13, 0x15, 0x15, 0x16, 0x16, 0x19, 0x19, 0x1A, 0x1A, 0x1C, 0x1C, 0x1F, 0x1F, 0x20, 0x20, 0x23, 0x23, 0x25, 0x25, 0x26, 0x26, 0x29, 0x29, 0x2A, 0x2A, 0x2C, 0x2C, 0x2F, 0x2F, 0x31, 0x31, 0x32, 0x32, 0x34, 0x34, 0x37, 0x37, 0x38, 0x38, 0x3B, 0x3B, 0x3D, 0x3D, 0x3E, 0x3E, 0x40, 0x40, 0x43, 0x43, 0x45, 0x45, 0x46, 0x46, 0x49, 0x49, 0x4A, 0x4A, 0x4C, 0x4C, 0x4F, 0x4F, 0x51, 0x51, 0x52, 0x52, 0x54, 0x54, 0x57, 0x57, 0x58, 0x58, 0x5B, 0x5B, 0x5D, 0x5D, 0x5E, 0x5E, 0x61, 0x61, 0x62, 0x62, 0x64, 0x64, 0x67, 0x67, 0x68, 0x68, 0x6B, 0x6B, 0x6D, 0x6D, 0x6E, 0x6E, 0x70, 0x70, 0x73, 0x73, 0x75, 0x75, 0x76, 0x76, 0x79, 0x79, 0x7A, 0x7A, 0x7C, 0x7C, 0x7F, 0x7F, 0x80, 0x80, 0x83, 0x83, 0x85, 0x85, 0x86, 0x86, 0x89, 0x89, 0x8A, 0x8A, 0x8C, 0x8C, 0x8F, 0x8F, 0x91, 0x91, 0x92, 0x92, 0x94, 0x94, 0x97, 0x97, 0x98, 0x98, 0x9B, 0x9B, 0x9D, 0x9D, 0x9E, 0x9E, 0xA1, 0xA1, 0xA2, 0xA2, 0xA4, 0xA4, 0xA7, 0xA7, 0xA8, 0xA8, 0xAB, 0xAB, 0xAD, 0xAD, 0xAE, 0xAE, 0xB0, 0xB0, 0xB3, 0xB3, 0xB5, 0xB5, 0xB6, 0xB6, 0xB9, 0xB9, 0xBA, 0xBA, 0xBC, 0xBC, 0xBF, 0xBF, 0xC1, 0xC1, 0xC2, 0xC2, 0xC4, 0xC4, 0xC7, 0xC7, 0xC8, 0xC8, 0xCB, 0xCB, 0xCD, 0xCD, 0xCE, 0xCE, 0xD0, 0xD0, 0xD3, 0xD3, 0xD5, 0xD5, 0xD6, 0xD6, 0xD9, 0xD9, 0xDA, 0xDA, 0xDC, 0xDC, 0xDF, 0xDF, 0xE0, 0xE0, 0xE3, 0xE3, 0xE5, 0xE5, 0xE6, 0xE6, 0xE9, 0xE9, 0xEA, 0xEA, 0xEC, 0xEC, 0xEF, 0xEF, 0xF1, 0xF1, 0xF2, 0xF2, 0xF4, 0xF4, 0xF7, 0xF7, 0xF8, 0xF8, 0xFB, 0xFB, 0xFD, 0xFD, 0xFE, 0xFE }; for(size_t j = 0; j != bits.size(); ++j) bits[j] = ODD_PARITY[bits[j]]; } /* * Hex encode an OctetString */ std::string OctetString::as_string() const { return hex_encode(&bits[0], bits.size()); } /* * XOR Operation for OctetStrings */ OctetString& OctetString::operator^=(const OctetString& k) { if(&k == this) { zeroise(bits); return (*this); } xor_buf(&bits[0], k.begin(), std::min(length(), k.length())); return (*this); } /* * Equality Operation for OctetStrings */ bool operator==(const OctetString& s1, const OctetString& s2) { return (s1.bits_of() == s2.bits_of()); } /* * Unequality Operation for OctetStrings */ bool operator!=(const OctetString& s1, const OctetString& s2) { return !(s1 == s2); } /* * Append Operation for OctetStrings */ OctetString operator+(const OctetString& k1, const OctetString& k2) { SecureVector out; out += k1.bits_of(); out += k2.bits_of(); return OctetString(out); } /* * XOR Operation for OctetStrings */ OctetString operator^(const OctetString& k1, const OctetString& k2) { SecureVector ret(std::max(k1.length(), k2.length())); ret.copy(k1.begin(), k1.length()); xor_buf(ret, k2.begin(), k2.length()); return OctetString(ret); } } /* * Algorithm Factory * (C) 2008-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ #include namespace Botan { namespace { /* * Template functions for the factory prototype/search algorithm */ template T* engine_get_algo(Engine*, const SCAN_Name&, Algorithm_Factory&) { return 0; } template<> BlockCipher* engine_get_algo(Engine* engine, const SCAN_Name& request, Algorithm_Factory& af) { return engine->find_block_cipher(request, af); } template<> StreamCipher* engine_get_algo(Engine* engine, const SCAN_Name& request, Algorithm_Factory& af) { return engine->find_stream_cipher(request, af); } template<> HashFunction* engine_get_algo(Engine* engine, const SCAN_Name& request, Algorithm_Factory& af) { return engine->find_hash(request, af); } template<> MessageAuthenticationCode* engine_get_algo(Engine* engine, const SCAN_Name& request, Algorithm_Factory& af) { return engine->find_mac(request, af); } template<> PBKDF* engine_get_algo(Engine* engine, const SCAN_Name& request, Algorithm_Factory& af) { return engine->find_pbkdf(request, af); } template const T* factory_prototype(const std::string& algo_spec, const std::string& provider, const std::vector& engines, Algorithm_Factory& af, Algorithm_Cache* cache) { if(const T* cache_hit = cache->get(algo_spec, provider)) return cache_hit; SCAN_Name scan_name(algo_spec); if(scan_name.cipher_mode() != "") return 0; for(size_t i = 0; i != engines.size(); ++i) { if(provider == "" || engines[i]->provider_name() == provider) { if(T* impl = engine_get_algo(engines[i], scan_name, af)) cache->add(impl, algo_spec, engines[i]->provider_name()); } } return cache->get(algo_spec, provider); } } /* * Setup caches */ Algorithm_Factory::Algorithm_Factory(Mutex_Factory& mf) { block_cipher_cache = new Algorithm_Cache(mf.make()); stream_cipher_cache = new Algorithm_Cache(mf.make()); hash_cache = new Algorithm_Cache(mf.make()); mac_cache = new Algorithm_Cache(mf.make()); pbkdf_cache = new Algorithm_Cache(mf.make()); } /* * Delete all engines */ Algorithm_Factory::~Algorithm_Factory() { delete block_cipher_cache; delete stream_cipher_cache; delete hash_cache; delete mac_cache; delete pbkdf_cache; std::for_each(engines.begin(), engines.end(), del_fun()); } void Algorithm_Factory::clear_caches() { block_cipher_cache->clear_cache(); stream_cipher_cache->clear_cache(); hash_cache->clear_cache(); mac_cache->clear_cache(); pbkdf_cache->clear_cache(); } void Algorithm_Factory::add_engine(Engine* engine) { clear_caches(); engines.push_back(engine); } /* * Set the preferred provider for an algorithm */ void Algorithm_Factory::set_preferred_provider(const std::string& algo_spec, const std::string& provider) { if(prototype_block_cipher(algo_spec)) block_cipher_cache->set_preferred_provider(algo_spec, provider); else if(prototype_stream_cipher(algo_spec)) stream_cipher_cache->set_preferred_provider(algo_spec, provider); else if(prototype_hash_function(algo_spec)) hash_cache->set_preferred_provider(algo_spec, provider); else if(prototype_mac(algo_spec)) mac_cache->set_preferred_provider(algo_spec, provider); else if(prototype_pbkdf(algo_spec)) pbkdf_cache->set_preferred_provider(algo_spec, provider); } /* * Get an engine out of the list */ Engine* Algorithm_Factory::get_engine_n(size_t n) const { if(n >= engines.size()) return 0; return engines[n]; } /* * Return the possible providers of a request * Note: assumes you don't have different types by the same name */ std::vector Algorithm_Factory::providers_of(const std::string& algo_spec) { /* The checks with if(prototype_X(algo_spec)) have the effect of forcing a full search, since otherwise there might not be any providers at all in the cache. */ if(prototype_block_cipher(algo_spec)) return block_cipher_cache->providers_of(algo_spec); else if(prototype_stream_cipher(algo_spec)) return stream_cipher_cache->providers_of(algo_spec); else if(prototype_hash_function(algo_spec)) return hash_cache->providers_of(algo_spec); else if(prototype_mac(algo_spec)) return mac_cache->providers_of(algo_spec); else if(prototype_pbkdf(algo_spec)) return pbkdf_cache->providers_of(algo_spec); else return std::vector(); } /* * Return the prototypical block cipher corresponding to this request */ const BlockCipher* Algorithm_Factory::prototype_block_cipher(const std::string& algo_spec, const std::string& provider) { return factory_prototype(algo_spec, provider, engines, *this, block_cipher_cache); } /* * Return the prototypical stream cipher corresponding to this request */ const StreamCipher* Algorithm_Factory::prototype_stream_cipher(const std::string& algo_spec, const std::string& provider) { return factory_prototype(algo_spec, provider, engines, *this, stream_cipher_cache); } /* * Return the prototypical object corresponding to this request (if found) */ const HashFunction* Algorithm_Factory::prototype_hash_function(const std::string& algo_spec, const std::string& provider) { return factory_prototype(algo_spec, provider, engines, *this, hash_cache); } /* * Return the prototypical object corresponding to this request */ const MessageAuthenticationCode* Algorithm_Factory::prototype_mac(const std::string& algo_spec, const std::string& provider) { return factory_prototype(algo_spec, provider, engines, *this, mac_cache); } /* * Return the prototypical object corresponding to this request */ const PBKDF* Algorithm_Factory::prototype_pbkdf(const std::string& algo_spec, const std::string& provider) { return factory_prototype(algo_spec, provider, engines, *this, pbkdf_cache); } /* * Return a new block cipher corresponding to this request */ BlockCipher* Algorithm_Factory::make_block_cipher(const std::string& algo_spec, const std::string& provider) { if(const BlockCipher* proto = prototype_block_cipher(algo_spec, provider)) return proto->clone(); throw Algorithm_Not_Found(algo_spec); } /* * Return a new stream cipher corresponding to this request */ StreamCipher* Algorithm_Factory::make_stream_cipher(const std::string& algo_spec, const std::string& provider) { if(const StreamCipher* proto = prototype_stream_cipher(algo_spec, provider)) return proto->clone(); throw Algorithm_Not_Found(algo_spec); } /* * Return a new object corresponding to this request */ HashFunction* Algorithm_Factory::make_hash_function(const std::string& algo_spec, const std::string& provider) { if(const HashFunction* proto = prototype_hash_function(algo_spec, provider)) return proto->clone(); throw Algorithm_Not_Found(algo_spec); } /* * Return a new object corresponding to this request */ MessageAuthenticationCode* Algorithm_Factory::make_mac(const std::string& algo_spec, const std::string& provider) { if(const MessageAuthenticationCode* proto = prototype_mac(algo_spec, provider)) return proto->clone(); throw Algorithm_Not_Found(algo_spec); } /* * Return a new object corresponding to this request */ PBKDF* Algorithm_Factory::make_pbkdf(const std::string& algo_spec, const std::string& provider) { if(const PBKDF* proto = prototype_pbkdf(algo_spec, provider)) return proto->clone(); throw Algorithm_Not_Found(algo_spec); } /* * Add a new block cipher */ void Algorithm_Factory::add_block_cipher(BlockCipher* block_cipher, const std::string& provider) { block_cipher_cache->add(block_cipher, block_cipher->name(), provider); } /* * Add a new stream cipher */ void Algorithm_Factory::add_stream_cipher(StreamCipher* stream_cipher, const std::string& provider) { stream_cipher_cache->add(stream_cipher, stream_cipher->name(), provider); } /* * Add a new hash */ void Algorithm_Factory::add_hash_function(HashFunction* hash, const std::string& provider) { hash_cache->add(hash, hash->name(), provider); } /* * Add a new mac */ void Algorithm_Factory::add_mac(MessageAuthenticationCode* mac, const std::string& provider) { mac_cache->add(mac, mac->name(), provider); } /* * Add a new PBKDF */ void Algorithm_Factory::add_pbkdf(PBKDF* pbkdf, const std::string& provider) { pbkdf_cache->add(pbkdf, pbkdf->name(), provider); } } /* * Default provider weights for Algorithm_Cache * (C) 2008 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { /** * Return a static provider weighing */ size_t static_provider_weight(const std::string& prov_name) { /* * Prefer asm over C++, but prefer anything over OpenSSL or GNU MP; to use * them, set the provider explicitly for the algorithms you want */ if(prov_name == "aes_isa") return 9; if(prov_name == "simd") return 8; if(prov_name == "asm") return 7; if(prov_name == "core") return 5; if(prov_name == "openssl") return 2; if(prov_name == "gmp") return 1; return 0; // other/unknown } } #ifdef Q_OS_UNIX /* * Memory Mapping Allocator * (C) 1999-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ #include #include #include #include #include #include #include #include #include #ifndef MAP_FAILED #define MAP_FAILED -1 #endif namespace Botan { namespace { /* * MemoryMapping_Allocator Exception */ class BOTAN_DLL MemoryMapping_Failed : public Exception { public: MemoryMapping_Failed(const std::string& msg) : Exception("MemoryMapping_Allocator: " + msg) {} }; } /* * Memory Map a File into Memory */ void* MemoryMapping_Allocator::alloc_block(size_t n) { class TemporaryFile { public: int get_fd() const { return fd; } TemporaryFile(const std::string& base) { const std::string mkstemp_template = base + "XXXXXX"; std::vector filepath(mkstemp_template.begin(), mkstemp_template.end()); filepath.push_back(0); // add terminating NULL mode_t old_umask = ::umask(077); fd = ::mkstemp(&filepath[0]); ::umask(old_umask); if(fd == -1) throw MemoryMapping_Failed("Temporary file allocation failed"); if(::unlink(&filepath[0]) != 0) throw MemoryMapping_Failed("Could not unlink temporary file"); } ~TemporaryFile() { /* * We can safely close here, because post-mmap the file * will continue to exist until the mmap is unmapped from * our address space upon deallocation (or process exit). */ if(fd != -1 && ::close(fd) == -1) throw MemoryMapping_Failed("Could not close file"); } private: int fd; }; TemporaryFile file("/tmp/botan_"); if(file.get_fd() == -1) throw MemoryMapping_Failed("Could not create file"); std::vector zeros(4096); size_t remaining = n; while(remaining) { const size_t write_try = std::min(zeros.size(), remaining); ssize_t wrote_got = ::write(file.get_fd(), &zeros[0], write_try); if(wrote_got == -1 && errno != EINTR) throw MemoryMapping_Failed("Could not write to file"); remaining -= wrote_got; } #ifndef MAP_NOSYNC #define MAP_NOSYNC 0 #endif void* ptr = ::mmap(0, n, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_NOSYNC, file.get_fd(), 0); if(ptr == static_cast(MAP_FAILED)) throw MemoryMapping_Failed("Could not map file"); return ptr; } /* * Remove a Memory Mapping */ void MemoryMapping_Allocator::dealloc_block(void* ptr, size_t n) { if(ptr == 0) return; const byte PATTERNS[] = { 0x00, 0xF5, 0x5A, 0xAF, 0x00 }; // The char* casts are for Solaris, args are void* on most other systems for(size_t i = 0; i != sizeof(PATTERNS); ++i) { std::memset(ptr, PATTERNS[i], n); if(::msync(static_cast(ptr), n, MS_SYNC)) throw MemoryMapping_Failed("Sync operation failed"); } if(::munmap(static_cast(ptr), n)) throw MemoryMapping_Failed("Could not unmap file"); } } #endif /* * Pooling Allocator * (C) 1999-2008 Jack Lloyd * 2005 Matthew Gregan * 2005-2006 Matt Johnston * * Distributed under the terms of the Botan license */ #include #include namespace Botan { /* * Memory_Block Constructor */ Pooling_Allocator::Memory_Block::Memory_Block(void* buf) { buffer = static_cast(buf); bitmap = 0; buffer_end = buffer + (BLOCK_SIZE * BITMAP_SIZE); } /* * See if ptr is contained by this block */ bool Pooling_Allocator::Memory_Block::contains(void* ptr, size_t length) const { return ((buffer <= ptr) && (buffer_end >= static_cast(ptr) + length * BLOCK_SIZE)); } /* * Allocate some memory, if possible */ byte* Pooling_Allocator::Memory_Block::alloc(size_t n) { if(n == 0 || n > BITMAP_SIZE) return 0; if(n == BITMAP_SIZE) { if(bitmap) return 0; else { bitmap = ~bitmap; return buffer; } } bitmap_type mask = (static_cast(1) << n) - 1; size_t offset = 0; while(bitmap & mask) { mask <<= 1; ++offset; if((bitmap & mask) == 0) break; if(mask >> 63) break; } if(bitmap & mask) return 0; bitmap |= mask; return buffer + offset * BLOCK_SIZE; } /* * Mark this memory as free, if we own it */ void Pooling_Allocator::Memory_Block::free(void* ptr, size_t blocks) { clear_mem(static_cast(ptr), blocks * BLOCK_SIZE); const size_t offset = (static_cast(ptr) - buffer) / BLOCK_SIZE; if(offset == 0 && blocks == BITMAP_SIZE) bitmap = ~bitmap; else { for(size_t j = 0; j != blocks; ++j) bitmap &= ~(static_cast(1) << (j+offset)); } } /* * Pooling_Allocator Constructor */ Pooling_Allocator::Pooling_Allocator(Mutex* m) : mutex(m) { last_used = blocks.begin(); } /* * Pooling_Allocator Destructor */ Pooling_Allocator::~Pooling_Allocator() { delete mutex; if(blocks.size()) throw Invalid_State("Pooling_Allocator: Never released memory"); } /* * Free all remaining memory */ void Pooling_Allocator::destroy() { Mutex_Holder lock(mutex); blocks.clear(); for(size_t j = 0; j != allocated.size(); ++j) dealloc_block(allocated[j].first, allocated[j].second); allocated.clear(); } /* * Allocation */ void* Pooling_Allocator::allocate(size_t n) { const size_t BITMAP_SIZE = Memory_Block::bitmap_size(); const size_t BLOCK_SIZE = Memory_Block::block_size(); Mutex_Holder lock(mutex); if(n <= BITMAP_SIZE * BLOCK_SIZE) { const size_t block_no = round_up(n, BLOCK_SIZE) / BLOCK_SIZE; byte* mem = allocate_blocks(block_no); if(mem) return mem; get_more_core(BOTAN_MEM_POOL_CHUNK_SIZE); mem = allocate_blocks(block_no); if(mem) return mem; throw Memory_Exhaustion(); } void* new_buf = alloc_block(n); if(new_buf) return new_buf; throw Memory_Exhaustion(); } /* * Deallocation */ void Pooling_Allocator::deallocate(void* ptr, size_t n) { const size_t BITMAP_SIZE = Memory_Block::bitmap_size(); const size_t BLOCK_SIZE = Memory_Block::block_size(); if(ptr == 0 && n == 0) return; Mutex_Holder lock(mutex); if(n > BITMAP_SIZE * BLOCK_SIZE) dealloc_block(ptr, n); else { const size_t block_no = round_up(n, BLOCK_SIZE) / BLOCK_SIZE; std::vector::iterator i = std::lower_bound(blocks.begin(), blocks.end(), Memory_Block(ptr)); if(i == blocks.end() || !i->contains(ptr, block_no)) throw Invalid_State("Pointer released to the wrong allocator"); i->free(ptr, block_no); } } /* * Try to get some memory from an existing block */ byte* Pooling_Allocator::allocate_blocks(size_t n) { if(blocks.empty()) return 0; std::vector::iterator i = last_used; do { byte* mem = i->alloc(n); if(mem) { last_used = i; return mem; } ++i; if(i == blocks.end()) i = blocks.begin(); } while(i != last_used); return 0; } /* * Allocate more memory for the pool */ void Pooling_Allocator::get_more_core(size_t in_bytes) { const size_t BITMAP_SIZE = Memory_Block::bitmap_size(); const size_t BLOCK_SIZE = Memory_Block::block_size(); const size_t TOTAL_BLOCK_SIZE = BLOCK_SIZE * BITMAP_SIZE; // upper bound on allocation is 1 MiB in_bytes = std::min(in_bytes, 1024 * 1024); const size_t in_blocks = round_up(in_bytes, BLOCK_SIZE) / TOTAL_BLOCK_SIZE; const size_t to_allocate = in_blocks * TOTAL_BLOCK_SIZE; void* ptr = alloc_block(to_allocate); if(ptr == 0) throw Memory_Exhaustion(); allocated.push_back(std::make_pair(ptr, to_allocate)); for(size_t j = 0; j != in_blocks; ++j) { byte* byte_ptr = static_cast(ptr); blocks.push_back(Memory_Block(byte_ptr + j * TOTAL_BLOCK_SIZE)); } std::sort(blocks.begin(), blocks.end()); last_used = std::lower_bound(blocks.begin(), blocks.end(), Memory_Block(ptr)); } } /* * Basic Allocators * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ #include #include namespace Botan { namespace { /* * Perform Memory Allocation */ void* do_malloc(size_t n, bool do_lock) { void* ptr = std::malloc(n); if(!ptr) return 0; if(do_lock) lock_mem(ptr, n); std::memset(ptr, 0, n); return ptr; } /* * Perform Memory Deallocation */ void do_free(void* ptr, size_t n, bool do_lock) { if(!ptr) return; std::memset(ptr, 0, n); if(do_lock) unlock_mem(ptr, n); std::free(ptr); } } /* * Malloc_Allocator's Allocation */ void* Malloc_Allocator::allocate(size_t n) { void* ptr = do_malloc(n, false); if(!ptr) throw Memory_Exhaustion(); return ptr; } /* * Malloc_Allocator's Deallocation */ void Malloc_Allocator::deallocate(void* ptr, size_t n) { do_free(ptr, n, false); } /* * Locking_Allocator's Allocation */ void* Locking_Allocator::alloc_block(size_t n) { return do_malloc(n, true); } /* * Locking_Allocator's Deallocation */ void Locking_Allocator::dealloc_block(void* ptr, size_t n) { do_free(ptr, n, true); } /* * Get an allocator */ Allocator* Allocator::get(bool locking) { std::string type = ""; if(!locking) type = "malloc"; Allocator* alloc = global_state().get_allocator(type); if(alloc) return alloc; throw Internal_Error("Couldn't find an allocator to use in get_allocator"); } } /* * Algorithm Identifier * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { /* * Create an AlgorithmIdentifier */ AlgorithmIdentifier::AlgorithmIdentifier(const OID& alg_id, const MemoryRegion& param) { oid = alg_id; parameters = param; } /* * Create an AlgorithmIdentifier */ AlgorithmIdentifier::AlgorithmIdentifier(const std::string& alg_id, const MemoryRegion& param) { oid = OIDS::lookup(alg_id); parameters = param; } /* * Create an AlgorithmIdentifier */ AlgorithmIdentifier::AlgorithmIdentifier(const OID& alg_id, Encoding_Option option) { const byte DER_NULL[] = { 0x05, 0x00 }; oid = alg_id; if(option == USE_NULL_PARAM) { parameters += std::pair(DER_NULL, sizeof(DER_NULL)); } } /* * Create an AlgorithmIdentifier */ AlgorithmIdentifier::AlgorithmIdentifier(const std::string& alg_id, Encoding_Option option) { const byte DER_NULL[] = { 0x05, 0x00 }; oid = OIDS::lookup(alg_id); if(option == USE_NULL_PARAM) { parameters += std::pair(DER_NULL, sizeof(DER_NULL)); } } /* * Compare two AlgorithmIdentifiers */ bool operator==(const AlgorithmIdentifier& a1, const AlgorithmIdentifier& a2) { if(a1.oid != a2.oid) return false; if(a1.parameters != a2.parameters) return false; return true; } /* * Compare two AlgorithmIdentifiers */ bool operator!=(const AlgorithmIdentifier& a1, const AlgorithmIdentifier& a2) { return !(a1 == a2); } /* * DER encode an AlgorithmIdentifier */ void AlgorithmIdentifier::encode_into(DER_Encoder& codec) const { codec.start_cons(SEQUENCE) .encode(oid) .raw_bytes(parameters) .end_cons(); } /* * Decode a BER encoded AlgorithmIdentifier */ void AlgorithmIdentifier::decode_from(BER_Decoder& codec) { codec.start_cons(SEQUENCE) .decode(oid) .raw_bytes(parameters) .end_cons(); } } /* * AlternativeName * (C) 1999-2007 Jack Lloyd * 2007 Yves Jerschow * * Distributed under the terms of the Botan license */ namespace Botan { namespace { /* * Check if type is a known ASN.1 string type */ bool is_string_type(ASN1_Tag tag) { return (tag == NUMERIC_STRING || tag == PRINTABLE_STRING || tag == VISIBLE_STRING || tag == T61_STRING || tag == IA5_STRING || tag == UTF8_STRING || tag == BMP_STRING); } } /* * Create an AlternativeName */ AlternativeName::AlternativeName(const std::string& email_addr, const std::string& uri, const std::string& dns, const std::string& ip) { add_attribute("RFC822", email_addr); add_attribute("DNS", dns); add_attribute("URI", uri); add_attribute("IP", ip); } /* * Add an attribute to an alternative name */ void AlternativeName::add_attribute(const std::string& type, const std::string& str) { if(type == "" || str == "") return; typedef std::multimap::iterator iter; std::pair range = alt_info.equal_range(type); for(iter j = range.first; j != range.second; ++j) if(j->second == str) return; multimap_insert(alt_info, type, str); } /* * Add an OtherName field */ void AlternativeName::add_othername(const OID& oid, const std::string& value, ASN1_Tag type) { if(value == "") return; multimap_insert(othernames, oid, ASN1_String(value, type)); } /* * Get the attributes of this alternative name */ std::multimap AlternativeName::get_attributes() const { return alt_info; } /* * Get the otherNames */ std::multimap AlternativeName::get_othernames() const { return othernames; } /* * Return all of the alternative names */ std::multimap AlternativeName::contents() const { std::multimap names; typedef std::multimap::const_iterator rdn_iter; for(rdn_iter j = alt_info.begin(); j != alt_info.end(); ++j) multimap_insert(names, j->first, j->second); typedef std::multimap::const_iterator on_iter; for(on_iter j = othernames.begin(); j != othernames.end(); ++j) multimap_insert(names, OIDS::lookup(j->first), j->second.value()); return names; } /* * Return if this object has anything useful */ bool AlternativeName::has_items() const { return (alt_info.size() > 0 || othernames.size() > 0); } namespace { /* * DER encode an AlternativeName entry */ void encode_entries(DER_Encoder& encoder, const std::multimap& attr, const std::string& type, ASN1_Tag tagging) { typedef std::multimap::const_iterator iter; std::pair range = attr.equal_range(type); for(iter j = range.first; j != range.second; ++j) { if(type == "RFC822" || type == "DNS" || type == "URI") { ASN1_String asn1_string(j->second, IA5_STRING); encoder.add_object(tagging, CONTEXT_SPECIFIC, asn1_string.iso_8859()); } else if(type == "IP") { const u32bit ip = string_to_ipv4(j->second); byte ip_buf[4] = { 0 }; store_be(ip, ip_buf); encoder.add_object(tagging, CONTEXT_SPECIFIC, ip_buf, 4); } } } } /* * DER encode an AlternativeName extension */ void AlternativeName::encode_into(DER_Encoder& der) const { der.start_cons(SEQUENCE); encode_entries(der, alt_info, "RFC822", ASN1_Tag(1)); encode_entries(der, alt_info, "DNS", ASN1_Tag(2)); encode_entries(der, alt_info, "URI", ASN1_Tag(6)); encode_entries(der, alt_info, "IP", ASN1_Tag(7)); std::multimap::const_iterator i; for(i = othernames.begin(); i != othernames.end(); ++i) { der.start_explicit(0) .encode(i->first) .start_explicit(0) .encode(i->second) .end_explicit() .end_explicit(); } der.end_cons(); } /* * Decode a BER encoded AlternativeName */ void AlternativeName::decode_from(BER_Decoder& source) { BER_Decoder names = source.start_cons(SEQUENCE); while(names.more_items()) { BER_Object obj = names.get_next_object(); if((obj.class_tag != CONTEXT_SPECIFIC) && (obj.class_tag != (CONTEXT_SPECIFIC | CONSTRUCTED))) continue; const ASN1_Tag tag = obj.type_tag; if(tag == 0) { BER_Decoder othername(obj.value); OID oid; othername.decode(oid); if(othername.more_items()) { BER_Object othername_value_outer = othername.get_next_object(); othername.verify_end(); if(othername_value_outer.type_tag != ASN1_Tag(0) || othername_value_outer.class_tag != (CONTEXT_SPECIFIC | CONSTRUCTED) ) throw Decoding_Error("Invalid tags on otherName value"); BER_Decoder othername_value_inner(othername_value_outer.value); BER_Object value = othername_value_inner.get_next_object(); othername_value_inner.verify_end(); const ASN1_Tag value_type = value.type_tag; if(is_string_type(value_type) && value.class_tag == UNIVERSAL) add_othername(oid, ASN1::to_string(value), value_type); } } else if(tag == 1 || tag == 2 || tag == 6) { const std::string value = Charset::transcode(ASN1::to_string(obj), LATIN1_CHARSET, LOCAL_CHARSET); if(tag == 1) add_attribute("RFC822", value); if(tag == 2) add_attribute("DNS", value); if(tag == 6) add_attribute("URI", value); } else if(tag == 7) { if(obj.value.size() == 4) { const u32bit ip = load_be(&obj.value[0], 0); add_attribute("IP", ipv4_to_string(ip)); } } } } } /* * Attribute * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { /* * Create an Attribute */ Attribute::Attribute(const OID& attr_oid, const MemoryRegion& attr_value) { oid = attr_oid; parameters = attr_value; } /* * Create an Attribute */ Attribute::Attribute(const std::string& attr_oid, const MemoryRegion& attr_value) { oid = OIDS::lookup(attr_oid); parameters = attr_value; } /* * DER encode a Attribute */ void Attribute::encode_into(DER_Encoder& codec) const { codec.start_cons(SEQUENCE) .encode(oid) .start_cons(SET) .raw_bytes(parameters) .end_cons() .end_cons(); } /* * Decode a BER encoded Attribute */ void Attribute::decode_from(BER_Decoder& codec) { codec.start_cons(SEQUENCE) .decode(oid) .start_cons(SET) .raw_bytes(parameters) .end_cons() .end_cons(); } } /* * ASN.1 Internals * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { /* * BER Decoding Exceptions */ BER_Decoding_Error::BER_Decoding_Error(const std::string& str) : Decoding_Error("BER: " + str) {} BER_Bad_Tag::BER_Bad_Tag(const std::string& str, ASN1_Tag tag) : BER_Decoding_Error(str + ": " + to_string(tag)) {} BER_Bad_Tag::BER_Bad_Tag(const std::string& str, ASN1_Tag tag1, ASN1_Tag tag2) : BER_Decoding_Error(str + ": " + to_string(tag1) + "/" + to_string(tag2)) {} namespace ASN1 { /* * Put some arbitrary bytes into a SEQUENCE */ SecureVector put_in_sequence(const MemoryRegion& contents) { return DER_Encoder() .start_cons(SEQUENCE) .raw_bytes(contents) .end_cons() .get_contents(); } /* * Convert a BER object into a string object */ std::string to_string(const BER_Object& obj) { return std::string(reinterpret_cast(&obj.value[0]), obj.value.size()); } /* * Do heuristic tests for BER data */ bool maybe_BER(DataSource& source) { byte first_byte; if(!source.peek_byte(first_byte)) throw Stream_IO_Error("ASN1::maybe_BER: Source was empty"); if(first_byte == (SEQUENCE | CONSTRUCTED)) return true; return false; } } } /* * ASN.1 OID * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { /* * ASN.1 OID Constructor */ OID::OID(const std::string& oid_str) { if(oid_str != "") { try { id = parse_asn1_oid(oid_str); } catch(...) { throw Invalid_OID(oid_str); } if(id.size() < 2 || id[0] > 2) throw Invalid_OID(oid_str); if((id[0] == 0 || id[0] == 1) && id[1] > 39) throw Invalid_OID(oid_str); } } /* * Clear the current OID */ void OID::clear() { id.clear(); } /* * Return this OID as a string */ std::string OID::as_string() const { std::string oid_str; for(size_t i = 0; i != id.size(); ++i) { oid_str += to_string(id[i]); if(i != id.size() - 1) oid_str += '.'; } return oid_str; } /* * OID equality comparison */ bool OID::operator==(const OID& oid) const { if(id.size() != oid.id.size()) return false; for(size_t i = 0; i != id.size(); ++i) if(id[i] != oid.id[i]) return false; return true; } /* * Append another component to the OID */ OID& OID::operator+=(u32bit component) { id.push_back(component); return (*this); } /* * Append another component to the OID */ OID operator+(const OID& oid, u32bit component) { OID new_oid(oid); new_oid += component; return new_oid; } /* * OID inequality comparison */ bool operator!=(const OID& a, const OID& b) { return !(a == b); } /* * Compare two OIDs */ bool operator<(const OID& a, const OID& b) { std::vector oid1 = a.get_id(); std::vector oid2 = b.get_id(); if(oid1.size() < oid2.size()) return true; if(oid1.size() > oid2.size()) return false; for(size_t i = 0; i != oid1.size(); ++i) { if(oid1[i] < oid2[i]) return true; if(oid1[i] > oid2[i]) return false; } return false; } /* * DER encode an OBJECT IDENTIFIER */ void OID::encode_into(DER_Encoder& der) const { if(id.size() < 2) throw Invalid_Argument("OID::encode_into: OID is invalid"); MemoryVector encoding; encoding.push_back(40 * id[0] + id[1]); for(size_t i = 2; i != id.size(); ++i) { if(id[i] == 0) encoding.push_back(0); else { size_t blocks = high_bit(id[i]) + 6; blocks = (blocks - (blocks % 7)) / 7; for(size_t j = 0; j != blocks - 1; ++j) encoding.push_back(0x80 | ((id[i] >> 7*(blocks-j-1)) & 0x7F)); encoding.push_back(id[i] & 0x7F); } } der.add_object(OBJECT_ID, UNIVERSAL, encoding); } /* * Decode a BER encoded OBJECT IDENTIFIER */ void OID::decode_from(BER_Decoder& decoder) { BER_Object obj = decoder.get_next_object(); if(obj.type_tag != OBJECT_ID || obj.class_tag != UNIVERSAL) throw BER_Bad_Tag("Error decoding OID, unknown tag", obj.type_tag, obj.class_tag); if(obj.value.size() < 2) throw BER_Decoding_Error("OID encoding is too short"); clear(); id.push_back(obj.value[0] / 40); id.push_back(obj.value[0] % 40); size_t i = 0; while(i != obj.value.size() - 1) { u32bit component = 0; while(i != obj.value.size() - 1) { ++i; component = (component << 7) + (obj.value[i] & 0x7F); if(!(obj.value[i] & 0x80)) break; } id.push_back(component); } } } /* * Simple ASN.1 String Types * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { namespace { /* * Choose an encoding for the string */ ASN1_Tag choose_encoding(const std::string& str, const std::string& type) { static const byte IS_PRINTABLE[256] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; for(size_t i = 0; i != str.size(); ++i) { if(!IS_PRINTABLE[static_cast(str[i])]) { if(type == "utf8") return UTF8_STRING; if(type == "latin1") return T61_STRING; throw Invalid_Argument("choose_encoding: Bad string type " + type); } } return PRINTABLE_STRING; } } /* * Create an ASN1_String */ ASN1_String::ASN1_String(const std::string& str, ASN1_Tag t) : tag(t) { iso_8859_str = Charset::transcode(str, LOCAL_CHARSET, LATIN1_CHARSET); if(tag == DIRECTORY_STRING) tag = choose_encoding(iso_8859_str, "latin1"); if(tag != NUMERIC_STRING && tag != PRINTABLE_STRING && tag != VISIBLE_STRING && tag != T61_STRING && tag != IA5_STRING && tag != UTF8_STRING && tag != BMP_STRING) throw Invalid_Argument("ASN1_String: Unknown string type " + to_string(tag)); } /* * Create an ASN1_String */ ASN1_String::ASN1_String(const std::string& str) { iso_8859_str = Charset::transcode(str, LOCAL_CHARSET, LATIN1_CHARSET); tag = choose_encoding(iso_8859_str, "latin1"); } /* * Return this string in ISO 8859-1 encoding */ std::string ASN1_String::iso_8859() const { return iso_8859_str; } /* * Return this string in local encoding */ std::string ASN1_String::value() const { return Charset::transcode(iso_8859_str, LATIN1_CHARSET, LOCAL_CHARSET); } /* * Return the type of this string object */ ASN1_Tag ASN1_String::tagging() const { return tag; } /* * DER encode an ASN1_String */ void ASN1_String::encode_into(DER_Encoder& encoder) const { std::string value = iso_8859(); if(tagging() == UTF8_STRING) value = Charset::transcode(value, LATIN1_CHARSET, UTF8_CHARSET); encoder.add_object(tagging(), UNIVERSAL, value); } /* * Decode a BER encoded ASN1_String */ void ASN1_String::decode_from(BER_Decoder& source) { BER_Object obj = source.get_next_object(); Character_Set charset_is; if(obj.type_tag == BMP_STRING) charset_is = UCS2_CHARSET; else if(obj.type_tag == UTF8_STRING) charset_is = UTF8_CHARSET; else charset_is = LATIN1_CHARSET; *this = ASN1_String( Charset::transcode(ASN1::to_string(obj), charset_is, LOCAL_CHARSET), obj.type_tag); } } /* * X.509 Time Types * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { /* * Create an X509_Time */ X509_Time::X509_Time(const std::string& time_str) { set_to(time_str); } /* * Create an X509_Time */ X509_Time::X509_Time(u64bit timer) { calendar_point cal = calendar_value(timer); year = cal.year; month = cal.month; day = cal.day; hour = cal.hour; minute = cal.minutes; second = cal.seconds; tag = (year >= 2050) ? GENERALIZED_TIME : UTC_TIME; } /* * Create an X509_Time */ X509_Time::X509_Time(const std::string& t_spec, ASN1_Tag t) : tag(t) { set_to(t_spec, tag); } /* * Set the time with a human readable string */ void X509_Time::set_to(const std::string& time_str) { if(time_str == "") { year = month = day = hour = minute = second = 0; tag = NO_OBJECT; return; } std::vector params; std::string current; for(size_t j = 0; j != time_str.size(); ++j) { if(Charset::is_digit(time_str[j])) current += time_str[j]; else { if(current != "") params.push_back(current); current.clear(); } } if(current != "") params.push_back(current); if(params.size() < 3 || params.size() > 6) throw Invalid_Argument("Invalid time specification " + time_str); year = to_u32bit(params[0]); month = to_u32bit(params[1]); day = to_u32bit(params[2]); hour = (params.size() >= 4) ? to_u32bit(params[3]) : 0; minute = (params.size() >= 5) ? to_u32bit(params[4]) : 0; second = (params.size() == 6) ? to_u32bit(params[5]) : 0; tag = (year >= 2050) ? GENERALIZED_TIME : UTC_TIME; if(!passes_sanity_check()) throw Invalid_Argument("Invalid time specification " + time_str); } /* * Set the time with an ISO time format string */ void X509_Time::set_to(const std::string& t_spec, ASN1_Tag spec_tag) { if(spec_tag != GENERALIZED_TIME && spec_tag != UTC_TIME) throw Invalid_Argument("X509_Time: Invalid tag " + to_string(spec_tag)); if(spec_tag == GENERALIZED_TIME && t_spec.size() != 13 && t_spec.size() != 15) throw Invalid_Argument("Invalid GeneralizedTime: " + t_spec); if(spec_tag == UTC_TIME && t_spec.size() != 11 && t_spec.size() != 13) throw Invalid_Argument("Invalid UTCTime: " + t_spec); if(t_spec[t_spec.size()-1] != 'Z') throw Invalid_Argument("Invalid time encoding: " + t_spec); const size_t YEAR_SIZE = (spec_tag == UTC_TIME) ? 2 : 4; std::vector params; std::string current; for(size_t j = 0; j != YEAR_SIZE; ++j) current += t_spec[j]; params.push_back(current); current.clear(); for(size_t j = YEAR_SIZE; j != t_spec.size() - 1; ++j) { current += t_spec[j]; if(current.size() == 2) { params.push_back(current); current.clear(); } } year = to_u32bit(params[0]); month = to_u32bit(params[1]); day = to_u32bit(params[2]); hour = to_u32bit(params[3]); minute = to_u32bit(params[4]); second = (params.size() == 6) ? to_u32bit(params[5]) : 0; tag = spec_tag; if(spec_tag == UTC_TIME) { if(year >= 50) year += 1900; else year += 2000; } if(!passes_sanity_check()) throw Invalid_Argument("Invalid time specification " + t_spec); } /* * DER encode a X509_Time */ void X509_Time::encode_into(DER_Encoder& der) const { if(tag != GENERALIZED_TIME && tag != UTC_TIME) throw Invalid_Argument("X509_Time: Bad encoding tag"); der.add_object(tag, UNIVERSAL, Charset::transcode(as_string(), LOCAL_CHARSET, LATIN1_CHARSET)); } /* * Decode a BER encoded X509_Time */ void X509_Time::decode_from(BER_Decoder& source) { BER_Object ber_time = source.get_next_object(); set_to(Charset::transcode(ASN1::to_string(ber_time), LATIN1_CHARSET, LOCAL_CHARSET), ber_time.type_tag); } /* * Return a string representation of the time */ std::string X509_Time::as_string() const { if(time_is_set() == false) throw Invalid_State("X509_Time::as_string: No time set"); std::string asn1rep; if(tag == GENERALIZED_TIME) asn1rep = to_string(year, 4); else if(tag == UTC_TIME) { if(year < 1950 || year >= 2050) throw Encoding_Error("X509_Time: The time " + readable_string() + " cannot be encoded as a UTCTime"); u32bit asn1year = (year >= 2000) ? (year - 2000) : (year - 1900); asn1rep = to_string(asn1year, 2); } else throw Invalid_Argument("X509_Time: Invalid tag " + to_string(tag)); asn1rep += to_string(month, 2) + to_string(day, 2); asn1rep += to_string(hour, 2) + to_string(minute, 2) + to_string(second, 2); asn1rep += "Z"; return asn1rep; } /* * Return if the time has been set somehow */ bool X509_Time::time_is_set() const { return (year != 0); } /* * Return a human readable string representation */ std::string X509_Time::readable_string() const { if(time_is_set() == false) throw Invalid_State("X509_Time::readable_string: No time set"); std::string readable; readable += to_string(year, 4) + "/"; readable += to_string(month ) + "/"; readable += to_string(day ) + " "; readable += to_string(hour ) + ":"; readable += to_string(minute, 2) + ":"; readable += to_string(second, 2) + " UTC"; return readable; } /* * Do a general sanity check on the time */ bool X509_Time::passes_sanity_check() const { if(year < 1950 || year > 2100) return false; if(month == 0 || month > 12) return false; if(day == 0 || day > 31) return false; if(hour >= 24 || minute > 60 || second > 60) return false; return true; } /* * Compare this time against another */ s32bit X509_Time::cmp(const X509_Time& other) const { if(time_is_set() == false) throw Invalid_State("X509_Time::cmp: No time set"); const s32bit EARLIER = -1, LATER = 1, SAME_TIME = 0; if(year < other.year) return EARLIER; if(year > other.year) return LATER; if(month < other.month) return EARLIER; if(month > other.month) return LATER; if(day < other.day) return EARLIER; if(day > other.day) return LATER; if(hour < other.hour) return EARLIER; if(hour > other.hour) return LATER; if(minute < other.minute) return EARLIER; if(minute > other.minute) return LATER; if(second < other.second) return EARLIER; if(second > other.second) return LATER; return SAME_TIME; } /* * Compare two X509_Times for in various ways */ bool operator==(const X509_Time& t1, const X509_Time& t2) { return (t1.cmp(t2) == 0); } bool operator!=(const X509_Time& t1, const X509_Time& t2) { return (t1.cmp(t2) != 0); } bool operator<=(const X509_Time& t1, const X509_Time& t2) { return (t1.cmp(t2) <= 0); } bool operator>=(const X509_Time& t1, const X509_Time& t2) { return (t1.cmp(t2) >= 0); } bool operator<(const X509_Time& t1, const X509_Time& t2) { return (t1.cmp(t2) < 0); } bool operator>(const X509_Time& t1, const X509_Time& t2) { return (t1.cmp(t2) > 0); } } /* * BER Decoder * (C) 1999-2008 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { namespace { /* * BER decode an ASN.1 type tag */ size_t decode_tag(DataSource* ber, ASN1_Tag& type_tag, ASN1_Tag& class_tag) { byte b; if(!ber->read_byte(b)) { class_tag = type_tag = NO_OBJECT; return 0; } if((b & 0x1F) != 0x1F) { type_tag = ASN1_Tag(b & 0x1F); class_tag = ASN1_Tag(b & 0xE0); return 1; } size_t tag_bytes = 1; class_tag = ASN1_Tag(b & 0xE0); size_t tag_buf = 0; while(true) { if(!ber->read_byte(b)) throw BER_Decoding_Error("Long-form tag truncated"); if(tag_buf & 0xFF000000) throw BER_Decoding_Error("Long-form tag overflowed 32 bits"); ++tag_bytes; tag_buf = (tag_buf << 7) | (b & 0x7F); if((b & 0x80) == 0) break; } type_tag = ASN1_Tag(tag_buf); return tag_bytes; } /* * Find the EOC marker */ size_t find_eoc(DataSource*); /* * BER decode an ASN.1 length field */ size_t decode_length(DataSource* ber, size_t& field_size) { byte b; if(!ber->read_byte(b)) throw BER_Decoding_Error("Length field not found"); field_size = 1; if((b & 0x80) == 0) return b; field_size += (b & 0x7F); if(field_size == 1) return find_eoc(ber); if(field_size > 5) throw BER_Decoding_Error("Length field is too large"); size_t length = 0; for(size_t i = 0; i != field_size - 1; ++i) { if(get_byte(0, length) != 0) throw BER_Decoding_Error("Field length overflow"); if(!ber->read_byte(b)) throw BER_Decoding_Error("Corrupted length field"); length = (length << 8) | b; } return length; } /* * BER decode an ASN.1 length field */ size_t decode_length(DataSource* ber) { size_t dummy; return decode_length(ber, dummy); } /* * Find the EOC marker */ size_t find_eoc(DataSource* ber) { SecureVector buffer(DEFAULT_BUFFERSIZE), data; while(true) { const size_t got = ber->peek(&buffer[0], buffer.size(), data.size()); if(got == 0) break; data += std::make_pair(&buffer[0], got); } DataSource_Memory source(data); data.clear(); size_t length = 0; while(true) { ASN1_Tag type_tag, class_tag; size_t tag_size = decode_tag(&source, type_tag, class_tag); if(type_tag == NO_OBJECT) break; size_t length_size = 0; size_t item_size = decode_length(&source, length_size); source.discard_next(item_size); length += item_size + length_size + tag_size; if(type_tag == EOC) break; } return length; } } /* * Check a type invariant on BER data */ void BER_Object::assert_is_a(ASN1_Tag type_tag, ASN1_Tag class_tag) { if(this->type_tag != type_tag || this->class_tag != class_tag) throw BER_Decoding_Error("Tag mismatch when decoding"); } /* * Check if more objects are there */ bool BER_Decoder::more_items() const { if(source->end_of_data() && (pushed.type_tag == NO_OBJECT)) return false; return true; } /* * Verify that no bytes remain in the source */ BER_Decoder& BER_Decoder::verify_end() { if(!source->end_of_data() || (pushed.type_tag != NO_OBJECT)) throw Invalid_State("BER_Decoder::verify_end called, but data remains"); return (*this); } /* * Save all the bytes remaining in the source */ BER_Decoder& BER_Decoder::raw_bytes(MemoryRegion& out) { out.clear(); byte buf; while(source->read_byte(buf)) out.push_back(buf); return (*this); } /* * Discard all the bytes remaining in the source */ BER_Decoder& BER_Decoder::discard_remaining() { byte buf; while(source->read_byte(buf)) ; return (*this); } /* * Return the BER encoding of the next object */ BER_Object BER_Decoder::get_next_object() { BER_Object next; if(pushed.type_tag != NO_OBJECT) { next = pushed; pushed.class_tag = pushed.type_tag = NO_OBJECT; return next; } decode_tag(source, next.type_tag, next.class_tag); if(next.type_tag == NO_OBJECT) return next; size_t length = decode_length(source); next.value.resize(length); if(source->read(&next.value[0], length) != length) throw BER_Decoding_Error("Value truncated"); if(next.type_tag == EOC && next.class_tag == UNIVERSAL) return get_next_object(); return next; } /* * Push a object back into the stream */ void BER_Decoder::push_back(const BER_Object& obj) { if(pushed.type_tag != NO_OBJECT) throw Invalid_State("BER_Decoder: Only one push back is allowed"); pushed = obj; } /* * Begin decoding a CONSTRUCTED type */ BER_Decoder BER_Decoder::start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag) { BER_Object obj = get_next_object(); obj.assert_is_a(type_tag, ASN1_Tag(class_tag | CONSTRUCTED)); BER_Decoder result(&obj.value[0], obj.value.size()); result.parent = this; return result; } /* * Finish decoding a CONSTRUCTED type */ BER_Decoder& BER_Decoder::end_cons() { if(!parent) throw Invalid_State("BER_Decoder::end_cons called with NULL parent"); if(!source->end_of_data()) throw Decoding_Error("BER_Decoder::end_cons called with data left"); return (*parent); } /* * BER_Decoder Constructor */ BER_Decoder::BER_Decoder(DataSource& src) { source = &src; owns = false; pushed.type_tag = pushed.class_tag = NO_OBJECT; parent = 0; } /* * BER_Decoder Constructor */ BER_Decoder::BER_Decoder(const byte data[], size_t length) { source = new DataSource_Memory(data, length); owns = true; pushed.type_tag = pushed.class_tag = NO_OBJECT; parent = 0; } /* * BER_Decoder Constructor */ BER_Decoder::BER_Decoder(const MemoryRegion& data) { source = new DataSource_Memory(data); owns = true; pushed.type_tag = pushed.class_tag = NO_OBJECT; parent = 0; } /* * BER_Decoder Copy Constructor */ BER_Decoder::BER_Decoder(const BER_Decoder& other) { source = other.source; owns = false; if(other.owns) { other.owns = false; owns = true; } pushed.type_tag = pushed.class_tag = NO_OBJECT; parent = other.parent; } /* * BER_Decoder Destructor */ BER_Decoder::~BER_Decoder() { if(owns) delete source; source = 0; } /* * Request for an object to decode itself */ BER_Decoder& BER_Decoder::decode(ASN1_Object& obj) { obj.decode_from(*this); return (*this); } /* * Decode a BER encoded NULL */ BER_Decoder& BER_Decoder::decode_null() { BER_Object obj = get_next_object(); obj.assert_is_a(NULL_TAG, UNIVERSAL); if(obj.value.size()) throw BER_Decoding_Error("NULL object had nonzero size"); return (*this); } /* * Decode a BER encoded BOOLEAN */ BER_Decoder& BER_Decoder::decode(bool& out) { return decode(out, BOOLEAN, UNIVERSAL); } /* * Decode a small BER encoded INTEGER */ BER_Decoder& BER_Decoder::decode(size_t& out) { return decode(out, INTEGER, UNIVERSAL); } /* * Decode a BER encoded INTEGER */ BER_Decoder& BER_Decoder::decode(BigInt& out) { return decode(out, INTEGER, UNIVERSAL); } BER_Decoder& BER_Decoder::decode_octet_string_bigint(BigInt& out) { SecureVector out_vec; decode(out_vec, OCTET_STRING); out = BigInt::decode(&out_vec[0], out_vec.size()); return (*this); } /* * Decode a BER encoded BOOLEAN */ BER_Decoder& BER_Decoder::decode(bool& out, ASN1_Tag type_tag, ASN1_Tag class_tag) { BER_Object obj = get_next_object(); obj.assert_is_a(type_tag, class_tag); if(obj.value.size() != 1) throw BER_Decoding_Error("BER boolean value had invalid size"); out = (obj.value[0]) ? true : false; return (*this); } /* * Decode a small BER encoded INTEGER */ BER_Decoder& BER_Decoder::decode(size_t& out, ASN1_Tag type_tag, ASN1_Tag class_tag) { BigInt integer; decode(integer, type_tag, class_tag); if(integer.bits() > 32) throw BER_Decoding_Error("Decoded integer value larger than expected"); out = 0; for(size_t i = 0; i != 4; ++i) out = (out << 8) | integer.byte_at(3-i); return (*this); } /* * Decode a BER encoded INTEGER */ BER_Decoder& BER_Decoder::decode(BigInt& out, ASN1_Tag type_tag, ASN1_Tag class_tag) { BER_Object obj = get_next_object(); obj.assert_is_a(type_tag, class_tag); if(obj.value.empty()) out = 0; else { const bool negative = (obj.value[0] & 0x80) ? true : false; if(negative) { for(size_t i = obj.value.size(); i > 0; --i) if(obj.value[i-1]--) break; for(size_t i = 0; i != obj.value.size(); ++i) obj.value[i] = ~obj.value[i]; } out = BigInt(&obj.value[0], obj.value.size()); if(negative) out.flip_sign(); } return (*this); } /* * BER decode a BIT STRING or OCTET STRING */ BER_Decoder& BER_Decoder::decode(MemoryRegion& out, ASN1_Tag real_type) { return decode(out, real_type, real_type, UNIVERSAL); } /* * BER decode a BIT STRING or OCTET STRING */ BER_Decoder& BER_Decoder::decode(MemoryRegion& buffer, ASN1_Tag real_type, ASN1_Tag type_tag, ASN1_Tag class_tag) { if(real_type != OCTET_STRING && real_type != BIT_STRING) throw BER_Bad_Tag("Bad tag for {BIT,OCTET} STRING", real_type); BER_Object obj = get_next_object(); obj.assert_is_a(type_tag, class_tag); if(real_type == OCTET_STRING) buffer = obj.value; else { if(obj.value[0] >= 8) throw BER_Decoding_Error("Bad number of unused bits in BIT STRING"); buffer.resize(obj.value.size() - 1); copy_mem(&buffer[0], &obj.value[1], obj.value.size() - 1); } return (*this); } /* * Decode an OPTIONAL string type */ BER_Decoder& BER_Decoder::decode_optional_string(MemoryRegion& out, ASN1_Tag real_type, u16bit type_no) { BER_Object obj = get_next_object(); ASN1_Tag type_tag = static_cast(type_no); out.clear(); push_back(obj); if(obj.type_tag == type_tag && obj.class_tag == CONTEXT_SPECIFIC) decode(out, real_type, type_tag, CONTEXT_SPECIFIC); return (*this); } } /* * DER Encoder * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ #include namespace Botan { namespace { /* * DER encode an ASN.1 type tag */ SecureVector encode_tag(ASN1_Tag type_tag, ASN1_Tag class_tag) { if((class_tag | 0xE0) != 0xE0) throw Encoding_Error("DER_Encoder: Invalid class tag " + to_string(class_tag)); SecureVector encoded_tag; if(type_tag <= 30) encoded_tag.push_back(static_cast(type_tag | class_tag)); else { size_t blocks = high_bit(type_tag) + 6; blocks = (blocks - (blocks % 7)) / 7; encoded_tag.push_back(class_tag | 0x1F); for(size_t i = 0; i != blocks - 1; ++i) encoded_tag.push_back(0x80 | ((type_tag >> 7*(blocks-i-1)) & 0x7F)); encoded_tag.push_back(type_tag & 0x7F); } return encoded_tag; } /* * DER encode an ASN.1 length field */ SecureVector encode_length(size_t length) { SecureVector encoded_length; if(length <= 127) encoded_length.push_back(static_cast(length)); else { const size_t top_byte = significant_bytes(length); encoded_length.push_back(static_cast(0x80 | top_byte)); for(size_t i = sizeof(length) - top_byte; i != sizeof(length); ++i) encoded_length.push_back(get_byte(i, length)); } return encoded_length; } } /* * Return the encoded SEQUENCE/SET */ SecureVector DER_Encoder::DER_Sequence::get_contents() { const ASN1_Tag real_class_tag = ASN1_Tag(class_tag | CONSTRUCTED); if(type_tag == SET) { std::sort(set_contents.begin(), set_contents.end()); for(size_t i = 0; i != set_contents.size(); ++i) contents += set_contents[i]; set_contents.clear(); } SecureVector result; result += encode_tag(type_tag, real_class_tag); result += encode_length(contents.size()); result += contents; contents.clear(); return result; } /* * Add an encoded value to the SEQUENCE/SET */ void DER_Encoder::DER_Sequence::add_bytes(const byte data[], size_t length) { if(type_tag == SET) set_contents.push_back(SecureVector(data, length)); else contents += std::make_pair(data, length); } /* * Return the type and class taggings */ ASN1_Tag DER_Encoder::DER_Sequence::tag_of() const { return ASN1_Tag(type_tag | class_tag); } /* * DER_Sequence Constructor */ DER_Encoder::DER_Sequence::DER_Sequence(ASN1_Tag t1, ASN1_Tag t2) : type_tag(t1), class_tag(t2) { } /* * Return the encoded contents */ SecureVector DER_Encoder::get_contents() { if(subsequences.size() != 0) throw Invalid_State("DER_Encoder: Sequence hasn't been marked done"); SecureVector output; std::swap(output, contents); return output; } /* * Start a new ASN.1 SEQUENCE/SET/EXPLICIT */ DER_Encoder& DER_Encoder::start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag) { subsequences.push_back(DER_Sequence(type_tag, class_tag)); return (*this); } /* * Finish the current ASN.1 SEQUENCE/SET/EXPLICIT */ DER_Encoder& DER_Encoder::end_cons() { if(subsequences.empty()) throw Invalid_State("DER_Encoder::end_cons: No such sequence"); SecureVector seq = subsequences[subsequences.size()-1].get_contents(); subsequences.pop_back(); raw_bytes(seq); return (*this); } /* * Start a new ASN.1 EXPLICIT encoding */ DER_Encoder& DER_Encoder::start_explicit(u16bit type_no) { ASN1_Tag type_tag = static_cast(type_no); if(type_tag == SET) throw Internal_Error("DER_Encoder.start_explicit(SET); cannot perform"); return start_cons(type_tag, CONTEXT_SPECIFIC); } /* * Finish the current ASN.1 EXPLICIT encoding */ DER_Encoder& DER_Encoder::end_explicit() { return end_cons(); } /* * Write raw bytes into the stream */ DER_Encoder& DER_Encoder::raw_bytes(const MemoryRegion& val) { return raw_bytes(&val[0], val.size()); } /* * Write raw bytes into the stream */ DER_Encoder& DER_Encoder::raw_bytes(const byte bytes[], size_t length) { if(subsequences.size()) subsequences[subsequences.size()-1].add_bytes(bytes, length); else contents += std::make_pair(bytes, length); return (*this); } /* * Encode a NULL object */ DER_Encoder& DER_Encoder::encode_null() { return add_object(NULL_TAG, UNIVERSAL, 0, 0); } /* * DER encode a BOOLEAN */ DER_Encoder& DER_Encoder::encode(bool is_true) { return encode(is_true, BOOLEAN, UNIVERSAL); } /* * DER encode a small INTEGER */ DER_Encoder& DER_Encoder::encode(size_t n) { return encode(BigInt(n), INTEGER, UNIVERSAL); } /* * DER encode a small INTEGER */ DER_Encoder& DER_Encoder::encode(const BigInt& n) { return encode(n, INTEGER, UNIVERSAL); } /* * DER encode an OCTET STRING or BIT STRING */ DER_Encoder& DER_Encoder::encode(const MemoryRegion& bytes, ASN1_Tag real_type) { return encode(&bytes[0], bytes.size(), real_type, real_type, UNIVERSAL); } /* * Encode this object */ DER_Encoder& DER_Encoder::encode(const byte bytes[], size_t length, ASN1_Tag real_type) { return encode(bytes, length, real_type, real_type, UNIVERSAL); } /* * DER encode a BOOLEAN */ DER_Encoder& DER_Encoder::encode(bool is_true, ASN1_Tag type_tag, ASN1_Tag class_tag) { byte val = is_true ? 0xFF : 0x00; return add_object(type_tag, class_tag, &val, 1); } /* * DER encode a small INTEGER */ DER_Encoder& DER_Encoder::encode(size_t n, ASN1_Tag type_tag, ASN1_Tag class_tag) { return encode(BigInt(n), type_tag, class_tag); } /* * DER encode an INTEGER */ DER_Encoder& DER_Encoder::encode(const BigInt& n, ASN1_Tag type_tag, ASN1_Tag class_tag) { if(n == 0) return add_object(type_tag, class_tag, 0); bool extra_zero = (n.bits() % 8 == 0); SecureVector contents(extra_zero + n.bytes()); BigInt::encode(&contents[extra_zero], n); if(n < 0) { for(size_t i = 0; i != contents.size(); ++i) contents[i] = ~contents[i]; for(size_t i = contents.size(); i > 0; --i) if(++contents[i-1]) break; } return add_object(type_tag, class_tag, contents); } /* * DER encode an OCTET STRING or BIT STRING */ DER_Encoder& DER_Encoder::encode(const MemoryRegion& bytes, ASN1_Tag real_type, ASN1_Tag type_tag, ASN1_Tag class_tag) { return encode(&bytes[0], bytes.size(), real_type, type_tag, class_tag); } /* * DER encode an OCTET STRING or BIT STRING */ DER_Encoder& DER_Encoder::encode(const byte bytes[], size_t length, ASN1_Tag real_type, ASN1_Tag type_tag, ASN1_Tag class_tag) { if(real_type != OCTET_STRING && real_type != BIT_STRING) throw Invalid_Argument("DER_Encoder: Invalid tag for byte/bit string"); if(real_type == BIT_STRING) { SecureVector encoded; encoded.push_back(0); encoded += std::make_pair(bytes, length); return add_object(type_tag, class_tag, encoded); } else return add_object(type_tag, class_tag, bytes, length); } /* * Conditionally write some values to the stream */ DER_Encoder& DER_Encoder::encode_if(bool cond, DER_Encoder& codec) { if(cond) return raw_bytes(codec.get_contents()); return (*this); } /* * Request for an object to encode itself */ DER_Encoder& DER_Encoder::encode(const ASN1_Object& obj) { obj.encode_into(*this); return (*this); } /* * Write the encoding of the byte(s) */ DER_Encoder& DER_Encoder::add_object(ASN1_Tag type_tag, ASN1_Tag class_tag, const byte rep[], size_t length) { SecureVector buffer; buffer += encode_tag(type_tag, class_tag); buffer += encode_length(length); buffer += std::make_pair(rep, length); return raw_bytes(buffer); } /* * Write the encoding of the byte(s) */ DER_Encoder& DER_Encoder::add_object(ASN1_Tag type_tag, ASN1_Tag class_tag, const MemoryRegion& rep_buf) { const byte* rep = &rep_buf[0]; const size_t rep_len = rep_buf.size(); return add_object(type_tag, class_tag, rep, rep_len); } /* * Write the encoding of the byte(s) */ DER_Encoder& DER_Encoder::add_object(ASN1_Tag type_tag, ASN1_Tag class_tag, const std::string& rep_str) { const byte* rep = reinterpret_cast(rep_str.data()); const size_t rep_len = rep_str.size(); return add_object(type_tag, class_tag, rep, rep_len); } /* * Write the encoding of the byte */ DER_Encoder& DER_Encoder::add_object(ASN1_Tag type_tag, ASN1_Tag class_tag, byte rep) { return add_object(type_tag, class_tag, &rep, 1); } } /* * X509_DN * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { /* * Create an empty X509_DN */ X509_DN::X509_DN() { } /* * Create an X509_DN */ X509_DN::X509_DN(const std::multimap& args) { std::multimap::const_iterator j; for(j = args.begin(); j != args.end(); ++j) add_attribute(j->first, j->second); } /* * Create an X509_DN */ X509_DN::X509_DN(const std::multimap& args) { std::multimap::const_iterator j; for(j = args.begin(); j != args.end(); ++j) add_attribute(OIDS::lookup(j->first), j->second); } /* * Add an attribute to a X509_DN */ void X509_DN::add_attribute(const std::string& type, const std::string& str) { OID oid = OIDS::lookup(type); add_attribute(oid, str); } /* * Add an attribute to a X509_DN */ void X509_DN::add_attribute(const OID& oid, const std::string& str) { if(str == "") return; typedef std::multimap::iterator rdn_iter; std::pair range = dn_info.equal_range(oid); for(rdn_iter j = range.first; j != range.second; ++j) if(j->second.value() == str) return; multimap_insert(dn_info, oid, ASN1_String(str)); dn_bits.clear(); } /* * Get the attributes of this X509_DN */ std::multimap X509_DN::get_attributes() const { typedef std::multimap::const_iterator rdn_iter; std::multimap retval; for(rdn_iter j = dn_info.begin(); j != dn_info.end(); ++j) multimap_insert(retval, j->first, j->second.value()); return retval; } /* * Get the contents of this X.500 Name */ std::multimap X509_DN::contents() const { typedef std::multimap::const_iterator rdn_iter; std::multimap retval; for(rdn_iter j = dn_info.begin(); j != dn_info.end(); ++j) multimap_insert(retval, OIDS::lookup(j->first), j->second.value()); return retval; } /* * Get a single attribute type */ std::vector X509_DN::get_attribute(const std::string& attr) const { typedef std::multimap::const_iterator rdn_iter; const OID oid = OIDS::lookup(deref_info_field(attr)); std::pair range = dn_info.equal_range(oid); std::vector values; for(rdn_iter j = range.first; j != range.second; ++j) values.push_back(j->second.value()); return values; } /* * Return the BER encoded data, if any */ MemoryVector X509_DN::get_bits() const { return dn_bits; } /* * Deref aliases in a subject/issuer info request */ std::string X509_DN::deref_info_field(const std::string& info) { if(info == "Name" || info == "CommonName") return "X520.CommonName"; if(info == "SerialNumber") return "X520.SerialNumber"; if(info == "Country") return "X520.Country"; if(info == "Organization") return "X520.Organization"; if(info == "Organizational Unit" || info == "OrgUnit") return "X520.OrganizationalUnit"; if(info == "Locality") return "X520.Locality"; if(info == "State" || info == "Province") return "X520.State"; if(info == "Email") return "RFC822"; return info; } /* * Compare two X509_DNs for equality */ bool operator==(const X509_DN& dn1, const X509_DN& dn2) { typedef std::multimap::const_iterator rdn_iter; std::multimap attr1 = dn1.get_attributes(); std::multimap attr2 = dn2.get_attributes(); if(attr1.size() != attr2.size()) return false; rdn_iter p1 = attr1.begin(); rdn_iter p2 = attr2.begin(); while(true) { if(p1 == attr1.end() && p2 == attr2.end()) break; if(p1 == attr1.end()) return false; if(p2 == attr2.end()) return false; if(p1->first != p2->first) return false; if(!x500_name_cmp(p1->second, p2->second)) return false; ++p1; ++p2; } return true; } /* * Compare two X509_DNs for inequality */ bool operator!=(const X509_DN& dn1, const X509_DN& dn2) { return !(dn1 == dn2); } /* * Compare two X509_DNs */ bool operator<(const X509_DN& dn1, const X509_DN& dn2) { typedef std::multimap::const_iterator rdn_iter; std::multimap attr1 = dn1.get_attributes(); std::multimap attr2 = dn2.get_attributes(); if(attr1.size() < attr2.size()) return true; if(attr1.size() > attr2.size()) return false; for(rdn_iter p1 = attr1.begin(); p1 != attr1.end(); ++p1) { std::multimap::const_iterator p2; p2 = attr2.find(p1->first); if(p2 == attr2.end()) return false; if(p1->second > p2->second) return false; if(p1->second < p2->second) return true; } return false; } namespace { /* * DER encode a RelativeDistinguishedName */ void do_ava(DER_Encoder& encoder, const std::multimap& dn_info, ASN1_Tag string_type, const std::string& oid_str, bool must_exist = false) { typedef std::multimap::const_iterator rdn_iter; const OID oid = OIDS::lookup(oid_str); const bool exists = (dn_info.find(oid) != dn_info.end()); if(!exists && must_exist) throw Encoding_Error("X509_DN: No entry for " + oid_str); if(!exists) return; std::pair range = dn_info.equal_range(oid); for(rdn_iter j = range.first; j != range.second; ++j) { encoder.start_cons(SET) .start_cons(SEQUENCE) .encode(oid) .encode(ASN1_String(j->second, string_type)) .end_cons() .end_cons(); } } } /* * DER encode a DistinguishedName */ void X509_DN::encode_into(DER_Encoder& der) const { std::multimap dn_info = get_attributes(); der.start_cons(SEQUENCE); if(!dn_bits.empty()) der.raw_bytes(dn_bits); else { do_ava(der, dn_info, PRINTABLE_STRING, "X520.Country"); do_ava(der, dn_info, DIRECTORY_STRING, "X520.State"); do_ava(der, dn_info, DIRECTORY_STRING, "X520.Locality"); do_ava(der, dn_info, DIRECTORY_STRING, "X520.Organization"); do_ava(der, dn_info, DIRECTORY_STRING, "X520.OrganizationalUnit"); do_ava(der, dn_info, DIRECTORY_STRING, "X520.CommonName"); do_ava(der, dn_info, PRINTABLE_STRING, "X520.SerialNumber"); } der.end_cons(); } /* * Decode a BER encoded DistinguishedName */ void X509_DN::decode_from(BER_Decoder& source) { MemoryVector bits; source.start_cons(SEQUENCE) .raw_bytes(bits) .end_cons(); BER_Decoder sequence(bits); while(sequence.more_items()) { BER_Decoder rdn = sequence.start_cons(SET); while(rdn.more_items()) { OID oid; ASN1_String str; rdn.start_cons(SEQUENCE) .decode(oid) .decode(str) .verify_end() .end_cons(); add_attribute(oid, str.value()); } } dn_bits = bits; } } /* * Runtime benchmarking * (C) 2008 Jack Lloyd * * Distributed under the terms of the Botan license */ #include namespace Botan { namespace { /** * Benchmark Buffered_Computation (hash or MAC) */ std::pair bench_buf_comp(Buffered_Computation* buf_comp, u64bit nanoseconds_max, const byte buf[], size_t buf_len) { u64bit reps = 0; u64bit nanoseconds_used = 0; while(nanoseconds_used < nanoseconds_max) { const u64bit start = get_nanoseconds_clock(); buf_comp->update(buf, buf_len); nanoseconds_used += get_nanoseconds_clock() - start; ++reps; } return std::make_pair(reps * buf_len, nanoseconds_used); } /** * Benchmark block cipher */ std::pair bench_block_cipher(BlockCipher* block_cipher, u64bit nanoseconds_max, byte buf[], size_t buf_len) { const size_t in_blocks = buf_len / block_cipher->block_size(); u64bit reps = 0; u64bit nanoseconds_used = 0; block_cipher->set_key(buf, block_cipher->maximum_keylength()); while(nanoseconds_used < nanoseconds_max) { const u64bit start = get_nanoseconds_clock(); block_cipher->encrypt_n(buf, buf, in_blocks); nanoseconds_used += get_nanoseconds_clock() - start; ++reps; } return std::make_pair(reps * in_blocks * block_cipher->block_size(), nanoseconds_used); } /** * Benchmark stream */ std::pair bench_stream_cipher(StreamCipher* stream_cipher, u64bit nanoseconds_max, byte buf[], size_t buf_len) { u64bit reps = 0; u64bit nanoseconds_used = 0; stream_cipher->set_key(buf, stream_cipher->maximum_keylength()); while(nanoseconds_used < nanoseconds_max) { const u64bit start = get_nanoseconds_clock(); stream_cipher->cipher1(buf, buf_len); nanoseconds_used += get_nanoseconds_clock() - start; ++reps; } return std::make_pair(reps * buf_len, nanoseconds_used); } /** * Benchmark hash */ std::pair bench_hash(HashFunction* hash, u64bit nanoseconds_max, const byte buf[], size_t buf_len) { return bench_buf_comp(hash, nanoseconds_max, buf, buf_len); } /** * Benchmark MAC */ std::pair bench_mac(MessageAuthenticationCode* mac, u64bit nanoseconds_max, const byte buf[], size_t buf_len) { mac->set_key(buf, mac->maximum_keylength()); return bench_buf_comp(mac, nanoseconds_max, buf, buf_len); } } std::map algorithm_benchmark(const std::string& name, Algorithm_Factory& af, RandomNumberGenerator& rng, u32bit milliseconds, size_t buf_size) { std::vector providers = af.providers_of(name); std::map all_results; if(providers.empty()) // no providers, nothing to do return all_results; const u64bit ns_per_provider = (static_cast(milliseconds) * 1000 * 1000) / providers.size(); std::vector buf(buf_size * 1024); rng.randomize(&buf[0], buf.size()); for(size_t i = 0; i != providers.size(); ++i) { const std::string provider = providers[i]; std::pair results(0, 0); if(const BlockCipher* proto = af.prototype_block_cipher(name, provider)) { std::unique_ptr block_cipher(proto->clone()); results = bench_block_cipher(block_cipher.get(), ns_per_provider, &buf[0], buf.size()); } else if(const StreamCipher* proto = af.prototype_stream_cipher(name, provider)) { std::unique_ptr stream_cipher(proto->clone()); results = bench_stream_cipher(stream_cipher.get(), ns_per_provider, &buf[0], buf.size()); } else if(const HashFunction* proto = af.prototype_hash_function(name, provider)) { std::unique_ptr hash(proto->clone()); results = bench_hash(hash.get(), ns_per_provider, &buf[0], buf.size()); } else if(const MessageAuthenticationCode* proto = af.prototype_mac(name, provider)) { std::unique_ptr mac(proto->clone()); results = bench_mac(mac.get(), ns_per_provider, &buf[0], buf.size()); } if(results.first && results.second) { /* 953.67 == 1000 * 1000 * 1000 / 1024 / 1024 - the conversion factor from bytes per nanosecond to mebibytes per second. */ double speed = (953.67 * results.first) / results.second; all_results[provider] = speed; } } return all_results; } } /* * AES * (C) 1999-2010 Jack Lloyd * * Based on the public domain reference implemenation * * Distributed under the terms of the Botan license */ namespace Botan { namespace { const byte SE[256] = { 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 }; const byte SD[256] = { 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D }; const u32bit TE[1024] = { 0xC66363A5, 0xF87C7C84, 0xEE777799, 0xF67B7B8D, 0xFFF2F20D, 0xD66B6BBD, 0xDE6F6FB1, 0x91C5C554, 0x60303050, 0x02010103, 0xCE6767A9, 0x562B2B7D, 0xE7FEFE19, 0xB5D7D762, 0x4DABABE6, 0xEC76769A, 0x8FCACA45, 0x1F82829D, 0x89C9C940, 0xFA7D7D87, 0xEFFAFA15, 0xB25959EB, 0x8E4747C9, 0xFBF0F00B, 0x41ADADEC, 0xB3D4D467, 0x5FA2A2FD, 0x45AFAFEA, 0x239C9CBF, 0x53A4A4F7, 0xE4727296, 0x9BC0C05B, 0x75B7B7C2, 0xE1FDFD1C, 0x3D9393AE, 0x4C26266A, 0x6C36365A, 0x7E3F3F41, 0xF5F7F702, 0x83CCCC4F, 0x6834345C, 0x51A5A5F4, 0xD1E5E534, 0xF9F1F108, 0xE2717193, 0xABD8D873, 0x62313153, 0x2A15153F, 0x0804040C, 0x95C7C752, 0x46232365, 0x9DC3C35E, 0x30181828, 0x379696A1, 0x0A05050F, 0x2F9A9AB5, 0x0E070709, 0x24121236, 0x1B80809B, 0xDFE2E23D, 0xCDEBEB26, 0x4E272769, 0x7FB2B2CD, 0xEA75759F, 0x1209091B, 0x1D83839E, 0x582C2C74, 0x341A1A2E, 0x361B1B2D, 0xDC6E6EB2, 0xB45A5AEE, 0x5BA0A0FB, 0xA45252F6, 0x763B3B4D, 0xB7D6D661, 0x7DB3B3CE, 0x5229297B, 0xDDE3E33E, 0x5E2F2F71, 0x13848497, 0xA65353F5, 0xB9D1D168, 0x00000000, 0xC1EDED2C, 0x40202060, 0xE3FCFC1F, 0x79B1B1C8, 0xB65B5BED, 0xD46A6ABE, 0x8DCBCB46, 0x67BEBED9, 0x7239394B, 0x944A4ADE, 0x984C4CD4, 0xB05858E8, 0x85CFCF4A, 0xBBD0D06B, 0xC5EFEF2A, 0x4FAAAAE5, 0xEDFBFB16, 0x864343C5, 0x9A4D4DD7, 0x66333355, 0x11858594, 0x8A4545CF, 0xE9F9F910, 0x04020206, 0xFE7F7F81, 0xA05050F0, 0x783C3C44, 0x259F9FBA, 0x4BA8A8E3, 0xA25151F3, 0x5DA3A3FE, 0x804040C0, 0x058F8F8A, 0x3F9292AD, 0x219D9DBC, 0x70383848, 0xF1F5F504, 0x63BCBCDF, 0x77B6B6C1, 0xAFDADA75, 0x42212163, 0x20101030, 0xE5FFFF1A, 0xFDF3F30E, 0xBFD2D26D, 0x81CDCD4C, 0x180C0C14, 0x26131335, 0xC3ECEC2F, 0xBE5F5FE1, 0x359797A2, 0x884444CC, 0x2E171739, 0x93C4C457, 0x55A7A7F2, 0xFC7E7E82, 0x7A3D3D47, 0xC86464AC, 0xBA5D5DE7, 0x3219192B, 0xE6737395, 0xC06060A0, 0x19818198, 0x9E4F4FD1, 0xA3DCDC7F, 0x44222266, 0x542A2A7E, 0x3B9090AB, 0x0B888883, 0x8C4646CA, 0xC7EEEE29, 0x6BB8B8D3, 0x2814143C, 0xA7DEDE79, 0xBC5E5EE2, 0x160B0B1D, 0xADDBDB76, 0xDBE0E03B, 0x64323256, 0x743A3A4E, 0x140A0A1E, 0x924949DB, 0x0C06060A, 0x4824246C, 0xB85C5CE4, 0x9FC2C25D, 0xBDD3D36E, 0x43ACACEF, 0xC46262A6, 0x399191A8, 0x319595A4, 0xD3E4E437, 0xF279798B, 0xD5E7E732, 0x8BC8C843, 0x6E373759, 0xDA6D6DB7, 0x018D8D8C, 0xB1D5D564, 0x9C4E4ED2, 0x49A9A9E0, 0xD86C6CB4, 0xAC5656FA, 0xF3F4F407, 0xCFEAEA25, 0xCA6565AF, 0xF47A7A8E, 0x47AEAEE9, 0x10080818, 0x6FBABAD5, 0xF0787888, 0x4A25256F, 0x5C2E2E72, 0x381C1C24, 0x57A6A6F1, 0x73B4B4C7, 0x97C6C651, 0xCBE8E823, 0xA1DDDD7C, 0xE874749C, 0x3E1F1F21, 0x964B4BDD, 0x61BDBDDC, 0x0D8B8B86, 0x0F8A8A85, 0xE0707090, 0x7C3E3E42, 0x71B5B5C4, 0xCC6666AA, 0x904848D8, 0x06030305, 0xF7F6F601, 0x1C0E0E12, 0xC26161A3, 0x6A35355F, 0xAE5757F9, 0x69B9B9D0, 0x17868691, 0x99C1C158, 0x3A1D1D27, 0x279E9EB9, 0xD9E1E138, 0xEBF8F813, 0x2B9898B3, 0x22111133, 0xD26969BB, 0xA9D9D970, 0x078E8E89, 0x339494A7, 0x2D9B9BB6, 0x3C1E1E22, 0x15878792, 0xC9E9E920, 0x87CECE49, 0xAA5555FF, 0x50282878, 0xA5DFDF7A, 0x038C8C8F, 0x59A1A1F8, 0x09898980, 0x1A0D0D17, 0x65BFBFDA, 0xD7E6E631, 0x844242C6, 0xD06868B8, 0x824141C3, 0x299999B0, 0x5A2D2D77, 0x1E0F0F11, 0x7BB0B0CB, 0xA85454FC, 0x6DBBBBD6, 0x2C16163A, 0xA5C66363, 0x84F87C7C, 0x99EE7777, 0x8DF67B7B, 0x0DFFF2F2, 0xBDD66B6B, 0xB1DE6F6F, 0x5491C5C5, 0x50603030, 0x03020101, 0xA9CE6767, 0x7D562B2B, 0x19E7FEFE, 0x62B5D7D7, 0xE64DABAB, 0x9AEC7676, 0x458FCACA, 0x9D1F8282, 0x4089C9C9, 0x87FA7D7D, 0x15EFFAFA, 0xEBB25959, 0xC98E4747, 0x0BFBF0F0, 0xEC41ADAD, 0x67B3D4D4, 0xFD5FA2A2, 0xEA45AFAF, 0xBF239C9C, 0xF753A4A4, 0x96E47272, 0x5B9BC0C0, 0xC275B7B7, 0x1CE1FDFD, 0xAE3D9393, 0x6A4C2626, 0x5A6C3636, 0x417E3F3F, 0x02F5F7F7, 0x4F83CCCC, 0x5C683434, 0xF451A5A5, 0x34D1E5E5, 0x08F9F1F1, 0x93E27171, 0x73ABD8D8, 0x53623131, 0x3F2A1515, 0x0C080404, 0x5295C7C7, 0x65462323, 0x5E9DC3C3, 0x28301818, 0xA1379696, 0x0F0A0505, 0xB52F9A9A, 0x090E0707, 0x36241212, 0x9B1B8080, 0x3DDFE2E2, 0x26CDEBEB, 0x694E2727, 0xCD7FB2B2, 0x9FEA7575, 0x1B120909, 0x9E1D8383, 0x74582C2C, 0x2E341A1A, 0x2D361B1B, 0xB2DC6E6E, 0xEEB45A5A, 0xFB5BA0A0, 0xF6A45252, 0x4D763B3B, 0x61B7D6D6, 0xCE7DB3B3, 0x7B522929, 0x3EDDE3E3, 0x715E2F2F, 0x97138484, 0xF5A65353, 0x68B9D1D1, 0x00000000, 0x2CC1EDED, 0x60402020, 0x1FE3FCFC, 0xC879B1B1, 0xEDB65B5B, 0xBED46A6A, 0x468DCBCB, 0xD967BEBE, 0x4B723939, 0xDE944A4A, 0xD4984C4C, 0xE8B05858, 0x4A85CFCF, 0x6BBBD0D0, 0x2AC5EFEF, 0xE54FAAAA, 0x16EDFBFB, 0xC5864343, 0xD79A4D4D, 0x55663333, 0x94118585, 0xCF8A4545, 0x10E9F9F9, 0x06040202, 0x81FE7F7F, 0xF0A05050, 0x44783C3C, 0xBA259F9F, 0xE34BA8A8, 0xF3A25151, 0xFE5DA3A3, 0xC0804040, 0x8A058F8F, 0xAD3F9292, 0xBC219D9D, 0x48703838, 0x04F1F5F5, 0xDF63BCBC, 0xC177B6B6, 0x75AFDADA, 0x63422121, 0x30201010, 0x1AE5FFFF, 0x0EFDF3F3, 0x6DBFD2D2, 0x4C81CDCD, 0x14180C0C, 0x35261313, 0x2FC3ECEC, 0xE1BE5F5F, 0xA2359797, 0xCC884444, 0x392E1717, 0x5793C4C4, 0xF255A7A7, 0x82FC7E7E, 0x477A3D3D, 0xACC86464, 0xE7BA5D5D, 0x2B321919, 0x95E67373, 0xA0C06060, 0x98198181, 0xD19E4F4F, 0x7FA3DCDC, 0x66442222, 0x7E542A2A, 0xAB3B9090, 0x830B8888, 0xCA8C4646, 0x29C7EEEE, 0xD36BB8B8, 0x3C281414, 0x79A7DEDE, 0xE2BC5E5E, 0x1D160B0B, 0x76ADDBDB, 0x3BDBE0E0, 0x56643232, 0x4E743A3A, 0x1E140A0A, 0xDB924949, 0x0A0C0606, 0x6C482424, 0xE4B85C5C, 0x5D9FC2C2, 0x6EBDD3D3, 0xEF43ACAC, 0xA6C46262, 0xA8399191, 0xA4319595, 0x37D3E4E4, 0x8BF27979, 0x32D5E7E7, 0x438BC8C8, 0x596E3737, 0xB7DA6D6D, 0x8C018D8D, 0x64B1D5D5, 0xD29C4E4E, 0xE049A9A9, 0xB4D86C6C, 0xFAAC5656, 0x07F3F4F4, 0x25CFEAEA, 0xAFCA6565, 0x8EF47A7A, 0xE947AEAE, 0x18100808, 0xD56FBABA, 0x88F07878, 0x6F4A2525, 0x725C2E2E, 0x24381C1C, 0xF157A6A6, 0xC773B4B4, 0x5197C6C6, 0x23CBE8E8, 0x7CA1DDDD, 0x9CE87474, 0x213E1F1F, 0xDD964B4B, 0xDC61BDBD, 0x860D8B8B, 0x850F8A8A, 0x90E07070, 0x427C3E3E, 0xC471B5B5, 0xAACC6666, 0xD8904848, 0x05060303, 0x01F7F6F6, 0x121C0E0E, 0xA3C26161, 0x5F6A3535, 0xF9AE5757, 0xD069B9B9, 0x91178686, 0x5899C1C1, 0x273A1D1D, 0xB9279E9E, 0x38D9E1E1, 0x13EBF8F8, 0xB32B9898, 0x33221111, 0xBBD26969, 0x70A9D9D9, 0x89078E8E, 0xA7339494, 0xB62D9B9B, 0x223C1E1E, 0x92158787, 0x20C9E9E9, 0x4987CECE, 0xFFAA5555, 0x78502828, 0x7AA5DFDF, 0x8F038C8C, 0xF859A1A1, 0x80098989, 0x171A0D0D, 0xDA65BFBF, 0x31D7E6E6, 0xC6844242, 0xB8D06868, 0xC3824141, 0xB0299999, 0x775A2D2D, 0x111E0F0F, 0xCB7BB0B0, 0xFCA85454, 0xD66DBBBB, 0x3A2C1616, 0x63A5C663, 0x7C84F87C, 0x7799EE77, 0x7B8DF67B, 0xF20DFFF2, 0x6BBDD66B, 0x6FB1DE6F, 0xC55491C5, 0x30506030, 0x01030201, 0x67A9CE67, 0x2B7D562B, 0xFE19E7FE, 0xD762B5D7, 0xABE64DAB, 0x769AEC76, 0xCA458FCA, 0x829D1F82, 0xC94089C9, 0x7D87FA7D, 0xFA15EFFA, 0x59EBB259, 0x47C98E47, 0xF00BFBF0, 0xADEC41AD, 0xD467B3D4, 0xA2FD5FA2, 0xAFEA45AF, 0x9CBF239C, 0xA4F753A4, 0x7296E472, 0xC05B9BC0, 0xB7C275B7, 0xFD1CE1FD, 0x93AE3D93, 0x266A4C26, 0x365A6C36, 0x3F417E3F, 0xF702F5F7, 0xCC4F83CC, 0x345C6834, 0xA5F451A5, 0xE534D1E5, 0xF108F9F1, 0x7193E271, 0xD873ABD8, 0x31536231, 0x153F2A15, 0x040C0804, 0xC75295C7, 0x23654623, 0xC35E9DC3, 0x18283018, 0x96A13796, 0x050F0A05, 0x9AB52F9A, 0x07090E07, 0x12362412, 0x809B1B80, 0xE23DDFE2, 0xEB26CDEB, 0x27694E27, 0xB2CD7FB2, 0x759FEA75, 0x091B1209, 0x839E1D83, 0x2C74582C, 0x1A2E341A, 0x1B2D361B, 0x6EB2DC6E, 0x5AEEB45A, 0xA0FB5BA0, 0x52F6A452, 0x3B4D763B, 0xD661B7D6, 0xB3CE7DB3, 0x297B5229, 0xE33EDDE3, 0x2F715E2F, 0x84971384, 0x53F5A653, 0xD168B9D1, 0x00000000, 0xED2CC1ED, 0x20604020, 0xFC1FE3FC, 0xB1C879B1, 0x5BEDB65B, 0x6ABED46A, 0xCB468DCB, 0xBED967BE, 0x394B7239, 0x4ADE944A, 0x4CD4984C, 0x58E8B058, 0xCF4A85CF, 0xD06BBBD0, 0xEF2AC5EF, 0xAAE54FAA, 0xFB16EDFB, 0x43C58643, 0x4DD79A4D, 0x33556633, 0x85941185, 0x45CF8A45, 0xF910E9F9, 0x02060402, 0x7F81FE7F, 0x50F0A050, 0x3C44783C, 0x9FBA259F, 0xA8E34BA8, 0x51F3A251, 0xA3FE5DA3, 0x40C08040, 0x8F8A058F, 0x92AD3F92, 0x9DBC219D, 0x38487038, 0xF504F1F5, 0xBCDF63BC, 0xB6C177B6, 0xDA75AFDA, 0x21634221, 0x10302010, 0xFF1AE5FF, 0xF30EFDF3, 0xD26DBFD2, 0xCD4C81CD, 0x0C14180C, 0x13352613, 0xEC2FC3EC, 0x5FE1BE5F, 0x97A23597, 0x44CC8844, 0x17392E17, 0xC45793C4, 0xA7F255A7, 0x7E82FC7E, 0x3D477A3D, 0x64ACC864, 0x5DE7BA5D, 0x192B3219, 0x7395E673, 0x60A0C060, 0x81981981, 0x4FD19E4F, 0xDC7FA3DC, 0x22664422, 0x2A7E542A, 0x90AB3B90, 0x88830B88, 0x46CA8C46, 0xEE29C7EE, 0xB8D36BB8, 0x143C2814, 0xDE79A7DE, 0x5EE2BC5E, 0x0B1D160B, 0xDB76ADDB, 0xE03BDBE0, 0x32566432, 0x3A4E743A, 0x0A1E140A, 0x49DB9249, 0x060A0C06, 0x246C4824, 0x5CE4B85C, 0xC25D9FC2, 0xD36EBDD3, 0xACEF43AC, 0x62A6C462, 0x91A83991, 0x95A43195, 0xE437D3E4, 0x798BF279, 0xE732D5E7, 0xC8438BC8, 0x37596E37, 0x6DB7DA6D, 0x8D8C018D, 0xD564B1D5, 0x4ED29C4E, 0xA9E049A9, 0x6CB4D86C, 0x56FAAC56, 0xF407F3F4, 0xEA25CFEA, 0x65AFCA65, 0x7A8EF47A, 0xAEE947AE, 0x08181008, 0xBAD56FBA, 0x7888F078, 0x256F4A25, 0x2E725C2E, 0x1C24381C, 0xA6F157A6, 0xB4C773B4, 0xC65197C6, 0xE823CBE8, 0xDD7CA1DD, 0x749CE874, 0x1F213E1F, 0x4BDD964B, 0xBDDC61BD, 0x8B860D8B, 0x8A850F8A, 0x7090E070, 0x3E427C3E, 0xB5C471B5, 0x66AACC66, 0x48D89048, 0x03050603, 0xF601F7F6, 0x0E121C0E, 0x61A3C261, 0x355F6A35, 0x57F9AE57, 0xB9D069B9, 0x86911786, 0xC15899C1, 0x1D273A1D, 0x9EB9279E, 0xE138D9E1, 0xF813EBF8, 0x98B32B98, 0x11332211, 0x69BBD269, 0xD970A9D9, 0x8E89078E, 0x94A73394, 0x9BB62D9B, 0x1E223C1E, 0x87921587, 0xE920C9E9, 0xCE4987CE, 0x55FFAA55, 0x28785028, 0xDF7AA5DF, 0x8C8F038C, 0xA1F859A1, 0x89800989, 0x0D171A0D, 0xBFDA65BF, 0xE631D7E6, 0x42C68442, 0x68B8D068, 0x41C38241, 0x99B02999, 0x2D775A2D, 0x0F111E0F, 0xB0CB7BB0, 0x54FCA854, 0xBBD66DBB, 0x163A2C16, 0x6363A5C6, 0x7C7C84F8, 0x777799EE, 0x7B7B8DF6, 0xF2F20DFF, 0x6B6BBDD6, 0x6F6FB1DE, 0xC5C55491, 0x30305060, 0x01010302, 0x6767A9CE, 0x2B2B7D56, 0xFEFE19E7, 0xD7D762B5, 0xABABE64D, 0x76769AEC, 0xCACA458F, 0x82829D1F, 0xC9C94089, 0x7D7D87FA, 0xFAFA15EF, 0x5959EBB2, 0x4747C98E, 0xF0F00BFB, 0xADADEC41, 0xD4D467B3, 0xA2A2FD5F, 0xAFAFEA45, 0x9C9CBF23, 0xA4A4F753, 0x727296E4, 0xC0C05B9B, 0xB7B7C275, 0xFDFD1CE1, 0x9393AE3D, 0x26266A4C, 0x36365A6C, 0x3F3F417E, 0xF7F702F5, 0xCCCC4F83, 0x34345C68, 0xA5A5F451, 0xE5E534D1, 0xF1F108F9, 0x717193E2, 0xD8D873AB, 0x31315362, 0x15153F2A, 0x04040C08, 0xC7C75295, 0x23236546, 0xC3C35E9D, 0x18182830, 0x9696A137, 0x05050F0A, 0x9A9AB52F, 0x0707090E, 0x12123624, 0x80809B1B, 0xE2E23DDF, 0xEBEB26CD, 0x2727694E, 0xB2B2CD7F, 0x75759FEA, 0x09091B12, 0x83839E1D, 0x2C2C7458, 0x1A1A2E34, 0x1B1B2D36, 0x6E6EB2DC, 0x5A5AEEB4, 0xA0A0FB5B, 0x5252F6A4, 0x3B3B4D76, 0xD6D661B7, 0xB3B3CE7D, 0x29297B52, 0xE3E33EDD, 0x2F2F715E, 0x84849713, 0x5353F5A6, 0xD1D168B9, 0x00000000, 0xEDED2CC1, 0x20206040, 0xFCFC1FE3, 0xB1B1C879, 0x5B5BEDB6, 0x6A6ABED4, 0xCBCB468D, 0xBEBED967, 0x39394B72, 0x4A4ADE94, 0x4C4CD498, 0x5858E8B0, 0xCFCF4A85, 0xD0D06BBB, 0xEFEF2AC5, 0xAAAAE54F, 0xFBFB16ED, 0x4343C586, 0x4D4DD79A, 0x33335566, 0x85859411, 0x4545CF8A, 0xF9F910E9, 0x02020604, 0x7F7F81FE, 0x5050F0A0, 0x3C3C4478, 0x9F9FBA25, 0xA8A8E34B, 0x5151F3A2, 0xA3A3FE5D, 0x4040C080, 0x8F8F8A05, 0x9292AD3F, 0x9D9DBC21, 0x38384870, 0xF5F504F1, 0xBCBCDF63, 0xB6B6C177, 0xDADA75AF, 0x21216342, 0x10103020, 0xFFFF1AE5, 0xF3F30EFD, 0xD2D26DBF, 0xCDCD4C81, 0x0C0C1418, 0x13133526, 0xECEC2FC3, 0x5F5FE1BE, 0x9797A235, 0x4444CC88, 0x1717392E, 0xC4C45793, 0xA7A7F255, 0x7E7E82FC, 0x3D3D477A, 0x6464ACC8, 0x5D5DE7BA, 0x19192B32, 0x737395E6, 0x6060A0C0, 0x81819819, 0x4F4FD19E, 0xDCDC7FA3, 0x22226644, 0x2A2A7E54, 0x9090AB3B, 0x8888830B, 0x4646CA8C, 0xEEEE29C7, 0xB8B8D36B, 0x14143C28, 0xDEDE79A7, 0x5E5EE2BC, 0x0B0B1D16, 0xDBDB76AD, 0xE0E03BDB, 0x32325664, 0x3A3A4E74, 0x0A0A1E14, 0x4949DB92, 0x06060A0C, 0x24246C48, 0x5C5CE4B8, 0xC2C25D9F, 0xD3D36EBD, 0xACACEF43, 0x6262A6C4, 0x9191A839, 0x9595A431, 0xE4E437D3, 0x79798BF2, 0xE7E732D5, 0xC8C8438B, 0x3737596E, 0x6D6DB7DA, 0x8D8D8C01, 0xD5D564B1, 0x4E4ED29C, 0xA9A9E049, 0x6C6CB4D8, 0x5656FAAC, 0xF4F407F3, 0xEAEA25CF, 0x6565AFCA, 0x7A7A8EF4, 0xAEAEE947, 0x08081810, 0xBABAD56F, 0x787888F0, 0x25256F4A, 0x2E2E725C, 0x1C1C2438, 0xA6A6F157, 0xB4B4C773, 0xC6C65197, 0xE8E823CB, 0xDDDD7CA1, 0x74749CE8, 0x1F1F213E, 0x4B4BDD96, 0xBDBDDC61, 0x8B8B860D, 0x8A8A850F, 0x707090E0, 0x3E3E427C, 0xB5B5C471, 0x6666AACC, 0x4848D890, 0x03030506, 0xF6F601F7, 0x0E0E121C, 0x6161A3C2, 0x35355F6A, 0x5757F9AE, 0xB9B9D069, 0x86869117, 0xC1C15899, 0x1D1D273A, 0x9E9EB927, 0xE1E138D9, 0xF8F813EB, 0x9898B32B, 0x11113322, 0x6969BBD2, 0xD9D970A9, 0x8E8E8907, 0x9494A733, 0x9B9BB62D, 0x1E1E223C, 0x87879215, 0xE9E920C9, 0xCECE4987, 0x5555FFAA, 0x28287850, 0xDFDF7AA5, 0x8C8C8F03, 0xA1A1F859, 0x89898009, 0x0D0D171A, 0xBFBFDA65, 0xE6E631D7, 0x4242C684, 0x6868B8D0, 0x4141C382, 0x9999B029, 0x2D2D775A, 0x0F0F111E, 0xB0B0CB7B, 0x5454FCA8, 0xBBBBD66D, 0x16163A2C }; const u32bit TD[1024] = { 0x51F4A750, 0x7E416553, 0x1A17A4C3, 0x3A275E96, 0x3BAB6BCB, 0x1F9D45F1, 0xACFA58AB, 0x4BE30393, 0x2030FA55, 0xAD766DF6, 0x88CC7691, 0xF5024C25, 0x4FE5D7FC, 0xC52ACBD7, 0x26354480, 0xB562A38F, 0xDEB15A49, 0x25BA1B67, 0x45EA0E98, 0x5DFEC0E1, 0xC32F7502, 0x814CF012, 0x8D4697A3, 0x6BD3F9C6, 0x038F5FE7, 0x15929C95, 0xBF6D7AEB, 0x955259DA, 0xD4BE832D, 0x587421D3, 0x49E06929, 0x8EC9C844, 0x75C2896A, 0xF48E7978, 0x99583E6B, 0x27B971DD, 0xBEE14FB6, 0xF088AD17, 0xC920AC66, 0x7DCE3AB4, 0x63DF4A18, 0xE51A3182, 0x97513360, 0x62537F45, 0xB16477E0, 0xBB6BAE84, 0xFE81A01C, 0xF9082B94, 0x70486858, 0x8F45FD19, 0x94DE6C87, 0x527BF8B7, 0xAB73D323, 0x724B02E2, 0xE31F8F57, 0x6655AB2A, 0xB2EB2807, 0x2FB5C203, 0x86C57B9A, 0xD33708A5, 0x302887F2, 0x23BFA5B2, 0x02036ABA, 0xED16825C, 0x8ACF1C2B, 0xA779B492, 0xF307F2F0, 0x4E69E2A1, 0x65DAF4CD, 0x0605BED5, 0xD134621F, 0xC4A6FE8A, 0x342E539D, 0xA2F355A0, 0x058AE132, 0xA4F6EB75, 0x0B83EC39, 0x4060EFAA, 0x5E719F06, 0xBD6E1051, 0x3E218AF9, 0x96DD063D, 0xDD3E05AE, 0x4DE6BD46, 0x91548DB5, 0x71C45D05, 0x0406D46F, 0x605015FF, 0x1998FB24, 0xD6BDE997, 0x894043CC, 0x67D99E77, 0xB0E842BD, 0x07898B88, 0xE7195B38, 0x79C8EEDB, 0xA17C0A47, 0x7C420FE9, 0xF8841EC9, 0x00000000, 0x09808683, 0x322BED48, 0x1E1170AC, 0x6C5A724E, 0xFD0EFFFB, 0x0F853856, 0x3DAED51E, 0x362D3927, 0x0A0FD964, 0x685CA621, 0x9B5B54D1, 0x24362E3A, 0x0C0A67B1, 0x9357E70F, 0xB4EE96D2, 0x1B9B919E, 0x80C0C54F, 0x61DC20A2, 0x5A774B69, 0x1C121A16, 0xE293BA0A, 0xC0A02AE5, 0x3C22E043, 0x121B171D, 0x0E090D0B, 0xF28BC7AD, 0x2DB6A8B9, 0x141EA9C8, 0x57F11985, 0xAF75074C, 0xEE99DDBB, 0xA37F60FD, 0xF701269F, 0x5C72F5BC, 0x44663BC5, 0x5BFB7E34, 0x8B432976, 0xCB23C6DC, 0xB6EDFC68, 0xB8E4F163, 0xD731DCCA, 0x42638510, 0x13972240, 0x84C61120, 0x854A247D, 0xD2BB3DF8, 0xAEF93211, 0xC729A16D, 0x1D9E2F4B, 0xDCB230F3, 0x0D8652EC, 0x77C1E3D0, 0x2BB3166C, 0xA970B999, 0x119448FA, 0x47E96422, 0xA8FC8CC4, 0xA0F03F1A, 0x567D2CD8, 0x223390EF, 0x87494EC7, 0xD938D1C1, 0x8CCAA2FE, 0x98D40B36, 0xA6F581CF, 0xA57ADE28, 0xDAB78E26, 0x3FADBFA4, 0x2C3A9DE4, 0x5078920D, 0x6A5FCC9B, 0x547E4662, 0xF68D13C2, 0x90D8B8E8, 0x2E39F75E, 0x82C3AFF5, 0x9F5D80BE, 0x69D0937C, 0x6FD52DA9, 0xCF2512B3, 0xC8AC993B, 0x10187DA7, 0xE89C636E, 0xDB3BBB7B, 0xCD267809, 0x6E5918F4, 0xEC9AB701, 0x834F9AA8, 0xE6956E65, 0xAAFFE67E, 0x21BCCF08, 0xEF15E8E6, 0xBAE79BD9, 0x4A6F36CE, 0xEA9F09D4, 0x29B07CD6, 0x31A4B2AF, 0x2A3F2331, 0xC6A59430, 0x35A266C0, 0x744EBC37, 0xFC82CAA6, 0xE090D0B0, 0x33A7D815, 0xF104984A, 0x41ECDAF7, 0x7FCD500E, 0x1791F62F, 0x764DD68D, 0x43EFB04D, 0xCCAA4D54, 0xE49604DF, 0x9ED1B5E3, 0x4C6A881B, 0xC12C1FB8, 0x4665517F, 0x9D5EEA04, 0x018C355D, 0xFA877473, 0xFB0B412E, 0xB3671D5A, 0x92DBD252, 0xE9105633, 0x6DD64713, 0x9AD7618C, 0x37A10C7A, 0x59F8148E, 0xEB133C89, 0xCEA927EE, 0xB761C935, 0xE11CE5ED, 0x7A47B13C, 0x9CD2DF59, 0x55F2733F, 0x1814CE79, 0x73C737BF, 0x53F7CDEA, 0x5FFDAA5B, 0xDF3D6F14, 0x7844DB86, 0xCAAFF381, 0xB968C43E, 0x3824342C, 0xC2A3405F, 0x161DC372, 0xBCE2250C, 0x283C498B, 0xFF0D9541, 0x39A80171, 0x080CB3DE, 0xD8B4E49C, 0x6456C190, 0x7BCB8461, 0xD532B670, 0x486C5C74, 0xD0B85742, 0x5051F4A7, 0x537E4165, 0xC31A17A4, 0x963A275E, 0xCB3BAB6B, 0xF11F9D45, 0xABACFA58, 0x934BE303, 0x552030FA, 0xF6AD766D, 0x9188CC76, 0x25F5024C, 0xFC4FE5D7, 0xD7C52ACB, 0x80263544, 0x8FB562A3, 0x49DEB15A, 0x6725BA1B, 0x9845EA0E, 0xE15DFEC0, 0x02C32F75, 0x12814CF0, 0xA38D4697, 0xC66BD3F9, 0xE7038F5F, 0x9515929C, 0xEBBF6D7A, 0xDA955259, 0x2DD4BE83, 0xD3587421, 0x2949E069, 0x448EC9C8, 0x6A75C289, 0x78F48E79, 0x6B99583E, 0xDD27B971, 0xB6BEE14F, 0x17F088AD, 0x66C920AC, 0xB47DCE3A, 0x1863DF4A, 0x82E51A31, 0x60975133, 0x4562537F, 0xE0B16477, 0x84BB6BAE, 0x1CFE81A0, 0x94F9082B, 0x58704868, 0x198F45FD, 0x8794DE6C, 0xB7527BF8, 0x23AB73D3, 0xE2724B02, 0x57E31F8F, 0x2A6655AB, 0x07B2EB28, 0x032FB5C2, 0x9A86C57B, 0xA5D33708, 0xF2302887, 0xB223BFA5, 0xBA02036A, 0x5CED1682, 0x2B8ACF1C, 0x92A779B4, 0xF0F307F2, 0xA14E69E2, 0xCD65DAF4, 0xD50605BE, 0x1FD13462, 0x8AC4A6FE, 0x9D342E53, 0xA0A2F355, 0x32058AE1, 0x75A4F6EB, 0x390B83EC, 0xAA4060EF, 0x065E719F, 0x51BD6E10, 0xF93E218A, 0x3D96DD06, 0xAEDD3E05, 0x464DE6BD, 0xB591548D, 0x0571C45D, 0x6F0406D4, 0xFF605015, 0x241998FB, 0x97D6BDE9, 0xCC894043, 0x7767D99E, 0xBDB0E842, 0x8807898B, 0x38E7195B, 0xDB79C8EE, 0x47A17C0A, 0xE97C420F, 0xC9F8841E, 0x00000000, 0x83098086, 0x48322BED, 0xAC1E1170, 0x4E6C5A72, 0xFBFD0EFF, 0x560F8538, 0x1E3DAED5, 0x27362D39, 0x640A0FD9, 0x21685CA6, 0xD19B5B54, 0x3A24362E, 0xB10C0A67, 0x0F9357E7, 0xD2B4EE96, 0x9E1B9B91, 0x4F80C0C5, 0xA261DC20, 0x695A774B, 0x161C121A, 0x0AE293BA, 0xE5C0A02A, 0x433C22E0, 0x1D121B17, 0x0B0E090D, 0xADF28BC7, 0xB92DB6A8, 0xC8141EA9, 0x8557F119, 0x4CAF7507, 0xBBEE99DD, 0xFDA37F60, 0x9FF70126, 0xBC5C72F5, 0xC544663B, 0x345BFB7E, 0x768B4329, 0xDCCB23C6, 0x68B6EDFC, 0x63B8E4F1, 0xCAD731DC, 0x10426385, 0x40139722, 0x2084C611, 0x7D854A24, 0xF8D2BB3D, 0x11AEF932, 0x6DC729A1, 0x4B1D9E2F, 0xF3DCB230, 0xEC0D8652, 0xD077C1E3, 0x6C2BB316, 0x99A970B9, 0xFA119448, 0x2247E964, 0xC4A8FC8C, 0x1AA0F03F, 0xD8567D2C, 0xEF223390, 0xC787494E, 0xC1D938D1, 0xFE8CCAA2, 0x3698D40B, 0xCFA6F581, 0x28A57ADE, 0x26DAB78E, 0xA43FADBF, 0xE42C3A9D, 0x0D507892, 0x9B6A5FCC, 0x62547E46, 0xC2F68D13, 0xE890D8B8, 0x5E2E39F7, 0xF582C3AF, 0xBE9F5D80, 0x7C69D093, 0xA96FD52D, 0xB3CF2512, 0x3BC8AC99, 0xA710187D, 0x6EE89C63, 0x7BDB3BBB, 0x09CD2678, 0xF46E5918, 0x01EC9AB7, 0xA8834F9A, 0x65E6956E, 0x7EAAFFE6, 0x0821BCCF, 0xE6EF15E8, 0xD9BAE79B, 0xCE4A6F36, 0xD4EA9F09, 0xD629B07C, 0xAF31A4B2, 0x312A3F23, 0x30C6A594, 0xC035A266, 0x37744EBC, 0xA6FC82CA, 0xB0E090D0, 0x1533A7D8, 0x4AF10498, 0xF741ECDA, 0x0E7FCD50, 0x2F1791F6, 0x8D764DD6, 0x4D43EFB0, 0x54CCAA4D, 0xDFE49604, 0xE39ED1B5, 0x1B4C6A88, 0xB8C12C1F, 0x7F466551, 0x049D5EEA, 0x5D018C35, 0x73FA8774, 0x2EFB0B41, 0x5AB3671D, 0x5292DBD2, 0x33E91056, 0x136DD647, 0x8C9AD761, 0x7A37A10C, 0x8E59F814, 0x89EB133C, 0xEECEA927, 0x35B761C9, 0xEDE11CE5, 0x3C7A47B1, 0x599CD2DF, 0x3F55F273, 0x791814CE, 0xBF73C737, 0xEA53F7CD, 0x5B5FFDAA, 0x14DF3D6F, 0x867844DB, 0x81CAAFF3, 0x3EB968C4, 0x2C382434, 0x5FC2A340, 0x72161DC3, 0x0CBCE225, 0x8B283C49, 0x41FF0D95, 0x7139A801, 0xDE080CB3, 0x9CD8B4E4, 0x906456C1, 0x617BCB84, 0x70D532B6, 0x74486C5C, 0x42D0B857, 0xA75051F4, 0x65537E41, 0xA4C31A17, 0x5E963A27, 0x6BCB3BAB, 0x45F11F9D, 0x58ABACFA, 0x03934BE3, 0xFA552030, 0x6DF6AD76, 0x769188CC, 0x4C25F502, 0xD7FC4FE5, 0xCBD7C52A, 0x44802635, 0xA38FB562, 0x5A49DEB1, 0x1B6725BA, 0x0E9845EA, 0xC0E15DFE, 0x7502C32F, 0xF012814C, 0x97A38D46, 0xF9C66BD3, 0x5FE7038F, 0x9C951592, 0x7AEBBF6D, 0x59DA9552, 0x832DD4BE, 0x21D35874, 0x692949E0, 0xC8448EC9, 0x896A75C2, 0x7978F48E, 0x3E6B9958, 0x71DD27B9, 0x4FB6BEE1, 0xAD17F088, 0xAC66C920, 0x3AB47DCE, 0x4A1863DF, 0x3182E51A, 0x33609751, 0x7F456253, 0x77E0B164, 0xAE84BB6B, 0xA01CFE81, 0x2B94F908, 0x68587048, 0xFD198F45, 0x6C8794DE, 0xF8B7527B, 0xD323AB73, 0x02E2724B, 0x8F57E31F, 0xAB2A6655, 0x2807B2EB, 0xC2032FB5, 0x7B9A86C5, 0x08A5D337, 0x87F23028, 0xA5B223BF, 0x6ABA0203, 0x825CED16, 0x1C2B8ACF, 0xB492A779, 0xF2F0F307, 0xE2A14E69, 0xF4CD65DA, 0xBED50605, 0x621FD134, 0xFE8AC4A6, 0x539D342E, 0x55A0A2F3, 0xE132058A, 0xEB75A4F6, 0xEC390B83, 0xEFAA4060, 0x9F065E71, 0x1051BD6E, 0x8AF93E21, 0x063D96DD, 0x05AEDD3E, 0xBD464DE6, 0x8DB59154, 0x5D0571C4, 0xD46F0406, 0x15FF6050, 0xFB241998, 0xE997D6BD, 0x43CC8940, 0x9E7767D9, 0x42BDB0E8, 0x8B880789, 0x5B38E719, 0xEEDB79C8, 0x0A47A17C, 0x0FE97C42, 0x1EC9F884, 0x00000000, 0x86830980, 0xED48322B, 0x70AC1E11, 0x724E6C5A, 0xFFFBFD0E, 0x38560F85, 0xD51E3DAE, 0x3927362D, 0xD9640A0F, 0xA621685C, 0x54D19B5B, 0x2E3A2436, 0x67B10C0A, 0xE70F9357, 0x96D2B4EE, 0x919E1B9B, 0xC54F80C0, 0x20A261DC, 0x4B695A77, 0x1A161C12, 0xBA0AE293, 0x2AE5C0A0, 0xE0433C22, 0x171D121B, 0x0D0B0E09, 0xC7ADF28B, 0xA8B92DB6, 0xA9C8141E, 0x198557F1, 0x074CAF75, 0xDDBBEE99, 0x60FDA37F, 0x269FF701, 0xF5BC5C72, 0x3BC54466, 0x7E345BFB, 0x29768B43, 0xC6DCCB23, 0xFC68B6ED, 0xF163B8E4, 0xDCCAD731, 0x85104263, 0x22401397, 0x112084C6, 0x247D854A, 0x3DF8D2BB, 0x3211AEF9, 0xA16DC729, 0x2F4B1D9E, 0x30F3DCB2, 0x52EC0D86, 0xE3D077C1, 0x166C2BB3, 0xB999A970, 0x48FA1194, 0x642247E9, 0x8CC4A8FC, 0x3F1AA0F0, 0x2CD8567D, 0x90EF2233, 0x4EC78749, 0xD1C1D938, 0xA2FE8CCA, 0x0B3698D4, 0x81CFA6F5, 0xDE28A57A, 0x8E26DAB7, 0xBFA43FAD, 0x9DE42C3A, 0x920D5078, 0xCC9B6A5F, 0x4662547E, 0x13C2F68D, 0xB8E890D8, 0xF75E2E39, 0xAFF582C3, 0x80BE9F5D, 0x937C69D0, 0x2DA96FD5, 0x12B3CF25, 0x993BC8AC, 0x7DA71018, 0x636EE89C, 0xBB7BDB3B, 0x7809CD26, 0x18F46E59, 0xB701EC9A, 0x9AA8834F, 0x6E65E695, 0xE67EAAFF, 0xCF0821BC, 0xE8E6EF15, 0x9BD9BAE7, 0x36CE4A6F, 0x09D4EA9F, 0x7CD629B0, 0xB2AF31A4, 0x23312A3F, 0x9430C6A5, 0x66C035A2, 0xBC37744E, 0xCAA6FC82, 0xD0B0E090, 0xD81533A7, 0x984AF104, 0xDAF741EC, 0x500E7FCD, 0xF62F1791, 0xD68D764D, 0xB04D43EF, 0x4D54CCAA, 0x04DFE496, 0xB5E39ED1, 0x881B4C6A, 0x1FB8C12C, 0x517F4665, 0xEA049D5E, 0x355D018C, 0x7473FA87, 0x412EFB0B, 0x1D5AB367, 0xD25292DB, 0x5633E910, 0x47136DD6, 0x618C9AD7, 0x0C7A37A1, 0x148E59F8, 0x3C89EB13, 0x27EECEA9, 0xC935B761, 0xE5EDE11C, 0xB13C7A47, 0xDF599CD2, 0x733F55F2, 0xCE791814, 0x37BF73C7, 0xCDEA53F7, 0xAA5B5FFD, 0x6F14DF3D, 0xDB867844, 0xF381CAAF, 0xC43EB968, 0x342C3824, 0x405FC2A3, 0xC372161D, 0x250CBCE2, 0x498B283C, 0x9541FF0D, 0x017139A8, 0xB3DE080C, 0xE49CD8B4, 0xC1906456, 0x84617BCB, 0xB670D532, 0x5C74486C, 0x5742D0B8, 0xF4A75051, 0x4165537E, 0x17A4C31A, 0x275E963A, 0xAB6BCB3B, 0x9D45F11F, 0xFA58ABAC, 0xE303934B, 0x30FA5520, 0x766DF6AD, 0xCC769188, 0x024C25F5, 0xE5D7FC4F, 0x2ACBD7C5, 0x35448026, 0x62A38FB5, 0xB15A49DE, 0xBA1B6725, 0xEA0E9845, 0xFEC0E15D, 0x2F7502C3, 0x4CF01281, 0x4697A38D, 0xD3F9C66B, 0x8F5FE703, 0x929C9515, 0x6D7AEBBF, 0x5259DA95, 0xBE832DD4, 0x7421D358, 0xE0692949, 0xC9C8448E, 0xC2896A75, 0x8E7978F4, 0x583E6B99, 0xB971DD27, 0xE14FB6BE, 0x88AD17F0, 0x20AC66C9, 0xCE3AB47D, 0xDF4A1863, 0x1A3182E5, 0x51336097, 0x537F4562, 0x6477E0B1, 0x6BAE84BB, 0x81A01CFE, 0x082B94F9, 0x48685870, 0x45FD198F, 0xDE6C8794, 0x7BF8B752, 0x73D323AB, 0x4B02E272, 0x1F8F57E3, 0x55AB2A66, 0xEB2807B2, 0xB5C2032F, 0xC57B9A86, 0x3708A5D3, 0x2887F230, 0xBFA5B223, 0x036ABA02, 0x16825CED, 0xCF1C2B8A, 0x79B492A7, 0x07F2F0F3, 0x69E2A14E, 0xDAF4CD65, 0x05BED506, 0x34621FD1, 0xA6FE8AC4, 0x2E539D34, 0xF355A0A2, 0x8AE13205, 0xF6EB75A4, 0x83EC390B, 0x60EFAA40, 0x719F065E, 0x6E1051BD, 0x218AF93E, 0xDD063D96, 0x3E05AEDD, 0xE6BD464D, 0x548DB591, 0xC45D0571, 0x06D46F04, 0x5015FF60, 0x98FB2419, 0xBDE997D6, 0x4043CC89, 0xD99E7767, 0xE842BDB0, 0x898B8807, 0x195B38E7, 0xC8EEDB79, 0x7C0A47A1, 0x420FE97C, 0x841EC9F8, 0x00000000, 0x80868309, 0x2BED4832, 0x1170AC1E, 0x5A724E6C, 0x0EFFFBFD, 0x8538560F, 0xAED51E3D, 0x2D392736, 0x0FD9640A, 0x5CA62168, 0x5B54D19B, 0x362E3A24, 0x0A67B10C, 0x57E70F93, 0xEE96D2B4, 0x9B919E1B, 0xC0C54F80, 0xDC20A261, 0x774B695A, 0x121A161C, 0x93BA0AE2, 0xA02AE5C0, 0x22E0433C, 0x1B171D12, 0x090D0B0E, 0x8BC7ADF2, 0xB6A8B92D, 0x1EA9C814, 0xF1198557, 0x75074CAF, 0x99DDBBEE, 0x7F60FDA3, 0x01269FF7, 0x72F5BC5C, 0x663BC544, 0xFB7E345B, 0x4329768B, 0x23C6DCCB, 0xEDFC68B6, 0xE4F163B8, 0x31DCCAD7, 0x63851042, 0x97224013, 0xC6112084, 0x4A247D85, 0xBB3DF8D2, 0xF93211AE, 0x29A16DC7, 0x9E2F4B1D, 0xB230F3DC, 0x8652EC0D, 0xC1E3D077, 0xB3166C2B, 0x70B999A9, 0x9448FA11, 0xE9642247, 0xFC8CC4A8, 0xF03F1AA0, 0x7D2CD856, 0x3390EF22, 0x494EC787, 0x38D1C1D9, 0xCAA2FE8C, 0xD40B3698, 0xF581CFA6, 0x7ADE28A5, 0xB78E26DA, 0xADBFA43F, 0x3A9DE42C, 0x78920D50, 0x5FCC9B6A, 0x7E466254, 0x8D13C2F6, 0xD8B8E890, 0x39F75E2E, 0xC3AFF582, 0x5D80BE9F, 0xD0937C69, 0xD52DA96F, 0x2512B3CF, 0xAC993BC8, 0x187DA710, 0x9C636EE8, 0x3BBB7BDB, 0x267809CD, 0x5918F46E, 0x9AB701EC, 0x4F9AA883, 0x956E65E6, 0xFFE67EAA, 0xBCCF0821, 0x15E8E6EF, 0xE79BD9BA, 0x6F36CE4A, 0x9F09D4EA, 0xB07CD629, 0xA4B2AF31, 0x3F23312A, 0xA59430C6, 0xA266C035, 0x4EBC3774, 0x82CAA6FC, 0x90D0B0E0, 0xA7D81533, 0x04984AF1, 0xECDAF741, 0xCD500E7F, 0x91F62F17, 0x4DD68D76, 0xEFB04D43, 0xAA4D54CC, 0x9604DFE4, 0xD1B5E39E, 0x6A881B4C, 0x2C1FB8C1, 0x65517F46, 0x5EEA049D, 0x8C355D01, 0x877473FA, 0x0B412EFB, 0x671D5AB3, 0xDBD25292, 0x105633E9, 0xD647136D, 0xD7618C9A, 0xA10C7A37, 0xF8148E59, 0x133C89EB, 0xA927EECE, 0x61C935B7, 0x1CE5EDE1, 0x47B13C7A, 0xD2DF599C, 0xF2733F55, 0x14CE7918, 0xC737BF73, 0xF7CDEA53, 0xFDAA5B5F, 0x3D6F14DF, 0x44DB8678, 0xAFF381CA, 0x68C43EB9, 0x24342C38, 0xA3405FC2, 0x1DC37216, 0xE2250CBC, 0x3C498B28, 0x0D9541FF, 0xA8017139, 0x0CB3DE08, 0xB4E49CD8, 0x56C19064, 0xCB84617B, 0x32B670D5, 0x6C5C7448, 0xB85742D0 }; /* * AES Encryption */ void aes_encrypt_n(const byte in[], byte out[], size_t blocks, const MemoryRegion& EK, const MemoryRegion& ME) { const size_t BLOCK_SIZE = 16; const u32bit* TE0 = TE; const u32bit* TE1 = TE + 256; const u32bit* TE2 = TE + 512; const u32bit* TE3 = TE + 768; for(size_t i = 0; i != blocks; ++i) { u32bit T0 = load_be(in, 0) ^ EK[0]; u32bit T1 = load_be(in, 1) ^ EK[1]; u32bit T2 = load_be(in, 2) ^ EK[2]; u32bit T3 = load_be(in, 3) ^ EK[3]; /* Use only the first 256 entries of the TE table and do the * rotations directly in the code. This reduces the number of * cache lines potentially used in the first round from 64 to 16 * (assuming a typical 64 byte cache line), which makes timing * attacks a little harder; the first round is particularly * vulnerable. */ u32bit B0 = TE[get_byte(0, T0)] ^ rotate_right(TE[get_byte(1, T1)], 8) ^ rotate_right(TE[get_byte(2, T2)], 16) ^ rotate_right(TE[get_byte(3, T3)], 24) ^ EK[4]; u32bit B1 = TE[get_byte(0, T1)] ^ rotate_right(TE[get_byte(1, T2)], 8) ^ rotate_right(TE[get_byte(2, T3)], 16) ^ rotate_right(TE[get_byte(3, T0)], 24) ^ EK[5]; u32bit B2 = TE[get_byte(0, T2)] ^ rotate_right(TE[get_byte(1, T3)], 8) ^ rotate_right(TE[get_byte(2, T0)], 16) ^ rotate_right(TE[get_byte(3, T1)], 24) ^ EK[6]; u32bit B3 = TE[get_byte(0, T3)] ^ rotate_right(TE[get_byte(1, T0)], 8) ^ rotate_right(TE[get_byte(2, T1)], 16) ^ rotate_right(TE[get_byte(3, T2)], 24) ^ EK[7]; for(size_t r = 2*4; r < EK.size(); r += 2*4) { T0 = TE0[get_byte(0, B0)] ^ TE1[get_byte(1, B1)] ^ TE2[get_byte(2, B2)] ^ TE3[get_byte(3, B3)] ^ EK[r]; T1 = TE0[get_byte(0, B1)] ^ TE1[get_byte(1, B2)] ^ TE2[get_byte(2, B3)] ^ TE3[get_byte(3, B0)] ^ EK[r+1]; T2 = TE0[get_byte(0, B2)] ^ TE1[get_byte(1, B3)] ^ TE2[get_byte(2, B0)] ^ TE3[get_byte(3, B1)] ^ EK[r+2]; T3 = TE0[get_byte(0, B3)] ^ TE1[get_byte(1, B0)] ^ TE2[get_byte(2, B1)] ^ TE3[get_byte(3, B2)] ^ EK[r+3]; B0 = TE0[get_byte(0, T0)] ^ TE1[get_byte(1, T1)] ^ TE2[get_byte(2, T2)] ^ TE3[get_byte(3, T3)] ^ EK[r+4]; B1 = TE0[get_byte(0, T1)] ^ TE1[get_byte(1, T2)] ^ TE2[get_byte(2, T3)] ^ TE3[get_byte(3, T0)] ^ EK[r+5]; B2 = TE0[get_byte(0, T2)] ^ TE1[get_byte(1, T3)] ^ TE2[get_byte(2, T0)] ^ TE3[get_byte(3, T1)] ^ EK[r+6]; B3 = TE0[get_byte(0, T3)] ^ TE1[get_byte(1, T0)] ^ TE2[get_byte(2, T1)] ^ TE3[get_byte(3, T2)] ^ EK[r+7]; } /* Joseph Bonneau and Ilya Mironov's paper "Cache-Collision Timing Attacks Against AES" describes an attack that can recover AES keys with as few as 2**13 samples. http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.88.4753 They recommend using a byte-wide table, which still allows an attack but increases the samples required from 2**13 to 2**25: """In addition to OpenSSL v. 0.9.8.(a), which was used in our experiments, the AES implementations of Crypto++ 5.2.1 and 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_decrypt_n(const byte in[], byte out[], size_t blocks, const MemoryRegion& DK, const MemoryRegion& MD) { const size_t BLOCK_SIZE = 16; const u32bit* TD0 = TD; const u32bit* TD1 = TD + 256; const u32bit* TD2 = TD + 512; const u32bit* TD3 = TD + 768; for(size_t i = 0; i != blocks; ++i) { u32bit T0 = load_be(in, 0) ^ DK[0]; u32bit T1 = load_be(in, 1) ^ DK[1]; u32bit T2 = load_be(in, 2) ^ DK[2]; u32bit T3 = load_be(in, 3) ^ DK[3]; u32bit B0 = TD[get_byte(0, T0)] ^ rotate_right(TD[get_byte(1, T3)], 8) ^ rotate_right(TD[get_byte(2, T2)], 16) ^ rotate_right(TD[get_byte(3, T1)], 24) ^ DK[4]; u32bit B1 = TD[get_byte(0, T1)] ^ rotate_right(TD[get_byte(1, T0)], 8) ^ rotate_right(TD[get_byte(2, T3)], 16) ^ rotate_right(TD[get_byte(3, T2)], 24) ^ DK[5]; u32bit B2 = TD[get_byte(0, T2)] ^ rotate_right(TD[get_byte(1, T1)], 8) ^ rotate_right(TD[get_byte(2, T0)], 16) ^ rotate_right(TD[get_byte(3, T3)], 24) ^ DK[6]; u32bit B3 = TD[get_byte(0, T3)] ^ rotate_right(TD[get_byte(1, T2)], 8) ^ rotate_right(TD[get_byte(2, T1)], 16) ^ rotate_right(TD[get_byte(3, T0)], 24) ^ DK[7]; for(size_t r = 2*4; r < DK.size(); r += 2*4) { T0 = TD0[get_byte(0, B0)] ^ TD1[get_byte(1, B3)] ^ TD2[get_byte(2, B2)] ^ TD3[get_byte(3, B1)] ^ DK[r]; T1 = TD0[get_byte(0, B1)] ^ TD1[get_byte(1, B0)] ^ TD2[get_byte(2, B3)] ^ TD3[get_byte(3, B2)] ^ DK[r+1]; T2 = TD0[get_byte(0, B2)] ^ TD1[get_byte(1, B1)] ^ TD2[get_byte(2, B0)] ^ TD3[get_byte(3, B3)] ^ DK[r+2]; T3 = TD0[get_byte(0, B3)] ^ TD1[get_byte(1, B2)] ^ TD2[get_byte(2, B1)] ^ TD3[get_byte(3, B0)] ^ DK[r+3]; B0 = TD0[get_byte(0, T0)] ^ TD1[get_byte(1, T3)] ^ TD2[get_byte(2, T2)] ^ TD3[get_byte(3, T1)] ^ DK[r+4]; B1 = TD0[get_byte(0, T1)] ^ TD1[get_byte(1, T0)] ^ TD2[get_byte(2, T3)] ^ TD3[get_byte(3, T2)] ^ DK[r+5]; B2 = TD0[get_byte(0, T2)] ^ TD1[get_byte(1, T1)] ^ TD2[get_byte(2, T0)] ^ TD3[get_byte(3, T3)] ^ DK[r+6]; B3 = TD0[get_byte(0, T3)] ^ TD1[get_byte(1, T2)] ^ TD2[get_byte(2, T1)] ^ TD3[get_byte(3, T0)] ^ DK[r+7]; } 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; } } void aes_key_schedule(const byte key[], size_t length, MemoryRegion& EK, MemoryRegion& DK, MemoryRegion& ME, MemoryRegion& MD) { static const u32bit RC[10] = { 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000 }; const size_t rounds = (length / 4) + 6; SecureVector XEK(length + 32), XDK(length + 32); const size_t X = length / 4; for(size_t i = 0; i != X; ++i) XEK[i] = load_be(key, i); for(size_t i = X; i < 4*(rounds+1); i += X) { XEK[i] = XEK[i-X] ^ RC[(i-X)/X] ^ make_u32bit(SE[get_byte(1, XEK[i-1])], SE[get_byte(2, XEK[i-1])], SE[get_byte(3, XEK[i-1])], SE[get_byte(0, XEK[i-1])]); for(size_t j = 1; j != X; ++j) { XEK[i+j] = XEK[i+j-X]; if(X == 8 && j == 4) XEK[i+j] ^= make_u32bit(SE[get_byte(0, XEK[i+j-1])], SE[get_byte(1, XEK[i+j-1])], SE[get_byte(2, XEK[i+j-1])], SE[get_byte(3, XEK[i+j-1])]); else XEK[i+j] ^= XEK[i+j-1]; } } for(size_t i = 0; i != 4*(rounds+1); i += 4) { XDK[i ] = XEK[4*rounds-i ]; XDK[i+1] = XEK[4*rounds-i+1]; XDK[i+2] = XEK[4*rounds-i+2]; XDK[i+3] = XEK[4*rounds-i+3]; } for(size_t i = 4; i != length + 24; ++i) XDK[i] = TD[SE[get_byte(0, XDK[i])] + 0] ^ TD[SE[get_byte(1, XDK[i])] + 256] ^ TD[SE[get_byte(2, XDK[i])] + 512] ^ TD[SE[get_byte(3, XDK[i])] + 768]; for(size_t i = 0; i != 4; ++i) { store_be(XEK[i+4*rounds], &ME[4*i]); store_be(XEK[i], &MD[4*i]); } EK.resize(length + 24); DK.resize(length + 24); copy_mem(&EK[0], &XEK[0], EK.size()); copy_mem(&DK[0], &XDK[0], DK.size()); } } void AES_128::encrypt_n(const byte in[], byte out[], size_t blocks) const { aes_encrypt_n(in, out, blocks, EK, ME); } void AES_128::decrypt_n(const byte in[], byte out[], size_t blocks) const { aes_decrypt_n(in, out, blocks, DK, MD); } void AES_128::key_schedule(const byte key[], size_t length) { aes_key_schedule(key, length, EK, DK, ME, MD); } void AES_128::clear() { zeroise(EK); zeroise(DK); zeroise(ME); zeroise(MD); } void AES_192::encrypt_n(const byte in[], byte out[], size_t blocks) const { aes_encrypt_n(in, out, blocks, EK, ME); } void AES_192::decrypt_n(const byte in[], byte out[], size_t blocks) const { aes_decrypt_n(in, out, blocks, DK, MD); } void AES_192::key_schedule(const byte key[], size_t length) { aes_key_schedule(key, length, EK, DK, ME, MD); } void AES_192::clear() { zeroise(EK); zeroise(DK); zeroise(ME); zeroise(MD); } void AES_256::encrypt_n(const byte in[], byte out[], size_t blocks) const { aes_encrypt_n(in, out, blocks, EK, ME); } void AES_256::decrypt_n(const byte in[], byte out[], size_t blocks) const { aes_decrypt_n(in, out, blocks, DK, MD); } void AES_256::key_schedule(const byte key[], size_t length) { aes_key_schedule(key, length, EK, DK, ME, MD); } void AES_256::clear() { zeroise(EK); zeroise(DK); zeroise(ME); zeroise(MD); } } /* * S-Box and P-Box Tables for Blowfish * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { const u32bit Blowfish::P_INIT[18] = { 0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344, 0xA4093822, 0x299F31D0, 0x082EFA98, 0xEC4E6C89, 0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C, 0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, 0xB5470917, 0x9216D5D9, 0x8979FB1B }; const u32bit Blowfish::S_INIT[1024] = { 0xD1310BA6, 0x98DFB5AC, 0x2FFD72DB, 0xD01ADFB7, 0xB8E1AFED, 0x6A267E96, 0xBA7C9045, 0xF12C7F99, 0x24A19947, 0xB3916CF7, 0x0801F2E2, 0x858EFC16, 0x636920D8, 0x71574E69, 0xA458FEA3, 0xF4933D7E, 0x0D95748F, 0x728EB658, 0x718BCD58, 0x82154AEE, 0x7B54A41D, 0xC25A59B5, 0x9C30D539, 0x2AF26013, 0xC5D1B023, 0x286085F0, 0xCA417918, 0xB8DB38EF, 0x8E79DCB0, 0x603A180E, 0x6C9E0E8B, 0xB01E8A3E, 0xD71577C1, 0xBD314B27, 0x78AF2FDA, 0x55605C60, 0xE65525F3, 0xAA55AB94, 0x57489862, 0x63E81440, 0x55CA396A, 0x2AAB10B6, 0xB4CC5C34, 0x1141E8CE, 0xA15486AF, 0x7C72E993, 0xB3EE1411, 0x636FBC2A, 0x2BA9C55D, 0x741831F6, 0xCE5C3E16, 0x9B87931E, 0xAFD6BA33, 0x6C24CF5C, 0x7A325381, 0x28958677, 0x3B8F4898, 0x6B4BB9AF, 0xC4BFE81B, 0x66282193, 0x61D809CC, 0xFB21A991, 0x487CAC60, 0x5DEC8032, 0xEF845D5D, 0xE98575B1, 0xDC262302, 0xEB651B88, 0x23893E81, 0xD396ACC5, 0x0F6D6FF3, 0x83F44239, 0x2E0B4482, 0xA4842004, 0x69C8F04A, 0x9E1F9B5E, 0x21C66842, 0xF6E96C9A, 0x670C9C61, 0xABD388F0, 0x6A51A0D2, 0xD8542F68, 0x960FA728, 0xAB5133A3, 0x6EEF0B6C, 0x137A3BE4, 0xBA3BF050, 0x7EFB2A98, 0xA1F1651D, 0x39AF0176, 0x66CA593E, 0x82430E88, 0x8CEE8619, 0x456F9FB4, 0x7D84A5C3, 0x3B8B5EBE, 0xE06F75D8, 0x85C12073, 0x401A449F, 0x56C16AA6, 0x4ED3AA62, 0x363F7706, 0x1BFEDF72, 0x429B023D, 0x37D0D724, 0xD00A1248, 0xDB0FEAD3, 0x49F1C09B, 0x075372C9, 0x80991B7B, 0x25D479D8, 0xF6E8DEF7, 0xE3FE501A, 0xB6794C3B, 0x976CE0BD, 0x04C006BA, 0xC1A94FB6, 0x409F60C4, 0x5E5C9EC2, 0x196A2463, 0x68FB6FAF, 0x3E6C53B5, 0x1339B2EB, 0x3B52EC6F, 0x6DFC511F, 0x9B30952C, 0xCC814544, 0xAF5EBD09, 0xBEE3D004, 0xDE334AFD, 0x660F2807, 0x192E4BB3, 0xC0CBA857, 0x45C8740F, 0xD20B5F39, 0xB9D3FBDB, 0x5579C0BD, 0x1A60320A, 0xD6A100C6, 0x402C7279, 0x679F25FE, 0xFB1FA3CC, 0x8EA5E9F8, 0xDB3222F8, 0x3C7516DF, 0xFD616B15, 0x2F501EC8, 0xAD0552AB, 0x323DB5FA, 0xFD238760, 0x53317B48, 0x3E00DF82, 0x9E5C57BB, 0xCA6F8CA0, 0x1A87562E, 0xDF1769DB, 0xD542A8F6, 0x287EFFC3, 0xAC6732C6, 0x8C4F5573, 0x695B27B0, 0xBBCA58C8, 0xE1FFA35D, 0xB8F011A0, 0x10FA3D98, 0xFD2183B8, 0x4AFCB56C, 0x2DD1D35B, 0x9A53E479, 0xB6F84565, 0xD28E49BC, 0x4BFB9790, 0xE1DDF2DA, 0xA4CB7E33, 0x62FB1341, 0xCEE4C6E8, 0xEF20CADA, 0x36774C01, 0xD07E9EFE, 0x2BF11FB4, 0x95DBDA4D, 0xAE909198, 0xEAAD8E71, 0x6B93D5A0, 0xD08ED1D0, 0xAFC725E0, 0x8E3C5B2F, 0x8E7594B7, 0x8FF6E2FB, 0xF2122B64, 0x8888B812, 0x900DF01C, 0x4FAD5EA0, 0x688FC31C, 0xD1CFF191, 0xB3A8C1AD, 0x2F2F2218, 0xBE0E1777, 0xEA752DFE, 0x8B021FA1, 0xE5A0CC0F, 0xB56F74E8, 0x18ACF3D6, 0xCE89E299, 0xB4A84FE0, 0xFD13E0B7, 0x7CC43B81, 0xD2ADA8D9, 0x165FA266, 0x80957705, 0x93CC7314, 0x211A1477, 0xE6AD2065, 0x77B5FA86, 0xC75442F5, 0xFB9D35CF, 0xEBCDAF0C, 0x7B3E89A0, 0xD6411BD3, 0xAE1E7E49, 0x00250E2D, 0x2071B35E, 0x226800BB, 0x57B8E0AF, 0x2464369B, 0xF009B91E, 0x5563911D, 0x59DFA6AA, 0x78C14389, 0xD95A537F, 0x207D5BA2, 0x02E5B9C5, 0x83260376, 0x6295CFA9, 0x11C81968, 0x4E734A41, 0xB3472DCA, 0x7B14A94A, 0x1B510052, 0x9A532915, 0xD60F573F, 0xBC9BC6E4, 0x2B60A476, 0x81E67400, 0x08BA6FB5, 0x571BE91F, 0xF296EC6B, 0x2A0DD915, 0xB6636521, 0xE7B9F9B6, 0xFF34052E, 0xC5855664, 0x53B02D5D, 0xA99F8FA1, 0x08BA4799, 0x6E85076A, 0x4B7A70E9, 0xB5B32944, 0xDB75092E, 0xC4192623, 0xAD6EA6B0, 0x49A7DF7D, 0x9CEE60B8, 0x8FEDB266, 0xECAA8C71, 0x699A17FF, 0x5664526C, 0xC2B19EE1, 0x193602A5, 0x75094C29, 0xA0591340, 0xE4183A3E, 0x3F54989A, 0x5B429D65, 0x6B8FE4D6, 0x99F73FD6, 0xA1D29C07, 0xEFE830F5, 0x4D2D38E6, 0xF0255DC1, 0x4CDD2086, 0x8470EB26, 0x6382E9C6, 0x021ECC5E, 0x09686B3F, 0x3EBAEFC9, 0x3C971814, 0x6B6A70A1, 0x687F3584, 0x52A0E286, 0xB79C5305, 0xAA500737, 0x3E07841C, 0x7FDEAE5C, 0x8E7D44EC, 0x5716F2B8, 0xB03ADA37, 0xF0500C0D, 0xF01C1F04, 0x0200B3FF, 0xAE0CF51A, 0x3CB574B2, 0x25837A58, 0xDC0921BD, 0xD19113F9, 0x7CA92FF6, 0x94324773, 0x22F54701, 0x3AE5E581, 0x37C2DADC, 0xC8B57634, 0x9AF3DDA7, 0xA9446146, 0x0FD0030E, 0xECC8C73E, 0xA4751E41, 0xE238CD99, 0x3BEA0E2F, 0x3280BBA1, 0x183EB331, 0x4E548B38, 0x4F6DB908, 0x6F420D03, 0xF60A04BF, 0x2CB81290, 0x24977C79, 0x5679B072, 0xBCAF89AF, 0xDE9A771F, 0xD9930810, 0xB38BAE12, 0xDCCF3F2E, 0x5512721F, 0x2E6B7124, 0x501ADDE6, 0x9F84CD87, 0x7A584718, 0x7408DA17, 0xBC9F9ABC, 0xE94B7D8C, 0xEC7AEC3A, 0xDB851DFA, 0x63094366, 0xC464C3D2, 0xEF1C1847, 0x3215D908, 0xDD433B37, 0x24C2BA16, 0x12A14D43, 0x2A65C451, 0x50940002, 0x133AE4DD, 0x71DFF89E, 0x10314E55, 0x81AC77D6, 0x5F11199B, 0x043556F1, 0xD7A3C76B, 0x3C11183B, 0x5924A509, 0xF28FE6ED, 0x97F1FBFA, 0x9EBABF2C, 0x1E153C6E, 0x86E34570, 0xEAE96FB1, 0x860E5E0A, 0x5A3E2AB3, 0x771FE71C, 0x4E3D06FA, 0x2965DCB9, 0x99E71D0F, 0x803E89D6, 0x5266C825, 0x2E4CC978, 0x9C10B36A, 0xC6150EBA, 0x94E2EA78, 0xA5FC3C53, 0x1E0A2DF4, 0xF2F74EA7, 0x361D2B3D, 0x1939260F, 0x19C27960, 0x5223A708, 0xF71312B6, 0xEBADFE6E, 0xEAC31F66, 0xE3BC4595, 0xA67BC883, 0xB17F37D1, 0x018CFF28, 0xC332DDEF, 0xBE6C5AA5, 0x65582185, 0x68AB9802, 0xEECEA50F, 0xDB2F953B, 0x2AEF7DAD, 0x5B6E2F84, 0x1521B628, 0x29076170, 0xECDD4775, 0x619F1510, 0x13CCA830, 0xEB61BD96, 0x0334FE1E, 0xAA0363CF, 0xB5735C90, 0x4C70A239, 0xD59E9E0B, 0xCBAADE14, 0xEECC86BC, 0x60622CA7, 0x9CAB5CAB, 0xB2F3846E, 0x648B1EAF, 0x19BDF0CA, 0xA02369B9, 0x655ABB50, 0x40685A32, 0x3C2AB4B3, 0x319EE9D5, 0xC021B8F7, 0x9B540B19, 0x875FA099, 0x95F7997E, 0x623D7DA8, 0xF837889A, 0x97E32D77, 0x11ED935F, 0x16681281, 0x0E358829, 0xC7E61FD6, 0x96DEDFA1, 0x7858BA99, 0x57F584A5, 0x1B227263, 0x9B83C3FF, 0x1AC24696, 0xCDB30AEB, 0x532E3054, 0x8FD948E4, 0x6DBC3128, 0x58EBF2EF, 0x34C6FFEA, 0xFE28ED61, 0xEE7C3C73, 0x5D4A14D9, 0xE864B7E3, 0x42105D14, 0x203E13E0, 0x45EEE2B6, 0xA3AAABEA, 0xDB6C4F15, 0xFACB4FD0, 0xC742F442, 0xEF6ABBB5, 0x654F3B1D, 0x41CD2105, 0xD81E799E, 0x86854DC7, 0xE44B476A, 0x3D816250, 0xCF62A1F2, 0x5B8D2646, 0xFC8883A0, 0xC1C7B6A3, 0x7F1524C3, 0x69CB7492, 0x47848A0B, 0x5692B285, 0x095BBF00, 0xAD19489D, 0x1462B174, 0x23820E00, 0x58428D2A, 0x0C55F5EA, 0x1DADF43E, 0x233F7061, 0x3372F092, 0x8D937E41, 0xD65FECF1, 0x6C223BDB, 0x7CDE3759, 0xCBEE7460, 0x4085F2A7, 0xCE77326E, 0xA6078084, 0x19F8509E, 0xE8EFD855, 0x61D99735, 0xA969A7AA, 0xC50C06C2, 0x5A04ABFC, 0x800BCADC, 0x9E447A2E, 0xC3453484, 0xFDD56705, 0x0E1E9EC9, 0xDB73DBD3, 0x105588CD, 0x675FDA79, 0xE3674340, 0xC5C43465, 0x713E38D8, 0x3D28F89E, 0xF16DFF20, 0x153E21E7, 0x8FB03D4A, 0xE6E39F2B, 0xDB83ADF7, 0xE93D5A68, 0x948140F7, 0xF64C261C, 0x94692934, 0x411520F7, 0x7602D4F7, 0xBCF46B2E, 0xD4A20068, 0xD4082471, 0x3320F46A, 0x43B7D4B7, 0x500061AF, 0x1E39F62E, 0x97244546, 0x14214F74, 0xBF8B8840, 0x4D95FC1D, 0x96B591AF, 0x70F4DDD3, 0x66A02F45, 0xBFBC09EC, 0x03BD9785, 0x7FAC6DD0, 0x31CB8504, 0x96EB27B3, 0x55FD3941, 0xDA2547E6, 0xABCA0A9A, 0x28507825, 0x530429F4, 0x0A2C86DA, 0xE9B66DFB, 0x68DC1462, 0xD7486900, 0x680EC0A4, 0x27A18DEE, 0x4F3FFEA2, 0xE887AD8C, 0xB58CE006, 0x7AF4D6B6, 0xAACE1E7C, 0xD3375FEC, 0xCE78A399, 0x406B2A42, 0x20FE9E35, 0xD9F385B9, 0xEE39D7AB, 0x3B124E8B, 0x1DC9FAF7, 0x4B6D1856, 0x26A36631, 0xEAE397B2, 0x3A6EFA74, 0xDD5B4332, 0x6841E7F7, 0xCA7820FB, 0xFB0AF54E, 0xD8FEB397, 0x454056AC, 0xBA489527, 0x55533A3A, 0x20838D87, 0xFE6BA9B7, 0xD096954B, 0x55A867BC, 0xA1159A58, 0xCCA92963, 0x99E1DB33, 0xA62A4A56, 0x3F3125F9, 0x5EF47E1C, 0x9029317C, 0xFDF8E802, 0x04272F70, 0x80BB155C, 0x05282CE3, 0x95C11548, 0xE4C66D22, 0x48C1133F, 0xC70F86DC, 0x07F9C9EE, 0x41041F0F, 0x404779A4, 0x5D886E17, 0x325F51EB, 0xD59BC0D1, 0xF2BCC18F, 0x41113564, 0x257B7834, 0x602A9C60, 0xDFF8E8A3, 0x1F636C1B, 0x0E12B4C2, 0x02E1329E, 0xAF664FD1, 0xCAD18115, 0x6B2395E0, 0x333E92E1, 0x3B240B62, 0xEEBEB922, 0x85B2A20E, 0xE6BA0D99, 0xDE720C8C, 0x2DA2F728, 0xD0127845, 0x95B794FD, 0x647D0862, 0xE7CCF5F0, 0x5449A36F, 0x877D48FA, 0xC39DFD27, 0xF33E8D1E, 0x0A476341, 0x992EFF74, 0x3A6F6EAB, 0xF4F8FD37, 0xA812DC60, 0xA1EBDDF8, 0x991BE14C, 0xDB6E6B0D, 0xC67B5510, 0x6D672C37, 0x2765D43B, 0xDCD0E804, 0xF1290DC7, 0xCC00FFA3, 0xB5390F92, 0x690FED0B, 0x667B9FFB, 0xCEDB7D9C, 0xA091CF0B, 0xD9155EA3, 0xBB132F88, 0x515BAD24, 0x7B9479BF, 0x763BD6EB, 0x37392EB3, 0xCC115979, 0x8026E297, 0xF42E312D, 0x6842ADA7, 0xC66A2B3B, 0x12754CCC, 0x782EF11C, 0x6A124237, 0xB79251E7, 0x06A1BBE6, 0x4BFB6350, 0x1A6B1018, 0x11CAEDFA, 0x3D25BDD8, 0xE2E1C3C9, 0x44421659, 0x0A121386, 0xD90CEC6E, 0xD5ABEA2A, 0x64AF674E, 0xDA86A85F, 0xBEBFE988, 0x64E4C3FE, 0x9DBC8057, 0xF0F7C086, 0x60787BF8, 0x6003604D, 0xD1FD8346, 0xF6381FB0, 0x7745AE04, 0xD736FCCC, 0x83426B33, 0xF01EAB71, 0xB0804187, 0x3C005E5F, 0x77A057BE, 0xBDE8AE24, 0x55464299, 0xBF582E61, 0x4E58F48F, 0xF2DDFDA2, 0xF474EF38, 0x8789BDC2, 0x5366F9C3, 0xC8B38E74, 0xB475F255, 0x46FCD9B9, 0x7AEB2661, 0x8B1DDF84, 0x846A0E79, 0x915F95E2, 0x466E598E, 0x20B45770, 0x8CD55591, 0xC902DE4C, 0xB90BACE1, 0xBB8205D0, 0x11A86248, 0x7574A99E, 0xB77F19B6, 0xE0A9DC09, 0x662D09A1, 0xC4324633, 0xE85A1F02, 0x09F0BE8C, 0x4A99A025, 0x1D6EFE10, 0x1AB93D1D, 0x0BA5A4DF, 0xA186F20F, 0x2868F169, 0xDCB7DA83, 0x573906FE, 0xA1E2CE9B, 0x4FCD7F52, 0x50115E01, 0xA70683FA, 0xA002B5C4, 0x0DE6D027, 0x9AF88C27, 0x773F8641, 0xC3604C06, 0x61A806B5, 0xF0177A28, 0xC0F586E0, 0x006058AA, 0x30DC7D62, 0x11E69ED7, 0x2338EA63, 0x53C2DD94, 0xC2C21634, 0xBBCBEE56, 0x90BCB6DE, 0xEBFC7DA1, 0xCE591D76, 0x6F05E409, 0x4B7C0188, 0x39720A3D, 0x7C927C24, 0x86E3725F, 0x724D9DB9, 0x1AC15BB4, 0xD39EB8FC, 0xED545578, 0x08FCA5B5, 0xD83D7CD3, 0x4DAD0FC4, 0x1E50EF5E, 0xB161E6F8, 0xA28514D9, 0x6C51133C, 0x6FD5C7E7, 0x56E14EC4, 0x362ABFCE, 0xDDC6C837, 0xD79A3234, 0x92638212, 0x670EFA8E, 0x406000E0, 0x3A39CE37, 0xD3FAF5CF, 0xABC27737, 0x5AC52D1B, 0x5CB0679E, 0x4FA33742, 0xD3822740, 0x99BC9BBE, 0xD5118E9D, 0xBF0F7315, 0xD62D1C7E, 0xC700C47B, 0xB78C1B6B, 0x21A19045, 0xB26EB1BE, 0x6A366EB4, 0x5748AB2F, 0xBC946E79, 0xC6A376D2, 0x6549C2C8, 0x530FF8EE, 0x468DDE7D, 0xD5730A1D, 0x4CD04DC6, 0x2939BBDB, 0xA9BA4650, 0xAC9526E8, 0xBE5EE304, 0xA1FAD5F0, 0x6A2D519A, 0x63EF8CE2, 0x9A86EE22, 0xC089C2B8, 0x43242EF6, 0xA51E03AA, 0x9CF2D0A4, 0x83C061BA, 0x9BE96A4D, 0x8FE51550, 0xBA645BD6, 0x2826A2F9, 0xA73A3AE1, 0x4BA99586, 0xEF5562E9, 0xC72FEFD3, 0xF752F7DA, 0x3F046F69, 0x77FA0A59, 0x80E4A915, 0x87B08601, 0x9B09E6AD, 0x3B3EE593, 0xE990FD5A, 0x9E34D797, 0x2CF0B7D9, 0x022B8B51, 0x96D5AC3A, 0x017DA67D, 0xD1CF3ED6, 0x7C7D2D28, 0x1F9F25CF, 0xADF2B89B, 0x5AD6B472, 0x5A88F54C, 0xE029AC71, 0xE019A5E6, 0x47B0ACFD, 0xED93FA9B, 0xE8D3C48D, 0x283B57CC, 0xF8D56629, 0x79132E28, 0x785F0191, 0xED756055, 0xF7960E44, 0xE3D35E8C, 0x15056DD4, 0x88F46DBA, 0x03A16125, 0x0564F0BD, 0xC3EB9E15, 0x3C9057A2, 0x97271AEC, 0xA93A072A, 0x1B3F6D9B, 0x1E6321F5, 0xF59C66FB, 0x26DCF319, 0x7533D928, 0xB155FDF5, 0x03563482, 0x8ABA3CBB, 0x28517711, 0xC20AD9F8, 0xABCC5167, 0xCCAD925F, 0x4DE81751, 0x3830DC8E, 0x379D5862, 0x9320F991, 0xEA7A90C2, 0xFB3E7BCE, 0x5121CE64, 0x774FBE32, 0xA8B6E37E, 0xC3293D46, 0x48DE5369, 0x6413E680, 0xA2AE0810, 0xDD6DB224, 0x69852DFD, 0x09072166, 0xB39A460A, 0x6445C0DD, 0x586CDECF, 0x1C20C8AE, 0x5BBEF7DD, 0x1B588D40, 0xCCD2017F, 0x6BB4E3BB, 0xDDA26A7E, 0x3A59FF45, 0x3E350A44, 0xBCB4CDD5, 0x72EACEA8, 0xFA6484BB, 0x8D6612AE, 0xBF3C6F47, 0xD29BE463, 0x542F5D9E, 0xAEC2771B, 0xF64E6370, 0x740E0D8D, 0xE75B1357, 0xF8721671, 0xAF537D5D, 0x4040CB08, 0x4EB4E2CC, 0x34D2466A, 0x0115AF84, 0xE1B00428, 0x95983A1D, 0x06B89FB4, 0xCE6EA048, 0x6F3F3B82, 0x3520AB82, 0x011A1D4B, 0x277227F8, 0x611560B1, 0xE7933FDC, 0xBB3A792B, 0x344525BD, 0xA08839E1, 0x51CE794B, 0x2F32C9B7, 0xA01FBAC9, 0xE01CC87E, 0xBCC7D1F6, 0xCF0111C3, 0xA1E8AAC7, 0x1A908749, 0xD44FBD9A, 0xD0DADECB, 0xD50ADA38, 0x0339C32A, 0xC6913667, 0x8DF9317C, 0xE0B12B4F, 0xF79E59B7, 0x43F5BB3A, 0xF2D519FF, 0x27D9459C, 0xBF97222C, 0x15E6FC2A, 0x0F91FC71, 0x9B941525, 0xFAE59361, 0xCEB69CEB, 0xC2A86459, 0x12BAA8D1, 0xB6C1075E, 0xE3056A0C, 0x10D25065, 0xCB03A442, 0xE0EC6E0E, 0x1698DB3B, 0x4C98A0BE, 0x3278E964, 0x9F1F9532, 0xE0D392DF, 0xD3A0342B, 0x8971F21E, 0x1B0A7441, 0x4BA3348C, 0xC5BE7120, 0xC37632D8, 0xDF359F8D, 0x9B992F2E, 0xE60B6F47, 0x0FE3F11D, 0xE54CDA54, 0x1EDAD891, 0xCE6279CF, 0xCD3E7E6F, 0x1618B166, 0xFD2C1D05, 0x848FD2C5, 0xF6FB2299, 0xF523F357, 0xA6327623, 0x93A83531, 0x56CCCD02, 0xACF08162, 0x5A75EBB5, 0x6E163697, 0x88D273CC, 0xDE966292, 0x81B949D0, 0x4C50901B, 0x71C65614, 0xE6C6C7BD, 0x327A140A, 0x45E1D006, 0xC3F27B9A, 0xC9AA53FD, 0x62A80F00, 0xBB25BFE2, 0x35BDD2F6, 0x71126905, 0xB2040222, 0xB6CBCF7C, 0xCD769C2B, 0x53113EC0, 0x1640E3D3, 0x38ABBD60, 0x2547ADF0, 0xBA38209C, 0xF746CE76, 0x77AFA1C5, 0x20756060, 0x85CBFE4E, 0x8AE88DD8, 0x7AAAF9B0, 0x4CF9AA7E, 0x1948C25C, 0x02FB8A8C, 0x01C36AE4, 0xD6EBE1F9, 0x90D4F869, 0xA65CDEA0, 0x3F09252D, 0xC208E69F, 0xB74E6132, 0xCE77E25B, 0x578FDFE3, 0x3AC372E6 }; } /* * Blowfish * (C) 1999-2011 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { /* * Blowfish Encryption */ void Blowfish::encrypt_n(const byte in[], byte out[], size_t blocks) const { const u32bit* S1 = &S[0]; const u32bit* S2 = &S[256]; const u32bit* S3 = &S[512]; const u32bit* S4 = &S[768]; for(size_t i = 0; i != blocks; ++i) { u32bit L = load_be(in, 0); u32bit R = load_be(in, 1); for(size_t 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)]; 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); in += BLOCK_SIZE; out += BLOCK_SIZE; } } /* * Blowfish Decryption */ void Blowfish::decrypt_n(const byte in[], byte out[], size_t blocks) const { const u32bit* S1 = &S[0]; const u32bit* S2 = &S[256]; const u32bit* S3 = &S[512]; const u32bit* S4 = &S[768]; for(size_t i = 0; i != blocks; ++i) { u32bit L = load_be(in, 0); u32bit R = load_be(in, 1); for(size_t 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)]; 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); in += BLOCK_SIZE; out += BLOCK_SIZE; } } /* * Blowfish Key Schedule */ void Blowfish::key_schedule(const byte key[], size_t length) { clear(); const byte null_salt[16] = { 0 }; key_expansion(key, length, null_salt); } void Blowfish::key_expansion(const byte key[], size_t length, const byte salt[16]) { for(size_t i = 0, j = 0; i != 18; ++i, j += 4) P[i] ^= make_u32bit(key[(j ) % length], key[(j+1) % length], key[(j+2) % length], key[(j+3) % length]); u32bit L = 0, R = 0; generate_sbox(P, L, R, salt, 0); generate_sbox(S, L, R, salt, 2); } /* * Modified key schedule used for bcrypt password hashing */ void Blowfish::eks_key_schedule(const byte key[], size_t length, const byte salt[16], size_t workfactor) { if(length == 0 || length >= 56) throw Invalid_Key_Length("EKSBlowfish", length); if(workfactor == 0) throw std::invalid_argument("Bcrypt work factor must be at least 1"); /* * On a 2.8 GHz Core-i7, workfactor == 18 takes about 25 seconds to * hash a password. This seems like a reasonable upper bound for the * time being. */ if(workfactor > 18) throw std::invalid_argument("Requested Bcrypt work factor too large"); clear(); const byte null_salt[16] = { 0 }; key_expansion(key, length, salt); const size_t rounds = 1 << workfactor; for(size_t r = 0; r != rounds; ++r) { key_expansion(key, length, null_salt); key_expansion(salt, 16, null_salt); } } /* * Generate one of the Sboxes */ void Blowfish::generate_sbox(MemoryRegion& box, u32bit& L, u32bit& R, const byte salt[16], size_t salt_off) const { const u32bit* S1 = &S[0]; const u32bit* S2 = &S[256]; const u32bit* S3 = &S[512]; const u32bit* S4 = &S[768]; for(size_t i = 0; i != box.size(); i += 2) { L ^= load_be(salt, (i + salt_off) % 4); R ^= load_be(salt, (i + salt_off + 1) % 4); for(size_t 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)]; 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)]; } u32bit T = R; R = L ^ P[16]; L = T ^ P[17]; box[i] = L; box[i+1] = R; } } /* * Clear memory of sensitive data */ void Blowfish::clear() { std::copy(P_INIT, P_INIT + 18, P.begin()); std::copy(S_INIT, S_INIT + 1024, S.begin()); } } /* * Camellia * (C) 2012 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { namespace Camellia_F { namespace { /* * We use the slow byte-wise version of F in the first and last rounds * to help protect against timing attacks */ u64bit F_SLOW(u64bit v, u64bit K) { static const byte SBOX[256] = { 0x70, 0x82, 0x2C, 0xEC, 0xB3, 0x27, 0xC0, 0xE5, 0xE4, 0x85, 0x57, 0x35, 0xEA, 0x0C, 0xAE, 0x41, 0x23, 0xEF, 0x6B, 0x93, 0x45, 0x19, 0xA5, 0x21, 0xED, 0x0E, 0x4F, 0x4E, 0x1D, 0x65, 0x92, 0xBD, 0x86, 0xB8, 0xAF, 0x8F, 0x7C, 0xEB, 0x1F, 0xCE, 0x3E, 0x30, 0xDC, 0x5F, 0x5E, 0xC5, 0x0B, 0x1A, 0xA6, 0xE1, 0x39, 0xCA, 0xD5, 0x47, 0x5D, 0x3D, 0xD9, 0x01, 0x5A, 0xD6, 0x51, 0x56, 0x6C, 0x4D, 0x8B, 0x0D, 0x9A, 0x66, 0xFB, 0xCC, 0xB0, 0x2D, 0x74, 0x12, 0x2B, 0x20, 0xF0, 0xB1, 0x84, 0x99, 0xDF, 0x4C, 0xCB, 0xC2, 0x34, 0x7E, 0x76, 0x05, 0x6D, 0xB7, 0xA9, 0x31, 0xD1, 0x17, 0x04, 0xD7, 0x14, 0x58, 0x3A, 0x61, 0xDE, 0x1B, 0x11, 0x1C, 0x32, 0x0F, 0x9C, 0x16, 0x53, 0x18, 0xF2, 0x22, 0xFE, 0x44, 0xCF, 0xB2, 0xC3, 0xB5, 0x7A, 0x91, 0x24, 0x08, 0xE8, 0xA8, 0x60, 0xFC, 0x69, 0x50, 0xAA, 0xD0, 0xA0, 0x7D, 0xA1, 0x89, 0x62, 0x97, 0x54, 0x5B, 0x1E, 0x95, 0xE0, 0xFF, 0x64, 0xD2, 0x10, 0xC4, 0x00, 0x48, 0xA3, 0xF7, 0x75, 0xDB, 0x8A, 0x03, 0xE6, 0xDA, 0x09, 0x3F, 0xDD, 0x94, 0x87, 0x5C, 0x83, 0x02, 0xCD, 0x4A, 0x90, 0x33, 0x73, 0x67, 0xF6, 0xF3, 0x9D, 0x7F, 0xBF, 0xE2, 0x52, 0x9B, 0xD8, 0x26, 0xC8, 0x37, 0xC6, 0x3B, 0x81, 0x96, 0x6F, 0x4B, 0x13, 0xBE, 0x63, 0x2E, 0xE9, 0x79, 0xA7, 0x8C, 0x9F, 0x6E, 0xBC, 0x8E, 0x29, 0xF5, 0xF9, 0xB6, 0x2F, 0xFD, 0xB4, 0x59, 0x78, 0x98, 0x06, 0x6A, 0xE7, 0x46, 0x71, 0xBA, 0xD4, 0x25, 0xAB, 0x42, 0x88, 0xA2, 0x8D, 0xFA, 0x72, 0x07, 0xB9, 0x55, 0xF8, 0xEE, 0xAC, 0x0A, 0x36, 0x49, 0x2A, 0x68, 0x3C, 0x38, 0xF1, 0xA4, 0x40, 0x28, 0xD3, 0x7B, 0xBB, 0xC9, 0x43, 0xC1, 0x15, 0xE3, 0xAD, 0xF4, 0x77, 0xC7, 0x80, 0x9E }; const u64bit x = v ^ K; const byte t1 = SBOX[get_byte(0, x)]; const byte t2 = rotate_left(SBOX[get_byte(1, x)], 1); const byte t3 = rotate_left(SBOX[get_byte(2, x)], 7); const byte t4 = SBOX[rotate_left(get_byte(3, x), 1)]; const byte t5 = rotate_left(SBOX[get_byte(4, x)], 1); const byte t6 = rotate_left(SBOX[get_byte(5, x)], 7); const byte t7 = SBOX[rotate_left(get_byte(6, x), 1)]; const byte t8 = SBOX[get_byte(7, x)]; const byte y1 = t1 ^ t3 ^ t4 ^ t6 ^ t7 ^ t8; const byte y2 = t1 ^ t2 ^ t4 ^ t5 ^ t7 ^ t8; const byte y3 = t1 ^ t2 ^ t3 ^ t5 ^ t6 ^ t8; const byte y4 = t2 ^ t3 ^ t4 ^ t5 ^ t6 ^ t7; const byte y5 = t1 ^ t2 ^ t6 ^ t7 ^ t8; const byte y6 = t2 ^ t3 ^ t5 ^ t7 ^ t8; const byte y7 = t3 ^ t4 ^ t5 ^ t6 ^ t8; const byte y8 = t1 ^ t4 ^ t5 ^ t6 ^ t7; return make_u64bit(y1, y2, y3, y4, y5, y6, y7, y8); } inline u64bit F(u64bit v, u64bit K) { const u64bit x = v ^ K; return Camellia_SBOX1[get_byte(0, x)] ^ Camellia_SBOX2[get_byte(1, x)] ^ Camellia_SBOX3[get_byte(2, x)] ^ Camellia_SBOX4[get_byte(3, x)] ^ Camellia_SBOX5[get_byte(4, x)] ^ Camellia_SBOX6[get_byte(5, x)] ^ Camellia_SBOX7[get_byte(6, x)] ^ Camellia_SBOX8[get_byte(7, x)]; } inline u64bit FL(u64bit v, u64bit K) { u32bit x1 = (v >> 32); u32bit x2 = (v & 0xFFFFFFFF); const u32bit k1 = (K >> 32); const u32bit k2 = (K & 0xFFFFFFFF); x2 ^= rotate_left(x1 & k1, 1); x1 ^= (x2 | k2); return ((static_cast(x1) << 32) | x2); } inline u64bit FLINV(u64bit v, u64bit K) { u32bit x1 = (v >> 32); u32bit x2 = (v & 0xFFFFFFFF); const u32bit k1 = (K >> 32); const u32bit k2 = (K & 0xFFFFFFFF); x1 ^= (x2 | k2); x2 ^= rotate_left(x1 & k1, 1); return ((static_cast(x1) << 32) | x2); } /* * Camellia Encryption */ void encrypt(const byte in[], byte out[], size_t blocks, const SecureVector& SK, const size_t rounds) { for(size_t i = 0; i != blocks; ++i) { u64bit D1 = load_be(in, 0); u64bit D2 = load_be(in, 1); const u64bit* K = &SK[0]; D1 ^= *K++; D2 ^= *K++; D2 ^= F_SLOW(D1, *K++); D1 ^= F_SLOW(D2, *K++); for(size_t r = 1; r != rounds - 1; ++r) { if(r % 3 == 0) { D1 = FL (D1, *K++); D2 = FLINV(D2, *K++); } D2 ^= F(D1, *K++); D1 ^= F(D2, *K++); } D2 ^= F_SLOW(D1, *K++); D1 ^= F_SLOW(D2, *K++); D2 ^= *K++; D1 ^= *K++; store_be(out, D2, D1); in += 16; out += 16; } } /* * Camellia Decryption */ void decrypt(const byte in[], byte out[], size_t blocks, const SecureVector& SK, const size_t rounds) { for(size_t i = 0; i != blocks; ++i) { u64bit D1 = load_be(in, 0); u64bit D2 = load_be(in, 1); const u64bit* K = &SK[SK.size()-1]; D2 ^= *K--; D1 ^= *K--; D2 ^= F_SLOW(D1, *K--); D1 ^= F_SLOW(D2, *K--); for(size_t r = 1; r != rounds - 1; ++r) { if(r % 3 == 0) { D1 = FL (D1, *K--); D2 = FLINV(D2, *K--); } D2 ^= F(D1, *K--); D1 ^= F(D2, *K--); } D2 ^= F_SLOW(D1, *K--); D1 ^= F_SLOW(D2, *K--); D1 ^= *K--; D2 ^= *K; store_be(out, D2, D1); in += 16; out += 16; } } u64bit left_rot_hi(u64bit h, u64bit l, size_t shift) { return (h << shift) | ((l >> (64-shift))); } u64bit left_rot_lo(u64bit h, u64bit l, size_t shift) { return (h >> (64-shift)) | (l << shift); } /* * Camellia Key Schedule */ void key_schedule(SecureVector& SK, const byte key[], size_t length) { const u64bit Sigma1 = 0xA09E667F3BCC908BULL; const u64bit Sigma2 = 0xB67AE8584CAA73B2ULL; const u64bit Sigma3 = 0xC6EF372FE94F82BEULL; const u64bit Sigma4 = 0x54FF53A5F1D36F1CULL; const u64bit Sigma5 = 0x10E527FADE682D1DULL; const u64bit Sigma6 = 0xB05688C2B3E6C1FDULL; const u64bit KL_H = load_be(key, 0); const u64bit KL_L = load_be(key, 1); const u64bit KR_H = (length >= 24) ? load_be(key, 2) : 0; const u64bit KR_L = (length == 32) ? load_be(key, 3) : ((length == 24) ? ~KR_H : 0); u64bit D1 = KL_H ^ KR_H; u64bit D2 = KL_L ^ KR_L; D2 ^= F(D1, Sigma1); D1 ^= F(D2, Sigma2); D1 ^= KL_H; D2 ^= KL_L; D2 ^= F(D1, Sigma3); D1 ^= F(D2, Sigma4); const u64bit KA_H = D1; const u64bit KA_L = D2; D1 = KA_H ^ KR_H; D2 = KA_L ^ KR_L; D2 ^= F(D1, Sigma5); D1 ^= F(D2, Sigma6); const u64bit KB_H = D1; const u64bit KB_L = D2; if(length == 16) { SK.resize(26); SK[ 0] = KL_H; SK[ 1] = KL_L; SK[ 2] = KA_H; SK[ 3] = KA_L; SK[ 4] = left_rot_hi(KL_H, KL_L, 15); SK[ 5] = left_rot_lo(KL_H, KL_L, 15); SK[ 6] = left_rot_hi(KA_H, KA_L, 15); SK[ 7] = left_rot_lo(KA_H, KA_L, 15); SK[ 8] = left_rot_hi(KA_H, KA_L, 30); SK[ 9] = left_rot_lo(KA_H, KA_L, 30); SK[10] = left_rot_hi(KL_H, KL_L, 45); SK[11] = left_rot_lo(KL_H, KL_L, 45); SK[12] = left_rot_hi(KA_H, KA_L, 45); SK[13] = left_rot_lo(KL_H, KL_L, 60); SK[14] = left_rot_hi(KA_H, KA_L, 60); SK[15] = left_rot_lo(KA_H, KA_L, 60); SK[16] = left_rot_lo(KL_H, KL_L, 77-64); SK[17] = left_rot_hi(KL_H, KL_L, 77-64); SK[18] = left_rot_lo(KL_H, KL_L, 94-64); SK[19] = left_rot_hi(KL_H, KL_L, 94-64); SK[20] = left_rot_lo(KA_H, KA_L, 94-64); SK[21] = left_rot_hi(KA_H, KA_L, 94-64); SK[22] = left_rot_lo(KL_H, KL_L, 111-64); SK[23] = left_rot_hi(KL_H, KL_L, 111-64); SK[24] = left_rot_lo(KA_H, KA_L, 111-64); SK[25] = left_rot_hi(KA_H, KA_L, 111-64); } else { SK.resize(34); SK[ 0] = KL_H; SK[ 1] = KL_L; SK[ 2] = KB_H; SK[ 3] = KB_L; SK[ 4] = left_rot_hi(KR_H, KR_L, 15); SK[ 5] = left_rot_lo(KR_H, KR_L, 15); SK[ 6] = left_rot_hi(KA_H, KA_L, 15); SK[ 7] = left_rot_lo(KA_H, KA_L, 15); SK[ 8] = left_rot_hi(KR_H, KR_L, 30); SK[ 9] = left_rot_lo(KR_H, KR_L, 30); SK[10] = left_rot_hi(KB_H, KB_L, 30); SK[11] = left_rot_lo(KB_H, KB_L, 30); SK[12] = left_rot_hi(KL_H, KL_L, 45); SK[13] = left_rot_lo(KL_H, KL_L, 45); SK[14] = left_rot_hi(KA_H, KA_L, 45); SK[15] = left_rot_lo(KA_H, KA_L, 45); SK[16] = left_rot_hi(KL_H, KL_L, 60); SK[17] = left_rot_lo(KL_H, KL_L, 60); SK[18] = left_rot_hi(KR_H, KR_L, 60); SK[19] = left_rot_lo(KR_H, KR_L, 60); SK[20] = left_rot_hi(KB_H, KB_L, 60); SK[21] = left_rot_lo(KB_H, KB_L, 60); SK[22] = left_rot_lo(KL_H, KL_L, 77-64); SK[23] = left_rot_hi(KL_H, KL_L, 77-64); SK[24] = left_rot_lo(KA_H, KA_L, 77-64); SK[25] = left_rot_hi(KA_H, KA_L, 77-64); SK[26] = left_rot_lo(KR_H, KR_L, 94-64); SK[27] = left_rot_hi(KR_H, KR_L, 94-64); SK[28] = left_rot_lo(KA_H, KA_L, 94-64); SK[29] = left_rot_hi(KA_H, KA_L, 94-64); SK[30] = left_rot_lo(KL_H, KL_L, 111-64); SK[31] = left_rot_hi(KL_H, KL_L, 111-64); SK[32] = left_rot_lo(KB_H, KB_L, 111-64); SK[33] = left_rot_hi(KB_H, KB_L, 111-64); } } } } void Camellia_128::encrypt_n(const byte in[], byte out[], size_t blocks) const { Camellia_F::encrypt(in, out, blocks, SK, 9); } void Camellia_192::encrypt_n(const byte in[], byte out[], size_t blocks) const { Camellia_F::encrypt(in, out, blocks, SK, 12); } void Camellia_256::encrypt_n(const byte in[], byte out[], size_t blocks) const { Camellia_F::encrypt(in, out, blocks, SK, 12); } void Camellia_128::decrypt_n(const byte in[], byte out[], size_t blocks) const { Camellia_F::decrypt(in, out, blocks, SK, 9); } void Camellia_192::decrypt_n(const byte in[], byte out[], size_t blocks) const { Camellia_F::decrypt(in, out, blocks, SK, 12); } void Camellia_256::decrypt_n(const byte in[], byte out[], size_t blocks) const { Camellia_F::decrypt(in, out, blocks, SK, 12); } void Camellia_128::key_schedule(const byte key[], size_t length) { Camellia_F::key_schedule(SK, key, length); } void Camellia_192::key_schedule(const byte key[], size_t length) { Camellia_F::key_schedule(SK, key, length); } void Camellia_256::key_schedule(const byte key[], size_t length) { Camellia_F::key_schedule(SK, key, length); } } /* * Block Cipher Cascade * (C) 2010 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { void Cascade_Cipher::encrypt_n(const byte in[], byte out[], size_t blocks) const { size_t c1_blocks = blocks * (block_size() / cipher1->block_size()); size_t c2_blocks = blocks * (block_size() / cipher2->block_size()); cipher1->encrypt_n(in, out, c1_blocks); cipher2->encrypt_n(out, out, c2_blocks); } void Cascade_Cipher::decrypt_n(const byte in[], byte out[], size_t blocks) const { size_t c1_blocks = blocks * (block_size() / cipher1->block_size()); size_t c2_blocks = blocks * (block_size() / cipher2->block_size()); cipher2->decrypt_n(in, out, c2_blocks); cipher1->decrypt_n(out, out, c1_blocks); } void Cascade_Cipher::key_schedule(const byte key[], size_t) { const byte* key2 = key + cipher1->maximum_keylength(); cipher1->set_key(key , cipher1->maximum_keylength()); cipher2->set_key(key2, cipher2->maximum_keylength()); } void Cascade_Cipher::clear() { cipher1->clear(); cipher2->clear(); } std::string Cascade_Cipher::name() const { return "Cascade(" + cipher1->name() + "," + cipher2->name() + ")"; } BlockCipher* Cascade_Cipher::clone() const { return new Cascade_Cipher(cipher1->clone(), cipher2->clone()); } namespace { size_t euclids_algorithm(size_t a, size_t b) { while(b != 0) // gcd { size_t t = b; b = a % b; a = t; } return a; } size_t block_size_for_cascade(size_t bs, size_t bs2) { if(bs == bs2) return bs; size_t gcd = euclids_algorithm(bs, bs2); return (bs * bs2) / gcd; } } Cascade_Cipher::Cascade_Cipher(BlockCipher* c1, BlockCipher* c2) : cipher1(c1), cipher2(c2) { block = block_size_for_cascade(c1->block_size(), c2->block_size()); if(block_size() % c1->block_size() || block_size() % c2->block_size()) throw Internal_Error("Failure in " + name() + " constructor"); } Cascade_Cipher::~Cascade_Cipher() { delete cipher1; delete cipher2; } } /* * CAST-128 * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { namespace { /* * CAST-128 Round Type 1 */ inline void R1(u32bit& L, u32bit R, u32bit MK, u32bit RK) { u32bit T = rotate_left(MK + R, RK); L ^= (CAST_SBOX1[get_byte(0, T)] ^ CAST_SBOX2[get_byte(1, T)]) - CAST_SBOX3[get_byte(2, T)] + CAST_SBOX4[get_byte(3, T)]; } /* * CAST-128 Round Type 2 */ inline void R2(u32bit& L, u32bit R, u32bit MK, u32bit RK) { u32bit T = rotate_left(MK ^ R, RK); L ^= (CAST_SBOX1[get_byte(0, T)] - CAST_SBOX2[get_byte(1, T)] + CAST_SBOX3[get_byte(2, T)]) ^ CAST_SBOX4[get_byte(3, T)]; } /* * CAST-128 Round Type 3 */ inline void R3(u32bit& L, u32bit R, u32bit MK, u32bit RK) { u32bit T = rotate_left(MK - R, RK); L ^= ((CAST_SBOX1[get_byte(0, T)] + CAST_SBOX2[get_byte(1, T)]) ^ CAST_SBOX3[get_byte(2, T)]) - CAST_SBOX4[get_byte(3, T)]; } } /* * CAST-128 Encryption */ void CAST_128::encrypt_n(const byte in[], byte out[], size_t blocks) const { for(size_t i = 0; i != blocks; ++i) { u32bit L = load_be(in, 0); u32bit R = load_be(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::decrypt_n(const byte in[], byte out[], size_t blocks) const { for(size_t i = 0; i != blocks; ++i) { u32bit L = load_be(in, 0); u32bit R = load_be(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; } } /* * CAST-128 Key Schedule */ void CAST_128::key_schedule(const byte key[], size_t length) { clear(); SecureVector X(4); for(size_t j = 0; j != length; ++j) X[j/4] = (X[j/4] << 8) + key[j]; cast_ks(MK, X); cast_ks(RK, X); for(size_t j = 0; j != 16; ++j) RK[j] %= 32; } /* * S-Box Based Key Expansion */ void CAST_128::cast_ks(MemoryRegion& K, MemoryRegion& X) { class ByteReader { public: byte operator()(size_t i) { return (X[i/4] >> (8*(3 - (i%4)))); } ByteReader(const u32bit* x) : X(x) {} private: const u32bit* X; }; SecureVector Z(4); ByteReader x(&X[0]), z(&Z[0]); Z[0] = X[0] ^ S5[x(13)] ^ S6[x(15)] ^ S7[x(12)] ^ S8[x(14)] ^ S7[x( 8)]; Z[1] = X[2] ^ S5[z( 0)] ^ S6[z( 2)] ^ S7[z( 1)] ^ S8[z( 3)] ^ S8[x(10)]; Z[2] = X[3] ^ S5[z( 7)] ^ S6[z( 6)] ^ S7[z( 5)] ^ S8[z( 4)] ^ S5[x( 9)]; Z[3] = X[1] ^ S5[z(10)] ^ S6[z( 9)] ^ S7[z(11)] ^ S8[z( 8)] ^ S6[x(11)]; K[ 0] = S5[z( 8)] ^ S6[z( 9)] ^ S7[z( 7)] ^ S8[z( 6)] ^ S5[z( 2)]; K[ 1] = S5[z(10)] ^ S6[z(11)] ^ S7[z( 5)] ^ S8[z( 4)] ^ S6[z( 6)]; K[ 2] = S5[z(12)] ^ S6[z(13)] ^ S7[z( 3)] ^ S8[z( 2)] ^ S7[z( 9)]; K[ 3] = S5[z(14)] ^ S6[z(15)] ^ S7[z( 1)] ^ S8[z( 0)] ^ S8[z(12)]; X[0] = Z[2] ^ S5[z( 5)] ^ S6[z( 7)] ^ S7[z( 4)] ^ S8[z( 6)] ^ S7[z( 0)]; X[1] = Z[0] ^ S5[x( 0)] ^ S6[x( 2)] ^ S7[x( 1)] ^ S8[x( 3)] ^ S8[z( 2)]; X[2] = Z[1] ^ S5[x( 7)] ^ S6[x( 6)] ^ S7[x( 5)] ^ S8[x( 4)] ^ S5[z( 1)]; X[3] = Z[3] ^ S5[x(10)] ^ S6[x( 9)] ^ S7[x(11)] ^ S8[x( 8)] ^ S6[z( 3)]; K[ 4] = S5[x( 3)] ^ S6[x( 2)] ^ S7[x(12)] ^ S8[x(13)] ^ S5[x( 8)]; K[ 5] = S5[x( 1)] ^ S6[x( 0)] ^ S7[x(14)] ^ S8[x(15)] ^ S6[x(13)]; K[ 6] = S5[x( 7)] ^ S6[x( 6)] ^ S7[x( 8)] ^ S8[x( 9)] ^ S7[x( 3)]; K[ 7] = S5[x( 5)] ^ S6[x( 4)] ^ S7[x(10)] ^ S8[x(11)] ^ S8[x( 7)]; Z[0] = X[0] ^ S5[x(13)] ^ S6[x(15)] ^ S7[x(12)] ^ S8[x(14)] ^ S7[x( 8)]; Z[1] = X[2] ^ S5[z( 0)] ^ S6[z( 2)] ^ S7[z( 1)] ^ S8[z( 3)] ^ S8[x(10)]; Z[2] = X[3] ^ S5[z( 7)] ^ S6[z( 6)] ^ S7[z( 5)] ^ S8[z( 4)] ^ S5[x( 9)]; Z[3] = X[1] ^ S5[z(10)] ^ S6[z( 9)] ^ S7[z(11)] ^ S8[z( 8)] ^ S6[x(11)]; K[ 8] = S5[z( 3)] ^ S6[z( 2)] ^ S7[z(12)] ^ S8[z(13)] ^ S5[z( 9)]; K[ 9] = S5[z( 1)] ^ S6[z( 0)] ^ S7[z(14)] ^ S8[z(15)] ^ S6[z(12)]; K[10] = S5[z( 7)] ^ S6[z( 6)] ^ S7[z( 8)] ^ S8[z( 9)] ^ S7[z( 2)]; K[11] = S5[z( 5)] ^ S6[z( 4)] ^ S7[z(10)] ^ S8[z(11)] ^ S8[z( 6)]; X[0] = Z[2] ^ S5[z( 5)] ^ S6[z( 7)] ^ S7[z( 4)] ^ S8[z( 6)] ^ S7[z( 0)]; X[1] = Z[0] ^ S5[x( 0)] ^ S6[x( 2)] ^ S7[x( 1)] ^ S8[x( 3)] ^ S8[z( 2)]; X[2] = Z[1] ^ S5[x( 7)] ^ S6[x( 6)] ^ S7[x( 5)] ^ S8[x( 4)] ^ S5[z( 1)]; X[3] = Z[3] ^ S5[x(10)] ^ S6[x( 9)] ^ S7[x(11)] ^ S8[x( 8)] ^ S6[z( 3)]; K[12] = S5[x( 8)] ^ S6[x( 9)] ^ S7[x( 7)] ^ S8[x( 6)] ^ S5[x( 3)]; K[13] = S5[x(10)] ^ S6[x(11)] ^ S7[x( 5)] ^ S8[x( 4)] ^ S6[x( 7)]; K[14] = S5[x(12)] ^ S6[x(13)] ^ S7[x( 3)] ^ S8[x( 2)] ^ S7[x( 8)]; K[15] = S5[x(14)] ^ S6[x(15)] ^ S7[x( 1)] ^ S8[x( 0)] ^ S8[x(13)]; } } /* * CAST-256 * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { namespace { /* * CAST-256 Round Type 1 */ void round1(u32bit& out, u32bit in, u32bit mask, u32bit rot) { u32bit temp = rotate_left(mask + in, rot); out ^= (CAST_SBOX1[get_byte(0, temp)] ^ CAST_SBOX2[get_byte(1, temp)]) - CAST_SBOX3[get_byte(2, temp)] + CAST_SBOX4[get_byte(3, temp)]; } /* * CAST-256 Round Type 2 */ void round2(u32bit& out, u32bit in, u32bit mask, u32bit rot) { u32bit temp = rotate_left(mask ^ in, rot); out ^= (CAST_SBOX1[get_byte(0, temp)] - CAST_SBOX2[get_byte(1, temp)] + CAST_SBOX3[get_byte(2, temp)]) ^ CAST_SBOX4[get_byte(3, temp)]; } /* * CAST-256 Round Type 3 */ void round3(u32bit& out, u32bit in, u32bit mask, u32bit rot) { u32bit temp = rotate_left(mask - in, rot); out ^= ((CAST_SBOX1[get_byte(0, temp)] + CAST_SBOX2[get_byte(1, temp)]) ^ CAST_SBOX3[get_byte(2, temp)]) - CAST_SBOX4[get_byte(3, temp)]; } } /* * CAST-256 Encryption */ void CAST_256::encrypt_n(const byte in[], byte out[], size_t blocks) const { for(size_t i = 0; i != blocks; ++i) { u32bit A = load_be(in, 0); u32bit B = load_be(in, 1); u32bit C = load_be(in, 2); u32bit D = load_be(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::decrypt_n(const byte in[], byte out[], size_t blocks) const { for(size_t i = 0; i != blocks; ++i) { u32bit A = load_be(in, 0); u32bit B = load_be(in, 1); u32bit C = load_be(in, 2); u32bit D = load_be(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; } } /* * CAST-256 Key Schedule */ void CAST_256::key_schedule(const byte key[], size_t length) { SecureVector K(8); for(size_t j = 0; j != length; ++j) K[j/4] = (K[j/4] << 8) + key[j]; u32bit A = K[0], B = K[1], C = K[2], D = K[3], E = K[4], F = K[5], G = K[6], H = K[7]; for(size_t j = 0; j != 48; j += 4) { round1(G, H, KEY_MASK[4*j+ 0], KEY_ROT[(4*j+ 0) % 32]); round2(F, G, KEY_MASK[4*j+ 1], KEY_ROT[(4*j+ 1) % 32]); round3(E, F, KEY_MASK[4*j+ 2], KEY_ROT[(4*j+ 2) % 32]); round1(D, E, KEY_MASK[4*j+ 3], KEY_ROT[(4*j+ 3) % 32]); round2(C, D, KEY_MASK[4*j+ 4], KEY_ROT[(4*j+ 4) % 32]); round3(B, C, KEY_MASK[4*j+ 5], KEY_ROT[(4*j+ 5) % 32]); round1(A, B, KEY_MASK[4*j+ 6], KEY_ROT[(4*j+ 6) % 32]); round2(H, A, KEY_MASK[4*j+ 7], KEY_ROT[(4*j+ 7) % 32]); round1(G, H, KEY_MASK[4*j+ 8], KEY_ROT[(4*j+ 8) % 32]); round2(F, G, KEY_MASK[4*j+ 9], KEY_ROT[(4*j+ 9) % 32]); round3(E, F, KEY_MASK[4*j+10], KEY_ROT[(4*j+10) % 32]); round1(D, E, KEY_MASK[4*j+11], KEY_ROT[(4*j+11) % 32]); round2(C, D, KEY_MASK[4*j+12], KEY_ROT[(4*j+12) % 32]); round3(B, C, KEY_MASK[4*j+13], KEY_ROT[(4*j+13) % 32]); round1(A, B, KEY_MASK[4*j+14], KEY_ROT[(4*j+14) % 32]); round2(H, A, KEY_MASK[4*j+15], KEY_ROT[(4*j+15) % 32]); RK[j ] = (A % 32); RK[j+1] = (C % 32); RK[j+2] = (E % 32); RK[j+3] = (G % 32); MK[j ] = H; MK[j+1] = F; MK[j+2] = D; MK[j+3] = B; } } } /* * S-Box Tables for CAST-128 and CAST-256 * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { const u32bit CAST_SBOX1[256] = { 0x30FB40D4, 0x9FA0FF0B, 0x6BECCD2F, 0x3F258C7A, 0x1E213F2F, 0x9C004DD3, 0x6003E540, 0xCF9FC949, 0xBFD4AF27, 0x88BBBDB5, 0xE2034090, 0x98D09675, 0x6E63A0E0, 0x15C361D2, 0xC2E7661D, 0x22D4FF8E, 0x28683B6F, 0xC07FD059, 0xFF2379C8, 0x775F50E2, 0x43C340D3, 0xDF2F8656, 0x887CA41A, 0xA2D2BD2D, 0xA1C9E0D6, 0x346C4819, 0x61B76D87, 0x22540F2F, 0x2ABE32E1, 0xAA54166B, 0x22568E3A, 0xA2D341D0, 0x66DB40C8, 0xA784392F, 0x004DFF2F, 0x2DB9D2DE, 0x97943FAC, 0x4A97C1D8, 0x527644B7, 0xB5F437A7, 0xB82CBAEF, 0xD751D159, 0x6FF7F0ED, 0x5A097A1F, 0x827B68D0, 0x90ECF52E, 0x22B0C054, 0xBC8E5935, 0x4B6D2F7F, 0x50BB64A2, 0xD2664910, 0xBEE5812D, 0xB7332290, 0xE93B159F, 0xB48EE411, 0x4BFF345D, 0xFD45C240, 0xAD31973F, 0xC4F6D02E, 0x55FC8165, 0xD5B1CAAD, 0xA1AC2DAE, 0xA2D4B76D, 0xC19B0C50, 0x882240F2, 0x0C6E4F38, 0xA4E4BFD7, 0x4F5BA272, 0x564C1D2F, 0xC59C5319, 0xB949E354, 0xB04669FE, 0xB1B6AB8A, 0xC71358DD, 0x6385C545, 0x110F935D, 0x57538AD5, 0x6A390493, 0xE63D37E0, 0x2A54F6B3, 0x3A787D5F, 0x6276A0B5, 0x19A6FCDF, 0x7A42206A, 0x29F9D4D5, 0xF61B1891, 0xBB72275E, 0xAA508167, 0x38901091, 0xC6B505EB, 0x84C7CB8C, 0x2AD75A0F, 0x874A1427, 0xA2D1936B, 0x2AD286AF, 0xAA56D291, 0xD7894360, 0x425C750D, 0x93B39E26, 0x187184C9, 0x6C00B32D, 0x73E2BB14, 0xA0BEBC3C, 0x54623779, 0x64459EAB, 0x3F328B82, 0x7718CF82, 0x59A2CEA6, 0x04EE002E, 0x89FE78E6, 0x3FAB0950, 0x325FF6C2, 0x81383F05, 0x6963C5C8, 0x76CB5AD6, 0xD49974C9, 0xCA180DCF, 0x380782D5, 0xC7FA5CF6, 0x8AC31511, 0x35E79E13, 0x47DA91D0, 0xF40F9086, 0xA7E2419E, 0x31366241, 0x051EF495, 0xAA573B04, 0x4A805D8D, 0x548300D0, 0x00322A3C, 0xBF64CDDF, 0xBA57A68E, 0x75C6372B, 0x50AFD341, 0xA7C13275, 0x915A0BF5, 0x6B54BFAB, 0x2B0B1426, 0xAB4CC9D7, 0x449CCD82, 0xF7FBF265, 0xAB85C5F3, 0x1B55DB94, 0xAAD4E324, 0xCFA4BD3F, 0x2DEAA3E2, 0x9E204D02, 0xC8BD25AC, 0xEADF55B3, 0xD5BD9E98, 0xE31231B2, 0x2AD5AD6C, 0x954329DE, 0xADBE4528, 0xD8710F69, 0xAA51C90F, 0xAA786BF6, 0x22513F1E, 0xAA51A79B, 0x2AD344CC, 0x7B5A41F0, 0xD37CFBAD, 0x1B069505, 0x41ECE491, 0xB4C332E6, 0x032268D4, 0xC9600ACC, 0xCE387E6D, 0xBF6BB16C, 0x6A70FB78, 0x0D03D9C9, 0xD4DF39DE, 0xE01063DA, 0x4736F464, 0x5AD328D8, 0xB347CC96, 0x75BB0FC3, 0x98511BFB, 0x4FFBCC35, 0xB58BCF6A, 0xE11F0ABC, 0xBFC5FE4A, 0xA70AEC10, 0xAC39570A, 0x3F04442F, 0x6188B153, 0xE0397A2E, 0x5727CB79, 0x9CEB418F, 0x1CACD68D, 0x2AD37C96, 0x0175CB9D, 0xC69DFF09, 0xC75B65F0, 0xD9DB40D8, 0xEC0E7779, 0x4744EAD4, 0xB11C3274, 0xDD24CB9E, 0x7E1C54BD, 0xF01144F9, 0xD2240EB1, 0x9675B3FD, 0xA3AC3755, 0xD47C27AF, 0x51C85F4D, 0x56907596, 0xA5BB15E6, 0x580304F0, 0xCA042CF1, 0x011A37EA, 0x8DBFAADB, 0x35BA3E4A, 0x3526FFA0, 0xC37B4D09, 0xBC306ED9, 0x98A52666, 0x5648F725, 0xFF5E569D, 0x0CED63D0, 0x7C63B2CF, 0x700B45E1, 0xD5EA50F1, 0x85A92872, 0xAF1FBDA7, 0xD4234870, 0xA7870BF3, 0x2D3B4D79, 0x42E04198, 0x0CD0EDE7, 0x26470DB8, 0xF881814C, 0x474D6AD7, 0x7C0C5E5C, 0xD1231959, 0x381B7298, 0xF5D2F4DB, 0xAB838653, 0x6E2F1E23, 0x83719C9E, 0xBD91E046, 0x9A56456E, 0xDC39200C, 0x20C8C571, 0x962BDA1C, 0xE1E696FF, 0xB141AB08, 0x7CCA89B9, 0x1A69E783, 0x02CC4843, 0xA2F7C579, 0x429EF47D, 0x427B169C, 0x5AC9F049, 0xDD8F0F00, 0x5C8165BF }; const u32bit CAST_SBOX2[256] = { 0x1F201094, 0xEF0BA75B, 0x69E3CF7E, 0x393F4380, 0xFE61CF7A, 0xEEC5207A, 0x55889C94, 0x72FC0651, 0xADA7EF79, 0x4E1D7235, 0xD55A63CE, 0xDE0436BA, 0x99C430EF, 0x5F0C0794, 0x18DCDB7D, 0xA1D6EFF3, 0xA0B52F7B, 0x59E83605, 0xEE15B094, 0xE9FFD909, 0xDC440086, 0xEF944459, 0xBA83CCB3, 0xE0C3CDFB, 0xD1DA4181, 0x3B092AB1, 0xF997F1C1, 0xA5E6CF7B, 0x01420DDB, 0xE4E7EF5B, 0x25A1FF41, 0xE180F806, 0x1FC41080, 0x179BEE7A, 0xD37AC6A9, 0xFE5830A4, 0x98DE8B7F, 0x77E83F4E, 0x79929269, 0x24FA9F7B, 0xE113C85B, 0xACC40083, 0xD7503525, 0xF7EA615F, 0x62143154, 0x0D554B63, 0x5D681121, 0xC866C359, 0x3D63CF73, 0xCEE234C0, 0xD4D87E87, 0x5C672B21, 0x071F6181, 0x39F7627F, 0x361E3084, 0xE4EB573B, 0x602F64A4, 0xD63ACD9C, 0x1BBC4635, 0x9E81032D, 0x2701F50C, 0x99847AB4, 0xA0E3DF79, 0xBA6CF38C, 0x10843094, 0x2537A95E, 0xF46F6FFE, 0xA1FF3B1F, 0x208CFB6A, 0x8F458C74, 0xD9E0A227, 0x4EC73A34, 0xFC884F69, 0x3E4DE8DF, 0xEF0E0088, 0x3559648D, 0x8A45388C, 0x1D804366, 0x721D9BFD, 0xA58684BB, 0xE8256333, 0x844E8212, 0x128D8098, 0xFED33FB4, 0xCE280AE1, 0x27E19BA5, 0xD5A6C252, 0xE49754BD, 0xC5D655DD, 0xEB667064, 0x77840B4D, 0xA1B6A801, 0x84DB26A9, 0xE0B56714, 0x21F043B7, 0xE5D05860, 0x54F03084, 0x066FF472, 0xA31AA153, 0xDADC4755, 0xB5625DBF, 0x68561BE6, 0x83CA6B94, 0x2D6ED23B, 0xECCF01DB, 0xA6D3D0BA, 0xB6803D5C, 0xAF77A709, 0x33B4A34C, 0x397BC8D6, 0x5EE22B95, 0x5F0E5304, 0x81ED6F61, 0x20E74364, 0xB45E1378, 0xDE18639B, 0x881CA122, 0xB96726D1, 0x8049A7E8, 0x22B7DA7B, 0x5E552D25, 0x5272D237, 0x79D2951C, 0xC60D894C, 0x488CB402, 0x1BA4FE5B, 0xA4B09F6B, 0x1CA815CF, 0xA20C3005, 0x8871DF63, 0xB9DE2FCB, 0x0CC6C9E9, 0x0BEEFF53, 0xE3214517, 0xB4542835, 0x9F63293C, 0xEE41E729, 0x6E1D2D7C, 0x50045286, 0x1E6685F3, 0xF33401C6, 0x30A22C95, 0x31A70850, 0x60930F13, 0x73F98417, 0xA1269859, 0xEC645C44, 0x52C877A9, 0xCDFF33A6, 0xA02B1741, 0x7CBAD9A2, 0x2180036F, 0x50D99C08, 0xCB3F4861, 0xC26BD765, 0x64A3F6AB, 0x80342676, 0x25A75E7B, 0xE4E6D1FC, 0x20C710E6, 0xCDF0B680, 0x17844D3B, 0x31EEF84D, 0x7E0824E4, 0x2CCB49EB, 0x846A3BAE, 0x8FF77888, 0xEE5D60F6, 0x7AF75673, 0x2FDD5CDB, 0xA11631C1, 0x30F66F43, 0xB3FAEC54, 0x157FD7FA, 0xEF8579CC, 0xD152DE58, 0xDB2FFD5E, 0x8F32CE19, 0x306AF97A, 0x02F03EF8, 0x99319AD5, 0xC242FA0F, 0xA7E3EBB0, 0xC68E4906, 0xB8DA230C, 0x80823028, 0xDCDEF3C8, 0xD35FB171, 0x088A1BC8, 0xBEC0C560, 0x61A3C9E8, 0xBCA8F54D, 0xC72FEFFA, 0x22822E99, 0x82C570B4, 0xD8D94E89, 0x8B1C34BC, 0x301E16E6, 0x273BE979, 0xB0FFEAA6, 0x61D9B8C6, 0x00B24869, 0xB7FFCE3F, 0x08DC283B, 0x43DAF65A, 0xF7E19798, 0x7619B72F, 0x8F1C9BA4, 0xDC8637A0, 0x16A7D3B1, 0x9FC393B7, 0xA7136EEB, 0xC6BCC63E, 0x1A513742, 0xEF6828BC, 0x520365D6, 0x2D6A77AB, 0x3527ED4B, 0x821FD216, 0x095C6E2E, 0xDB92F2FB, 0x5EEA29CB, 0x145892F5, 0x91584F7F, 0x5483697B, 0x2667A8CC, 0x85196048, 0x8C4BACEA, 0x833860D4, 0x0D23E0F9, 0x6C387E8A, 0x0AE6D249, 0xB284600C, 0xD835731D, 0xDCB1C647, 0xAC4C56EA, 0x3EBD81B3, 0x230EABB0, 0x6438BC87, 0xF0B5B1FA, 0x8F5EA2B3, 0xFC184642, 0x0A036B7A, 0x4FB089BD, 0x649DA589, 0xA345415E, 0x5C038323, 0x3E5D3BB9, 0x43D79572, 0x7E6DD07C, 0x06DFDF1E, 0x6C6CC4EF, 0x7160A539, 0x73BFBE70, 0x83877605, 0x4523ECF1 }; const u32bit CAST_SBOX3[256] = { 0x8DEFC240, 0x25FA5D9F, 0xEB903DBF, 0xE810C907, 0x47607FFF, 0x369FE44B, 0x8C1FC644, 0xAECECA90, 0xBEB1F9BF, 0xEEFBCAEA, 0xE8CF1950, 0x51DF07AE, 0x920E8806, 0xF0AD0548, 0xE13C8D83, 0x927010D5, 0x11107D9F, 0x07647DB9, 0xB2E3E4D4, 0x3D4F285E, 0xB9AFA820, 0xFADE82E0, 0xA067268B, 0x8272792E, 0x553FB2C0, 0x489AE22B, 0xD4EF9794, 0x125E3FBC, 0x21FFFCEE, 0x825B1BFD, 0x9255C5ED, 0x1257A240, 0x4E1A8302, 0xBAE07FFF, 0x528246E7, 0x8E57140E, 0x3373F7BF, 0x8C9F8188, 0xA6FC4EE8, 0xC982B5A5, 0xA8C01DB7, 0x579FC264, 0x67094F31, 0xF2BD3F5F, 0x40FFF7C1, 0x1FB78DFC, 0x8E6BD2C1, 0x437BE59B, 0x99B03DBF, 0xB5DBC64B, 0x638DC0E6, 0x55819D99, 0xA197C81C, 0x4A012D6E, 0xC5884A28, 0xCCC36F71, 0xB843C213, 0x6C0743F1, 0x8309893C, 0x0FEDDD5F, 0x2F7FE850, 0xD7C07F7E, 0x02507FBF, 0x5AFB9A04, 0xA747D2D0, 0x1651192E, 0xAF70BF3E, 0x58C31380, 0x5F98302E, 0x727CC3C4, 0x0A0FB402, 0x0F7FEF82, 0x8C96FDAD, 0x5D2C2AAE, 0x8EE99A49, 0x50DA88B8, 0x8427F4A0, 0x1EAC5790, 0x796FB449, 0x8252DC15, 0xEFBD7D9B, 0xA672597D, 0xADA840D8, 0x45F54504, 0xFA5D7403, 0xE83EC305, 0x4F91751A, 0x925669C2, 0x23EFE941, 0xA903F12E, 0x60270DF2, 0x0276E4B6, 0x94FD6574, 0x927985B2, 0x8276DBCB, 0x02778176, 0xF8AF918D, 0x4E48F79E, 0x8F616DDF, 0xE29D840E, 0x842F7D83, 0x340CE5C8, 0x96BBB682, 0x93B4B148, 0xEF303CAB, 0x984FAF28, 0x779FAF9B, 0x92DC560D, 0x224D1E20, 0x8437AA88, 0x7D29DC96, 0x2756D3DC, 0x8B907CEE, 0xB51FD240, 0xE7C07CE3, 0xE566B4A1, 0xC3E9615E, 0x3CF8209D, 0x6094D1E3, 0xCD9CA341, 0x5C76460E, 0x00EA983B, 0xD4D67881, 0xFD47572C, 0xF76CEDD9, 0xBDA8229C, 0x127DADAA, 0x438A074E, 0x1F97C090, 0x081BDB8A, 0x93A07EBE, 0xB938CA15, 0x97B03CFF, 0x3DC2C0F8, 0x8D1AB2EC, 0x64380E51, 0x68CC7BFB, 0xD90F2788, 0x12490181, 0x5DE5FFD4, 0xDD7EF86A, 0x76A2E214, 0xB9A40368, 0x925D958F, 0x4B39FFFA, 0xBA39AEE9, 0xA4FFD30B, 0xFAF7933B, 0x6D498623, 0x193CBCFA, 0x27627545, 0x825CF47A, 0x61BD8BA0, 0xD11E42D1, 0xCEAD04F4, 0x127EA392, 0x10428DB7, 0x8272A972, 0x9270C4A8, 0x127DE50B, 0x285BA1C8, 0x3C62F44F, 0x35C0EAA5, 0xE805D231, 0x428929FB, 0xB4FCDF82, 0x4FB66A53, 0x0E7DC15B, 0x1F081FAB, 0x108618AE, 0xFCFD086D, 0xF9FF2889, 0x694BCC11, 0x236A5CAE, 0x12DECA4D, 0x2C3F8CC5, 0xD2D02DFE, 0xF8EF5896, 0xE4CF52DA, 0x95155B67, 0x494A488C, 0xB9B6A80C, 0x5C8F82BC, 0x89D36B45, 0x3A609437, 0xEC00C9A9, 0x44715253, 0x0A874B49, 0xD773BC40, 0x7C34671C, 0x02717EF6, 0x4FEB5536, 0xA2D02FFF, 0xD2BF60C4, 0xD43F03C0, 0x50B4EF6D, 0x07478CD1, 0x006E1888, 0xA2E53F55, 0xB9E6D4BC, 0xA2048016, 0x97573833, 0xD7207D67, 0xDE0F8F3D, 0x72F87B33, 0xABCC4F33, 0x7688C55D, 0x7B00A6B0, 0x947B0001, 0x570075D2, 0xF9BB88F8, 0x8942019E, 0x4264A5FF, 0x856302E0, 0x72DBD92B, 0xEE971B69, 0x6EA22FDE, 0x5F08AE2B, 0xAF7A616D, 0xE5C98767, 0xCF1FEBD2, 0x61EFC8C2, 0xF1AC2571, 0xCC8239C2, 0x67214CB8, 0xB1E583D1, 0xB7DC3E62, 0x7F10BDCE, 0xF90A5C38, 0x0FF0443D, 0x606E6DC6, 0x60543A49, 0x5727C148, 0x2BE98A1D, 0x8AB41738, 0x20E1BE24, 0xAF96DA0F, 0x68458425, 0x99833BE5, 0x600D457D, 0x282F9350, 0x8334B362, 0xD91D1120, 0x2B6D8DA0, 0x642B1E31, 0x9C305A00, 0x52BCE688, 0x1B03588A, 0xF7BAEFD5, 0x4142ED9C, 0xA4315C11, 0x83323EC5, 0xDFEF4636, 0xA133C501, 0xE9D3531C, 0xEE353783 }; const u32bit CAST_SBOX4[256] = { 0x9DB30420, 0x1FB6E9DE, 0xA7BE7BEF, 0xD273A298, 0x4A4F7BDB, 0x64AD8C57, 0x85510443, 0xFA020ED1, 0x7E287AFF, 0xE60FB663, 0x095F35A1, 0x79EBF120, 0xFD059D43, 0x6497B7B1, 0xF3641F63, 0x241E4ADF, 0x28147F5F, 0x4FA2B8CD, 0xC9430040, 0x0CC32220, 0xFDD30B30, 0xC0A5374F, 0x1D2D00D9, 0x24147B15, 0xEE4D111A, 0x0FCA5167, 0x71FF904C, 0x2D195FFE, 0x1A05645F, 0x0C13FEFE, 0x081B08CA, 0x05170121, 0x80530100, 0xE83E5EFE, 0xAC9AF4F8, 0x7FE72701, 0xD2B8EE5F, 0x06DF4261, 0xBB9E9B8A, 0x7293EA25, 0xCE84FFDF, 0xF5718801, 0x3DD64B04, 0xA26F263B, 0x7ED48400, 0x547EEBE6, 0x446D4CA0, 0x6CF3D6F5, 0x2649ABDF, 0xAEA0C7F5, 0x36338CC1, 0x503F7E93, 0xD3772061, 0x11B638E1, 0x72500E03, 0xF80EB2BB, 0xABE0502E, 0xEC8D77DE, 0x57971E81, 0xE14F6746, 0xC9335400, 0x6920318F, 0x081DBB99, 0xFFC304A5, 0x4D351805, 0x7F3D5CE3, 0xA6C866C6, 0x5D5BCCA9, 0xDAEC6FEA, 0x9F926F91, 0x9F46222F, 0x3991467D, 0xA5BF6D8E, 0x1143C44F, 0x43958302, 0xD0214EEB, 0x022083B8, 0x3FB6180C, 0x18F8931E, 0x281658E6, 0x26486E3E, 0x8BD78A70, 0x7477E4C1, 0xB506E07C, 0xF32D0A25, 0x79098B02, 0xE4EABB81, 0x28123B23, 0x69DEAD38, 0x1574CA16, 0xDF871B62, 0x211C40B7, 0xA51A9EF9, 0x0014377B, 0x041E8AC8, 0x09114003, 0xBD59E4D2, 0xE3D156D5, 0x4FE876D5, 0x2F91A340, 0x557BE8DE, 0x00EAE4A7, 0x0CE5C2EC, 0x4DB4BBA6, 0xE756BDFF, 0xDD3369AC, 0xEC17B035, 0x06572327, 0x99AFC8B0, 0x56C8C391, 0x6B65811C, 0x5E146119, 0x6E85CB75, 0xBE07C002, 0xC2325577, 0x893FF4EC, 0x5BBFC92D, 0xD0EC3B25, 0xB7801AB7, 0x8D6D3B24, 0x20C763EF, 0xC366A5FC, 0x9C382880, 0x0ACE3205, 0xAAC9548A, 0xECA1D7C7, 0x041AFA32, 0x1D16625A, 0x6701902C, 0x9B757A54, 0x31D477F7, 0x9126B031, 0x36CC6FDB, 0xC70B8B46, 0xD9E66A48, 0x56E55A79, 0x026A4CEB, 0x52437EFF, 0x2F8F76B4, 0x0DF980A5, 0x8674CDE3, 0xEDDA04EB, 0x17A9BE04, 0x2C18F4DF, 0xB7747F9D, 0xAB2AF7B4, 0xEFC34D20, 0x2E096B7C, 0x1741A254, 0xE5B6A035, 0x213D42F6, 0x2C1C7C26, 0x61C2F50F, 0x6552DAF9, 0xD2C231F8, 0x25130F69, 0xD8167FA2, 0x0418F2C8, 0x001A96A6, 0x0D1526AB, 0x63315C21, 0x5E0A72EC, 0x49BAFEFD, 0x187908D9, 0x8D0DBD86, 0x311170A7, 0x3E9B640C, 0xCC3E10D7, 0xD5CAD3B6, 0x0CAEC388, 0xF73001E1, 0x6C728AFF, 0x71EAE2A1, 0x1F9AF36E, 0xCFCBD12F, 0xC1DE8417, 0xAC07BE6B, 0xCB44A1D8, 0x8B9B0F56, 0x013988C3, 0xB1C52FCA, 0xB4BE31CD, 0xD8782806, 0x12A3A4E2, 0x6F7DE532, 0x58FD7EB6, 0xD01EE900, 0x24ADFFC2, 0xF4990FC5, 0x9711AAC5, 0x001D7B95, 0x82E5E7D2, 0x109873F6, 0x00613096, 0xC32D9521, 0xADA121FF, 0x29908415, 0x7FBB977F, 0xAF9EB3DB, 0x29C9ED2A, 0x5CE2A465, 0xA730F32C, 0xD0AA3FE8, 0x8A5CC091, 0xD49E2CE7, 0x0CE454A9, 0xD60ACD86, 0x015F1919, 0x77079103, 0xDEA03AF6, 0x78A8565E, 0xDEE356DF, 0x21F05CBE, 0x8B75E387, 0xB3C50651, 0xB8A5C3EF, 0xD8EEB6D2, 0xE523BE77, 0xC2154529, 0x2F69EFDF, 0xAFE67AFB, 0xF470C4B2, 0xF3E0EB5B, 0xD6CC9876, 0x39E4460C, 0x1FDA8538, 0x1987832F, 0xCA007367, 0xA99144F8, 0x296B299E, 0x492FC295, 0x9266BEAB, 0xB5676E69, 0x9BD3DDDA, 0xDF7E052F, 0xDB25701C, 0x1B5E51EE, 0xF65324E6, 0x6AFCE36C, 0x0316CC04, 0x8644213E, 0xB7DC59D0, 0x7965291F, 0xCCD6FD43, 0x41823979, 0x932BCDF6, 0xB657C34D, 0x4EDFD282, 0x7AE5290C, 0x3CB9536B, 0x851E20FE, 0x9833557E, 0x13ECF0B0, 0xD3FFB372, 0x3F85C5C1, 0x0AEF7ED2 }; const u32bit CAST_128::S5[256] = { 0x7EC90C04, 0x2C6E74B9, 0x9B0E66DF, 0xA6337911, 0xB86A7FFF, 0x1DD358F5, 0x44DD9D44, 0x1731167F, 0x08FBF1FA, 0xE7F511CC, 0xD2051B00, 0x735ABA00, 0x2AB722D8, 0x386381CB, 0xACF6243A, 0x69BEFD7A, 0xE6A2E77F, 0xF0C720CD, 0xC4494816, 0xCCF5C180, 0x38851640, 0x15B0A848, 0xE68B18CB, 0x4CAADEFF, 0x5F480A01, 0x0412B2AA, 0x259814FC, 0x41D0EFE2, 0x4E40B48D, 0x248EB6FB, 0x8DBA1CFE, 0x41A99B02, 0x1A550A04, 0xBA8F65CB, 0x7251F4E7, 0x95A51725, 0xC106ECD7, 0x97A5980A, 0xC539B9AA, 0x4D79FE6A, 0xF2F3F763, 0x68AF8040, 0xED0C9E56, 0x11B4958B, 0xE1EB5A88, 0x8709E6B0, 0xD7E07156, 0x4E29FEA7, 0x6366E52D, 0x02D1C000, 0xC4AC8E05, 0x9377F571, 0x0C05372A, 0x578535F2, 0x2261BE02, 0xD642A0C9, 0xDF13A280, 0x74B55BD2, 0x682199C0, 0xD421E5EC, 0x53FB3CE8, 0xC8ADEDB3, 0x28A87FC9, 0x3D959981, 0x5C1FF900, 0xFE38D399, 0x0C4EFF0B, 0x062407EA, 0xAA2F4FB1, 0x4FB96976, 0x90C79505, 0xB0A8A774, 0xEF55A1FF, 0xE59CA2C2, 0xA6B62D27, 0xE66A4263, 0xDF65001F, 0x0EC50966, 0xDFDD55BC, 0x29DE0655, 0x911E739A, 0x17AF8975, 0x32C7911C, 0x89F89468, 0x0D01E980, 0x524755F4, 0x03B63CC9, 0x0CC844B2, 0xBCF3F0AA, 0x87AC36E9, 0xE53A7426, 0x01B3D82B, 0x1A9E7449, 0x64EE2D7E, 0xCDDBB1DA, 0x01C94910, 0xB868BF80, 0x0D26F3FD, 0x9342EDE7, 0x04A5C284, 0x636737B6, 0x50F5B616, 0xF24766E3, 0x8ECA36C1, 0x136E05DB, 0xFEF18391, 0xFB887A37, 0xD6E7F7D4, 0xC7FB7DC9, 0x3063FCDF, 0xB6F589DE, 0xEC2941DA, 0x26E46695, 0xB7566419, 0xF654EFC5, 0xD08D58B7, 0x48925401, 0xC1BACB7F, 0xE5FF550F, 0xB6083049, 0x5BB5D0E8, 0x87D72E5A, 0xAB6A6EE1, 0x223A66CE, 0xC62BF3CD, 0x9E0885F9, 0x68CB3E47, 0x086C010F, 0xA21DE820, 0xD18B69DE, 0xF3F65777, 0xFA02C3F6, 0x407EDAC3, 0xCBB3D550, 0x1793084D, 0xB0D70EBA, 0x0AB378D5, 0xD951FB0C, 0xDED7DA56, 0x4124BBE4, 0x94CA0B56, 0x0F5755D1, 0xE0E1E56E, 0x6184B5BE, 0x580A249F, 0x94F74BC0, 0xE327888E, 0x9F7B5561, 0xC3DC0280, 0x05687715, 0x646C6BD7, 0x44904DB3, 0x66B4F0A3, 0xC0F1648A, 0x697ED5AF, 0x49E92FF6, 0x309E374F, 0x2CB6356A, 0x85808573, 0x4991F840, 0x76F0AE02, 0x083BE84D, 0x28421C9A, 0x44489406, 0x736E4CB8, 0xC1092910, 0x8BC95FC6, 0x7D869CF4, 0x134F616F, 0x2E77118D, 0xB31B2BE1, 0xAA90B472, 0x3CA5D717, 0x7D161BBA, 0x9CAD9010, 0xAF462BA2, 0x9FE459D2, 0x45D34559, 0xD9F2DA13, 0xDBC65487, 0xF3E4F94E, 0x176D486F, 0x097C13EA, 0x631DA5C7, 0x445F7382, 0x175683F4, 0xCDC66A97, 0x70BE0288, 0xB3CDCF72, 0x6E5DD2F3, 0x20936079, 0x459B80A5, 0xBE60E2DB, 0xA9C23101, 0xEBA5315C, 0x224E42F2, 0x1C5C1572, 0xF6721B2C, 0x1AD2FFF3, 0x8C25404E, 0x324ED72F, 0x4067B7FD, 0x0523138E, 0x5CA3BC78, 0xDC0FD66E, 0x75922283, 0x784D6B17, 0x58EBB16E, 0x44094F85, 0x3F481D87, 0xFCFEAE7B, 0x77B5FF76, 0x8C2302BF, 0xAAF47556, 0x5F46B02A, 0x2B092801, 0x3D38F5F7, 0x0CA81F36, 0x52AF4A8A, 0x66D5E7C0, 0xDF3B0874, 0x95055110, 0x1B5AD7A8, 0xF61ED5AD, 0x6CF6E479, 0x20758184, 0xD0CEFA65, 0x88F7BE58, 0x4A046826, 0x0FF6F8F3, 0xA09C7F70, 0x5346ABA0, 0x5CE96C28, 0xE176EDA3, 0x6BAC307F, 0x376829D2, 0x85360FA9, 0x17E3FE2A, 0x24B79767, 0xF5A96B20, 0xD6CD2595, 0x68FF1EBF, 0x7555442C, 0xF19F06BE, 0xF9E0659A, 0xEEB9491D, 0x34010718, 0xBB30CAB8, 0xE822FE15, 0x88570983, 0x750E6249, 0xDA627E55, 0x5E76FFA8, 0xB1534546, 0x6D47DE08, 0xEFE9E7D4 }; const u32bit CAST_128::S6[256] = { 0xF6FA8F9D, 0x2CAC6CE1, 0x4CA34867, 0xE2337F7C, 0x95DB08E7, 0x016843B4, 0xECED5CBC, 0x325553AC, 0xBF9F0960, 0xDFA1E2ED, 0x83F0579D, 0x63ED86B9, 0x1AB6A6B8, 0xDE5EBE39, 0xF38FF732, 0x8989B138, 0x33F14961, 0xC01937BD, 0xF506C6DA, 0xE4625E7E, 0xA308EA99, 0x4E23E33C, 0x79CBD7CC, 0x48A14367, 0xA3149619, 0xFEC94BD5, 0xA114174A, 0xEAA01866, 0xA084DB2D, 0x09A8486F, 0xA888614A, 0x2900AF98, 0x01665991, 0xE1992863, 0xC8F30C60, 0x2E78EF3C, 0xD0D51932, 0xCF0FEC14, 0xF7CA07D2, 0xD0A82072, 0xFD41197E, 0x9305A6B0, 0xE86BE3DA, 0x74BED3CD, 0x372DA53C, 0x4C7F4448, 0xDAB5D440, 0x6DBA0EC3, 0x083919A7, 0x9FBAEED9, 0x49DBCFB0, 0x4E670C53, 0x5C3D9C01, 0x64BDB941, 0x2C0E636A, 0xBA7DD9CD, 0xEA6F7388, 0xE70BC762, 0x35F29ADB, 0x5C4CDD8D, 0xF0D48D8C, 0xB88153E2, 0x08A19866, 0x1AE2EAC8, 0x284CAF89, 0xAA928223, 0x9334BE53, 0x3B3A21BF, 0x16434BE3, 0x9AEA3906, 0xEFE8C36E, 0xF890CDD9, 0x80226DAE, 0xC340A4A3, 0xDF7E9C09, 0xA694A807, 0x5B7C5ECC, 0x221DB3A6, 0x9A69A02F, 0x68818A54, 0xCEB2296F, 0x53C0843A, 0xFE893655, 0x25BFE68A, 0xB4628ABC, 0xCF222EBF, 0x25AC6F48, 0xA9A99387, 0x53BDDB65, 0xE76FFBE7, 0xE967FD78, 0x0BA93563, 0x8E342BC1, 0xE8A11BE9, 0x4980740D, 0xC8087DFC, 0x8DE4BF99, 0xA11101A0, 0x7FD37975, 0xDA5A26C0, 0xE81F994F, 0x9528CD89, 0xFD339FED, 0xB87834BF, 0x5F04456D, 0x22258698, 0xC9C4C83B, 0x2DC156BE, 0x4F628DAA, 0x57F55EC5, 0xE2220ABE, 0xD2916EBF, 0x4EC75B95, 0x24F2C3C0, 0x42D15D99, 0xCD0D7FA0, 0x7B6E27FF, 0xA8DC8AF0, 0x7345C106, 0xF41E232F, 0x35162386, 0xE6EA8926, 0x3333B094, 0x157EC6F2, 0x372B74AF, 0x692573E4, 0xE9A9D848, 0xF3160289, 0x3A62EF1D, 0xA787E238, 0xF3A5F676, 0x74364853, 0x20951063, 0x4576698D, 0xB6FAD407, 0x592AF950, 0x36F73523, 0x4CFB6E87, 0x7DA4CEC0, 0x6C152DAA, 0xCB0396A8, 0xC50DFE5D, 0xFCD707AB, 0x0921C42F, 0x89DFF0BB, 0x5FE2BE78, 0x448F4F33, 0x754613C9, 0x2B05D08D, 0x48B9D585, 0xDC049441, 0xC8098F9B, 0x7DEDE786, 0xC39A3373, 0x42410005, 0x6A091751, 0x0EF3C8A6, 0x890072D6, 0x28207682, 0xA9A9F7BE, 0xBF32679D, 0xD45B5B75, 0xB353FD00, 0xCBB0E358, 0x830F220A, 0x1F8FB214, 0xD372CF08, 0xCC3C4A13, 0x8CF63166, 0x061C87BE, 0x88C98F88, 0x6062E397, 0x47CF8E7A, 0xB6C85283, 0x3CC2ACFB, 0x3FC06976, 0x4E8F0252, 0x64D8314D, 0xDA3870E3, 0x1E665459, 0xC10908F0, 0x513021A5, 0x6C5B68B7, 0x822F8AA0, 0x3007CD3E, 0x74719EEF, 0xDC872681, 0x073340D4, 0x7E432FD9, 0x0C5EC241, 0x8809286C, 0xF592D891, 0x08A930F6, 0x957EF305, 0xB7FBFFBD, 0xC266E96F, 0x6FE4AC98, 0xB173ECC0, 0xBC60B42A, 0x953498DA, 0xFBA1AE12, 0x2D4BD736, 0x0F25FAAB, 0xA4F3FCEB, 0xE2969123, 0x257F0C3D, 0x9348AF49, 0x361400BC, 0xE8816F4A, 0x3814F200, 0xA3F94043, 0x9C7A54C2, 0xBC704F57, 0xDA41E7F9, 0xC25AD33A, 0x54F4A084, 0xB17F5505, 0x59357CBE, 0xEDBD15C8, 0x7F97C5AB, 0xBA5AC7B5, 0xB6F6DEAF, 0x3A479C3A, 0x5302DA25, 0x653D7E6A, 0x54268D49, 0x51A477EA, 0x5017D55B, 0xD7D25D88, 0x44136C76, 0x0404A8C8, 0xB8E5A121, 0xB81A928A, 0x60ED5869, 0x97C55B96, 0xEAEC991B, 0x29935913, 0x01FDB7F1, 0x088E8DFA, 0x9AB6F6F5, 0x3B4CBF9F, 0x4A5DE3AB, 0xE6051D35, 0xA0E1D855, 0xD36B4CF1, 0xF544EDEB, 0xB0E93524, 0xBEBB8FBD, 0xA2D762CF, 0x49C92F54, 0x38B5F331, 0x7128A454, 0x48392905, 0xA65B1DB8, 0x851C97BD, 0xD675CF2F }; const u32bit CAST_128::S7[256] = { 0x85E04019, 0x332BF567, 0x662DBFFF, 0xCFC65693, 0x2A8D7F6F, 0xAB9BC912, 0xDE6008A1, 0x2028DA1F, 0x0227BCE7, 0x4D642916, 0x18FAC300, 0x50F18B82, 0x2CB2CB11, 0xB232E75C, 0x4B3695F2, 0xB28707DE, 0xA05FBCF6, 0xCD4181E9, 0xE150210C, 0xE24EF1BD, 0xB168C381, 0xFDE4E789, 0x5C79B0D8, 0x1E8BFD43, 0x4D495001, 0x38BE4341, 0x913CEE1D, 0x92A79C3F, 0x089766BE, 0xBAEEADF4, 0x1286BECF, 0xB6EACB19, 0x2660C200, 0x7565BDE4, 0x64241F7A, 0x8248DCA9, 0xC3B3AD66, 0x28136086, 0x0BD8DFA8, 0x356D1CF2, 0x107789BE, 0xB3B2E9CE, 0x0502AA8F, 0x0BC0351E, 0x166BF52A, 0xEB12FF82, 0xE3486911, 0xD34D7516, 0x4E7B3AFF, 0x5F43671B, 0x9CF6E037, 0x4981AC83, 0x334266CE, 0x8C9341B7, 0xD0D854C0, 0xCB3A6C88, 0x47BC2829, 0x4725BA37, 0xA66AD22B, 0x7AD61F1E, 0x0C5CBAFA, 0x4437F107, 0xB6E79962, 0x42D2D816, 0x0A961288, 0xE1A5C06E, 0x13749E67, 0x72FC081A, 0xB1D139F7, 0xF9583745, 0xCF19DF58, 0xBEC3F756, 0xC06EBA30, 0x07211B24, 0x45C28829, 0xC95E317F, 0xBC8EC511, 0x38BC46E9, 0xC6E6FA14, 0xBAE8584A, 0xAD4EBC46, 0x468F508B, 0x7829435F, 0xF124183B, 0x821DBA9F, 0xAFF60FF4, 0xEA2C4E6D, 0x16E39264, 0x92544A8B, 0x009B4FC3, 0xABA68CED, 0x9AC96F78, 0x06A5B79A, 0xB2856E6E, 0x1AEC3CA9, 0xBE838688, 0x0E0804E9, 0x55F1BE56, 0xE7E5363B, 0xB3A1F25D, 0xF7DEBB85, 0x61FE033C, 0x16746233, 0x3C034C28, 0xDA6D0C74, 0x79AAC56C, 0x3CE4E1AD, 0x51F0C802, 0x98F8F35A, 0x1626A49F, 0xEED82B29, 0x1D382FE3, 0x0C4FB99A, 0xBB325778, 0x3EC6D97B, 0x6E77A6A9, 0xCB658B5C, 0xD45230C7, 0x2BD1408B, 0x60C03EB7, 0xB9068D78, 0xA33754F4, 0xF430C87D, 0xC8A71302, 0xB96D8C32, 0xEBD4E7BE, 0xBE8B9D2D, 0x7979FB06, 0xE7225308, 0x8B75CF77, 0x11EF8DA4, 0xE083C858, 0x8D6B786F, 0x5A6317A6, 0xFA5CF7A0, 0x5DDA0033, 0xF28EBFB0, 0xF5B9C310, 0xA0EAC280, 0x08B9767A, 0xA3D9D2B0, 0x79D34217, 0x021A718D, 0x9AC6336A, 0x2711FD60, 0x438050E3, 0x069908A8, 0x3D7FEDC4, 0x826D2BEF, 0x4EEB8476, 0x488DCF25, 0x36C9D566, 0x28E74E41, 0xC2610ACA, 0x3D49A9CF, 0xBAE3B9DF, 0xB65F8DE6, 0x92AEAF64, 0x3AC7D5E6, 0x9EA80509, 0xF22B017D, 0xA4173F70, 0xDD1E16C3, 0x15E0D7F9, 0x50B1B887, 0x2B9F4FD5, 0x625ABA82, 0x6A017962, 0x2EC01B9C, 0x15488AA9, 0xD716E740, 0x40055A2C, 0x93D29A22, 0xE32DBF9A, 0x058745B9, 0x3453DC1E, 0xD699296E, 0x496CFF6F, 0x1C9F4986, 0xDFE2ED07, 0xB87242D1, 0x19DE7EAE, 0x053E561A, 0x15AD6F8C, 0x66626C1C, 0x7154C24C, 0xEA082B2A, 0x93EB2939, 0x17DCB0F0, 0x58D4F2AE, 0x9EA294FB, 0x52CF564C, 0x9883FE66, 0x2EC40581, 0x763953C3, 0x01D6692E, 0xD3A0C108, 0xA1E7160E, 0xE4F2DFA6, 0x693ED285, 0x74904698, 0x4C2B0EDD, 0x4F757656, 0x5D393378, 0xA132234F, 0x3D321C5D, 0xC3F5E194, 0x4B269301, 0xC79F022F, 0x3C997E7E, 0x5E4F9504, 0x3FFAFBBD, 0x76F7AD0E, 0x296693F4, 0x3D1FCE6F, 0xC61E45BE, 0xD3B5AB34, 0xF72BF9B7, 0x1B0434C0, 0x4E72B567, 0x5592A33D, 0xB5229301, 0xCFD2A87F, 0x60AEB767, 0x1814386B, 0x30BCC33D, 0x38A0C07D, 0xFD1606F2, 0xC363519B, 0x589DD390, 0x5479F8E6, 0x1CB8D647, 0x97FD61A9, 0xEA7759F4, 0x2D57539D, 0x569A58CF, 0xE84E63AD, 0x462E1B78, 0x6580F87E, 0xF3817914, 0x91DA55F4, 0x40A230F3, 0xD1988F35, 0xB6E318D2, 0x3FFA50BC, 0x3D40F021, 0xC3C0BDAE, 0x4958C24C, 0x518F36B2, 0x84B1D370, 0x0FEDCE83, 0x878DDADA, 0xF2A279C7, 0x94E01BE8, 0x90716F4B, 0x954B8AA3 }; const u32bit CAST_128::S8[256] = { 0xE216300D, 0xBBDDFFFC, 0xA7EBDABD, 0x35648095, 0x7789F8B7, 0xE6C1121B, 0x0E241600, 0x052CE8B5, 0x11A9CFB0, 0xE5952F11, 0xECE7990A, 0x9386D174, 0x2A42931C, 0x76E38111, 0xB12DEF3A, 0x37DDDDFC, 0xDE9ADEB1, 0x0A0CC32C, 0xBE197029, 0x84A00940, 0xBB243A0F, 0xB4D137CF, 0xB44E79F0, 0x049EEDFD, 0x0B15A15D, 0x480D3168, 0x8BBBDE5A, 0x669DED42, 0xC7ECE831, 0x3F8F95E7, 0x72DF191B, 0x7580330D, 0x94074251, 0x5C7DCDFA, 0xABBE6D63, 0xAA402164, 0xB301D40A, 0x02E7D1CA, 0x53571DAE, 0x7A3182A2, 0x12A8DDEC, 0xFDAA335D, 0x176F43E8, 0x71FB46D4, 0x38129022, 0xCE949AD4, 0xB84769AD, 0x965BD862, 0x82F3D055, 0x66FB9767, 0x15B80B4E, 0x1D5B47A0, 0x4CFDE06F, 0xC28EC4B8, 0x57E8726E, 0x647A78FC, 0x99865D44, 0x608BD593, 0x6C200E03, 0x39DC5FF6, 0x5D0B00A3, 0xAE63AFF2, 0x7E8BD632, 0x70108C0C, 0xBBD35049, 0x2998DF04, 0x980CF42A, 0x9B6DF491, 0x9E7EDD53, 0x06918548, 0x58CB7E07, 0x3B74EF2E, 0x522FFFB1, 0xD24708CC, 0x1C7E27CD, 0xA4EB215B, 0x3CF1D2E2, 0x19B47A38, 0x424F7618, 0x35856039, 0x9D17DEE7, 0x27EB35E6, 0xC9AFF67B, 0x36BAF5B8, 0x09C467CD, 0xC18910B1, 0xE11DBF7B, 0x06CD1AF8, 0x7170C608, 0x2D5E3354, 0xD4DE495A, 0x64C6D006, 0xBCC0C62C, 0x3DD00DB3, 0x708F8F34, 0x77D51B42, 0x264F620F, 0x24B8D2BF, 0x15C1B79E, 0x46A52564, 0xF8D7E54E, 0x3E378160, 0x7895CDA5, 0x859C15A5, 0xE6459788, 0xC37BC75F, 0xDB07BA0C, 0x0676A3AB, 0x7F229B1E, 0x31842E7B, 0x24259FD7, 0xF8BEF472, 0x835FFCB8, 0x6DF4C1F2, 0x96F5B195, 0xFD0AF0FC, 0xB0FE134C, 0xE2506D3D, 0x4F9B12EA, 0xF215F225, 0xA223736F, 0x9FB4C428, 0x25D04979, 0x34C713F8, 0xC4618187, 0xEA7A6E98, 0x7CD16EFC, 0x1436876C, 0xF1544107, 0xBEDEEE14, 0x56E9AF27, 0xA04AA441, 0x3CF7C899, 0x92ECBAE6, 0xDD67016D, 0x151682EB, 0xA842EEDF, 0xFDBA60B4, 0xF1907B75, 0x20E3030F, 0x24D8C29E, 0xE139673B, 0xEFA63FB8, 0x71873054, 0xB6F2CF3B, 0x9F326442, 0xCB15A4CC, 0xB01A4504, 0xF1E47D8D, 0x844A1BE5, 0xBAE7DFDC, 0x42CBDA70, 0xCD7DAE0A, 0x57E85B7A, 0xD53F5AF6, 0x20CF4D8C, 0xCEA4D428, 0x79D130A4, 0x3486EBFB, 0x33D3CDDC, 0x77853B53, 0x37EFFCB5, 0xC5068778, 0xE580B3E6, 0x4E68B8F4, 0xC5C8B37E, 0x0D809EA2, 0x398FEB7C, 0x132A4F94, 0x43B7950E, 0x2FEE7D1C, 0x223613BD, 0xDD06CAA2, 0x37DF932B, 0xC4248289, 0xACF3EBC3, 0x5715F6B7, 0xEF3478DD, 0xF267616F, 0xC148CBE4, 0x9052815E, 0x5E410FAB, 0xB48A2465, 0x2EDA7FA4, 0xE87B40E4, 0xE98EA084, 0x5889E9E1, 0xEFD390FC, 0xDD07D35B, 0xDB485694, 0x38D7E5B2, 0x57720101, 0x730EDEBC, 0x5B643113, 0x94917E4F, 0x503C2FBA, 0x646F1282, 0x7523D24A, 0xE0779695, 0xF9C17A8F, 0x7A5B2121, 0xD187B896, 0x29263A4D, 0xBA510CDF, 0x81F47C9F, 0xAD1163ED, 0xEA7B5965, 0x1A00726E, 0x11403092, 0x00DA6D77, 0x4A0CDD61, 0xAD1F4603, 0x605BDFB0, 0x9EEDC364, 0x22EBE6A8, 0xCEE7D28A, 0xA0E736A0, 0x5564A6B9, 0x10853209, 0xC7EB8F37, 0x2DE705CA, 0x8951570F, 0xDF09822B, 0xBD691A6C, 0xAA12E4F2, 0x87451C0F, 0xE0F6A27A, 0x3ADA4819, 0x4CF1764F, 0x0D771C2B, 0x67CDB156, 0x350D8384, 0x5938FA0F, 0x42399EF3, 0x36997B07, 0x0E84093D, 0x4AA93E61, 0x8360D87B, 0x1FA98B0C, 0x1149382C, 0xE97625A5, 0x0614D1B7, 0x0E25244B, 0x0C768347, 0x589E8D82, 0x0D2059D1, 0xA466BB1E, 0xF8DA0A82, 0x04F19130, 0xBA6E4EC0, 0x99265164, 0x1EE7230D, 0x50B2AD80, 0xEAEE6801, 0x8DB2A283, 0xEA8BF59E }; const u32bit CAST_256::KEY_MASK[192] = { 0x5A827999, 0xC95C653A, 0x383650DB, 0xA7103C7C, 0x15EA281D, 0x84C413BE, 0xF39DFF5F, 0x6277EB00, 0xD151D6A1, 0x402BC242, 0xAF05ADE3, 0x1DDF9984, 0x8CB98525, 0xFB9370C6, 0x6A6D5C67, 0xD9474808, 0x482133A9, 0xB6FB1F4A, 0x25D50AEB, 0x94AEF68C, 0x0388E22D, 0x7262CDCE, 0xE13CB96F, 0x5016A510, 0xBEF090B1, 0x2DCA7C52, 0x9CA467F3, 0x0B7E5394, 0x7A583F35, 0xE9322AD6, 0x580C1677, 0xC6E60218, 0x35BFEDB9, 0xA499D95A, 0x1373C4FB, 0x824DB09C, 0xF1279C3D, 0x600187DE, 0xCEDB737F, 0x3DB55F20, 0xAC8F4AC1, 0x1B693662, 0x8A432203, 0xF91D0DA4, 0x67F6F945, 0xD6D0E4E6, 0x45AAD087, 0xB484BC28, 0x235EA7C9, 0x9238936A, 0x01127F0B, 0x6FEC6AAC, 0xDEC6564D, 0x4DA041EE, 0xBC7A2D8F, 0x2B541930, 0x9A2E04D1, 0x0907F072, 0x77E1DC13, 0xE6BBC7B4, 0x5595B355, 0xC46F9EF6, 0x33498A97, 0xA2237638, 0x10FD61D9, 0x7FD74D7A, 0xEEB1391B, 0x5D8B24BC, 0xCC65105D, 0x3B3EFBFE, 0xAA18E79F, 0x18F2D340, 0x87CCBEE1, 0xF6A6AA82, 0x65809623, 0xD45A81C4, 0x43346D65, 0xB20E5906, 0x20E844A7, 0x8FC23048, 0xFE9C1BE9, 0x6D76078A, 0xDC4FF32B, 0x4B29DECC, 0xBA03CA6D, 0x28DDB60E, 0x97B7A1AF, 0x06918D50, 0x756B78F1, 0xE4456492, 0x531F5033, 0xC1F93BD4, 0x30D32775, 0x9FAD1316, 0x0E86FEB7, 0x7D60EA58, 0xEC3AD5F9, 0x5B14C19A, 0xC9EEAD3B, 0x38C898DC, 0xA7A2847D, 0x167C701E, 0x85565BBF, 0xF4304760, 0x630A3301, 0xD1E41EA2, 0x40BE0A43, 0xAF97F5E4, 0x1E71E185, 0x8D4BCD26, 0xFC25B8C7, 0x6AFFA468, 0xD9D99009, 0x48B37BAA, 0xB78D674B, 0x266752EC, 0x95413E8D, 0x041B2A2E, 0x72F515CF, 0xE1CF0170, 0x50A8ED11, 0xBF82D8B2, 0x2E5CC453, 0x9D36AFF4, 0x0C109B95, 0x7AEA8736, 0xE9C472D7, 0x589E5E78, 0xC7784A19, 0x365235BA, 0xA52C215B, 0x14060CFC, 0x82DFF89D, 0xF1B9E43E, 0x6093CFDF, 0xCF6DBB80, 0x3E47A721, 0xAD2192C2, 0x1BFB7E63, 0x8AD56A04, 0xF9AF55A5, 0x68894146, 0xD7632CE7, 0x463D1888, 0xB5170429, 0x23F0EFCA, 0x92CADB6B, 0x01A4C70C, 0x707EB2AD, 0xDF589E4E, 0x4E3289EF, 0xBD0C7590, 0x2BE66131, 0x9AC04CD2, 0x099A3873, 0x78742414, 0xE74E0FB5, 0x5627FB56, 0xC501E6F7, 0x33DBD298, 0xA2B5BE39, 0x118FA9DA, 0x8069957B, 0xEF43811C, 0x5E1D6CBD, 0xCCF7585E, 0x3BD143FF, 0xAAAB2FA0, 0x19851B41, 0x885F06E2, 0xF738F283, 0x6612DE24, 0xD4ECC9C5, 0x43C6B566, 0xB2A0A107, 0x217A8CA8, 0x90547849, 0xFF2E63EA, 0x6E084F8B, 0xDCE23B2C, 0x4BBC26CD, 0xBA96126E, 0x296FFE0F, 0x9849E9B0, 0x0723D551, 0x75FDC0F2, 0xE4D7AC93, 0x53B19834, 0xC28B83D5, 0x31656F76, 0xA03F5B17, 0x0F1946B8 }; const byte CAST_256::KEY_ROT[32] = { 0x13, 0x04, 0x15, 0x06, 0x17, 0x08, 0x19, 0x0A, 0x1B, 0x0C, 0x1D, 0x0E, 0x1F, 0x10, 0x01, 0x12, 0x03, 0x14, 0x05, 0x16, 0x07, 0x18, 0x09, 0x1A, 0x0B, 0x1C, 0x0D, 0x1E, 0x0F, 0x00, 0x11, 0x02 }; } /* * DES * (C) 1999-2008 Jack Lloyd * * Based on a public domain implemenation by Phil Karn (who in turn * credited Richard Outerbridge and Jim Gillogly) * * Distributed under the terms of the Botan license */ namespace Botan { namespace { /* * DES Key Schedule */ void des_key_schedule(u32bit round_key[32], const byte key[8]) { static const byte ROT[16] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 }; u32bit C = ((key[7] & 0x80) << 20) | ((key[6] & 0x80) << 19) | ((key[5] & 0x80) << 18) | ((key[4] & 0x80) << 17) | ((key[3] & 0x80) << 16) | ((key[2] & 0x80) << 15) | ((key[1] & 0x80) << 14) | ((key[0] & 0x80) << 13) | ((key[7] & 0x40) << 13) | ((key[6] & 0x40) << 12) | ((key[5] & 0x40) << 11) | ((key[4] & 0x40) << 10) | ((key[3] & 0x40) << 9) | ((key[2] & 0x40) << 8) | ((key[1] & 0x40) << 7) | ((key[0] & 0x40) << 6) | ((key[7] & 0x20) << 6) | ((key[6] & 0x20) << 5) | ((key[5] & 0x20) << 4) | ((key[4] & 0x20) << 3) | ((key[3] & 0x20) << 2) | ((key[2] & 0x20) << 1) | ((key[1] & 0x20) ) | ((key[0] & 0x20) >> 1) | ((key[7] & 0x10) >> 1) | ((key[6] & 0x10) >> 2) | ((key[5] & 0x10) >> 3) | ((key[4] & 0x10) >> 4); u32bit D = ((key[7] & 0x02) << 26) | ((key[6] & 0x02) << 25) | ((key[5] & 0x02) << 24) | ((key[4] & 0x02) << 23) | ((key[3] & 0x02) << 22) | ((key[2] & 0x02) << 21) | ((key[1] & 0x02) << 20) | ((key[0] & 0x02) << 19) | ((key[7] & 0x04) << 17) | ((key[6] & 0x04) << 16) | ((key[5] & 0x04) << 15) | ((key[4] & 0x04) << 14) | ((key[3] & 0x04) << 13) | ((key[2] & 0x04) << 12) | ((key[1] & 0x04) << 11) | ((key[0] & 0x04) << 10) | ((key[7] & 0x08) << 8) | ((key[6] & 0x08) << 7) | ((key[5] & 0x08) << 6) | ((key[4] & 0x08) << 5) | ((key[3] & 0x08) << 4) | ((key[2] & 0x08) << 3) | ((key[1] & 0x08) << 2) | ((key[0] & 0x08) << 1) | ((key[3] & 0x10) >> 1) | ((key[2] & 0x10) >> 2) | ((key[1] & 0x10) >> 3) | ((key[0] & 0x10) >> 4); for(size_t i = 0; i != 16; ++i) { C = ((C << ROT[i]) | (C >> (28-ROT[i]))) & 0x0FFFFFFF; D = ((D << ROT[i]) | (D >> (28-ROT[i]))) & 0x0FFFFFFF; round_key[2*i ] = ((C & 0x00000010) << 22) | ((C & 0x00000800) << 17) | ((C & 0x00000020) << 16) | ((C & 0x00004004) << 15) | ((C & 0x00000200) << 11) | ((C & 0x00020000) << 10) | ((C & 0x01000000) >> 6) | ((C & 0x00100000) >> 4) | ((C & 0x00010000) << 3) | ((C & 0x08000000) >> 2) | ((C & 0x00800000) << 1) | ((D & 0x00000010) << 8) | ((D & 0x00000002) << 7) | ((D & 0x00000001) << 2) | ((D & 0x00000200) ) | ((D & 0x00008000) >> 2) | ((D & 0x00000088) >> 3) | ((D & 0x00001000) >> 7) | ((D & 0x00080000) >> 9) | ((D & 0x02020000) >> 14) | ((D & 0x00400000) >> 21); round_key[2*i+1] = ((C & 0x00000001) << 28) | ((C & 0x00000082) << 18) | ((C & 0x00002000) << 14) | ((C & 0x00000100) << 10) | ((C & 0x00001000) << 9) | ((C & 0x00040000) << 6) | ((C & 0x02400000) << 4) | ((C & 0x00008000) << 2) | ((C & 0x00200000) >> 1) | ((C & 0x04000000) >> 10) | ((D & 0x00000020) << 6) | ((D & 0x00000100) ) | ((D & 0x00000800) >> 1) | ((D & 0x00000040) >> 3) | ((D & 0x00010000) >> 4) | ((D & 0x00000400) >> 5) | ((D & 0x00004000) >> 10) | ((D & 0x04000000) >> 13) | ((D & 0x00800000) >> 14) | ((D & 0x00100000) >> 18) | ((D & 0x01000000) >> 24) | ((D & 0x08000000) >> 26); } } /* * DES Encryption */ void des_encrypt(u32bit& L, u32bit& R, const u32bit round_key[32]) { for(size_t i = 0; i != 16; i += 2) { u32bit T0, T1; T0 = rotate_right(R, 4) ^ round_key[2*i]; T1 = R ^ round_key[2*i + 1]; L ^= DES_SPBOX1[get_byte(0, T0)] ^ DES_SPBOX2[get_byte(0, T1)] ^ DES_SPBOX3[get_byte(1, T0)] ^ DES_SPBOX4[get_byte(1, T1)] ^ DES_SPBOX5[get_byte(2, T0)] ^ DES_SPBOX6[get_byte(2, T1)] ^ DES_SPBOX7[get_byte(3, T0)] ^ DES_SPBOX8[get_byte(3, T1)]; T0 = rotate_right(L, 4) ^ round_key[2*i + 2]; T1 = L ^ round_key[2*i + 3]; R ^= DES_SPBOX1[get_byte(0, T0)] ^ DES_SPBOX2[get_byte(0, T1)] ^ DES_SPBOX3[get_byte(1, T0)] ^ DES_SPBOX4[get_byte(1, T1)] ^ DES_SPBOX5[get_byte(2, T0)] ^ DES_SPBOX6[get_byte(2, T1)] ^ DES_SPBOX7[get_byte(3, T0)] ^ DES_SPBOX8[get_byte(3, T1)]; } } /* * DES Decryption */ void des_decrypt(u32bit& L, u32bit& R, const u32bit round_key[32]) { for(size_t i = 16; i != 0; i -= 2) { u32bit T0, T1; T0 = rotate_right(R, 4) ^ round_key[2*i - 2]; T1 = R ^ round_key[2*i - 1]; L ^= DES_SPBOX1[get_byte(0, T0)] ^ DES_SPBOX2[get_byte(0, T1)] ^ DES_SPBOX3[get_byte(1, T0)] ^ DES_SPBOX4[get_byte(1, T1)] ^ DES_SPBOX5[get_byte(2, T0)] ^ DES_SPBOX6[get_byte(2, T1)] ^ DES_SPBOX7[get_byte(3, T0)] ^ DES_SPBOX8[get_byte(3, T1)]; T0 = rotate_right(L, 4) ^ round_key[2*i - 4]; T1 = L ^ round_key[2*i - 3]; R ^= DES_SPBOX1[get_byte(0, T0)] ^ DES_SPBOX2[get_byte(0, T1)] ^ DES_SPBOX3[get_byte(1, T0)] ^ DES_SPBOX4[get_byte(1, T1)] ^ DES_SPBOX5[get_byte(2, T0)] ^ DES_SPBOX6[get_byte(2, T1)] ^ DES_SPBOX7[get_byte(3, T0)] ^ DES_SPBOX8[get_byte(3, T1)]; } } } /* * DES Encryption */ void DES::encrypt_n(const byte in[], byte out[], size_t blocks) const { for(size_t 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(T >> 32); u32bit R = static_cast(T); des_encrypt(L, R, &round_key[0]); 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); store_be(T, out); in += BLOCK_SIZE; out += BLOCK_SIZE; } } /* * DES Decryption */ void DES::decrypt_n(const byte in[], byte out[], size_t blocks) const { for(size_t 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(T >> 32); u32bit R = static_cast(T); des_decrypt(L, R, &round_key[0]); 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); store_be(T, out); in += BLOCK_SIZE; out += BLOCK_SIZE; } } /* * DES Key Schedule */ void DES::key_schedule(const byte key[], size_t) { des_key_schedule(&round_key[0], key); } /* * TripleDES Encryption */ void TripleDES::encrypt_n(const byte in[], byte out[], size_t blocks) const { for(size_t 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(T >> 32); u32bit R = static_cast(T); des_encrypt(L, R, &round_key[0]); 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 = rotate_left(T, 32); store_be(T, out); in += BLOCK_SIZE; out += BLOCK_SIZE; } } /* * TripleDES Decryption */ void TripleDES::decrypt_n(const byte in[], byte out[], size_t blocks) const { for(size_t 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(T >> 32); u32bit R = static_cast(T); des_decrypt(L, R, &round_key[64]); des_encrypt(R, L, &round_key[32]); des_decrypt(L, R, &round_key[0]); 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); store_be(T, out); in += BLOCK_SIZE; out += BLOCK_SIZE; } } /* * TripleDES Key Schedule */ void TripleDES::key_schedule(const byte key[], size_t length) { des_key_schedule(&round_key[0], key); des_key_schedule(&round_key[32], key + 8); if(length == 24) des_key_schedule(&round_key[64], key + 16); else copy_mem(&round_key[64], &round_key[0], 32); } } /* * Substitution/Permutation Tables for DES * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { const u32bit DES_SPBOX1[256] = { 0x01010400, 0x00000000, 0x00010000, 0x01010404, 0x01010004, 0x00010404, 0x00000004, 0x00010000, 0x00000400, 0x01010400, 0x01010404, 0x00000400, 0x01000404, 0x01010004, 0x01000000, 0x00000004, 0x00000404, 0x01000400, 0x01000400, 0x00010400, 0x00010400, 0x01010000, 0x01010000, 0x01000404, 0x00010004, 0x01000004, 0x01000004, 0x00010004, 0x00000000, 0x00000404, 0x00010404, 0x01000000, 0x00010000, 0x01010404, 0x00000004, 0x01010000, 0x01010400, 0x01000000, 0x01000000, 0x00000400, 0x01010004, 0x00010000, 0x00010400, 0x01000004, 0x00000400, 0x00000004, 0x01000404, 0x00010404, 0x01010404, 0x00010004, 0x01010000, 0x01000404, 0x01000004, 0x00000404, 0x00010404, 0x01010400, 0x00000404, 0x01000400, 0x01000400, 0x00000000, 0x00010004, 0x00010400, 0x00000000, 0x01010004, 0x01010400, 0x00000000, 0x00010000, 0x01010404, 0x01010004, 0x00010404, 0x00000004, 0x00010000, 0x00000400, 0x01010400, 0x01010404, 0x00000400, 0x01000404, 0x01010004, 0x01000000, 0x00000004, 0x00000404, 0x01000400, 0x01000400, 0x00010400, 0x00010400, 0x01010000, 0x01010000, 0x01000404, 0x00010004, 0x01000004, 0x01000004, 0x00010004, 0x00000000, 0x00000404, 0x00010404, 0x01000000, 0x00010000, 0x01010404, 0x00000004, 0x01010000, 0x01010400, 0x01000000, 0x01000000, 0x00000400, 0x01010004, 0x00010000, 0x00010400, 0x01000004, 0x00000400, 0x00000004, 0x01000404, 0x00010404, 0x01010404, 0x00010004, 0x01010000, 0x01000404, 0x01000004, 0x00000404, 0x00010404, 0x01010400, 0x00000404, 0x01000400, 0x01000400, 0x00000000, 0x00010004, 0x00010400, 0x00000000, 0x01010004, 0x01010400, 0x00000000, 0x00010000, 0x01010404, 0x01010004, 0x00010404, 0x00000004, 0x00010000, 0x00000400, 0x01010400, 0x01010404, 0x00000400, 0x01000404, 0x01010004, 0x01000000, 0x00000004, 0x00000404, 0x01000400, 0x01000400, 0x00010400, 0x00010400, 0x01010000, 0x01010000, 0x01000404, 0x00010004, 0x01000004, 0x01000004, 0x00010004, 0x00000000, 0x00000404, 0x00010404, 0x01000000, 0x00010000, 0x01010404, 0x00000004, 0x01010000, 0x01010400, 0x01000000, 0x01000000, 0x00000400, 0x01010004, 0x00010000, 0x00010400, 0x01000004, 0x00000400, 0x00000004, 0x01000404, 0x00010404, 0x01010404, 0x00010004, 0x01010000, 0x01000404, 0x01000004, 0x00000404, 0x00010404, 0x01010400, 0x00000404, 0x01000400, 0x01000400, 0x00000000, 0x00010004, 0x00010400, 0x00000000, 0x01010004, 0x01010400, 0x00000000, 0x00010000, 0x01010404, 0x01010004, 0x00010404, 0x00000004, 0x00010000, 0x00000400, 0x01010400, 0x01010404, 0x00000400, 0x01000404, 0x01010004, 0x01000000, 0x00000004, 0x00000404, 0x01000400, 0x01000400, 0x00010400, 0x00010400, 0x01010000, 0x01010000, 0x01000404, 0x00010004, 0x01000004, 0x01000004, 0x00010004, 0x00000000, 0x00000404, 0x00010404, 0x01000000, 0x00010000, 0x01010404, 0x00000004, 0x01010000, 0x01010400, 0x01000000, 0x01000000, 0x00000400, 0x01010004, 0x00010000, 0x00010400, 0x01000004, 0x00000400, 0x00000004, 0x01000404, 0x00010404, 0x01010404, 0x00010004, 0x01010000, 0x01000404, 0x01000004, 0x00000404, 0x00010404, 0x01010400, 0x00000404, 0x01000400, 0x01000400, 0x00000000, 0x00010004, 0x00010400, 0x00000000, 0x01010004 }; const u32bit DES_SPBOX2[256] = { 0x80108020, 0x80008000, 0x00008000, 0x00108020, 0x00100000, 0x00000020, 0x80100020, 0x80008020, 0x80000020, 0x80108020, 0x80108000, 0x80000000, 0x80008000, 0x00100000, 0x00000020, 0x80100020, 0x00108000, 0x00100020, 0x80008020, 0x00000000, 0x80000000, 0x00008000, 0x00108020, 0x80100000, 0x00100020, 0x80000020, 0x00000000, 0x00108000, 0x00008020, 0x80108000, 0x80100000, 0x00008020, 0x00000000, 0x00108020, 0x80100020, 0x00100000, 0x80008020, 0x80100000, 0x80108000, 0x00008000, 0x80100000, 0x80008000, 0x00000020, 0x80108020, 0x00108020, 0x00000020, 0x00008000, 0x80000000, 0x00008020, 0x80108000, 0x00100000, 0x80000020, 0x00100020, 0x80008020, 0x80000020, 0x00100020, 0x00108000, 0x00000000, 0x80008000, 0x00008020, 0x80000000, 0x80100020, 0x80108020, 0x00108000, 0x80108020, 0x80008000, 0x00008000, 0x00108020, 0x00100000, 0x00000020, 0x80100020, 0x80008020, 0x80000020, 0x80108020, 0x80108000, 0x80000000, 0x80008000, 0x00100000, 0x00000020, 0x80100020, 0x00108000, 0x00100020, 0x80008020, 0x00000000, 0x80000000, 0x00008000, 0x00108020, 0x80100000, 0x00100020, 0x80000020, 0x00000000, 0x00108000, 0x00008020, 0x80108000, 0x80100000, 0x00008020, 0x00000000, 0x00108020, 0x80100020, 0x00100000, 0x80008020, 0x80100000, 0x80108000, 0x00008000, 0x80100000, 0x80008000, 0x00000020, 0x80108020, 0x00108020, 0x00000020, 0x00008000, 0x80000000, 0x00008020, 0x80108000, 0x00100000, 0x80000020, 0x00100020, 0x80008020, 0x80000020, 0x00100020, 0x00108000, 0x00000000, 0x80008000, 0x00008020, 0x80000000, 0x80100020, 0x80108020, 0x00108000, 0x80108020, 0x80008000, 0x00008000, 0x00108020, 0x00100000, 0x00000020, 0x80100020, 0x80008020, 0x80000020, 0x80108020, 0x80108000, 0x80000000, 0x80008000, 0x00100000, 0x00000020, 0x80100020, 0x00108000, 0x00100020, 0x80008020, 0x00000000, 0x80000000, 0x00008000, 0x00108020, 0x80100000, 0x00100020, 0x80000020, 0x00000000, 0x00108000, 0x00008020, 0x80108000, 0x80100000, 0x00008020, 0x00000000, 0x00108020, 0x80100020, 0x00100000, 0x80008020, 0x80100000, 0x80108000, 0x00008000, 0x80100000, 0x80008000, 0x00000020, 0x80108020, 0x00108020, 0x00000020, 0x00008000, 0x80000000, 0x00008020, 0x80108000, 0x00100000, 0x80000020, 0x00100020, 0x80008020, 0x80000020, 0x00100020, 0x00108000, 0x00000000, 0x80008000, 0x00008020, 0x80000000, 0x80100020, 0x80108020, 0x00108000, 0x80108020, 0x80008000, 0x00008000, 0x00108020, 0x00100000, 0x00000020, 0x80100020, 0x80008020, 0x80000020, 0x80108020, 0x80108000, 0x80000000, 0x80008000, 0x00100000, 0x00000020, 0x80100020, 0x00108000, 0x00100020, 0x80008020, 0x00000000, 0x80000000, 0x00008000, 0x00108020, 0x80100000, 0x00100020, 0x80000020, 0x00000000, 0x00108000, 0x00008020, 0x80108000, 0x80100000, 0x00008020, 0x00000000, 0x00108020, 0x80100020, 0x00100000, 0x80008020, 0x80100000, 0x80108000, 0x00008000, 0x80100000, 0x80008000, 0x00000020, 0x80108020, 0x00108020, 0x00000020, 0x00008000, 0x80000000, 0x00008020, 0x80108000, 0x00100000, 0x80000020, 0x00100020, 0x80008020, 0x80000020, 0x00100020, 0x00108000, 0x00000000, 0x80008000, 0x00008020, 0x80000000, 0x80100020, 0x80108020, 0x00108000 }; const u32bit DES_SPBOX3[256] = { 0x00000208, 0x08020200, 0x00000000, 0x08020008, 0x08000200, 0x00000000, 0x00020208, 0x08000200, 0x00020008, 0x08000008, 0x08000008, 0x00020000, 0x08020208, 0x00020008, 0x08020000, 0x00000208, 0x08000000, 0x00000008, 0x08020200, 0x00000200, 0x00020200, 0x08020000, 0x08020008, 0x00020208, 0x08000208, 0x00020200, 0x00020000, 0x08000208, 0x00000008, 0x08020208, 0x00000200, 0x08000000, 0x08020200, 0x08000000, 0x00020008, 0x00000208, 0x00020000, 0x08020200, 0x08000200, 0x00000000, 0x00000200, 0x00020008, 0x08020208, 0x08000200, 0x08000008, 0x00000200, 0x00000000, 0x08020008, 0x08000208, 0x00020000, 0x08000000, 0x08020208, 0x00000008, 0x00020208, 0x00020200, 0x08000008, 0x08020000, 0x08000208, 0x00000208, 0x08020000, 0x00020208, 0x00000008, 0x08020008, 0x00020200, 0x00000208, 0x08020200, 0x00000000, 0x08020008, 0x08000200, 0x00000000, 0x00020208, 0x08000200, 0x00020008, 0x08000008, 0x08000008, 0x00020000, 0x08020208, 0x00020008, 0x08020000, 0x00000208, 0x08000000, 0x00000008, 0x08020200, 0x00000200, 0x00020200, 0x08020000, 0x08020008, 0x00020208, 0x08000208, 0x00020200, 0x00020000, 0x08000208, 0x00000008, 0x08020208, 0x00000200, 0x08000000, 0x08020200, 0x08000000, 0x00020008, 0x00000208, 0x00020000, 0x08020200, 0x08000200, 0x00000000, 0x00000200, 0x00020008, 0x08020208, 0x08000200, 0x08000008, 0x00000200, 0x00000000, 0x08020008, 0x08000208, 0x00020000, 0x08000000, 0x08020208, 0x00000008, 0x00020208, 0x00020200, 0x08000008, 0x08020000, 0x08000208, 0x00000208, 0x08020000, 0x00020208, 0x00000008, 0x08020008, 0x00020200, 0x00000208, 0x08020200, 0x00000000, 0x08020008, 0x08000200, 0x00000000, 0x00020208, 0x08000200, 0x00020008, 0x08000008, 0x08000008, 0x00020000, 0x08020208, 0x00020008, 0x08020000, 0x00000208, 0x08000000, 0x00000008, 0x08020200, 0x00000200, 0x00020200, 0x08020000, 0x08020008, 0x00020208, 0x08000208, 0x00020200, 0x00020000, 0x08000208, 0x00000008, 0x08020208, 0x00000200, 0x08000000, 0x08020200, 0x08000000, 0x00020008, 0x00000208, 0x00020000, 0x08020200, 0x08000200, 0x00000000, 0x00000200, 0x00020008, 0x08020208, 0x08000200, 0x08000008, 0x00000200, 0x00000000, 0x08020008, 0x08000208, 0x00020000, 0x08000000, 0x08020208, 0x00000008, 0x00020208, 0x00020200, 0x08000008, 0x08020000, 0x08000208, 0x00000208, 0x08020000, 0x00020208, 0x00000008, 0x08020008, 0x00020200, 0x00000208, 0x08020200, 0x00000000, 0x08020008, 0x08000200, 0x00000000, 0x00020208, 0x08000200, 0x00020008, 0x08000008, 0x08000008, 0x00020000, 0x08020208, 0x00020008, 0x08020000, 0x00000208, 0x08000000, 0x00000008, 0x08020200, 0x00000200, 0x00020200, 0x08020000, 0x08020008, 0x00020208, 0x08000208, 0x00020200, 0x00020000, 0x08000208, 0x00000008, 0x08020208, 0x00000200, 0x08000000, 0x08020200, 0x08000000, 0x00020008, 0x00000208, 0x00020000, 0x08020200, 0x08000200, 0x00000000, 0x00000200, 0x00020008, 0x08020208, 0x08000200, 0x08000008, 0x00000200, 0x00000000, 0x08020008, 0x08000208, 0x00020000, 0x08000000, 0x08020208, 0x00000008, 0x00020208, 0x00020200, 0x08000008, 0x08020000, 0x08000208, 0x00000208, 0x08020000, 0x00020208, 0x00000008, 0x08020008, 0x00020200 }; const u32bit DES_SPBOX4[256] = { 0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802080, 0x00800081, 0x00800001, 0x00002001, 0x00000000, 0x00802000, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00800080, 0x00800001, 0x00000001, 0x00002000, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002001, 0x00002080, 0x00800081, 0x00000001, 0x00002080, 0x00800080, 0x00002000, 0x00802080, 0x00802081, 0x00000081, 0x00800080, 0x00800001, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00000000, 0x00802000, 0x00002080, 0x00800080, 0x00800081, 0x00000001, 0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802081, 0x00000081, 0x00000001, 0x00002000, 0x00800001, 0x00002001, 0x00802080, 0x00800081, 0x00002001, 0x00002080, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002000, 0x00802080, 0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802080, 0x00800081, 0x00800001, 0x00002001, 0x00000000, 0x00802000, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00800080, 0x00800001, 0x00000001, 0x00002000, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002001, 0x00002080, 0x00800081, 0x00000001, 0x00002080, 0x00800080, 0x00002000, 0x00802080, 0x00802081, 0x00000081, 0x00800080, 0x00800001, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00000000, 0x00802000, 0x00002080, 0x00800080, 0x00800081, 0x00000001, 0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802081, 0x00000081, 0x00000001, 0x00002000, 0x00800001, 0x00002001, 0x00802080, 0x00800081, 0x00002001, 0x00002080, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002000, 0x00802080, 0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802080, 0x00800081, 0x00800001, 0x00002001, 0x00000000, 0x00802000, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00800080, 0x00800001, 0x00000001, 0x00002000, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002001, 0x00002080, 0x00800081, 0x00000001, 0x00002080, 0x00800080, 0x00002000, 0x00802080, 0x00802081, 0x00000081, 0x00800080, 0x00800001, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00000000, 0x00802000, 0x00002080, 0x00800080, 0x00800081, 0x00000001, 0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802081, 0x00000081, 0x00000001, 0x00002000, 0x00800001, 0x00002001, 0x00802080, 0x00800081, 0x00002001, 0x00002080, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002000, 0x00802080, 0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802080, 0x00800081, 0x00800001, 0x00002001, 0x00000000, 0x00802000, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00800080, 0x00800001, 0x00000001, 0x00002000, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002001, 0x00002080, 0x00800081, 0x00000001, 0x00002080, 0x00800080, 0x00002000, 0x00802080, 0x00802081, 0x00000081, 0x00800080, 0x00800001, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00000000, 0x00802000, 0x00002080, 0x00800080, 0x00800081, 0x00000001, 0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802081, 0x00000081, 0x00000001, 0x00002000, 0x00800001, 0x00002001, 0x00802080, 0x00800081, 0x00002001, 0x00002080, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002000, 0x00802080 }; const u32bit DES_SPBOX5[256] = { 0x00000100, 0x02080100, 0x02080000, 0x42000100, 0x00080000, 0x00000100, 0x40000000, 0x02080000, 0x40080100, 0x00080000, 0x02000100, 0x40080100, 0x42000100, 0x42080000, 0x00080100, 0x40000000, 0x02000000, 0x40080000, 0x40080000, 0x00000000, 0x40000100, 0x42080100, 0x42080100, 0x02000100, 0x42080000, 0x40000100, 0x00000000, 0x42000000, 0x02080100, 0x02000000, 0x42000000, 0x00080100, 0x00080000, 0x42000100, 0x00000100, 0x02000000, 0x40000000, 0x02080000, 0x42000100, 0x40080100, 0x02000100, 0x40000000, 0x42080000, 0x02080100, 0x40080100, 0x00000100, 0x02000000, 0x42080000, 0x42080100, 0x00080100, 0x42000000, 0x42080100, 0x02080000, 0x00000000, 0x40080000, 0x42000000, 0x00080100, 0x02000100, 0x40000100, 0x00080000, 0x00000000, 0x40080000, 0x02080100, 0x40000100, 0x00000100, 0x02080100, 0x02080000, 0x42000100, 0x00080000, 0x00000100, 0x40000000, 0x02080000, 0x40080100, 0x00080000, 0x02000100, 0x40080100, 0x42000100, 0x42080000, 0x00080100, 0x40000000, 0x02000000, 0x40080000, 0x40080000, 0x00000000, 0x40000100, 0x42080100, 0x42080100, 0x02000100, 0x42080000, 0x40000100, 0x00000000, 0x42000000, 0x02080100, 0x02000000, 0x42000000, 0x00080100, 0x00080000, 0x42000100, 0x00000100, 0x02000000, 0x40000000, 0x02080000, 0x42000100, 0x40080100, 0x02000100, 0x40000000, 0x42080000, 0x02080100, 0x40080100, 0x00000100, 0x02000000, 0x42080000, 0x42080100, 0x00080100, 0x42000000, 0x42080100, 0x02080000, 0x00000000, 0x40080000, 0x42000000, 0x00080100, 0x02000100, 0x40000100, 0x00080000, 0x00000000, 0x40080000, 0x02080100, 0x40000100, 0x00000100, 0x02080100, 0x02080000, 0x42000100, 0x00080000, 0x00000100, 0x40000000, 0x02080000, 0x40080100, 0x00080000, 0x02000100, 0x40080100, 0x42000100, 0x42080000, 0x00080100, 0x40000000, 0x02000000, 0x40080000, 0x40080000, 0x00000000, 0x40000100, 0x42080100, 0x42080100, 0x02000100, 0x42080000, 0x40000100, 0x00000000, 0x42000000, 0x02080100, 0x02000000, 0x42000000, 0x00080100, 0x00080000, 0x42000100, 0x00000100, 0x02000000, 0x40000000, 0x02080000, 0x42000100, 0x40080100, 0x02000100, 0x40000000, 0x42080000, 0x02080100, 0x40080100, 0x00000100, 0x02000000, 0x42080000, 0x42080100, 0x00080100, 0x42000000, 0x42080100, 0x02080000, 0x00000000, 0x40080000, 0x42000000, 0x00080100, 0x02000100, 0x40000100, 0x00080000, 0x00000000, 0x40080000, 0x02080100, 0x40000100, 0x00000100, 0x02080100, 0x02080000, 0x42000100, 0x00080000, 0x00000100, 0x40000000, 0x02080000, 0x40080100, 0x00080000, 0x02000100, 0x40080100, 0x42000100, 0x42080000, 0x00080100, 0x40000000, 0x02000000, 0x40080000, 0x40080000, 0x00000000, 0x40000100, 0x42080100, 0x42080100, 0x02000100, 0x42080000, 0x40000100, 0x00000000, 0x42000000, 0x02080100, 0x02000000, 0x42000000, 0x00080100, 0x00080000, 0x42000100, 0x00000100, 0x02000000, 0x40000000, 0x02080000, 0x42000100, 0x40080100, 0x02000100, 0x40000000, 0x42080000, 0x02080100, 0x40080100, 0x00000100, 0x02000000, 0x42080000, 0x42080100, 0x00080100, 0x42000000, 0x42080100, 0x02080000, 0x00000000, 0x40080000, 0x42000000, 0x00080100, 0x02000100, 0x40000100, 0x00080000, 0x00000000, 0x40080000, 0x02080100, 0x40000100 }; const u32bit DES_SPBOX6[256] = { 0x20000010, 0x20400000, 0x00004000, 0x20404010, 0x20400000, 0x00000010, 0x20404010, 0x00400000, 0x20004000, 0x00404010, 0x00400000, 0x20000010, 0x00400010, 0x20004000, 0x20000000, 0x00004010, 0x00000000, 0x00400010, 0x20004010, 0x00004000, 0x00404000, 0x20004010, 0x00000010, 0x20400010, 0x20400010, 0x00000000, 0x00404010, 0x20404000, 0x00004010, 0x00404000, 0x20404000, 0x20000000, 0x20004000, 0x00000010, 0x20400010, 0x00404000, 0x20404010, 0x00400000, 0x00004010, 0x20000010, 0x00400000, 0x20004000, 0x20000000, 0x00004010, 0x20000010, 0x20404010, 0x00404000, 0x20400000, 0x00404010, 0x20404000, 0x00000000, 0x20400010, 0x00000010, 0x00004000, 0x20400000, 0x00404010, 0x00004000, 0x00400010, 0x20004010, 0x00000000, 0x20404000, 0x20000000, 0x00400010, 0x20004010, 0x20000010, 0x20400000, 0x00004000, 0x20404010, 0x20400000, 0x00000010, 0x20404010, 0x00400000, 0x20004000, 0x00404010, 0x00400000, 0x20000010, 0x00400010, 0x20004000, 0x20000000, 0x00004010, 0x00000000, 0x00400010, 0x20004010, 0x00004000, 0x00404000, 0x20004010, 0x00000010, 0x20400010, 0x20400010, 0x00000000, 0x00404010, 0x20404000, 0x00004010, 0x00404000, 0x20404000, 0x20000000, 0x20004000, 0x00000010, 0x20400010, 0x00404000, 0x20404010, 0x00400000, 0x00004010, 0x20000010, 0x00400000, 0x20004000, 0x20000000, 0x00004010, 0x20000010, 0x20404010, 0x00404000, 0x20400000, 0x00404010, 0x20404000, 0x00000000, 0x20400010, 0x00000010, 0x00004000, 0x20400000, 0x00404010, 0x00004000, 0x00400010, 0x20004010, 0x00000000, 0x20404000, 0x20000000, 0x00400010, 0x20004010, 0x20000010, 0x20400000, 0x00004000, 0x20404010, 0x20400000, 0x00000010, 0x20404010, 0x00400000, 0x20004000, 0x00404010, 0x00400000, 0x20000010, 0x00400010, 0x20004000, 0x20000000, 0x00004010, 0x00000000, 0x00400010, 0x20004010, 0x00004000, 0x00404000, 0x20004010, 0x00000010, 0x20400010, 0x20400010, 0x00000000, 0x00404010, 0x20404000, 0x00004010, 0x00404000, 0x20404000, 0x20000000, 0x20004000, 0x00000010, 0x20400010, 0x00404000, 0x20404010, 0x00400000, 0x00004010, 0x20000010, 0x00400000, 0x20004000, 0x20000000, 0x00004010, 0x20000010, 0x20404010, 0x00404000, 0x20400000, 0x00404010, 0x20404000, 0x00000000, 0x20400010, 0x00000010, 0x00004000, 0x20400000, 0x00404010, 0x00004000, 0x00400010, 0x20004010, 0x00000000, 0x20404000, 0x20000000, 0x00400010, 0x20004010, 0x20000010, 0x20400000, 0x00004000, 0x20404010, 0x20400000, 0x00000010, 0x20404010, 0x00400000, 0x20004000, 0x00404010, 0x00400000, 0x20000010, 0x00400010, 0x20004000, 0x20000000, 0x00004010, 0x00000000, 0x00400010, 0x20004010, 0x00004000, 0x00404000, 0x20004010, 0x00000010, 0x20400010, 0x20400010, 0x00000000, 0x00404010, 0x20404000, 0x00004010, 0x00404000, 0x20404000, 0x20000000, 0x20004000, 0x00000010, 0x20400010, 0x00404000, 0x20404010, 0x00400000, 0x00004010, 0x20000010, 0x00400000, 0x20004000, 0x20000000, 0x00004010, 0x20000010, 0x20404010, 0x00404000, 0x20400000, 0x00404010, 0x20404000, 0x00000000, 0x20400010, 0x00000010, 0x00004000, 0x20400000, 0x00404010, 0x00004000, 0x00400010, 0x20004010, 0x00000000, 0x20404000, 0x20000000, 0x00400010, 0x20004010 }; const u32bit DES_SPBOX7[256] = { 0x00200000, 0x04200002, 0x04000802, 0x00000000, 0x00000800, 0x04000802, 0x00200802, 0x04200800, 0x04200802, 0x00200000, 0x00000000, 0x04000002, 0x00000002, 0x04000000, 0x04200002, 0x00000802, 0x04000800, 0x00200802, 0x00200002, 0x04000800, 0x04000002, 0x04200000, 0x04200800, 0x00200002, 0x04200000, 0x00000800, 0x00000802, 0x04200802, 0x00200800, 0x00000002, 0x04000000, 0x00200800, 0x04000000, 0x00200800, 0x00200000, 0x04000802, 0x04000802, 0x04200002, 0x04200002, 0x00000002, 0x00200002, 0x04000000, 0x04000800, 0x00200000, 0x04200800, 0x00000802, 0x00200802, 0x04200800, 0x00000802, 0x04000002, 0x04200802, 0x04200000, 0x00200800, 0x00000000, 0x00000002, 0x04200802, 0x00000000, 0x00200802, 0x04200000, 0x00000800, 0x04000002, 0x04000800, 0x00000800, 0x00200002, 0x00200000, 0x04200002, 0x04000802, 0x00000000, 0x00000800, 0x04000802, 0x00200802, 0x04200800, 0x04200802, 0x00200000, 0x00000000, 0x04000002, 0x00000002, 0x04000000, 0x04200002, 0x00000802, 0x04000800, 0x00200802, 0x00200002, 0x04000800, 0x04000002, 0x04200000, 0x04200800, 0x00200002, 0x04200000, 0x00000800, 0x00000802, 0x04200802, 0x00200800, 0x00000002, 0x04000000, 0x00200800, 0x04000000, 0x00200800, 0x00200000, 0x04000802, 0x04000802, 0x04200002, 0x04200002, 0x00000002, 0x00200002, 0x04000000, 0x04000800, 0x00200000, 0x04200800, 0x00000802, 0x00200802, 0x04200800, 0x00000802, 0x04000002, 0x04200802, 0x04200000, 0x00200800, 0x00000000, 0x00000002, 0x04200802, 0x00000000, 0x00200802, 0x04200000, 0x00000800, 0x04000002, 0x04000800, 0x00000800, 0x00200002, 0x00200000, 0x04200002, 0x04000802, 0x00000000, 0x00000800, 0x04000802, 0x00200802, 0x04200800, 0x04200802, 0x00200000, 0x00000000, 0x04000002, 0x00000002, 0x04000000, 0x04200002, 0x00000802, 0x04000800, 0x00200802, 0x00200002, 0x04000800, 0x04000002, 0x04200000, 0x04200800, 0x00200002, 0x04200000, 0x00000800, 0x00000802, 0x04200802, 0x00200800, 0x00000002, 0x04000000, 0x00200800, 0x04000000, 0x00200800, 0x00200000, 0x04000802, 0x04000802, 0x04200002, 0x04200002, 0x00000002, 0x00200002, 0x04000000, 0x04000800, 0x00200000, 0x04200800, 0x00000802, 0x00200802, 0x04200800, 0x00000802, 0x04000002, 0x04200802, 0x04200000, 0x00200800, 0x00000000, 0x00000002, 0x04200802, 0x00000000, 0x00200802, 0x04200000, 0x00000800, 0x04000002, 0x04000800, 0x00000800, 0x00200002, 0x00200000, 0x04200002, 0x04000802, 0x00000000, 0x00000800, 0x04000802, 0x00200802, 0x04200800, 0x04200802, 0x00200000, 0x00000000, 0x04000002, 0x00000002, 0x04000000, 0x04200002, 0x00000802, 0x04000800, 0x00200802, 0x00200002, 0x04000800, 0x04000002, 0x04200000, 0x04200800, 0x00200002, 0x04200000, 0x00000800, 0x00000802, 0x04200802, 0x00200800, 0x00000002, 0x04000000, 0x00200800, 0x04000000, 0x00200800, 0x00200000, 0x04000802, 0x04000802, 0x04200002, 0x04200002, 0x00000002, 0x00200002, 0x04000000, 0x04000800, 0x00200000, 0x04200800, 0x00000802, 0x00200802, 0x04200800, 0x00000802, 0x04000002, 0x04200802, 0x04200000, 0x00200800, 0x00000000, 0x00000002, 0x04200802, 0x00000000, 0x00200802, 0x04200000, 0x00000800, 0x04000002, 0x04000800, 0x00000800, 0x00200002 }; const u32bit DES_SPBOX8[256] = { 0x10001040, 0x00001000, 0x00040000, 0x10041040, 0x10000000, 0x10001040, 0x00000040, 0x10000000, 0x00040040, 0x10040000, 0x10041040, 0x00041000, 0x10041000, 0x00041040, 0x00001000, 0x00000040, 0x10040000, 0x10000040, 0x10001000, 0x00001040, 0x00041000, 0x00040040, 0x10040040, 0x10041000, 0x00001040, 0x00000000, 0x00000000, 0x10040040, 0x10000040, 0x10001000, 0x00041040, 0x00040000, 0x00041040, 0x00040000, 0x10041000, 0x00001000, 0x00000040, 0x10040040, 0x00001000, 0x00041040, 0x10001000, 0x00000040, 0x10000040, 0x10040000, 0x10040040, 0x10000000, 0x00040000, 0x10001040, 0x00000000, 0x10041040, 0x00040040, 0x10000040, 0x10040000, 0x10001000, 0x10001040, 0x00000000, 0x10041040, 0x00041000, 0x00041000, 0x00001040, 0x00001040, 0x00040040, 0x10000000, 0x10041000, 0x10001040, 0x00001000, 0x00040000, 0x10041040, 0x10000000, 0x10001040, 0x00000040, 0x10000000, 0x00040040, 0x10040000, 0x10041040, 0x00041000, 0x10041000, 0x00041040, 0x00001000, 0x00000040, 0x10040000, 0x10000040, 0x10001000, 0x00001040, 0x00041000, 0x00040040, 0x10040040, 0x10041000, 0x00001040, 0x00000000, 0x00000000, 0x10040040, 0x10000040, 0x10001000, 0x00041040, 0x00040000, 0x00041040, 0x00040000, 0x10041000, 0x00001000, 0x00000040, 0x10040040, 0x00001000, 0x00041040, 0x10001000, 0x00000040, 0x10000040, 0x10040000, 0x10040040, 0x10000000, 0x00040000, 0x10001040, 0x00000000, 0x10041040, 0x00040040, 0x10000040, 0x10040000, 0x10001000, 0x10001040, 0x00000000, 0x10041040, 0x00041000, 0x00041000, 0x00001040, 0x00001040, 0x00040040, 0x10000000, 0x10041000, 0x10001040, 0x00001000, 0x00040000, 0x10041040, 0x10000000, 0x10001040, 0x00000040, 0x10000000, 0x00040040, 0x10040000, 0x10041040, 0x00041000, 0x10041000, 0x00041040, 0x00001000, 0x00000040, 0x10040000, 0x10000040, 0x10001000, 0x00001040, 0x00041000, 0x00040040, 0x10040040, 0x10041000, 0x00001040, 0x00000000, 0x00000000, 0x10040040, 0x10000040, 0x10001000, 0x00041040, 0x00040000, 0x00041040, 0x00040000, 0x10041000, 0x00001000, 0x00000040, 0x10040040, 0x00001000, 0x00041040, 0x10001000, 0x00000040, 0x10000040, 0x10040000, 0x10040040, 0x10000000, 0x00040000, 0x10001040, 0x00000000, 0x10041040, 0x00040040, 0x10000040, 0x10040000, 0x10001000, 0x10001040, 0x00000000, 0x10041040, 0x00041000, 0x00041000, 0x00001040, 0x00001040, 0x00040040, 0x10000000, 0x10041000, 0x10001040, 0x00001000, 0x00040000, 0x10041040, 0x10000000, 0x10001040, 0x00000040, 0x10000000, 0x00040040, 0x10040000, 0x10041040, 0x00041000, 0x10041000, 0x00041040, 0x00001000, 0x00000040, 0x10040000, 0x10000040, 0x10001000, 0x00001040, 0x00041000, 0x00040040, 0x10040040, 0x10041000, 0x00001040, 0x00000000, 0x00000000, 0x10040040, 0x10000040, 0x10001000, 0x00041040, 0x00040000, 0x00041040, 0x00040000, 0x10041000, 0x00001000, 0x00000040, 0x10040040, 0x00001000, 0x00041040, 0x10001000, 0x00000040, 0x10000040, 0x10040000, 0x10040040, 0x10000000, 0x00040000, 0x10001040, 0x00000000, 0x10041040, 0x00040040, 0x10000040, 0x10040000, 0x10001000, 0x10001040, 0x00000000, 0x10041040, 0x00041000, 0x00041000, 0x00001040, 0x00001040, 0x00040040, 0x10000000, 0x10041000 }; const u64bit DES_IPTAB1[256] = { 0x0000000000000000ULL, 0x0000000200000000ULL, 0x0000000000000002ULL, 0x0000000200000002ULL, 0x0000020000000000ULL, 0x0000020200000000ULL, 0x0000020000000002ULL, 0x0000020200000002ULL, 0x0000000000000200ULL, 0x0000000200000200ULL, 0x0000000000000202ULL, 0x0000000200000202ULL, 0x0000020000000200ULL, 0x0000020200000200ULL, 0x0000020000000202ULL, 0x0000020200000202ULL, 0x0002000000000000ULL, 0x0002000200000000ULL, 0x0002000000000002ULL, 0x0002000200000002ULL, 0x0002020000000000ULL, 0x0002020200000000ULL, 0x0002020000000002ULL, 0x0002020200000002ULL, 0x0002000000000200ULL, 0x0002000200000200ULL, 0x0002000000000202ULL, 0x0002000200000202ULL, 0x0002020000000200ULL, 0x0002020200000200ULL, 0x0002020000000202ULL, 0x0002020200000202ULL, 0x0000000000020000ULL, 0x0000000200020000ULL, 0x0000000000020002ULL, 0x0000000200020002ULL, 0x0000020000020000ULL, 0x0000020200020000ULL, 0x0000020000020002ULL, 0x0000020200020002ULL, 0x0000000000020200ULL, 0x0000000200020200ULL, 0x0000000000020202ULL, 0x0000000200020202ULL, 0x0000020000020200ULL, 0x0000020200020200ULL, 0x0000020000020202ULL, 0x0000020200020202ULL, 0x0002000000020000ULL, 0x0002000200020000ULL, 0x0002000000020002ULL, 0x0002000200020002ULL, 0x0002020000020000ULL, 0x0002020200020000ULL, 0x0002020000020002ULL, 0x0002020200020002ULL, 0x0002000000020200ULL, 0x0002000200020200ULL, 0x0002000000020202ULL, 0x0002000200020202ULL, 0x0002020000020200ULL, 0x0002020200020200ULL, 0x0002020000020202ULL, 0x0002020200020202ULL, 0x0200000000000000ULL, 0x0200000200000000ULL, 0x0200000000000002ULL, 0x0200000200000002ULL, 0x0200020000000000ULL, 0x0200020200000000ULL, 0x0200020000000002ULL, 0x0200020200000002ULL, 0x0200000000000200ULL, 0x0200000200000200ULL, 0x0200000000000202ULL, 0x0200000200000202ULL, 0x0200020000000200ULL, 0x0200020200000200ULL, 0x0200020000000202ULL, 0x0200020200000202ULL, 0x0202000000000000ULL, 0x0202000200000000ULL, 0x0202000000000002ULL, 0x0202000200000002ULL, 0x0202020000000000ULL, 0x0202020200000000ULL, 0x0202020000000002ULL, 0x0202020200000002ULL, 0x0202000000000200ULL, 0x0202000200000200ULL, 0x0202000000000202ULL, 0x0202000200000202ULL, 0x0202020000000200ULL, 0x0202020200000200ULL, 0x0202020000000202ULL, 0x0202020200000202ULL, 0x0200000000020000ULL, 0x0200000200020000ULL, 0x0200000000020002ULL, 0x0200000200020002ULL, 0x0200020000020000ULL, 0x0200020200020000ULL, 0x0200020000020002ULL, 0x0200020200020002ULL, 0x0200000000020200ULL, 0x0200000200020200ULL, 0x0200000000020202ULL, 0x0200000200020202ULL, 0x0200020000020200ULL, 0x0200020200020200ULL, 0x0200020000020202ULL, 0x0200020200020202ULL, 0x0202000000020000ULL, 0x0202000200020000ULL, 0x0202000000020002ULL, 0x0202000200020002ULL, 0x0202020000020000ULL, 0x0202020200020000ULL, 0x0202020000020002ULL, 0x0202020200020002ULL, 0x0202000000020200ULL, 0x0202000200020200ULL, 0x0202000000020202ULL, 0x0202000200020202ULL, 0x0202020000020200ULL, 0x0202020200020200ULL, 0x0202020000020202ULL, 0x0202020200020202ULL, 0x0000000002000000ULL, 0x0000000202000000ULL, 0x0000000002000002ULL, 0x0000000202000002ULL, 0x0000020002000000ULL, 0x0000020202000000ULL, 0x0000020002000002ULL, 0x0000020202000002ULL, 0x0000000002000200ULL, 0x0000000202000200ULL, 0x0000000002000202ULL, 0x0000000202000202ULL, 0x0000020002000200ULL, 0x0000020202000200ULL, 0x0000020002000202ULL, 0x0000020202000202ULL, 0x0002000002000000ULL, 0x0002000202000000ULL, 0x0002000002000002ULL, 0x0002000202000002ULL, 0x0002020002000000ULL, 0x0002020202000000ULL, 0x0002020002000002ULL, 0x0002020202000002ULL, 0x0002000002000200ULL, 0x0002000202000200ULL, 0x0002000002000202ULL, 0x0002000202000202ULL, 0x0002020002000200ULL, 0x0002020202000200ULL, 0x0002020002000202ULL, 0x0002020202000202ULL, 0x0000000002020000ULL, 0x0000000202020000ULL, 0x0000000002020002ULL, 0x0000000202020002ULL, 0x0000020002020000ULL, 0x0000020202020000ULL, 0x0000020002020002ULL, 0x0000020202020002ULL, 0x0000000002020200ULL, 0x0000000202020200ULL, 0x0000000002020202ULL, 0x0000000202020202ULL, 0x0000020002020200ULL, 0x0000020202020200ULL, 0x0000020002020202ULL, 0x0000020202020202ULL, 0x0002000002020000ULL, 0x0002000202020000ULL, 0x0002000002020002ULL, 0x0002000202020002ULL, 0x0002020002020000ULL, 0x0002020202020000ULL, 0x0002020002020002ULL, 0x0002020202020002ULL, 0x0002000002020200ULL, 0x0002000202020200ULL, 0x0002000002020202ULL, 0x0002000202020202ULL, 0x0002020002020200ULL, 0x0002020202020200ULL, 0x0002020002020202ULL, 0x0002020202020202ULL, 0x0200000002000000ULL, 0x0200000202000000ULL, 0x0200000002000002ULL, 0x0200000202000002ULL, 0x0200020002000000ULL, 0x0200020202000000ULL, 0x0200020002000002ULL, 0x0200020202000002ULL, 0x0200000002000200ULL, 0x0200000202000200ULL, 0x0200000002000202ULL, 0x0200000202000202ULL, 0x0200020002000200ULL, 0x0200020202000200ULL, 0x0200020002000202ULL, 0x0200020202000202ULL, 0x0202000002000000ULL, 0x0202000202000000ULL, 0x0202000002000002ULL, 0x0202000202000002ULL, 0x0202020002000000ULL, 0x0202020202000000ULL, 0x0202020002000002ULL, 0x0202020202000002ULL, 0x0202000002000200ULL, 0x0202000202000200ULL, 0x0202000002000202ULL, 0x0202000202000202ULL, 0x0202020002000200ULL, 0x0202020202000200ULL, 0x0202020002000202ULL, 0x0202020202000202ULL, 0x0200000002020000ULL, 0x0200000202020000ULL, 0x0200000002020002ULL, 0x0200000202020002ULL, 0x0200020002020000ULL, 0x0200020202020000ULL, 0x0200020002020002ULL, 0x0200020202020002ULL, 0x0200000002020200ULL, 0x0200000202020200ULL, 0x0200000002020202ULL, 0x0200000202020202ULL, 0x0200020002020200ULL, 0x0200020202020200ULL, 0x0200020002020202ULL, 0x0200020202020202ULL, 0x0202000002020000ULL, 0x0202000202020000ULL, 0x0202000002020002ULL, 0x0202000202020002ULL, 0x0202020002020000ULL, 0x0202020202020000ULL, 0x0202020002020002ULL, 0x0202020202020002ULL, 0x0202000002020200ULL, 0x0202000202020200ULL, 0x0202000002020202ULL, 0x0202000202020202ULL, 0x0202020002020200ULL, 0x0202020202020200ULL, 0x0202020002020202ULL, 0x0202020202020202ULL }; const u64bit DES_IPTAB2[256] = { 0x0000000000000000ULL, 0x0000010000000000ULL, 0x0000000000000100ULL, 0x0000010000000100ULL, 0x0001000000000000ULL, 0x0001010000000000ULL, 0x0001000000000100ULL, 0x0001010000000100ULL, 0x0000000000010000ULL, 0x0000010000010000ULL, 0x0000000000010100ULL, 0x0000010000010100ULL, 0x0001000000010000ULL, 0x0001010000010000ULL, 0x0001000000010100ULL, 0x0001010000010100ULL, 0x0100000000000000ULL, 0x0100010000000000ULL, 0x0100000000000100ULL, 0x0100010000000100ULL, 0x0101000000000000ULL, 0x0101010000000000ULL, 0x0101000000000100ULL, 0x0101010000000100ULL, 0x0100000000010000ULL, 0x0100010000010000ULL, 0x0100000000010100ULL, 0x0100010000010100ULL, 0x0101000000010000ULL, 0x0101010000010000ULL, 0x0101000000010100ULL, 0x0101010000010100ULL, 0x0000000001000000ULL, 0x0000010001000000ULL, 0x0000000001000100ULL, 0x0000010001000100ULL, 0x0001000001000000ULL, 0x0001010001000000ULL, 0x0001000001000100ULL, 0x0001010001000100ULL, 0x0000000001010000ULL, 0x0000010001010000ULL, 0x0000000001010100ULL, 0x0000010001010100ULL, 0x0001000001010000ULL, 0x0001010001010000ULL, 0x0001000001010100ULL, 0x0001010001010100ULL, 0x0100000001000000ULL, 0x0100010001000000ULL, 0x0100000001000100ULL, 0x0100010001000100ULL, 0x0101000001000000ULL, 0x0101010001000000ULL, 0x0101000001000100ULL, 0x0101010001000100ULL, 0x0100000001010000ULL, 0x0100010001010000ULL, 0x0100000001010100ULL, 0x0100010001010100ULL, 0x0101000001010000ULL, 0x0101010001010000ULL, 0x0101000001010100ULL, 0x0101010001010100ULL, 0x0000000100000000ULL, 0x0000010100000000ULL, 0x0000000100000100ULL, 0x0000010100000100ULL, 0x0001000100000000ULL, 0x0001010100000000ULL, 0x0001000100000100ULL, 0x0001010100000100ULL, 0x0000000100010000ULL, 0x0000010100010000ULL, 0x0000000100010100ULL, 0x0000010100010100ULL, 0x0001000100010000ULL, 0x0001010100010000ULL, 0x0001000100010100ULL, 0x0001010100010100ULL, 0x0100000100000000ULL, 0x0100010100000000ULL, 0x0100000100000100ULL, 0x0100010100000100ULL, 0x0101000100000000ULL, 0x0101010100000000ULL, 0x0101000100000100ULL, 0x0101010100000100ULL, 0x0100000100010000ULL, 0x0100010100010000ULL, 0x0100000100010100ULL, 0x0100010100010100ULL, 0x0101000100010000ULL, 0x0101010100010000ULL, 0x0101000100010100ULL, 0x0101010100010100ULL, 0x0000000101000000ULL, 0x0000010101000000ULL, 0x0000000101000100ULL, 0x0000010101000100ULL, 0x0001000101000000ULL, 0x0001010101000000ULL, 0x0001000101000100ULL, 0x0001010101000100ULL, 0x0000000101010000ULL, 0x0000010101010000ULL, 0x0000000101010100ULL, 0x0000010101010100ULL, 0x0001000101010000ULL, 0x0001010101010000ULL, 0x0001000101010100ULL, 0x0001010101010100ULL, 0x0100000101000000ULL, 0x0100010101000000ULL, 0x0100000101000100ULL, 0x0100010101000100ULL, 0x0101000101000000ULL, 0x0101010101000000ULL, 0x0101000101000100ULL, 0x0101010101000100ULL, 0x0100000101010000ULL, 0x0100010101010000ULL, 0x0100000101010100ULL, 0x0100010101010100ULL, 0x0101000101010000ULL, 0x0101010101010000ULL, 0x0101000101010100ULL, 0x0101010101010100ULL, 0x0000000000000001ULL, 0x0000010000000001ULL, 0x0000000000000101ULL, 0x0000010000000101ULL, 0x0001000000000001ULL, 0x0001010000000001ULL, 0x0001000000000101ULL, 0x0001010000000101ULL, 0x0000000000010001ULL, 0x0000010000010001ULL, 0x0000000000010101ULL, 0x0000010000010101ULL, 0x0001000000010001ULL, 0x0001010000010001ULL, 0x0001000000010101ULL, 0x0001010000010101ULL, 0x0100000000000001ULL, 0x0100010000000001ULL, 0x0100000000000101ULL, 0x0100010000000101ULL, 0x0101000000000001ULL, 0x0101010000000001ULL, 0x0101000000000101ULL, 0x0101010000000101ULL, 0x0100000000010001ULL, 0x0100010000010001ULL, 0x0100000000010101ULL, 0x0100010000010101ULL, 0x0101000000010001ULL, 0x0101010000010001ULL, 0x0101000000010101ULL, 0x0101010000010101ULL, 0x0000000001000001ULL, 0x0000010001000001ULL, 0x0000000001000101ULL, 0x0000010001000101ULL, 0x0001000001000001ULL, 0x0001010001000001ULL, 0x0001000001000101ULL, 0x0001010001000101ULL, 0x0000000001010001ULL, 0x0000010001010001ULL, 0x0000000001010101ULL, 0x0000010001010101ULL, 0x0001000001010001ULL, 0x0001010001010001ULL, 0x0001000001010101ULL, 0x0001010001010101ULL, 0x0100000001000001ULL, 0x0100010001000001ULL, 0x0100000001000101ULL, 0x0100010001000101ULL, 0x0101000001000001ULL, 0x0101010001000001ULL, 0x0101000001000101ULL, 0x0101010001000101ULL, 0x0100000001010001ULL, 0x0100010001010001ULL, 0x0100000001010101ULL, 0x0100010001010101ULL, 0x0101000001010001ULL, 0x0101010001010001ULL, 0x0101000001010101ULL, 0x0101010001010101ULL, 0x0000000100000001ULL, 0x0000010100000001ULL, 0x0000000100000101ULL, 0x0000010100000101ULL, 0x0001000100000001ULL, 0x0001010100000001ULL, 0x0001000100000101ULL, 0x0001010100000101ULL, 0x0000000100010001ULL, 0x0000010100010001ULL, 0x0000000100010101ULL, 0x0000010100010101ULL, 0x0001000100010001ULL, 0x0001010100010001ULL, 0x0001000100010101ULL, 0x0001010100010101ULL, 0x0100000100000001ULL, 0x0100010100000001ULL, 0x0100000100000101ULL, 0x0100010100000101ULL, 0x0101000100000001ULL, 0x0101010100000001ULL, 0x0101000100000101ULL, 0x0101010100000101ULL, 0x0100000100010001ULL, 0x0100010100010001ULL, 0x0100000100010101ULL, 0x0100010100010101ULL, 0x0101000100010001ULL, 0x0101010100010001ULL, 0x0101000100010101ULL, 0x0101010100010101ULL, 0x0000000101000001ULL, 0x0000010101000001ULL, 0x0000000101000101ULL, 0x0000010101000101ULL, 0x0001000101000001ULL, 0x0001010101000001ULL, 0x0001000101000101ULL, 0x0001010101000101ULL, 0x0000000101010001ULL, 0x0000010101010001ULL, 0x0000000101010101ULL, 0x0000010101010101ULL, 0x0001000101010001ULL, 0x0001010101010001ULL, 0x0001000101010101ULL, 0x0001010101010101ULL, 0x0100000101000001ULL, 0x0100010101000001ULL, 0x0100000101000101ULL, 0x0100010101000101ULL, 0x0101000101000001ULL, 0x0101010101000001ULL, 0x0101000101000101ULL, 0x0101010101000101ULL, 0x0100000101010001ULL, 0x0100010101010001ULL, 0x0100000101010101ULL, 0x0100010101010101ULL, 0x0101000101010001ULL, 0x0101010101010001ULL, 0x0101000101010101ULL, 0x0101010101010101ULL }; const u64bit DES_FPTAB1[256] = { 0x0000000000000000ULL, 0x0000000100000000ULL, 0x0000000004000000ULL, 0x0000000104000000ULL, 0x0000000000040000ULL, 0x0000000100040000ULL, 0x0000000004040000ULL, 0x0000000104040000ULL, 0x0000000000000400ULL, 0x0000000100000400ULL, 0x0000000004000400ULL, 0x0000000104000400ULL, 0x0000000000040400ULL, 0x0000000100040400ULL, 0x0000000004040400ULL, 0x0000000104040400ULL, 0x0000000000000004ULL, 0x0000000100000004ULL, 0x0000000004000004ULL, 0x0000000104000004ULL, 0x0000000000040004ULL, 0x0000000100040004ULL, 0x0000000004040004ULL, 0x0000000104040004ULL, 0x0000000000000404ULL, 0x0000000100000404ULL, 0x0000000004000404ULL, 0x0000000104000404ULL, 0x0000000000040404ULL, 0x0000000100040404ULL, 0x0000000004040404ULL, 0x0000000104040404ULL, 0x0400000000000000ULL, 0x0400000100000000ULL, 0x0400000004000000ULL, 0x0400000104000000ULL, 0x0400000000040000ULL, 0x0400000100040000ULL, 0x0400000004040000ULL, 0x0400000104040000ULL, 0x0400000000000400ULL, 0x0400000100000400ULL, 0x0400000004000400ULL, 0x0400000104000400ULL, 0x0400000000040400ULL, 0x0400000100040400ULL, 0x0400000004040400ULL, 0x0400000104040400ULL, 0x0400000000000004ULL, 0x0400000100000004ULL, 0x0400000004000004ULL, 0x0400000104000004ULL, 0x0400000000040004ULL, 0x0400000100040004ULL, 0x0400000004040004ULL, 0x0400000104040004ULL, 0x0400000000000404ULL, 0x0400000100000404ULL, 0x0400000004000404ULL, 0x0400000104000404ULL, 0x0400000000040404ULL, 0x0400000100040404ULL, 0x0400000004040404ULL, 0x0400000104040404ULL, 0x0004000000000000ULL, 0x0004000100000000ULL, 0x0004000004000000ULL, 0x0004000104000000ULL, 0x0004000000040000ULL, 0x0004000100040000ULL, 0x0004000004040000ULL, 0x0004000104040000ULL, 0x0004000000000400ULL, 0x0004000100000400ULL, 0x0004000004000400ULL, 0x0004000104000400ULL, 0x0004000000040400ULL, 0x0004000100040400ULL, 0x0004000004040400ULL, 0x0004000104040400ULL, 0x0004000000000004ULL, 0x0004000100000004ULL, 0x0004000004000004ULL, 0x0004000104000004ULL, 0x0004000000040004ULL, 0x0004000100040004ULL, 0x0004000004040004ULL, 0x0004000104040004ULL, 0x0004000000000404ULL, 0x0004000100000404ULL, 0x0004000004000404ULL, 0x0004000104000404ULL, 0x0004000000040404ULL, 0x0004000100040404ULL, 0x0004000004040404ULL, 0x0004000104040404ULL, 0x0404000000000000ULL, 0x0404000100000000ULL, 0x0404000004000000ULL, 0x0404000104000000ULL, 0x0404000000040000ULL, 0x0404000100040000ULL, 0x0404000004040000ULL, 0x0404000104040000ULL, 0x0404000000000400ULL, 0x0404000100000400ULL, 0x0404000004000400ULL, 0x0404000104000400ULL, 0x0404000000040400ULL, 0x0404000100040400ULL, 0x0404000004040400ULL, 0x0404000104040400ULL, 0x0404000000000004ULL, 0x0404000100000004ULL, 0x0404000004000004ULL, 0x0404000104000004ULL, 0x0404000000040004ULL, 0x0404000100040004ULL, 0x0404000004040004ULL, 0x0404000104040004ULL, 0x0404000000000404ULL, 0x0404000100000404ULL, 0x0404000004000404ULL, 0x0404000104000404ULL, 0x0404000000040404ULL, 0x0404000100040404ULL, 0x0404000004040404ULL, 0x0404000104040404ULL, 0x0000040000000000ULL, 0x0000040100000000ULL, 0x0000040004000000ULL, 0x0000040104000000ULL, 0x0000040000040000ULL, 0x0000040100040000ULL, 0x0000040004040000ULL, 0x0000040104040000ULL, 0x0000040000000400ULL, 0x0000040100000400ULL, 0x0000040004000400ULL, 0x0000040104000400ULL, 0x0000040000040400ULL, 0x0000040100040400ULL, 0x0000040004040400ULL, 0x0000040104040400ULL, 0x0000040000000004ULL, 0x0000040100000004ULL, 0x0000040004000004ULL, 0x0000040104000004ULL, 0x0000040000040004ULL, 0x0000040100040004ULL, 0x0000040004040004ULL, 0x0000040104040004ULL, 0x0000040000000404ULL, 0x0000040100000404ULL, 0x0000040004000404ULL, 0x0000040104000404ULL, 0x0000040000040404ULL, 0x0000040100040404ULL, 0x0000040004040404ULL, 0x0000040104040404ULL, 0x0400040000000000ULL, 0x0400040100000000ULL, 0x0400040004000000ULL, 0x0400040104000000ULL, 0x0400040000040000ULL, 0x0400040100040000ULL, 0x0400040004040000ULL, 0x0400040104040000ULL, 0x0400040000000400ULL, 0x0400040100000400ULL, 0x0400040004000400ULL, 0x0400040104000400ULL, 0x0400040000040400ULL, 0x0400040100040400ULL, 0x0400040004040400ULL, 0x0400040104040400ULL, 0x0400040000000004ULL, 0x0400040100000004ULL, 0x0400040004000004ULL, 0x0400040104000004ULL, 0x0400040000040004ULL, 0x0400040100040004ULL, 0x0400040004040004ULL, 0x0400040104040004ULL, 0x0400040000000404ULL, 0x0400040100000404ULL, 0x0400040004000404ULL, 0x0400040104000404ULL, 0x0400040000040404ULL, 0x0400040100040404ULL, 0x0400040004040404ULL, 0x0400040104040404ULL, 0x0004040000000000ULL, 0x0004040100000000ULL, 0x0004040004000000ULL, 0x0004040104000000ULL, 0x0004040000040000ULL, 0x0004040100040000ULL, 0x0004040004040000ULL, 0x0004040104040000ULL, 0x0004040000000400ULL, 0x0004040100000400ULL, 0x0004040004000400ULL, 0x0004040104000400ULL, 0x0004040000040400ULL, 0x0004040100040400ULL, 0x0004040004040400ULL, 0x0004040104040400ULL, 0x0004040000000004ULL, 0x0004040100000004ULL, 0x0004040004000004ULL, 0x0004040104000004ULL, 0x0004040000040004ULL, 0x0004040100040004ULL, 0x0004040004040004ULL, 0x0004040104040004ULL, 0x0004040000000404ULL, 0x0004040100000404ULL, 0x0004040004000404ULL, 0x0004040104000404ULL, 0x0004040000040404ULL, 0x0004040100040404ULL, 0x0004040004040404ULL, 0x0004040104040404ULL, 0x0404040000000000ULL, 0x0404040100000000ULL, 0x0404040004000000ULL, 0x0404040104000000ULL, 0x0404040000040000ULL, 0x0404040100040000ULL, 0x0404040004040000ULL, 0x0404040104040000ULL, 0x0404040000000400ULL, 0x0404040100000400ULL, 0x0404040004000400ULL, 0x0404040104000400ULL, 0x0404040000040400ULL, 0x0404040100040400ULL, 0x0404040004040400ULL, 0x0404040104040400ULL, 0x0404040000000004ULL, 0x0404040100000004ULL, 0x0404040004000004ULL, 0x0404040104000004ULL, 0x0404040000040004ULL, 0x0404040100040004ULL, 0x0404040004040004ULL, 0x0404040104040004ULL, 0x0404040000000404ULL, 0x0404040100000404ULL, 0x0404040004000404ULL, 0x0404040104000404ULL, 0x0404040000040404ULL, 0x0404040100040404ULL, 0x0404040004040404ULL, 0x0404040104040404ULL }; const u64bit DES_FPTAB2[256] = { 0x0000000000000000ULL, 0x0000004000000000ULL, 0x0000000001000000ULL, 0x0000004001000000ULL, 0x0000000000010000ULL, 0x0000004000010000ULL, 0x0000000001010000ULL, 0x0000004001010000ULL, 0x0000000000000100ULL, 0x0000004000000100ULL, 0x0000000001000100ULL, 0x0000004001000100ULL, 0x0000000000010100ULL, 0x0000004000010100ULL, 0x0000000001010100ULL, 0x0000004001010100ULL, 0x0000000000000001ULL, 0x0000004000000001ULL, 0x0000000001000001ULL, 0x0000004001000001ULL, 0x0000000000010001ULL, 0x0000004000010001ULL, 0x0000000001010001ULL, 0x0000004001010001ULL, 0x0000000000000101ULL, 0x0000004000000101ULL, 0x0000000001000101ULL, 0x0000004001000101ULL, 0x0000000000010101ULL, 0x0000004000010101ULL, 0x0000000001010101ULL, 0x0000004001010101ULL, 0x0100000000000000ULL, 0x0100004000000000ULL, 0x0100000001000000ULL, 0x0100004001000000ULL, 0x0100000000010000ULL, 0x0100004000010000ULL, 0x0100000001010000ULL, 0x0100004001010000ULL, 0x0100000000000100ULL, 0x0100004000000100ULL, 0x0100000001000100ULL, 0x0100004001000100ULL, 0x0100000000010100ULL, 0x0100004000010100ULL, 0x0100000001010100ULL, 0x0100004001010100ULL, 0x0100000000000001ULL, 0x0100004000000001ULL, 0x0100000001000001ULL, 0x0100004001000001ULL, 0x0100000000010001ULL, 0x0100004000010001ULL, 0x0100000001010001ULL, 0x0100004001010001ULL, 0x0100000000000101ULL, 0x0100004000000101ULL, 0x0100000001000101ULL, 0x0100004001000101ULL, 0x0100000000010101ULL, 0x0100004000010101ULL, 0x0100000001010101ULL, 0x0100004001010101ULL, 0x0001000000000000ULL, 0x0001004000000000ULL, 0x0001000001000000ULL, 0x0001004001000000ULL, 0x0001000000010000ULL, 0x0001004000010000ULL, 0x0001000001010000ULL, 0x0001004001010000ULL, 0x0001000000000100ULL, 0x0001004000000100ULL, 0x0001000001000100ULL, 0x0001004001000100ULL, 0x0001000000010100ULL, 0x0001004000010100ULL, 0x0001000001010100ULL, 0x0001004001010100ULL, 0x0001000000000001ULL, 0x0001004000000001ULL, 0x0001000001000001ULL, 0x0001004001000001ULL, 0x0001000000010001ULL, 0x0001004000010001ULL, 0x0001000001010001ULL, 0x0001004001010001ULL, 0x0001000000000101ULL, 0x0001004000000101ULL, 0x0001000001000101ULL, 0x0001004001000101ULL, 0x0001000000010101ULL, 0x0001004000010101ULL, 0x0001000001010101ULL, 0x0001004001010101ULL, 0x0101000000000000ULL, 0x0101004000000000ULL, 0x0101000001000000ULL, 0x0101004001000000ULL, 0x0101000000010000ULL, 0x0101004000010000ULL, 0x0101000001010000ULL, 0x0101004001010000ULL, 0x0101000000000100ULL, 0x0101004000000100ULL, 0x0101000001000100ULL, 0x0101004001000100ULL, 0x0101000000010100ULL, 0x0101004000010100ULL, 0x0101000001010100ULL, 0x0101004001010100ULL, 0x0101000000000001ULL, 0x0101004000000001ULL, 0x0101000001000001ULL, 0x0101004001000001ULL, 0x0101000000010001ULL, 0x0101004000010001ULL, 0x0101000001010001ULL, 0x0101004001010001ULL, 0x0101000000000101ULL, 0x0101004000000101ULL, 0x0101000001000101ULL, 0x0101004001000101ULL, 0x0101000000010101ULL, 0x0101004000010101ULL, 0x0101000001010101ULL, 0x0101004001010101ULL, 0x0000010000000000ULL, 0x0000014000000000ULL, 0x0000010001000000ULL, 0x0000014001000000ULL, 0x0000010000010000ULL, 0x0000014000010000ULL, 0x0000010001010000ULL, 0x0000014001010000ULL, 0x0000010000000100ULL, 0x0000014000000100ULL, 0x0000010001000100ULL, 0x0000014001000100ULL, 0x0000010000010100ULL, 0x0000014000010100ULL, 0x0000010001010100ULL, 0x0000014001010100ULL, 0x0000010000000001ULL, 0x0000014000000001ULL, 0x0000010001000001ULL, 0x0000014001000001ULL, 0x0000010000010001ULL, 0x0000014000010001ULL, 0x0000010001010001ULL, 0x0000014001010001ULL, 0x0000010000000101ULL, 0x0000014000000101ULL, 0x0000010001000101ULL, 0x0000014001000101ULL, 0x0000010000010101ULL, 0x0000014000010101ULL, 0x0000010001010101ULL, 0x0000014001010101ULL, 0x0100010000000000ULL, 0x0100014000000000ULL, 0x0100010001000000ULL, 0x0100014001000000ULL, 0x0100010000010000ULL, 0x0100014000010000ULL, 0x0100010001010000ULL, 0x0100014001010000ULL, 0x0100010000000100ULL, 0x0100014000000100ULL, 0x0100010001000100ULL, 0x0100014001000100ULL, 0x0100010000010100ULL, 0x0100014000010100ULL, 0x0100010001010100ULL, 0x0100014001010100ULL, 0x0100010000000001ULL, 0x0100014000000001ULL, 0x0100010001000001ULL, 0x0100014001000001ULL, 0x0100010000010001ULL, 0x0100014000010001ULL, 0x0100010001010001ULL, 0x0100014001010001ULL, 0x0100010000000101ULL, 0x0100014000000101ULL, 0x0100010001000101ULL, 0x0100014001000101ULL, 0x0100010000010101ULL, 0x0100014000010101ULL, 0x0100010001010101ULL, 0x0100014001010101ULL, 0x0001010000000000ULL, 0x0001014000000000ULL, 0x0001010001000000ULL, 0x0001014001000000ULL, 0x0001010000010000ULL, 0x0001014000010000ULL, 0x0001010001010000ULL, 0x0001014001010000ULL, 0x0001010000000100ULL, 0x0001014000000100ULL, 0x0001010001000100ULL, 0x0001014001000100ULL, 0x0001010000010100ULL, 0x0001014000010100ULL, 0x0001010001010100ULL, 0x0001014001010100ULL, 0x0001010000000001ULL, 0x0001014000000001ULL, 0x0001010001000001ULL, 0x0001014001000001ULL, 0x0001010000010001ULL, 0x0001014000010001ULL, 0x0001010001010001ULL, 0x0001014001010001ULL, 0x0001010000000101ULL, 0x0001014000000101ULL, 0x0001010001000101ULL, 0x0001014001000101ULL, 0x0001010000010101ULL, 0x0001014000010101ULL, 0x0001010001010101ULL, 0x0001014001010101ULL, 0x0101010000000000ULL, 0x0101014000000000ULL, 0x0101010001000000ULL, 0x0101014001000000ULL, 0x0101010000010000ULL, 0x0101014000010000ULL, 0x0101010001010000ULL, 0x0101014001010000ULL, 0x0101010000000100ULL, 0x0101014000000100ULL, 0x0101010001000100ULL, 0x0101014001000100ULL, 0x0101010000010100ULL, 0x0101014000010100ULL, 0x0101010001010100ULL, 0x0101014001010100ULL, 0x0101010000000001ULL, 0x0101014000000001ULL, 0x0101010001000001ULL, 0x0101014001000001ULL, 0x0101010000010001ULL, 0x0101014000010001ULL, 0x0101010001010001ULL, 0x0101014001010001ULL, 0x0101010000000101ULL, 0x0101014000000101ULL, 0x0101010001000101ULL, 0x0101014001000101ULL, 0x0101010000010101ULL, 0x0101014000010101ULL, 0x0101010001010101ULL, 0x0101014001010101ULL }; } /* * DES * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { /* * DESX Encryption */ void DESX::encrypt_n(const byte in[], byte out[], size_t blocks) const { for(size_t i = 0; i != blocks; ++i) { xor_buf(out, in, &K1[0], BLOCK_SIZE); des.encrypt(out); xor_buf(out, &K2[0], BLOCK_SIZE); in += BLOCK_SIZE; out += BLOCK_SIZE; } } /* * DESX Decryption */ void DESX::decrypt_n(const byte in[], byte out[], size_t blocks) const { for(size_t i = 0; i != blocks; ++i) { xor_buf(out, in, &K2[0], BLOCK_SIZE); des.decrypt(out); xor_buf(out, &K1[0], BLOCK_SIZE); in += BLOCK_SIZE; out += BLOCK_SIZE; } } /* * DESX Key Schedule */ void DESX::key_schedule(const byte key[], size_t) { K1.copy(key, 8); des.set_key(key + 8, 8); K2.copy(key + 16, 8); } } /* * GOST 28147-89 * (C) 1999-2009,2011 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { byte GOST_28147_89_Params::sbox_entry(size_t row, size_t col) const { byte x = sboxes[4 * col + (row / 2)]; return (row % 2 == 0) ? (x >> 4) : (x & 0x0F); } GOST_28147_89_Params::GOST_28147_89_Params(const std::string& n) : name(n) { // Encoded in the packed fromat from RFC 4357 // GostR3411_94_TestParamSet (OID 1.2.643.2.2.31.0) static const byte GOST_R_3411_TEST_PARAMS[64] = { 0x4E, 0x57, 0x64, 0xD1, 0xAB, 0x8D, 0xCB, 0xBF, 0x94, 0x1A, 0x7A, 0x4D, 0x2C, 0xD1, 0x10, 0x10, 0xD6, 0xA0, 0x57, 0x35, 0x8D, 0x38, 0xF2, 0xF7, 0x0F, 0x49, 0xD1, 0x5A, 0xEA, 0x2F, 0x8D, 0x94, 0x62, 0xEE, 0x43, 0x09, 0xB3, 0xF4, 0xA6, 0xA2, 0x18, 0xC6, 0x98, 0xE3, 0xC1, 0x7C, 0xE5, 0x7E, 0x70, 0x6B, 0x09, 0x66, 0xF7, 0x02, 0x3C, 0x8B, 0x55, 0x95, 0xBF, 0x28, 0x39, 0xB3, 0x2E, 0xCC }; // GostR3411-94-CryptoProParamSet (OID 1.2.643.2.2.31.1) static const byte GOST_R_3411_CRYPTOPRO_PARAMS[64] = { 0xA5, 0x74, 0x77, 0xD1, 0x4F, 0xFA, 0x66, 0xE3, 0x54, 0xC7, 0x42, 0x4A, 0x60, 0xEC, 0xB4, 0x19, 0x82, 0x90, 0x9D, 0x75, 0x1D, 0x4F, 0xC9, 0x0B, 0x3B, 0x12, 0x2F, 0x54, 0x79, 0x08, 0xA0, 0xAF, 0xD1, 0x3E, 0x1A, 0x38, 0xC7, 0xB1, 0x81, 0xC6, 0xE6, 0x56, 0x05, 0x87, 0x03, 0x25, 0xEB, 0xFE, 0x9C, 0x6D, 0xF8, 0x6D, 0x2E, 0xAB, 0xDE, 0x20, 0xBA, 0x89, 0x3C, 0x92, 0xF8, 0xD3, 0x53, 0xBC }; if(name == "R3411_94_TestParam") sboxes = GOST_R_3411_TEST_PARAMS; else if(name == "R3411_CryptoPro") sboxes = GOST_R_3411_CRYPTOPRO_PARAMS; else throw Invalid_Argument("GOST_28147_89_Params: Unknown " + name); } /* * GOST Constructor */ GOST_28147_89::GOST_28147_89(const GOST_28147_89_Params& param) : SBOX(1024), EK(8) { // Convert the parallel 4x4 sboxes into larger word-based sboxes for(size_t i = 0; i != 4; ++i) for(size_t j = 0; j != 256; ++j) { const u32bit T = (param.sbox_entry(2*i , j % 16)) | (param.sbox_entry(2*i+1, j / 16) << 4); SBOX[256*i+j] = rotate_left(T, (11+8*i) % 32); } } std::string GOST_28147_89::name() const { /* 'Guess' the right name for the sbox on the basis of the values. This would need to be updated if support for other sbox parameters is added. Preferably, we would just store the string value in the constructor, but can't break binary compat. */ std::string sbox_name = ""; if(SBOX[0] == 0x00072000) sbox_name = "R3411_94_TestParam"; else if(SBOX[0] == 0x0002D000) sbox_name = "R3411_CryptoPro"; else throw Internal_Error("GOST-28147 unrecognized sbox value"); return "GOST-28147-89(" + sbox_name + ")"; } /* * Two rounds of GOST */ #define GOST_2ROUND(N1, N2, R1, R2) \ do { \ u32bit T0 = N1 + EK[R1]; \ N2 ^= SBOX[get_byte(3, T0)] | \ SBOX[get_byte(2, T0)+256] | \ SBOX[get_byte(1, T0)+512] | \ SBOX[get_byte(0, T0)+768]; \ \ u32bit T1 = N2 + EK[R2]; \ N1 ^= SBOX[get_byte(3, T1)] | \ SBOX[get_byte(2, T1)+256] | \ SBOX[get_byte(1, T1)+512] | \ SBOX[get_byte(0, T1)+768]; \ } while(0) /* * GOST Encryption */ void GOST_28147_89::encrypt_n(const byte in[], byte out[], size_t blocks) const { for(size_t i = 0; i != blocks; ++i) { u32bit N1 = load_le(in, 0); u32bit N2 = load_le(in, 1); 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); } 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::decrypt_n(const byte in[], byte out[], size_t blocks) const { for(size_t i = 0; i != blocks; ++i) { u32bit N1 = load_le(in, 0); u32bit N2 = load_le(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); for(size_t j = 0; j != 3; ++j) { 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 Key Schedule */ void GOST_28147_89::key_schedule(const byte key[], size_t) { for(size_t i = 0; i != 8; ++i) EK[i] = load_le(key, i); } } /* * IDEA * (C) 1999-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { namespace { /* * Multiplication modulo 65537 */ inline u16bit mul(u16bit x, u16bit y) { const u32bit P = static_cast(x) * y; // P ? 0xFFFF : 0 const u16bit P_mask = !P - 1; const u32bit P_hi = P >> 16; const u32bit P_lo = P & 0xFFFF; const u16bit r_1 = (P_lo - P_hi) + (P_lo < P_hi); const u16bit r_2 = 1 - x - y; return (r_1 & P_mask) | (r_2 & ~P_mask); } /* * Find multiplicative inverses modulo 65537 * * 65537 is prime; thus Fermat's little theorem tells us that * x^65537 == x modulo 65537, which means * x^(65537-2) == x^-1 modulo 65537 since * x^(65537-2) * x == 1 mod 65537 * * Do the exponentiation with a basic square and multiply: all bits are * of exponent are 1 so we always multiply */ u16bit mul_inv(u16bit x) { u16bit y = x; for(size_t i = 0; i != 15; ++i) { y = mul(y, y); // square y = mul(y, x); } return y; } /** * IDEA is involutional, depending only on the key schedule */ void idea_op(const byte in[], byte out[], size_t blocks, const u16bit K[52]) { const size_t BLOCK_SIZE = 8; for(size_t i = 0; i != blocks; ++i) { u16bit X1 = load_be(in, 0); u16bit X2 = load_be(in, 1); u16bit X3 = load_be(in, 2); u16bit X4 = load_be(in, 3); for(size_t j = 0; j != 8; ++j) { X1 = mul(X1, K[6*j+0]); X2 += K[6*j+1]; X3 += K[6*j+2]; X4 = mul(X4, K[6*j+3]); u16bit T0 = X3; X3 = mul(X3 ^ X1, K[6*j+4]); u16bit T1 = X2; X2 = mul((X2 ^ X4) + X3, K[6*j+5]); X3 += X2; X1 ^= X2; X4 ^= X3; X2 ^= T0; X3 ^= T1; } X1 = mul(X1, K[48]); X2 += K[50]; X3 += K[49]; X4 = mul(X4, K[51]); store_be(out, X1, X3, X2, X4); in += BLOCK_SIZE; out += BLOCK_SIZE; } } } /* * IDEA Encryption */ void IDEA::encrypt_n(const byte in[], byte out[], size_t blocks) const { idea_op(in, out, blocks, &EK[0]); } /* * IDEA Decryption */ void IDEA::decrypt_n(const byte in[], byte out[], size_t blocks) const { idea_op(in, out, blocks, &DK[0]); } /* * IDEA Key Schedule */ void IDEA::key_schedule(const byte key[], size_t) { for(size_t i = 0; i != 8; ++i) EK[i] = load_be(key, i); for(size_t i = 1, j = 8, offset = 0; j != 52; i %= 8, ++i, ++j) { EK[i+7+offset] = static_cast((EK[(i % 8) + offset] << 9) | (EK[((i+1) % 8) + offset] >> 7)); offset += (i == 8) ? 8 : 0; } DK[51] = mul_inv(EK[3]); DK[50] = -EK[2]; DK[49] = -EK[1]; DK[48] = mul_inv(EK[0]); for(size_t i = 1, j = 4, counter = 47; i != 8; ++i, j += 6) { DK[counter--] = EK[j+1]; DK[counter--] = EK[j]; DK[counter--] = mul_inv(EK[j+5]); DK[counter--] = -EK[j+3]; DK[counter--] = -EK[j+4]; DK[counter--] = mul_inv(EK[j+2]); } DK[5] = EK[47]; DK[4] = EK[46]; DK[3] = mul_inv(EK[51]); DK[2] = -EK[50]; DK[1] = -EK[49]; DK[0] = mul_inv(EK[48]); } } /* * KASUMI * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { namespace { /* * KASUMI S-Boxes */ const byte KASUMI_SBOX_S7[128] = { 0x36, 0x32, 0x3E, 0x38, 0x16, 0x22, 0x5E, 0x60, 0x26, 0x06, 0x3F, 0x5D, 0x02, 0x12, 0x7B, 0x21, 0x37, 0x71, 0x27, 0x72, 0x15, 0x43, 0x41, 0x0C, 0x2F, 0x49, 0x2E, 0x1B, 0x19, 0x6F, 0x7C, 0x51, 0x35, 0x09, 0x79, 0x4F, 0x34, 0x3C, 0x3A, 0x30, 0x65, 0x7F, 0x28, 0x78, 0x68, 0x46, 0x47, 0x2B, 0x14, 0x7A, 0x48, 0x3D, 0x17, 0x6D, 0x0D, 0x64, 0x4D, 0x01, 0x10, 0x07, 0x52, 0x0A, 0x69, 0x62, 0x75, 0x74, 0x4C, 0x0B, 0x59, 0x6A, 0x00, 0x7D, 0x76, 0x63, 0x56, 0x45, 0x1E, 0x39, 0x7E, 0x57, 0x70, 0x33, 0x11, 0x05, 0x5F, 0x0E, 0x5A, 0x54, 0x5B, 0x08, 0x23, 0x67, 0x20, 0x61, 0x1C, 0x42, 0x66, 0x1F, 0x1A, 0x2D, 0x4B, 0x04, 0x55, 0x5C, 0x25, 0x4A, 0x50, 0x31, 0x44, 0x1D, 0x73, 0x2C, 0x40, 0x6B, 0x6C, 0x18, 0x6E, 0x53, 0x24, 0x4E, 0x2A, 0x13, 0x0F, 0x29, 0x58, 0x77, 0x3B, 0x03 }; const u16bit KASUMI_SBOX_S9[512] = { 0x00A7, 0x00EF, 0x00A1, 0x017B, 0x0187, 0x014E, 0x0009, 0x0152, 0x0026, 0x00E2, 0x0030, 0x0166, 0x01C4, 0x0181, 0x005A, 0x018D, 0x00B7, 0x00FD, 0x0093, 0x014B, 0x019F, 0x0154, 0x0033, 0x016A, 0x0132, 0x01F4, 0x0106, 0x0052, 0x00D8, 0x009F, 0x0164, 0x00B1, 0x00AF, 0x00F1, 0x01E9, 0x0025, 0x00CE, 0x0011, 0x0000, 0x014D, 0x002C, 0x00FE, 0x017A, 0x003A, 0x008F, 0x00DC, 0x0051, 0x0190, 0x005F, 0x0003, 0x013B, 0x00F5, 0x0036, 0x00EB, 0x00DA, 0x0195, 0x01D8, 0x0108, 0x00AC, 0x01EE, 0x0173, 0x0122, 0x018F, 0x004C, 0x00A5, 0x00C5, 0x018B, 0x0079, 0x0101, 0x01E0, 0x01A7, 0x00D4, 0x00F0, 0x001C, 0x01CE, 0x00B0, 0x0196, 0x01FB, 0x0120, 0x00DF, 0x01F5, 0x0197, 0x00F9, 0x0109, 0x0059, 0x00BA, 0x00DD, 0x01AC, 0x00A4, 0x004A, 0x01B8, 0x00C4, 0x01CA, 0x01A5, 0x015E, 0x00A3, 0x00E8, 0x009E, 0x0086, 0x0162, 0x000D, 0x00FA, 0x01EB, 0x008E, 0x00BF, 0x0045, 0x00C1, 0x01A9, 0x0098, 0x00E3, 0x016E, 0x0087, 0x0158, 0x012C, 0x0114, 0x00F2, 0x01B5, 0x0140, 0x0071, 0x0116, 0x000B, 0x00F3, 0x0057, 0x013D, 0x0024, 0x005D, 0x01F0, 0x001B, 0x01E7, 0x01BE, 0x01E2, 0x0029, 0x0044, 0x009C, 0x01C9, 0x0083, 0x0146, 0x0193, 0x0153, 0x0014, 0x0027, 0x0073, 0x01BA, 0x007C, 0x01DB, 0x0180, 0x01FC, 0x0035, 0x0070, 0x00AA, 0x01DF, 0x0097, 0x007E, 0x00A9, 0x0049, 0x010C, 0x0117, 0x0141, 0x00A8, 0x016C, 0x016B, 0x0124, 0x002E, 0x01F3, 0x0189, 0x0147, 0x0144, 0x0018, 0x01C8, 0x010B, 0x009D, 0x01CC, 0x01E8, 0x01AA, 0x0135, 0x00E5, 0x01B7, 0x01FA, 0x00D0, 0x010F, 0x015D, 0x0191, 0x01B2, 0x00EC, 0x0010, 0x00D1, 0x0167, 0x0034, 0x0038, 0x0078, 0x00C7, 0x0115, 0x01D1, 0x01A0, 0x00FC, 0x011F, 0x00F6, 0x0006, 0x0053, 0x0131, 0x01A4, 0x0159, 0x0099, 0x01F6, 0x0041, 0x003D, 0x00F4, 0x011A, 0x00AD, 0x00DE, 0x01A2, 0x0043, 0x0182, 0x0170, 0x0105, 0x0065, 0x01DC, 0x0123, 0x00C3, 0x01AE, 0x0031, 0x004F, 0x00A6, 0x014A, 0x0118, 0x017F, 0x0175, 0x0080, 0x017E, 0x0198, 0x009B, 0x01EF, 0x016F, 0x0184, 0x0112, 0x006B, 0x01CB, 0x01A1, 0x003E, 0x01C6, 0x0084, 0x00E1, 0x00CB, 0x013C, 0x00EA, 0x000E, 0x012D, 0x005B, 0x01F7, 0x011E, 0x01A8, 0x00D3, 0x015B, 0x0133, 0x008C, 0x0176, 0x0023, 0x0067, 0x007D, 0x01AB, 0x0013, 0x00D6, 0x01C5, 0x0092, 0x01F2, 0x013A, 0x01BC, 0x00E6, 0x0100, 0x0149, 0x00C6, 0x011D, 0x0032, 0x0074, 0x004E, 0x019A, 0x000A, 0x00CD, 0x01FE, 0x00AB, 0x00E7, 0x002D, 0x008B, 0x01D3, 0x001D, 0x0056, 0x01F9, 0x0020, 0x0048, 0x001A, 0x0156, 0x0096, 0x0139, 0x01EA, 0x01AF, 0x00EE, 0x019B, 0x0145, 0x0095, 0x01D9, 0x0028, 0x0077, 0x00AE, 0x0163, 0x00B9, 0x00E9, 0x0185, 0x0047, 0x01C0, 0x0111, 0x0174, 0x0037, 0x006E, 0x00B2, 0x0142, 0x000C, 0x01D5, 0x0188, 0x0171, 0x00BE, 0x0001, 0x006D, 0x0177, 0x0089, 0x00B5, 0x0058, 0x004B, 0x0134, 0x0104, 0x01E4, 0x0062, 0x0110, 0x0172, 0x0113, 0x019C, 0x006F, 0x0150, 0x013E, 0x0004, 0x01F8, 0x01EC, 0x0103, 0x0130, 0x004D, 0x0151, 0x01B3, 0x0015, 0x0165, 0x012F, 0x014C, 0x01E3, 0x0012, 0x002F, 0x0055, 0x0019, 0x01F1, 0x01DA, 0x0121, 0x0064, 0x010D, 0x0128, 0x01DE, 0x010E, 0x006A, 0x001F, 0x0068, 0x01B1, 0x0054, 0x019E, 0x01E6, 0x018A, 0x0060, 0x0063, 0x009A, 0x01FF, 0x0094, 0x019D, 0x0169, 0x0199, 0x00FF, 0x00A2, 0x00D7, 0x012E, 0x00C9, 0x010A, 0x015F, 0x0157, 0x0090, 0x01B9, 0x016D, 0x006C, 0x012A, 0x00FB, 0x0022, 0x00B6, 0x01FD, 0x008A, 0x00D2, 0x014F, 0x0085, 0x0137, 0x0160, 0x0148, 0x008D, 0x018C, 0x015A, 0x007B, 0x013F, 0x01C2, 0x0119, 0x01AD, 0x00E4, 0x01BB, 0x01E1, 0x005C, 0x0194, 0x01E5, 0x01A6, 0x00F8, 0x0129, 0x0017, 0x00D5, 0x0082, 0x01D2, 0x0016, 0x00D9, 0x011B, 0x0046, 0x0126, 0x0168, 0x01A3, 0x007F, 0x0138, 0x0179, 0x0007, 0x01D4, 0x00C2, 0x0002, 0x0075, 0x0127, 0x01CF, 0x0102, 0x00E0, 0x01BF, 0x00F7, 0x00BB, 0x0050, 0x018E, 0x011C, 0x0161, 0x0069, 0x0186, 0x012B, 0x01D7, 0x01D6, 0x00B8, 0x0039, 0x00C8, 0x015C, 0x003F, 0x00CC, 0x00BC, 0x0021, 0x01C3, 0x0061, 0x001E, 0x0136, 0x00DB, 0x005E, 0x00A0, 0x0081, 0x01ED, 0x0040, 0x00B3, 0x0107, 0x0066, 0x00BD, 0x00CF, 0x0072, 0x0192, 0x01B6, 0x01DD, 0x0183, 0x007A, 0x00C0, 0x002A, 0x017D, 0x0005, 0x0091, 0x0076, 0x00B4, 0x01C1, 0x0125, 0x0143, 0x0088, 0x017C, 0x002B, 0x0042, 0x003C, 0x01C7, 0x0155, 0x01BD, 0x00CA, 0x01B0, 0x0008, 0x00ED, 0x000F, 0x0178, 0x01B4, 0x01D0, 0x003B, 0x01CD }; /* * KASUMI FI Function */ u16bit FI(u16bit I, u16bit K) { u16bit D9 = (I >> 7); byte D7 = (I & 0x7F); D9 = KASUMI_SBOX_S9[D9] ^ D7; D7 = KASUMI_SBOX_S7[D7] ^ (D9 & 0x7F); D7 ^= (K >> 9); D9 = KASUMI_SBOX_S9[D9 ^ (K & 0x1FF)] ^ D7; D7 = KASUMI_SBOX_S7[D7] ^ (D9 & 0x7F); return (D7 << 9) | D9; } } /* * KASUMI Encryption */ void KASUMI::encrypt_n(const byte in[], byte out[], size_t blocks) const { for(size_t i = 0; i != blocks; ++i) { u16bit B0 = load_be(in, 0); u16bit B1 = load_be(in, 1); u16bit B2 = load_be(in, 2); u16bit B3 = load_be(in, 3); for(size_t j = 0; j != 8; j += 2) { const u16bit* K = &EK[8*j]; u16bit R = B1 ^ (rotate_left(B0, 1) & K[0]); u16bit L = B0 ^ (rotate_left(R, 1) | K[1]); 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 = B2 ^= R; L = B3 ^= L; 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 ^= (rotate_left(L, 1) & K[8]); L ^= (rotate_left(R, 1) | K[9]); B0 ^= L; B1 ^= R; } store_be(out, B0, B1, B2, B3); in += BLOCK_SIZE; out += BLOCK_SIZE; } } /* * KASUMI Decryption */ void KASUMI::decrypt_n(const byte in[], byte out[], size_t blocks) const { for(size_t i = 0; i != blocks; ++i) { u16bit B0 = load_be(in, 0); u16bit B1 = load_be(in, 1); u16bit B2 = load_be(in, 2); u16bit B3 = load_be(in, 3); for(size_t j = 0; j != 8; j += 2) { const u16bit* K = &EK[8*(6-j)]; u16bit L = B2, R = B3; L = FI(L ^ K[10], K[11]) ^ R; R = FI(R ^ K[12], K[13]) ^ L; L = FI(L ^ K[14], K[15]) ^ R; L ^= (rotate_left(R, 1) & K[8]); R ^= (rotate_left(L, 1) | K[9]); R = B0 ^= R; L = B1 ^= L; L ^= (rotate_left(R, 1) & K[0]); R ^= (rotate_left(L, 1) | K[1]); 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); in += BLOCK_SIZE; out += BLOCK_SIZE; } } /* * KASUMI Key Schedule */ void KASUMI::key_schedule(const byte key[], size_t) { static const u16bit RC[] = { 0x0123, 0x4567, 0x89AB, 0xCDEF, 0xFEDC, 0xBA98, 0x7654, 0x3210 }; SecureVector K(16); for(size_t i = 0; i != 8; ++i) { K[i] = load_be(key, i); K[i+8] = K[i] ^ RC[i]; } for(size_t i = 0; i != 8; ++i) { EK[8*i ] = rotate_left(K[(i+0) % 8 ], 2); EK[8*i+1] = rotate_left(K[(i+2) % 8 + 8], 1); EK[8*i+2] = rotate_left(K[(i+1) % 8 ], 5); EK[8*i+3] = K[(i+4) % 8 + 8]; EK[8*i+4] = rotate_left(K[(i+5) % 8 ], 8); EK[8*i+5] = K[(i+3) % 8 + 8]; EK[8*i+6] = rotate_left(K[(i+6) % 8 ], 13); EK[8*i+7] = K[(i+7) % 8 + 8]; } } } /* * Lion * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { /* * Lion Encryption */ void Lion::encrypt_n(const byte in[], byte out[], size_t blocks) const { SecureVector buffer_vec(LEFT_SIZE); byte* buffer = &buffer_vec[0]; for(size_t i = 0; i != blocks; ++i) { xor_buf(buffer, in, &key1[0], LEFT_SIZE); cipher->set_key(buffer, LEFT_SIZE); cipher->cipher(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); xor_buf(buffer, out, &key2[0], LEFT_SIZE); cipher->set_key(buffer, LEFT_SIZE); cipher->cipher1(out + LEFT_SIZE, RIGHT_SIZE); in += BLOCK_SIZE; out += BLOCK_SIZE; } } /* * Lion Decryption */ void Lion::decrypt_n(const byte in[], byte out[], size_t blocks) const { SecureVector buffer_vec(LEFT_SIZE); byte* buffer = &buffer_vec[0]; for(size_t i = 0; i != blocks; ++i) { xor_buf(buffer, in, &key2[0], LEFT_SIZE); cipher->set_key(buffer, LEFT_SIZE); cipher->cipher(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); xor_buf(buffer, out, &key1[0], LEFT_SIZE); cipher->set_key(buffer, LEFT_SIZE); cipher->cipher1(out + LEFT_SIZE, RIGHT_SIZE); in += BLOCK_SIZE; out += BLOCK_SIZE; } } /* * Lion Key Schedule */ void Lion::key_schedule(const byte key[], size_t length) { clear(); key1.copy(key, length / 2); key2.copy(key + length / 2, length / 2); } /* * Return the name of this type */ std::string Lion::name() const { return "Lion(" + hash->name() + "," + cipher->name() + "," + to_string(BLOCK_SIZE) + ")"; } /* * Return a clone of this object */ BlockCipher* Lion::clone() const { return new Lion(hash->clone(), cipher->clone(), BLOCK_SIZE); } /* * Clear memory of sensitive data */ void Lion::clear() { hash->clear(); cipher->clear(); zeroise(key1); zeroise(key2); } /* * Lion Constructor */ Lion::Lion(HashFunction* hash_in, StreamCipher* sc_in, size_t block_len) : BLOCK_SIZE(std::max(2*hash_in->output_length() + 1, block_len)), LEFT_SIZE(hash_in->output_length()), RIGHT_SIZE(BLOCK_SIZE - LEFT_SIZE), hash(hash_in), cipher(sc_in) { if(2*LEFT_SIZE + 1 > BLOCK_SIZE) throw Invalid_Argument(name() + ": Chosen block size is too small"); if(!cipher->valid_keylength(LEFT_SIZE)) throw Invalid_Argument(name() + ": This stream/hash combo is invalid"); key1.resize(LEFT_SIZE); key2.resize(LEFT_SIZE); } } /* * Luby-Rackoff * (C) 1999-2008 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { /* * Luby-Rackoff Encryption */ void LubyRackoff::encrypt_n(const byte in[], byte out[], size_t blocks) const { const size_t len = hash->output_length(); SecureVector buffer_vec(len); byte* buffer = &buffer_vec[0]; for(size_t i = 0; i != blocks; ++i) { 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 += 2 * len; out += 2 * len; } } /* * Luby-Rackoff Decryption */ void LubyRackoff::decrypt_n(const byte in[], byte out[], size_t blocks) const { const size_t len = hash->output_length(); SecureVector buffer_vec(len); byte* buffer = &buffer_vec[0]; for(size_t i = 0; i != blocks; ++i) { 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 += 2 * len; out += 2 * len; } } /* * Luby-Rackoff Key Schedule */ void LubyRackoff::key_schedule(const byte key[], size_t length) { K1.resize(length / 2); K2.resize(length / 2); copy_mem(&K1[0], key , length / 2); copy_mem(&K2[0], key + length / 2, length / 2); } /* * Clear memory of sensitive data */ void LubyRackoff::clear() { zeroise(K1); zeroise(K2); hash->clear(); } /* * Return a clone of this object */ BlockCipher* LubyRackoff::clone() const { return new LubyRackoff(hash->clone()); } /* * Return the name of this type */ std::string LubyRackoff::name() const { return "Luby-Rackoff(" + hash->name() + ")"; } /* * Luby-Rackoff Constructor */ LubyRackoff::LubyRackoff(HashFunction* h) : hash(h) { } } /* * MARS * (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { namespace { /** * The MARS sbox */ const u32bit SBOX[512] = { 0x09D0C479, 0x28C8FFE0, 0x84AA6C39, 0x9DAD7287, 0x7DFF9BE3, 0xD4268361, 0xC96DA1D4, 0x7974CC93, 0x85D0582E, 0x2A4B5705, 0x1CA16A62, 0xC3BD279D, 0x0F1F25E5, 0x5160372F, 0xC695C1FB, 0x4D7FF1E4, 0xAE5F6BF4, 0x0D72EE46, 0xFF23DE8A, 0xB1CF8E83, 0xF14902E2, 0x3E981E42, 0x8BF53EB6, 0x7F4BF8AC, 0x83631F83, 0x25970205, 0x76AFE784, 0x3A7931D4, 0x4F846450, 0x5C64C3F6, 0x210A5F18, 0xC6986A26, 0x28F4E826, 0x3A60A81C, 0xD340A664, 0x7EA820C4, 0x526687C5, 0x7EDDD12B, 0x32A11D1D, 0x9C9EF086, 0x80F6E831, 0xAB6F04AD, 0x56FB9B53, 0x8B2E095C, 0xB68556AE, 0xD2250B0D, 0x294A7721, 0xE21FB253, 0xAE136749, 0xE82AAE86, 0x93365104, 0x99404A66, 0x78A784DC, 0xB69BA84B, 0x04046793, 0x23DB5C1E, 0x46CAE1D6, 0x2FE28134, 0x5A223942, 0x1863CD5B, 0xC190C6E3, 0x07DFB846, 0x6EB88816, 0x2D0DCC4A, 0xA4CCAE59, 0x3798670D, 0xCBFA9493, 0x4F481D45, 0xEAFC8CA8, 0xDB1129D6, 0xB0449E20, 0x0F5407FB, 0x6167D9A8, 0xD1F45763, 0x4DAA96C3, 0x3BEC5958, 0xABABA014, 0xB6CCD201, 0x38D6279F, 0x02682215, 0x8F376CD5, 0x092C237E, 0xBFC56593, 0x32889D2C, 0x854B3E95, 0x05BB9B43, 0x7DCD5DCD, 0xA02E926C, 0xFAE527E5, 0x36A1C330, 0x3412E1AE, 0xF257F462, 0x3C4F1D71, 0x30A2E809, 0x68E5F551, 0x9C61BA44, 0x5DED0AB8, 0x75CE09C8, 0x9654F93E, 0x698C0CCA, 0x243CB3E4, 0x2B062B97, 0x0F3B8D9E, 0x00E050DF, 0xFC5D6166, 0xE35F9288, 0xC079550D, 0x0591AEE8, 0x8E531E74, 0x75FE3578, 0x2F6D829A, 0xF60B21AE, 0x95E8EB8D, 0x6699486B, 0x901D7D9B, 0xFD6D6E31, 0x1090ACEF, 0xE0670DD8, 0xDAB2E692, 0xCD6D4365, 0xE5393514, 0x3AF345F0, 0x6241FC4D, 0x460DA3A3, 0x7BCF3729, 0x8BF1D1E0, 0x14AAC070, 0x1587ED55, 0x3AFD7D3E, 0xD2F29E01, 0x29A9D1F6, 0xEFB10C53, 0xCF3B870F, 0xB414935C, 0x664465ED, 0x024ACAC7, 0x59A744C1, 0x1D2936A7, 0xDC580AA6, 0xCF574CA8, 0x040A7A10, 0x6CD81807, 0x8A98BE4C, 0xACCEA063, 0xC33E92B5, 0xD1E0E03D, 0xB322517E, 0x2092BD13, 0x386B2C4A, 0x52E8DD58, 0x58656DFB, 0x50820371, 0x41811896, 0xE337EF7E, 0xD39FB119, 0xC97F0DF6, 0x68FEA01B, 0xA150A6E5, 0x55258962, 0xEB6FF41B, 0xD7C9CD7A, 0xA619CD9E, 0xBCF09576, 0x2672C073, 0xF003FB3C, 0x4AB7A50B, 0x1484126A, 0x487BA9B1, 0xA64FC9C6, 0xF6957D49, 0x38B06A75, 0xDD805FCD, 0x63D094CF, 0xF51C999E, 0x1AA4D343, 0xB8495294, 0xCE9F8E99, 0xBFFCD770, 0xC7C275CC, 0x378453A7, 0x7B21BE33, 0x397F41BD, 0x4E94D131, 0x92CC1F98, 0x5915EA51, 0x99F861B7, 0xC9980A88, 0x1D74FD5F, 0xB0A495F8, 0x614DEED0, 0xB5778EEA, 0x5941792D, 0xFA90C1F8, 0x33F824B4, 0xC4965372, 0x3FF6D550, 0x4CA5FEC0, 0x8630E964, 0x5B3FBBD6, 0x7DA26A48, 0xB203231A, 0x04297514, 0x2D639306, 0x2EB13149, 0x16A45272, 0x532459A0, 0x8E5F4872, 0xF966C7D9, 0x07128DC0, 0x0D44DB62, 0xAFC8D52D, 0x06316131, 0xD838E7CE, 0x1BC41D00, 0x3A2E8C0F, 0xEA83837E, 0xB984737D, 0x13BA4891, 0xC4F8B949, 0xA6D6ACB3, 0xA215CDCE, 0x8359838B, 0x6BD1AA31, 0xF579DD52, 0x21B93F93, 0xF5176781, 0x187DFDDE, 0xE94AEB76, 0x2B38FD54, 0x431DE1DA, 0xAB394825, 0x9AD3048F, 0xDFEA32AA, 0x659473E3, 0x623F7863, 0xF3346C59, 0xAB3AB685, 0x3346A90B, 0x6B56443E, 0xC6DE01F8, 0x8D421FC0, 0x9B0ED10C, 0x88F1A1E9, 0x54C1F029, 0x7DEAD57B, 0x8D7BA426, 0x4CF5178A, 0x551A7CCA, 0x1A9A5F08, 0xFCD651B9, 0x25605182, 0xE11FC6C3, 0xB6FD9676, 0x337B3027, 0xB7C8EB14, 0x9E5FD030, 0x6B57E354, 0xAD913CF7, 0x7E16688D, 0x58872A69, 0x2C2FC7DF, 0xE389CCC6, 0x30738DF1, 0x0824A734, 0xE1797A8B, 0xA4A8D57B, 0x5B5D193B, 0xC8A8309B, 0x73F9A978, 0x73398D32, 0x0F59573E, 0xE9DF2B03, 0xE8A5B6C8, 0x848D0704, 0x98DF93C2, 0x720A1DC3, 0x684F259A, 0x943BA848, 0xA6370152, 0x863B5EA3, 0xD17B978B, 0x6D9B58EF, 0x0A700DD4, 0xA73D36BF, 0x8E6A0829, 0x8695BC14, 0xE35B3447, 0x933AC568, 0x8894B022, 0x2F511C27, 0xDDFBCC3C, 0x006662B6, 0x117C83FE, 0x4E12B414, 0xC2BCA766, 0x3A2FEC10, 0xF4562420, 0x55792E2A, 0x46F5D857, 0xCEDA25CE, 0xC3601D3B, 0x6C00AB46, 0xEFAC9C28, 0xB3C35047, 0x611DFEE3, 0x257C3207, 0xFDD58482, 0x3B14D84F, 0x23BECB64, 0xA075F3A3, 0x088F8EAD, 0x07ADF158, 0x7796943C, 0xFACABF3D, 0xC09730CD, 0xF7679969, 0xDA44E9ED, 0x2C854C12, 0x35935FA3, 0x2F057D9F, 0x690624F8, 0x1CB0BAFD, 0x7B0DBDC6, 0x810F23BB, 0xFA929A1A, 0x6D969A17, 0x6742979B, 0x74AC7D05, 0x010E65C4, 0x86A3D963, 0xF907B5A0, 0xD0042BD3, 0x158D7D03, 0x287A8255, 0xBBA8366F, 0x096EDC33, 0x21916A7B, 0x77B56B86, 0x951622F9, 0xA6C5E650, 0x8CEA17D1, 0xCD8C62BC, 0xA3D63433, 0x358A68FD, 0x0F9B9D3C, 0xD6AA295B, 0xFE33384A, 0xC000738E, 0xCD67EB2F, 0xE2EB6DC2, 0x97338B02, 0x06C9F246, 0x419CF1AD, 0x2B83C045, 0x3723F18A, 0xCB5B3089, 0x160BEAD7, 0x5D494656, 0x35F8A74B, 0x1E4E6C9E, 0x000399BD, 0x67466880, 0xB4174831, 0xACF423B2, 0xCA815AB3, 0x5A6395E7, 0x302A67C5, 0x8BDB446B, 0x108F8FA4, 0x10223EDA, 0x92B8B48B, 0x7F38D0EE, 0xAB2701D4, 0x0262D415, 0xAF224A30, 0xB3D88ABA, 0xF8B2C3AF, 0xDAF7EF70, 0xCC97D3B7, 0xE9614B6C, 0x2BAEBFF4, 0x70F687CF, 0x386C9156, 0xCE092EE5, 0x01E87DA6, 0x6CE91E6A, 0xBB7BCC84, 0xC7922C20, 0x9D3B71FD, 0x060E41C6, 0xD7590F15, 0x4E03BB47, 0x183C198E, 0x63EEB240, 0x2DDBF49A, 0x6D5CBA54, 0x923750AF, 0xF9E14236, 0x7838162B, 0x59726C72, 0x81B66760, 0xBB2926C1, 0x48A0CE0D, 0xA6C0496D, 0xAD43507B, 0x718D496A, 0x9DF057AF, 0x44B1BDE6, 0x054356DC, 0xDE7CED35, 0xD51A138B, 0x62088CC9, 0x35830311, 0xC96EFCA2, 0x686F86EC, 0x8E77CB68, 0x63E1D6B8, 0xC80F9778, 0x79C491FD, 0x1B4C67F2, 0x72698D7D, 0x5E368C31, 0xF7D95E2E, 0xA1D3493F, 0xDCD9433E, 0x896F1552, 0x4BC4CA7A, 0xA6D1BAF4, 0xA5A96DCC, 0x0BEF8B46, 0xA169FDA7, 0x74DF40B7, 0x4E208804, 0x9A756607, 0x038E87C8, 0x20211E44, 0x8B7AD4BF, 0xC6403F35, 0x1848E36D, 0x80BDB038, 0x1E62891C, 0x643D2107, 0xBF04D6F8, 0x21092C8C, 0xF644F389, 0x0778404E, 0x7B78ADB8, 0xA2C52D53, 0x42157ABE, 0xA2253E2E, 0x7BF3F4AE, 0x80F594F9, 0x953194E7, 0x77EB92ED, 0xB3816930, 0xDA8D9336, 0xBF447469, 0xF26D9483, 0xEE6FAED5, 0x71371235, 0xDE425F73, 0xB4E59F43, 0x7DBE2D4E, 0x2D37B185, 0x49DC9A63, 0x98C39D98, 0x1301C9A2, 0x389B1BBF, 0x0C18588D, 0xA421C1BA, 0x7AA3865C, 0x71E08558, 0x3C5CFCAA, 0x7D239CA4, 0x0297D9DD, 0xD7DC2830, 0x4B37802B, 0x7428AB54, 0xAEEE0347, 0x4B3FBB85, 0x692F2F08, 0x134E578E, 0x36D9E0BF, 0xAE8B5FCF, 0xEDB93ECF, 0x2B27248E, 0x170EB1EF, 0x7DC57FD6, 0x1E760F16, 0xB1136601, 0x864E1B9B, 0xD7EA7319, 0x3AB871BD, 0xCFA4D76F, 0xE31BD782, 0x0DBEB469, 0xABB96061, 0x5370F85D, 0xFFB07E37, 0xDA30D0FB, 0xEBC977B6, 0x0B98B40F, 0x3A4D0FE6, 0xDF4FC26B, 0x159CF22A, 0xC298D6E2, 0x2B78EF6A, 0x61A94AC0, 0xAB561187, 0x14EEA0F0, 0xDF0D4164, 0x19AF70EE }; /* * MARS Encryption Round */ inline void encrypt_round(u32bit& A, u32bit& B, u32bit& C, u32bit& D, u32bit EK1, u32bit EK2) { const u32bit X = A + EK1; A = rotate_left(A, 13); u32bit Y = A * EK2; u32bit Z = SBOX[X % 512]; Y = rotate_left(Y, 5); Z ^= Y; C += rotate_left(X, Y % 32); Y = rotate_left(Y, 5); Z ^= Y; D ^= Y; B += rotate_left(Z, Y % 32); } /* * MARS Decryption Round */ inline void decrypt_round(u32bit& A, u32bit& B, u32bit& C, u32bit& D, u32bit EK1, u32bit EK2) { u32bit Y = A * EK1; A = rotate_right(A, 13); const u32bit X = A + EK2; u32bit Z = SBOX[X % 512]; Y = rotate_left(Y, 5); Z ^= Y; C -= rotate_left(X, Y % 32); Y = rotate_left(Y, 5); Z ^= Y; D ^= Y; B -= rotate_left(Z, Y % 32); } /* * MARS Forward Mixing Operation */ void forward_mix(u32bit& A, u32bit& B, u32bit& C, u32bit& D) { for(size_t j = 0; j != 2; ++j) { B ^= SBOX[get_byte(3, A)]; B += SBOX[get_byte(2, A) + 256]; C += SBOX[get_byte(1, A)]; D ^= SBOX[get_byte(0, A) + 256]; A = rotate_right(A, 24) + D; C ^= SBOX[get_byte(3, B)]; C += SBOX[get_byte(2, B) + 256]; D += SBOX[get_byte(1, B)]; A ^= SBOX[get_byte(0, B) + 256]; B = rotate_right(B, 24) + C; D ^= SBOX[get_byte(3, C)]; D += SBOX[get_byte(2, C) + 256]; A += SBOX[get_byte(1, C)]; B ^= SBOX[get_byte(0, C) + 256]; C = rotate_right(C, 24); A ^= SBOX[get_byte(3, D)]; A += SBOX[get_byte(2, D) + 256]; B += SBOX[get_byte(1, D)]; C ^= SBOX[get_byte(0, D) + 256]; D = rotate_right(D, 24); } } /* * MARS Reverse Mixing Operation */ void reverse_mix(u32bit& A, u32bit& B, u32bit& C, u32bit& D) { for(size_t j = 0; j != 2; ++j) { B ^= SBOX[get_byte(3, A) + 256]; C -= SBOX[get_byte(0, A)]; D -= SBOX[get_byte(1, A) + 256]; D ^= SBOX[get_byte(2, A)]; A = rotate_left(A, 24); C ^= SBOX[get_byte(3, B) + 256]; D -= SBOX[get_byte(0, B)]; A -= SBOX[get_byte(1, B) + 256]; A ^= SBOX[get_byte(2, B)]; C -= (B = rotate_left(B, 24)); D ^= SBOX[get_byte(3, C) + 256]; A -= SBOX[get_byte(0, C)]; B -= SBOX[get_byte(1, C) + 256]; B ^= SBOX[get_byte(2, C)]; C = rotate_left(C, 24); D -= A; A ^= SBOX[get_byte(3, D) + 256]; B -= SBOX[get_byte(0, D)]; C -= SBOX[get_byte(1, D) + 256]; C ^= SBOX[get_byte(2, D)]; D = rotate_left(D, 24); } } /* * Generate a mask for runs of bits */ u32bit gen_mask(u32bit input) { u32bit mask = 0; for(u32bit j = 2; j != 31; ++j) { const u32bit region = (input >> (j-1)) & 0x07; if(region == 0x00 || region == 0x07) { const u32bit low = (j < 9) ? 0 : (j - 9); const u32bit high = (j < 23) ? j : 23; for(u32bit k = low; k != high; ++k) { const u32bit value = (input >> k) & 0x3FF; if(value == 0 || value == 0x3FF) { mask |= 1 << j; break; } } } } return mask; } } /* * MARS Encryption */ void MARS::encrypt_n(const byte in[], byte out[], size_t blocks) const { for(size_t i = 0; i != blocks; ++i) { u32bit A = load_le(in, 0) + EK[0]; u32bit B = load_le(in, 1) + EK[1]; u32bit C = load_le(in, 2) + EK[2]; u32bit D = load_le(in, 3) + EK[3]; forward_mix(A, B, C, D); encrypt_round(A, B, C, D, EK[ 4], EK[ 5]); encrypt_round(B, C, D, A, EK[ 6], EK[ 7]); encrypt_round(C, D, A, B, EK[ 8], EK[ 9]); encrypt_round(D, A, B, C, EK[10], EK[11]); encrypt_round(A, B, C, D, EK[12], EK[13]); encrypt_round(B, C, D, A, EK[14], EK[15]); encrypt_round(C, D, A, B, EK[16], EK[17]); encrypt_round(D, A, B, C, EK[18], EK[19]); encrypt_round(A, D, C, B, EK[20], EK[21]); encrypt_round(B, A, D, C, EK[22], EK[23]); encrypt_round(C, B, A, D, EK[24], EK[25]); encrypt_round(D, C, B, A, EK[26], EK[27]); encrypt_round(A, D, C, B, EK[28], EK[29]); encrypt_round(B, A, D, C, EK[30], EK[31]); encrypt_round(C, B, A, D, EK[32], EK[33]); encrypt_round(D, C, B, A, EK[34], EK[35]); 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::decrypt_n(const byte in[], byte out[], size_t blocks) const { for(size_t i = 0; i != blocks; ++i) { u32bit A = load_le(in, 3) + EK[39]; u32bit B = load_le(in, 2) + EK[38]; u32bit C = load_le(in, 1) + EK[37]; u32bit D = load_le(in, 0) + EK[36]; forward_mix(A, B, C, D); decrypt_round(A, B, C, D, EK[35], EK[34]); decrypt_round(B, C, D, A, EK[33], EK[32]); decrypt_round(C, D, A, B, EK[31], EK[30]); decrypt_round(D, A, B, C, EK[29], EK[28]); decrypt_round(A, B, C, D, EK[27], EK[26]); decrypt_round(B, C, D, A, EK[25], EK[24]); decrypt_round(C, D, A, B, EK[23], EK[22]); decrypt_round(D, A, B, C, EK[21], EK[20]); decrypt_round(A, D, C, B, EK[19], EK[18]); decrypt_round(B, A, D, C, EK[17], EK[16]); decrypt_round(C, B, A, D, EK[15], EK[14]); decrypt_round(D, C, B, A, EK[13], EK[12]); decrypt_round(A, D, C, B, EK[11], EK[10]); decrypt_round(B, A, D, C, EK[ 9], EK[ 8]); decrypt_round(C, B, A, D, EK[ 7], EK[ 6]); decrypt_round(D, C, B, A, EK[ 5], EK[ 4]); 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; } } /* * MARS Key Schedule */ void MARS::key_schedule(const byte key[], size_t length) { SecureVector T(15); for(size_t i = 0; i != length / 4; ++i) T[i] = load_le(key, i); T[length / 4] = static_cast(length) / 4; for(u32bit i = 0; i != 4; ++i) { T[ 0] ^= rotate_left(T[ 8] ^ T[13], 3) ^ (i ); T[ 1] ^= rotate_left(T[ 9] ^ T[14], 3) ^ (i + 4); T[ 2] ^= rotate_left(T[10] ^ T[ 0], 3) ^ (i + 8); T[ 3] ^= rotate_left(T[11] ^ T[ 1], 3) ^ (i + 12); T[ 4] ^= rotate_left(T[12] ^ T[ 2], 3) ^ (i + 16); T[ 5] ^= rotate_left(T[13] ^ T[ 3], 3) ^ (i + 20); T[ 6] ^= rotate_left(T[14] ^ T[ 4], 3) ^ (i + 24); T[ 7] ^= rotate_left(T[ 0] ^ T[ 5], 3) ^ (i + 28); T[ 8] ^= rotate_left(T[ 1] ^ T[ 6], 3) ^ (i + 32); T[ 9] ^= rotate_left(T[ 2] ^ T[ 7], 3) ^ (i + 36); T[10] ^= rotate_left(T[ 3] ^ T[ 8], 3) ^ (i + 40); T[11] ^= rotate_left(T[ 4] ^ T[ 9], 3) ^ (i + 44); T[12] ^= rotate_left(T[ 5] ^ T[10], 3) ^ (i + 48); T[13] ^= rotate_left(T[ 6] ^ T[11], 3) ^ (i + 52); T[14] ^= rotate_left(T[ 7] ^ T[12], 3) ^ (i + 56); for(size_t j = 0; j != 4; ++j) { T[ 0] = rotate_left(T[ 0] + SBOX[T[14] % 512], 9); T[ 1] = rotate_left(T[ 1] + SBOX[T[ 0] % 512], 9); T[ 2] = rotate_left(T[ 2] + SBOX[T[ 1] % 512], 9); T[ 3] = rotate_left(T[ 3] + SBOX[T[ 2] % 512], 9); T[ 4] = rotate_left(T[ 4] + SBOX[T[ 3] % 512], 9); T[ 5] = rotate_left(T[ 5] + SBOX[T[ 4] % 512], 9); T[ 6] = rotate_left(T[ 6] + SBOX[T[ 5] % 512], 9); T[ 7] = rotate_left(T[ 7] + SBOX[T[ 6] % 512], 9); T[ 8] = rotate_left(T[ 8] + SBOX[T[ 7] % 512], 9); T[ 9] = rotate_left(T[ 9] + SBOX[T[ 8] % 512], 9); T[10] = rotate_left(T[10] + SBOX[T[ 9] % 512], 9); T[11] = rotate_left(T[11] + SBOX[T[10] % 512], 9); T[12] = rotate_left(T[12] + SBOX[T[11] % 512], 9); T[13] = rotate_left(T[13] + SBOX[T[12] % 512], 9); T[14] = rotate_left(T[14] + SBOX[T[13] % 512], 9); } EK[10*i + 0] = T[ 0]; EK[10*i + 1] = T[ 4]; EK[10*i + 2] = T[ 8]; EK[10*i + 3] = T[12]; EK[10*i + 4] = T[ 1]; EK[10*i + 5] = T[ 5]; EK[10*i + 6] = T[ 9]; EK[10*i + 7] = T[13]; EK[10*i + 8] = T[ 2]; EK[10*i + 9] = T[ 6]; } for(size_t i = 5; i != 37; i += 2) { const u32bit key3 = EK[i] & 3; EK[i] |= 3; EK[i] ^= rotate_left(SBOX[265 + key3], EK[i-1] % 32) & gen_mask(EK[i]); } } } /* * MISTY1 * (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { namespace { static const byte MISTY1_SBOX_S7[128] = { 0x1B, 0x32, 0x33, 0x5A, 0x3B, 0x10, 0x17, 0x54, 0x5B, 0x1A, 0x72, 0x73, 0x6B, 0x2C, 0x66, 0x49, 0x1F, 0x24, 0x13, 0x6C, 0x37, 0x2E, 0x3F, 0x4A, 0x5D, 0x0F, 0x40, 0x56, 0x25, 0x51, 0x1C, 0x04, 0x0B, 0x46, 0x20, 0x0D, 0x7B, 0x35, 0x44, 0x42, 0x2B, 0x1E, 0x41, 0x14, 0x4B, 0x79, 0x15, 0x6F, 0x0E, 0x55, 0x09, 0x36, 0x74, 0x0C, 0x67, 0x53, 0x28, 0x0A, 0x7E, 0x38, 0x02, 0x07, 0x60, 0x29, 0x19, 0x12, 0x65, 0x2F, 0x30, 0x39, 0x08, 0x68, 0x5F, 0x78, 0x2A, 0x4C, 0x64, 0x45, 0x75, 0x3D, 0x59, 0x48, 0x03, 0x57, 0x7C, 0x4F, 0x62, 0x3C, 0x1D, 0x21, 0x5E, 0x27, 0x6A, 0x70, 0x4D, 0x3A, 0x01, 0x6D, 0x6E, 0x63, 0x18, 0x77, 0x23, 0x05, 0x26, 0x76, 0x00, 0x31, 0x2D, 0x7A, 0x7F, 0x61, 0x50, 0x22, 0x11, 0x06, 0x47, 0x16, 0x52, 0x4E, 0x71, 0x3E, 0x69, 0x43, 0x34, 0x5C, 0x58, 0x7D }; static const u16bit MISTY1_SBOX_S9[512] = { 0x01C3, 0x00CB, 0x0153, 0x019F, 0x01E3, 0x00E9, 0x00FB, 0x0035, 0x0181, 0x00B9, 0x0117, 0x01EB, 0x0133, 0x0009, 0x002D, 0x00D3, 0x00C7, 0x014A, 0x0037, 0x007E, 0x00EB, 0x0164, 0x0193, 0x01D8, 0x00A3, 0x011E, 0x0055, 0x002C, 0x001D, 0x01A2, 0x0163, 0x0118, 0x014B, 0x0152, 0x01D2, 0x000F, 0x002B, 0x0030, 0x013A, 0x00E5, 0x0111, 0x0138, 0x018E, 0x0063, 0x00E3, 0x00C8, 0x01F4, 0x001B, 0x0001, 0x009D, 0x00F8, 0x01A0, 0x016D, 0x01F3, 0x001C, 0x0146, 0x007D, 0x00D1, 0x0082, 0x01EA, 0x0183, 0x012D, 0x00F4, 0x019E, 0x01D3, 0x00DD, 0x01E2, 0x0128, 0x01E0, 0x00EC, 0x0059, 0x0091, 0x0011, 0x012F, 0x0026, 0x00DC, 0x00B0, 0x018C, 0x010F, 0x01F7, 0x00E7, 0x016C, 0x00B6, 0x00F9, 0x00D8, 0x0151, 0x0101, 0x014C, 0x0103, 0x00B8, 0x0154, 0x012B, 0x01AE, 0x0017, 0x0071, 0x000C, 0x0047, 0x0058, 0x007F, 0x01A4, 0x0134, 0x0129, 0x0084, 0x015D, 0x019D, 0x01B2, 0x01A3, 0x0048, 0x007C, 0x0051, 0x01CA, 0x0023, 0x013D, 0x01A7, 0x0165, 0x003B, 0x0042, 0x00DA, 0x0192, 0x00CE, 0x00C1, 0x006B, 0x009F, 0x01F1, 0x012C, 0x0184, 0x00FA, 0x0196, 0x01E1, 0x0169, 0x017D, 0x0031, 0x0180, 0x010A, 0x0094, 0x01DA, 0x0186, 0x013E, 0x011C, 0x0060, 0x0175, 0x01CF, 0x0067, 0x0119, 0x0065, 0x0068, 0x0099, 0x0150, 0x0008, 0x0007, 0x017C, 0x00B7, 0x0024, 0x0019, 0x00DE, 0x0127, 0x00DB, 0x00E4, 0x01A9, 0x0052, 0x0109, 0x0090, 0x019C, 0x01C1, 0x0028, 0x01B3, 0x0135, 0x016A, 0x0176, 0x00DF, 0x01E5, 0x0188, 0x00C5, 0x016E, 0x01DE, 0x01B1, 0x00C3, 0x01DF, 0x0036, 0x00EE, 0x01EE, 0x00F0, 0x0093, 0x0049, 0x009A, 0x01B6, 0x0069, 0x0081, 0x0125, 0x000B, 0x005E, 0x00B4, 0x0149, 0x01C7, 0x0174, 0x003E, 0x013B, 0x01B7, 0x008E, 0x01C6, 0x00AE, 0x0010, 0x0095, 0x01EF, 0x004E, 0x00F2, 0x01FD, 0x0085, 0x00FD, 0x00F6, 0x00A0, 0x016F, 0x0083, 0x008A, 0x0156, 0x009B, 0x013C, 0x0107, 0x0167, 0x0098, 0x01D0, 0x01E9, 0x0003, 0x01FE, 0x00BD, 0x0122, 0x0089, 0x00D2, 0x018F, 0x0012, 0x0033, 0x006A, 0x0142, 0x00ED, 0x0170, 0x011B, 0x00E2, 0x014F, 0x0158, 0x0131, 0x0147, 0x005D, 0x0113, 0x01CD, 0x0079, 0x0161, 0x01A5, 0x0179, 0x009E, 0x01B4, 0x00CC, 0x0022, 0x0132, 0x001A, 0x00E8, 0x0004, 0x0187, 0x01ED, 0x0197, 0x0039, 0x01BF, 0x01D7, 0x0027, 0x018B, 0x00C6, 0x009C, 0x00D0, 0x014E, 0x006C, 0x0034, 0x01F2, 0x006E, 0x00CA, 0x0025, 0x00BA, 0x0191, 0x00FE, 0x0013, 0x0106, 0x002F, 0x01AD, 0x0172, 0x01DB, 0x00C0, 0x010B, 0x01D6, 0x00F5, 0x01EC, 0x010D, 0x0076, 0x0114, 0x01AB, 0x0075, 0x010C, 0x01E4, 0x0159, 0x0054, 0x011F, 0x004B, 0x00C4, 0x01BE, 0x00F7, 0x0029, 0x00A4, 0x000E, 0x01F0, 0x0077, 0x004D, 0x017A, 0x0086, 0x008B, 0x00B3, 0x0171, 0x00BF, 0x010E, 0x0104, 0x0097, 0x015B, 0x0160, 0x0168, 0x00D7, 0x00BB, 0x0066, 0x01CE, 0x00FC, 0x0092, 0x01C5, 0x006F, 0x0016, 0x004A, 0x00A1, 0x0139, 0x00AF, 0x00F1, 0x0190, 0x000A, 0x01AA, 0x0143, 0x017B, 0x0056, 0x018D, 0x0166, 0x00D4, 0x01FB, 0x014D, 0x0194, 0x019A, 0x0087, 0x01F8, 0x0123, 0x00A7, 0x01B8, 0x0141, 0x003C, 0x01F9, 0x0140, 0x002A, 0x0155, 0x011A, 0x01A1, 0x0198, 0x00D5, 0x0126, 0x01AF, 0x0061, 0x012E, 0x0157, 0x01DC, 0x0072, 0x018A, 0x00AA, 0x0096, 0x0115, 0x00EF, 0x0045, 0x007B, 0x008D, 0x0145, 0x0053, 0x005F, 0x0178, 0x00B2, 0x002E, 0x0020, 0x01D5, 0x003F, 0x01C9, 0x01E7, 0x01AC, 0x0044, 0x0038, 0x0014, 0x00B1, 0x016B, 0x00AB, 0x00B5, 0x005A, 0x0182, 0x01C8, 0x01D4, 0x0018, 0x0177, 0x0064, 0x00CF, 0x006D, 0x0100, 0x0199, 0x0130, 0x015A, 0x0005, 0x0120, 0x01BB, 0x01BD, 0x00E0, 0x004F, 0x00D6, 0x013F, 0x01C4, 0x012A, 0x0015, 0x0006, 0x00FF, 0x019B, 0x00A6, 0x0043, 0x0088, 0x0050, 0x015F, 0x01E8, 0x0121, 0x0073, 0x017E, 0x00BC, 0x00C2, 0x00C9, 0x0173, 0x0189, 0x01F5, 0x0074, 0x01CC, 0x01E6, 0x01A8, 0x0195, 0x001F, 0x0041, 0x000D, 0x01BA, 0x0032, 0x003D, 0x01D1, 0x0080, 0x00A8, 0x0057, 0x01B9, 0x0162, 0x0148, 0x00D9, 0x0105, 0x0062, 0x007A, 0x0021, 0x01FF, 0x0112, 0x0108, 0x01C0, 0x00A9, 0x011D, 0x01B0, 0x01A6, 0x00CD, 0x00F3, 0x005C, 0x0102, 0x005B, 0x01D9, 0x0144, 0x01F6, 0x00AD, 0x00A5, 0x003A, 0x01CB, 0x0136, 0x017F, 0x0046, 0x00E1, 0x001E, 0x01DD, 0x00E6, 0x0137, 0x01FA, 0x0185, 0x008C, 0x008F, 0x0040, 0x01B5, 0x00BE, 0x0078, 0x0000, 0x00AC, 0x0110, 0x015E, 0x0124, 0x0002, 0x01BC, 0x00A2, 0x00EA, 0x0070, 0x01FC, 0x0116, 0x015C, 0x004C, 0x01C2 }; /* * MISTY1 FI Function */ u16bit FI(u16bit input, u16bit key7, u16bit key9) { u16bit D9 = input >> 7, D7 = input & 0x7F; D9 = MISTY1_SBOX_S9[D9] ^ D7; D7 = (MISTY1_SBOX_S7[D7] ^ key7 ^ D9) & 0x7F; D9 = MISTY1_SBOX_S9[D9 ^ key9] ^ D7; return static_cast((D7 << 9) | D9); } } /* * MISTY1 Encryption */ void MISTY1::encrypt_n(const byte in[], byte out[], size_t blocks) const { for(size_t i = 0; i != blocks; ++i) { u16bit B0 = load_be(in, 0); u16bit B1 = load_be(in, 1); u16bit B2 = load_be(in, 2); u16bit B3 = load_be(in, 3); for(size_t j = 0; j != 12; j += 3) { const u16bit* RK = &EK[8 * j]; B1 ^= B0 & RK[0]; B0 ^= B1 | RK[1]; B3 ^= B2 & RK[2]; B2 ^= B3 | RK[3]; u32bit T0, T1; 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; B2 ^= T1 ^ RK[13]; B3 ^= 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]; store_be(out, B2, B3, B0, B1); in += BLOCK_SIZE; out += BLOCK_SIZE; } } /* * MISTY1 Decryption */ void MISTY1::decrypt_n(const byte in[], byte out[], size_t blocks) const { for(size_t i = 0; i != blocks; ++i) { u16bit B0 = load_be(in, 2); u16bit B1 = load_be(in, 3); u16bit B2 = load_be(in, 0); u16bit B3 = load_be(in, 1); for(size_t j = 0; j != 12; j += 3) { const u16bit* RK = &DK[8 * j]; B2 ^= B3 | RK[0]; B3 ^= B2 & RK[1]; B0 ^= B1 | RK[2]; B1 ^= B0 & RK[3]; u32bit T0, T1; 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; B0 ^= T1 ^ RK[13]; B1 ^= 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]; store_be(out, B0, B1, B2, B3); in += BLOCK_SIZE; out += BLOCK_SIZE; } } /* * MISTY1 Key Schedule */ void MISTY1::key_schedule(const byte key[], size_t length) { SecureVector KS(32); for(size_t i = 0; i != length / 2; ++i) KS[i] = load_be(key, i); for(size_t i = 0; i != 8; ++i) { KS[i+ 8] = FI(KS[i], KS[(i+1) % 8] >> 9, KS[(i+1) % 8] & 0x1FF); KS[i+16] = KS[i+8] >> 9; KS[i+24] = KS[i+8] & 0x1FF; } /* * Precomputed indexes for the orderings of the subkeys (MISTY1 reuses * values) */ static const byte EK_ORDER[100] = { 0x00, 0x0E, 0x0A, 0x04, 0x00, 0x15, 0x1D, 0x02, 0x11, 0x19, 0x07, 0x13, 0x1B, 0x04, 0x01, 0x16, 0x1E, 0x03, 0x12, 0x1A, 0x00, 0x14, 0x1C, 0x05, 0x01, 0x0F, 0x0B, 0x05, 0x02, 0x17, 0x1F, 0x04, 0x13, 0x1B, 0x01, 0x15, 0x1D, 0x06, 0x03, 0x10, 0x18, 0x05, 0x14, 0x1C, 0x02, 0x16, 0x1E, 0x07, 0x02, 0x08, 0x0C, 0x06, 0x04, 0x11, 0x19, 0x06, 0x15, 0x1D, 0x03, 0x17, 0x1F, 0x00, 0x05, 0x12, 0x1A, 0x07, 0x16, 0x1E, 0x04, 0x10, 0x18, 0x01, 0x03, 0x09, 0x0D, 0x07, 0x06, 0x13, 0x1B, 0x00, 0x17, 0x1F, 0x05, 0x11, 0x19, 0x02, 0x07, 0x14, 0x1C, 0x01, 0x10, 0x18, 0x06, 0x12, 0x1A, 0x03, 0x04, 0x0A, 0x0E, 0x00 }; static const byte DK_ORDER[100] = { 0x00, 0x0E, 0x0A, 0x04, 0x07, 0x14, 0x1C, 0x01, 0x10, 0x18, 0x06, 0x12, 0x1A, 0x03, 0x06, 0x13, 0x1B, 0x00, 0x17, 0x1F, 0x05, 0x11, 0x19, 0x02, 0x07, 0x0D, 0x09, 0x03, 0x05, 0x12, 0x1A, 0x07, 0x16, 0x1E, 0x04, 0x10, 0x18, 0x01, 0x04, 0x11, 0x19, 0x06, 0x15, 0x1D, 0x03, 0x17, 0x1F, 0x00, 0x06, 0x0C, 0x08, 0x02, 0x03, 0x10, 0x18, 0x05, 0x14, 0x1C, 0x02, 0x16, 0x1E, 0x07, 0x02, 0x17, 0x1F, 0x04, 0x13, 0x1B, 0x01, 0x15, 0x1D, 0x06, 0x05, 0x0B, 0x0F, 0x01, 0x01, 0x16, 0x1E, 0x03, 0x12, 0x1A, 0x00, 0x14, 0x1C, 0x05, 0x00, 0x15, 0x1D, 0x02, 0x11, 0x19, 0x07, 0x13, 0x1B, 0x04, 0x04, 0x0A, 0x0E, 0x00 }; for(size_t i = 0; i != 100; ++i) { EK[i] = KS[EK_ORDER[i]]; DK[i] = KS[DK_ORDER[i]]; } } /* * MISTY1 Constructor */ MISTY1::MISTY1(size_t rounds) : EK(100), DK(100) { if(rounds != 8) throw Invalid_Argument("MISTY1: Invalid number of rounds: " + to_string(rounds)); } } /* * Noekeon * (C) 1999-2008 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { namespace { /* * Noekeon's Theta Operation */ inline void theta(u32bit& A0, u32bit& A1, u32bit& A2, u32bit& A3, const u32bit EK[4]) { u32bit T = A0 ^ A2; T ^= rotate_left(T, 8) ^ rotate_right(T, 8); A1 ^= T; A3 ^= T; A0 ^= EK[0]; A1 ^= EK[1]; A2 ^= EK[2]; A3 ^= EK[3]; T = A1 ^ A3; T ^= rotate_left(T, 8) ^ rotate_right(T, 8); A0 ^= T; A2 ^= T; } /* * Theta With Null Key */ inline void theta(u32bit& A0, u32bit& A1, u32bit& A2, u32bit& A3) { u32bit T = A0 ^ A2; T ^= rotate_left(T, 8) ^ rotate_right(T, 8); A1 ^= T; A3 ^= T; T = A1 ^ A3; T ^= rotate_left(T, 8) ^ rotate_right(T, 8); A0 ^= T; A2 ^= T; } /* * Noekeon's Gamma S-Box Layer */ inline void gamma(u32bit& A0, u32bit& A1, u32bit& A2, u32bit& A3) { A1 ^= ~A3 & ~A2; A0 ^= A2 & A1; u32bit T = A3; A3 = A0; A0 = T; A2 ^= A0 ^ A1 ^ A3; A1 ^= ~A3 & ~A2; A0 ^= A2 & A1; } } /* * Noekeon Round Constants */ const byte Noekeon::RC[] = { 0x80, 0x1B, 0x36, 0x6C, 0xD8, 0xAB, 0x4D, 0x9A, 0x2F, 0x5E, 0xBC, 0x63, 0xC6, 0x97, 0x35, 0x6A, 0xD4 }; /* * Noekeon Encryption */ void Noekeon::encrypt_n(const byte in[], byte out[], size_t blocks) const { for(size_t i = 0; i != blocks; ++i) { u32bit A0 = load_be(in, 0); u32bit A1 = load_be(in, 1); u32bit A2 = load_be(in, 2); u32bit A3 = load_be(in, 3); for(size_t j = 0; j != 16; ++j) { A0 ^= RC[j]; theta(A0, A1, A2, A3, &EK[0]); A1 = rotate_left(A1, 1); A2 = rotate_left(A2, 5); A3 = rotate_left(A3, 2); gamma(A0, A1, A2, A3); A1 = rotate_right(A1, 1); A2 = rotate_right(A2, 5); A3 = rotate_right(A3, 2); } A0 ^= RC[16]; theta(A0, A1, A2, A3, &EK[0]); store_be(out, A0, A1, A2, A3); in += BLOCK_SIZE; out += BLOCK_SIZE; } } /* * Noekeon Encryption */ void Noekeon::decrypt_n(const byte in[], byte out[], size_t blocks) const { for(size_t i = 0; i != blocks; ++i) { u32bit A0 = load_be(in, 0); u32bit A1 = load_be(in, 1); u32bit A2 = load_be(in, 2); u32bit A3 = load_be(in, 3); for(size_t j = 16; j != 0; --j) { theta(A0, A1, A2, A3, &DK[0]); A0 ^= RC[j]; A1 = rotate_left(A1, 1); A2 = rotate_left(A2, 5); A3 = rotate_left(A3, 2); gamma(A0, A1, A2, A3); A1 = rotate_right(A1, 1); A2 = rotate_right(A2, 5); A3 = rotate_right(A3, 2); } theta(A0, A1, A2, A3, &DK[0]); A0 ^= RC[0]; store_be(out, A0, A1, A2, A3); in += BLOCK_SIZE; out += BLOCK_SIZE; } } /* * Noekeon Key Schedule */ void Noekeon::key_schedule(const byte key[], size_t) { u32bit A0 = load_be(key, 0); u32bit A1 = load_be(key, 1); u32bit A2 = load_be(key, 2); u32bit A3 = load_be(key, 3); for(size_t i = 0; i != 16; ++i) { A0 ^= RC[i]; theta(A0, A1, A2, A3); A1 = rotate_left(A1, 1); A2 = rotate_left(A2, 5); A3 = rotate_left(A3, 2); gamma(A0, A1, A2, A3); A1 = rotate_right(A1, 1); A2 = rotate_right(A2, 5); A3 = rotate_right(A3, 2); } A0 ^= RC[16]; DK[0] = A0; DK[1] = A1; DK[2] = A2; DK[3] = A3; theta(A0, A1, A2, A3); EK[0] = A0; EK[1] = A1; EK[2] = A2; EK[3] = A3; } /* * Clear memory of sensitive data */ void Noekeon::clear() { zeroise(EK); zeroise(DK); } } /* * Noekeon in SIMD * (C) 2010 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { /* * Noekeon's Theta Operation */ #define NOK_SIMD_THETA(A0, A1, A2, A3, K0, K1, K2, K3) \ do { \ SIMD_32 T = A0 ^ A2; \ SIMD_32 T_l8 = T; \ SIMD_32 T_r8 = T; \ T_l8.rotate_left(8); \ T_r8.rotate_right(8); \ T ^= T_l8; \ T ^= T_r8; \ A1 ^= T; \ A3 ^= T; \ \ A0 ^= K0; \ A1 ^= K1; \ A2 ^= K2; \ A3 ^= K3; \ \ T = A1 ^ A3; \ T_l8 = T; \ T_r8 = T; \ T_l8.rotate_left(8); \ T_r8.rotate_right(8); \ T ^= T_l8; \ T ^= T_r8; \ A0 ^= T; \ A2 ^= T; \ } while(0) /* * Noekeon's Gamma S-Box Layer */ #define NOK_SIMD_GAMMA(A0, A1, A2, A3) \ do \ { \ A1 ^= A3.andc(~A2); \ A0 ^= A2 & A1; \ \ SIMD_32 T = A3; \ A3 = A0; \ A0 = T; \ \ A2 ^= A0 ^ A1 ^ A3; \ \ A1 ^= A3.andc(~A2); \ A0 ^= A2 & A1; \ } while(0) /* * Noekeon Encryption */ void Noekeon_SIMD::encrypt_n(const byte in[], byte out[], size_t blocks) const { const SecureVector& EK = this->get_EK(); SIMD_32 K0 = SIMD_32(EK[0]); SIMD_32 K1 = SIMD_32(EK[1]); SIMD_32 K2 = SIMD_32(EK[2]); SIMD_32 K3 = SIMD_32(EK[3]); while(blocks >= 4) { SIMD_32 A0 = SIMD_32::load_be(in ); SIMD_32 A1 = SIMD_32::load_be(in + 16); SIMD_32 A2 = SIMD_32::load_be(in + 32); SIMD_32 A3 = SIMD_32::load_be(in + 48); SIMD_32::transpose(A0, A1, A2, A3); for(size_t i = 0; i != 16; ++i) { A0 ^= SIMD_32(RC[i]); NOK_SIMD_THETA(A0, A1, A2, A3, K0, K1, K2, K3); A1.rotate_left(1); A2.rotate_left(5); A3.rotate_left(2); NOK_SIMD_GAMMA(A0, A1, A2, A3); A1.rotate_right(1); A2.rotate_right(5); A3.rotate_right(2); } A0 ^= SIMD_32(RC[16]); NOK_SIMD_THETA(A0, A1, A2, A3, K0, K1, K2, K3); SIMD_32::transpose(A0, A1, A2, A3); A0.store_be(out); A1.store_be(out + 16); A2.store_be(out + 32); A3.store_be(out + 48); in += 64; out += 64; blocks -= 4; } if(blocks) Noekeon::encrypt_n(in, out, blocks); } /* * Noekeon Encryption */ void Noekeon_SIMD::decrypt_n(const byte in[], byte out[], size_t blocks) const { const SecureVector& DK = this->get_DK(); SIMD_32 K0 = SIMD_32(DK[0]); SIMD_32 K1 = SIMD_32(DK[1]); SIMD_32 K2 = SIMD_32(DK[2]); SIMD_32 K3 = SIMD_32(DK[3]); while(blocks >= 4) { SIMD_32 A0 = SIMD_32::load_be(in ); SIMD_32 A1 = SIMD_32::load_be(in + 16); SIMD_32 A2 = SIMD_32::load_be(in + 32); SIMD_32 A3 = SIMD_32::load_be(in + 48); SIMD_32::transpose(A0, A1, A2, A3); for(size_t i = 0; i != 16; ++i) { NOK_SIMD_THETA(A0, A1, A2, A3, K0, K1, K2, K3); A0 ^= SIMD_32(RC[16-i]); A1.rotate_left(1); A2.rotate_left(5); A3.rotate_left(2); NOK_SIMD_GAMMA(A0, A1, A2, A3); A1.rotate_right(1); A2.rotate_right(5); A3.rotate_right(2); } NOK_SIMD_THETA(A0, A1, A2, A3, K0, K1, K2, K3); A0 ^= SIMD_32(RC[0]); SIMD_32::transpose(A0, A1, A2, A3); A0.store_be(out); A1.store_be(out + 16); A2.store_be(out + 32); A3.store_be(out + 48); in += 64; out += 64; blocks -= 4; } if(blocks) Noekeon::decrypt_n(in, out, blocks); } } /* * RC2 * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { /* * RC2 Encryption */ void RC2::encrypt_n(const byte in[], byte out[], size_t blocks) const { for(size_t i = 0; i != blocks; ++i) { u16bit R0 = load_le(in, 0); u16bit R1 = load_le(in, 1); u16bit R2 = load_le(in, 2); u16bit R3 = load_le(in, 3); for(size_t 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); 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); 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); in += BLOCK_SIZE; out += BLOCK_SIZE; } } /* * RC2 Decryption */ void RC2::decrypt_n(const byte in[], byte out[], size_t blocks) const { for(size_t i = 0; i != blocks; ++i) { u16bit R0 = load_le(in, 0); u16bit R1 = load_le(in, 1); u16bit R2 = load_le(in, 2); u16bit R3 = load_le(in, 3); for(size_t 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)]; 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)]; 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); in += BLOCK_SIZE; out += BLOCK_SIZE; } } /* * RC2 Key Schedule */ void RC2::key_schedule(const byte key[], size_t length) { static const byte TABLE[256] = { 0xD9, 0x78, 0xF9, 0xC4, 0x19, 0xDD, 0xB5, 0xED, 0x28, 0xE9, 0xFD, 0x79, 0x4A, 0xA0, 0xD8, 0x9D, 0xC6, 0x7E, 0x37, 0x83, 0x2B, 0x76, 0x53, 0x8E, 0x62, 0x4C, 0x64, 0x88, 0x44, 0x8B, 0xFB, 0xA2, 0x17, 0x9A, 0x59, 0xF5, 0x87, 0xB3, 0x4F, 0x13, 0x61, 0x45, 0x6D, 0x8D, 0x09, 0x81, 0x7D, 0x32, 0xBD, 0x8F, 0x40, 0xEB, 0x86, 0xB7, 0x7B, 0x0B, 0xF0, 0x95, 0x21, 0x22, 0x5C, 0x6B, 0x4E, 0x82, 0x54, 0xD6, 0x65, 0x93, 0xCE, 0x60, 0xB2, 0x1C, 0x73, 0x56, 0xC0, 0x14, 0xA7, 0x8C, 0xF1, 0xDC, 0x12, 0x75, 0xCA, 0x1F, 0x3B, 0xBE, 0xE4, 0xD1, 0x42, 0x3D, 0xD4, 0x30, 0xA3, 0x3C, 0xB6, 0x26, 0x6F, 0xBF, 0x0E, 0xDA, 0x46, 0x69, 0x07, 0x57, 0x27, 0xF2, 0x1D, 0x9B, 0xBC, 0x94, 0x43, 0x03, 0xF8, 0x11, 0xC7, 0xF6, 0x90, 0xEF, 0x3E, 0xE7, 0x06, 0xC3, 0xD5, 0x2F, 0xC8, 0x66, 0x1E, 0xD7, 0x08, 0xE8, 0xEA, 0xDE, 0x80, 0x52, 0xEE, 0xF7, 0x84, 0xAA, 0x72, 0xAC, 0x35, 0x4D, 0x6A, 0x2A, 0x96, 0x1A, 0xD2, 0x71, 0x5A, 0x15, 0x49, 0x74, 0x4B, 0x9F, 0xD0, 0x5E, 0x04, 0x18, 0xA4, 0xEC, 0xC2, 0xE0, 0x41, 0x6E, 0x0F, 0x51, 0xCB, 0xCC, 0x24, 0x91, 0xAF, 0x50, 0xA1, 0xF4, 0x70, 0x39, 0x99, 0x7C, 0x3A, 0x85, 0x23, 0xB8, 0xB4, 0x7A, 0xFC, 0x02, 0x36, 0x5B, 0x25, 0x55, 0x97, 0x31, 0x2D, 0x5D, 0xFA, 0x98, 0xE3, 0x8A, 0x92, 0xAE, 0x05, 0xDF, 0x29, 0x10, 0x67, 0x6C, 0xBA, 0xC9, 0xD3, 0x00, 0xE6, 0xCF, 0xE1, 0x9E, 0xA8, 0x2C, 0x63, 0x16, 0x01, 0x3F, 0x58, 0xE2, 0x89, 0xA9, 0x0D, 0x38, 0x34, 0x1B, 0xAB, 0x33, 0xFF, 0xB0, 0xBB, 0x48, 0x0C, 0x5F, 0xB9, 0xB1, 0xCD, 0x2E, 0xC5, 0xF3, 0xDB, 0x47, 0xE5, 0xA5, 0x9C, 0x77, 0x0A, 0xA6, 0x20, 0x68, 0xFE, 0x7F, 0xC1, 0xAD }; SecureVector L(128); L.copy(key, length); for(size_t i = length; i != 128; ++i) L[i] = TABLE[(L[i-1] + L[i-length]) % 256]; L[128-length] = TABLE[L[128-length]]; for(s32bit i = 127-length; i >= 0; --i) L[i] = TABLE[L[i+1] ^ L[i+length]]; load_le(&K[0], &L[0], 64); } /* * Return the code of the effective key bits */ byte RC2::EKB_code(size_t ekb) { const byte EKB[256] = { 0xBD, 0x56, 0xEA, 0xF2, 0xA2, 0xF1, 0xAC, 0x2A, 0xB0, 0x93, 0xD1, 0x9C, 0x1B, 0x33, 0xFD, 0xD0, 0x30, 0x04, 0xB6, 0xDC, 0x7D, 0xDF, 0x32, 0x4B, 0xF7, 0xCB, 0x45, 0x9B, 0x31, 0xBB, 0x21, 0x5A, 0x41, 0x9F, 0xE1, 0xD9, 0x4A, 0x4D, 0x9E, 0xDA, 0xA0, 0x68, 0x2C, 0xC3, 0x27, 0x5F, 0x80, 0x36, 0x3E, 0xEE, 0xFB, 0x95, 0x1A, 0xFE, 0xCE, 0xA8, 0x34, 0xA9, 0x13, 0xF0, 0xA6, 0x3F, 0xD8, 0x0C, 0x78, 0x24, 0xAF, 0x23, 0x52, 0xC1, 0x67, 0x17, 0xF5, 0x66, 0x90, 0xE7, 0xE8, 0x07, 0xB8, 0x60, 0x48, 0xE6, 0x1E, 0x53, 0xF3, 0x92, 0xA4, 0x72, 0x8C, 0x08, 0x15, 0x6E, 0x86, 0x00, 0x84, 0xFA, 0xF4, 0x7F, 0x8A, 0x42, 0x19, 0xF6, 0xDB, 0xCD, 0x14, 0x8D, 0x50, 0x12, 0xBA, 0x3C, 0x06, 0x4E, 0xEC, 0xB3, 0x35, 0x11, 0xA1, 0x88, 0x8E, 0x2B, 0x94, 0x99, 0xB7, 0x71, 0x74, 0xD3, 0xE4, 0xBF, 0x3A, 0xDE, 0x96, 0x0E, 0xBC, 0x0A, 0xED, 0x77, 0xFC, 0x37, 0x6B, 0x03, 0x79, 0x89, 0x62, 0xC6, 0xD7, 0xC0, 0xD2, 0x7C, 0x6A, 0x8B, 0x22, 0xA3, 0x5B, 0x05, 0x5D, 0x02, 0x75, 0xD5, 0x61, 0xE3, 0x18, 0x8F, 0x55, 0x51, 0xAD, 0x1F, 0x0B, 0x5E, 0x85, 0xE5, 0xC2, 0x57, 0x63, 0xCA, 0x3D, 0x6C, 0xB4, 0xC5, 0xCC, 0x70, 0xB2, 0x91, 0x59, 0x0D, 0x47, 0x20, 0xC8, 0x4F, 0x58, 0xE0, 0x01, 0xE2, 0x16, 0x38, 0xC4, 0x6F, 0x3B, 0x0F, 0x65, 0x46, 0xBE, 0x7E, 0x2D, 0x7B, 0x82, 0xF9, 0x40, 0xB5, 0x1D, 0x73, 0xF8, 0xEB, 0x26, 0xC7, 0x87, 0x97, 0x25, 0x54, 0xB1, 0x28, 0xAA, 0x98, 0x9D, 0xA5, 0x64, 0x6D, 0x7A, 0xD4, 0x10, 0x81, 0x44, 0xEF, 0x49, 0xD6, 0xAE, 0x2E, 0xDD, 0x76, 0x5C, 0x2F, 0xA7, 0x1C, 0xC9, 0x09, 0x69, 0x9A, 0x83, 0xCF, 0x29, 0x39, 0xB9, 0xE9, 0x4C, 0xFF, 0x43, 0xAB }; if(ekb < 256) return EKB[ekb]; else throw Encoding_Error("RC2::EKB_code: EKB is too large"); } } /* * RC5 * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ #include namespace Botan { /* * RC5 Encryption */ void RC5::encrypt_n(const byte in[], byte out[], size_t blocks) const { const size_t rounds = (S.size() - 2) / 2; for(size_t i = 0; i != blocks; ++i) { u32bit A = load_le(in, 0); u32bit B = load_le(in, 1); A += S[0]; B += S[1]; for(size_t 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); in += BLOCK_SIZE; out += BLOCK_SIZE; } } /* * RC5 Decryption */ void RC5::decrypt_n(const byte in[], byte out[], size_t blocks) const { const size_t rounds = (S.size() - 2) / 2; for(size_t i = 0; i != blocks; ++i) { u32bit A = load_le(in, 0); u32bit B = load_le(in, 1); for(size_t 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); in += BLOCK_SIZE; out += BLOCK_SIZE; } } /* * RC5 Key Schedule */ void RC5::key_schedule(const byte key[], size_t length) { const size_t WORD_KEYLENGTH = (((length - 1) / 4) + 1); const size_t MIX_ROUNDS = 3 * std::max(WORD_KEYLENGTH, S.size()); S[0] = 0xB7E15163; for(size_t i = 1; i != S.size(); ++i) S[i] = S[i-1] + 0x9E3779B9; SecureVector K(8); for(s32bit i = length-1; i >= 0; --i) K[i/4] = (K[i/4] << 8) + key[i]; u32bit A = 0, B = 0; for(size_t i = 0; i != MIX_ROUNDS; ++i) { A = rotate_left(S[i % S.size()] + A + B, 3); B = rotate_left(K[i % WORD_KEYLENGTH] + A + B, (A + B) % 32); S[i % S.size()] = A; K[i % WORD_KEYLENGTH] = B; } } /* * Return the name of this type */ std::string RC5::name() const { return "RC5(" + to_string(get_rounds()) + ")"; } /* * RC5 Constructor */ RC5::RC5(size_t rounds) { if(rounds < 8 || rounds > 32 || (rounds % 4 != 0)) throw Invalid_Argument("RC5: Invalid number of rounds " + to_string(rounds)); S.resize(2*rounds + 2); } } /* * RC6 * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ #include namespace Botan { /* * RC6 Encryption */ void RC6::encrypt_n(const byte in[], byte out[], size_t blocks) const { for(size_t i = 0; i != blocks; ++i) { u32bit A = load_le(in, 0); u32bit B = load_le(in, 1); u32bit C = load_le(in, 2); u32bit D = load_le(in, 3); B += S[0]; D += S[1]; for(size_t 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]; } A += S[42]; C += S[43]; store_le(out, A, B, C, D); in += BLOCK_SIZE; out += BLOCK_SIZE; } } /* * RC6 Decryption */ void RC6::decrypt_n(const byte in[], byte out[], size_t blocks) const { for(size_t i = 0; i != blocks; ++i) { u32bit A = load_le(in, 0); u32bit B = load_le(in, 1); u32bit C = load_le(in, 2); u32bit D = load_le(in, 3); C -= S[43]; A -= S[42]; for(size_t 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; } D -= S[1]; B -= S[0]; store_le(out, A, B, C, D); in += BLOCK_SIZE; out += BLOCK_SIZE; } } /* * RC6 Key Schedule */ void RC6::key_schedule(const byte key[], size_t length) { const size_t WORD_KEYLENGTH = (((length - 1) / 4) + 1); const size_t MIX_ROUNDS = 3 * std::max(WORD_KEYLENGTH, S.size()); S[0] = 0xB7E15163; for(size_t i = 1; i != S.size(); ++i) S[i] = S[i-1] + 0x9E3779B9; SecureVector K(8); for(s32bit i = length-1; i >= 0; --i) K[i/4] = (K[i/4] << 8) + key[i]; u32bit A = 0, B = 0; for(size_t i = 0; i != MIX_ROUNDS; ++i) { A = rotate_left(S[i % S.size()] + A + B, 3); B = rotate_left(K[i % WORD_KEYLENGTH] + A + B, (A + B) % 32); S[i % S.size()] = A; K[i % WORD_KEYLENGTH] = B; } } } /* * SAFER-SK * (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { namespace { const byte EXP[256] = { 0x01, 0x2D, 0xE2, 0x93, 0xBE, 0x45, 0x15, 0xAE, 0x78, 0x03, 0x87, 0xA4, 0xB8, 0x38, 0xCF, 0x3F, 0x08, 0x67, 0x09, 0x94, 0xEB, 0x26, 0xA8, 0x6B, 0xBD, 0x18, 0x34, 0x1B, 0xBB, 0xBF, 0x72, 0xF7, 0x40, 0x35, 0x48, 0x9C, 0x51, 0x2F, 0x3B, 0x55, 0xE3, 0xC0, 0x9F, 0xD8, 0xD3, 0xF3, 0x8D, 0xB1, 0xFF, 0xA7, 0x3E, 0xDC, 0x86, 0x77, 0xD7, 0xA6, 0x11, 0xFB, 0xF4, 0xBA, 0x92, 0x91, 0x64, 0x83, 0xF1, 0x33, 0xEF, 0xDA, 0x2C, 0xB5, 0xB2, 0x2B, 0x88, 0xD1, 0x99, 0xCB, 0x8C, 0x84, 0x1D, 0x14, 0x81, 0x97, 0x71, 0xCA, 0x5F, 0xA3, 0x8B, 0x57, 0x3C, 0x82, 0xC4, 0x52, 0x5C, 0x1C, 0xE8, 0xA0, 0x04, 0xB4, 0x85, 0x4A, 0xF6, 0x13, 0x54, 0xB6, 0xDF, 0x0C, 0x1A, 0x8E, 0xDE, 0xE0, 0x39, 0xFC, 0x20, 0x9B, 0x24, 0x4E, 0xA9, 0x98, 0x9E, 0xAB, 0xF2, 0x60, 0xD0, 0x6C, 0xEA, 0xFA, 0xC7, 0xD9, 0x00, 0xD4, 0x1F, 0x6E, 0x43, 0xBC, 0xEC, 0x53, 0x89, 0xFE, 0x7A, 0x5D, 0x49, 0xC9, 0x32, 0xC2, 0xF9, 0x9A, 0xF8, 0x6D, 0x16, 0xDB, 0x59, 0x96, 0x44, 0xE9, 0xCD, 0xE6, 0x46, 0x42, 0x8F, 0x0A, 0xC1, 0xCC, 0xB9, 0x65, 0xB0, 0xD2, 0xC6, 0xAC, 0x1E, 0x41, 0x62, 0x29, 0x2E, 0x0E, 0x74, 0x50, 0x02, 0x5A, 0xC3, 0x25, 0x7B, 0x8A, 0x2A, 0x5B, 0xF0, 0x06, 0x0D, 0x47, 0x6F, 0x70, 0x9D, 0x7E, 0x10, 0xCE, 0x12, 0x27, 0xD5, 0x4C, 0x4F, 0xD6, 0x79, 0x30, 0x68, 0x36, 0x75, 0x7D, 0xE4, 0xED, 0x80, 0x6A, 0x90, 0x37, 0xA2, 0x5E, 0x76, 0xAA, 0xC5, 0x7F, 0x3D, 0xAF, 0xA5, 0xE5, 0x19, 0x61, 0xFD, 0x4D, 0x7C, 0xB7, 0x0B, 0xEE, 0xAD, 0x4B, 0x22, 0xF5, 0xE7, 0x73, 0x23, 0x21, 0xC8, 0x05, 0xE1, 0x66, 0xDD, 0xB3, 0x58, 0x69, 0x63, 0x56, 0x0F, 0xA1, 0x31, 0x95, 0x17, 0x07, 0x3A, 0x28 }; const byte LOG[512] = { 0x80, 0x00, 0xB0, 0x09, 0x60, 0xEF, 0xB9, 0xFD, 0x10, 0x12, 0x9F, 0xE4, 0x69, 0xBA, 0xAD, 0xF8, 0xC0, 0x38, 0xC2, 0x65, 0x4F, 0x06, 0x94, 0xFC, 0x19, 0xDE, 0x6A, 0x1B, 0x5D, 0x4E, 0xA8, 0x82, 0x70, 0xED, 0xE8, 0xEC, 0x72, 0xB3, 0x15, 0xC3, 0xFF, 0xAB, 0xB6, 0x47, 0x44, 0x01, 0xAC, 0x25, 0xC9, 0xFA, 0x8E, 0x41, 0x1A, 0x21, 0xCB, 0xD3, 0x0D, 0x6E, 0xFE, 0x26, 0x58, 0xDA, 0x32, 0x0F, 0x20, 0xA9, 0x9D, 0x84, 0x98, 0x05, 0x9C, 0xBB, 0x22, 0x8C, 0x63, 0xE7, 0xC5, 0xE1, 0x73, 0xC6, 0xAF, 0x24, 0x5B, 0x87, 0x66, 0x27, 0xF7, 0x57, 0xF4, 0x96, 0xB1, 0xB7, 0x5C, 0x8B, 0xD5, 0x54, 0x79, 0xDF, 0xAA, 0xF6, 0x3E, 0xA3, 0xF1, 0x11, 0xCA, 0xF5, 0xD1, 0x17, 0x7B, 0x93, 0x83, 0xBC, 0xBD, 0x52, 0x1E, 0xEB, 0xAE, 0xCC, 0xD6, 0x35, 0x08, 0xC8, 0x8A, 0xB4, 0xE2, 0xCD, 0xBF, 0xD9, 0xD0, 0x50, 0x59, 0x3F, 0x4D, 0x62, 0x34, 0x0A, 0x48, 0x88, 0xB5, 0x56, 0x4C, 0x2E, 0x6B, 0x9E, 0xD2, 0x3D, 0x3C, 0x03, 0x13, 0xFB, 0x97, 0x51, 0x75, 0x4A, 0x91, 0x71, 0x23, 0xBE, 0x76, 0x2A, 0x5F, 0xF9, 0xD4, 0x55, 0x0B, 0xDC, 0x37, 0x31, 0x16, 0x74, 0xD7, 0x77, 0xA7, 0xE6, 0x07, 0xDB, 0xA4, 0x2F, 0x46, 0xF3, 0x61, 0x45, 0x67, 0xE3, 0x0C, 0xA2, 0x3B, 0x1C, 0x85, 0x18, 0x04, 0x1D, 0x29, 0xA0, 0x8F, 0xB2, 0x5A, 0xD8, 0xA6, 0x7E, 0xEE, 0x8D, 0x53, 0x4B, 0xA1, 0x9A, 0xC1, 0x0E, 0x7A, 0x49, 0xA5, 0x2C, 0x81, 0xC4, 0xC7, 0x36, 0x2B, 0x7F, 0x43, 0x95, 0x33, 0xF2, 0x6C, 0x68, 0x6D, 0xF0, 0x02, 0x28, 0xCE, 0xDD, 0x9B, 0xEA, 0x5E, 0x99, 0x7C, 0x14, 0x86, 0xCF, 0xE5, 0x42, 0xB8, 0x40, 0x78, 0x2D, 0x3A, 0xE9, 0x64, 0x1F, 0x92, 0x90, 0x7D, 0x39, 0x6F, 0xE0, 0x89, 0x30, 0x80, 0x00, 0xB0, 0x09, 0x60, 0xEF, 0xB9, 0xFD, 0x10, 0x12, 0x9F, 0xE4, 0x69, 0xBA, 0xAD, 0xF8, 0xC0, 0x38, 0xC2, 0x65, 0x4F, 0x06, 0x94, 0xFC, 0x19, 0xDE, 0x6A, 0x1B, 0x5D, 0x4E, 0xA8, 0x82, 0x70, 0xED, 0xE8, 0xEC, 0x72, 0xB3, 0x15, 0xC3, 0xFF, 0xAB, 0xB6, 0x47, 0x44, 0x01, 0xAC, 0x25, 0xC9, 0xFA, 0x8E, 0x41, 0x1A, 0x21, 0xCB, 0xD3, 0x0D, 0x6E, 0xFE, 0x26, 0x58, 0xDA, 0x32, 0x0F, 0x20, 0xA9, 0x9D, 0x84, 0x98, 0x05, 0x9C, 0xBB, 0x22, 0x8C, 0x63, 0xE7, 0xC5, 0xE1, 0x73, 0xC6, 0xAF, 0x24, 0x5B, 0x87, 0x66, 0x27, 0xF7, 0x57, 0xF4, 0x96, 0xB1, 0xB7, 0x5C, 0x8B, 0xD5, 0x54, 0x79, 0xDF, 0xAA, 0xF6, 0x3E, 0xA3, 0xF1, 0x11, 0xCA, 0xF5, 0xD1, 0x17, 0x7B, 0x93, 0x83, 0xBC, 0xBD, 0x52, 0x1E, 0xEB, 0xAE, 0xCC, 0xD6, 0x35, 0x08, 0xC8, 0x8A, 0xB4, 0xE2, 0xCD, 0xBF, 0xD9, 0xD0, 0x50, 0x59, 0x3F, 0x4D, 0x62, 0x34, 0x0A, 0x48, 0x88, 0xB5, 0x56, 0x4C, 0x2E, 0x6B, 0x9E, 0xD2, 0x3D, 0x3C, 0x03, 0x13, 0xFB, 0x97, 0x51, 0x75, 0x4A, 0x91, 0x71, 0x23, 0xBE, 0x76, 0x2A, 0x5F, 0xF9, 0xD4, 0x55, 0x0B, 0xDC, 0x37, 0x31, 0x16, 0x74, 0xD7, 0x77, 0xA7, 0xE6, 0x07, 0xDB, 0xA4, 0x2F, 0x46, 0xF3, 0x61, 0x45, 0x67, 0xE3, 0x0C, 0xA2, 0x3B, 0x1C, 0x85, 0x18, 0x04, 0x1D, 0x29, 0xA0, 0x8F, 0xB2, 0x5A, 0xD8, 0xA6, 0x7E, 0xEE, 0x8D, 0x53, 0x4B, 0xA1, 0x9A, 0xC1, 0x0E, 0x7A, 0x49, 0xA5, 0x2C, 0x81, 0xC4, 0xC7, 0x36, 0x2B, 0x7F, 0x43, 0x95, 0x33, 0xF2, 0x6C, 0x68, 0x6D, 0xF0, 0x02, 0x28, 0xCE, 0xDD, 0x9B, 0xEA, 0x5E, 0x99, 0x7C, 0x14, 0x86, 0xCF, 0xE5, 0x42, 0xB8, 0x40, 0x78, 0x2D, 0x3A, 0xE9, 0x64, 0x1F, 0x92, 0x90, 0x7D, 0x39, 0x6F, 0xE0, 0x89, 0x30 }; } /* * SAFER-SK Encryption */ void SAFER_SK::encrypt_n(const byte in[], byte out[], size_t blocks) const { const size_t rounds = get_rounds(); for(size_t i = 0; i != blocks; ++i) { 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(size_t 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; } } /* * SAFER-SK Decryption */ void SAFER_SK::decrypt_n(const byte in[], byte out[], size_t blocks) const { const size_t rounds = get_rounds(); for(size_t i = 0; i != blocks; ++i) { 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; } } /* * SAFER-SK Key Schedule */ void SAFER_SK::key_schedule(const byte key[], size_t) { const byte BIAS[208] = { 0x16, 0x73, 0x3B, 0x1E, 0x8E, 0x70, 0xBD, 0x86, 0x47, 0x7E, 0x24, 0x56, 0xF1, 0x77, 0x88, 0x46, 0xB1, 0xBA, 0xA3, 0xB7, 0x10, 0x0A, 0xC5, 0x37, 0xC9, 0x5A, 0x28, 0xAC, 0x64, 0xA5, 0xEC, 0xAB, 0xC6, 0x67, 0x95, 0x58, 0x0D, 0xF8, 0x9A, 0xF6, 0x66, 0xDC, 0x05, 0x3D, 0xD3, 0x8A, 0xC3, 0xD8, 0x6A, 0xE9, 0x36, 0x49, 0x43, 0xBF, 0xEB, 0xD4, 0x9B, 0x68, 0xA0, 0x65, 0x5D, 0x57, 0x92, 0x1F, 0x71, 0x5C, 0xBB, 0x22, 0xC1, 0xBE, 0x7B, 0xBC, 0x63, 0x94, 0x5F, 0x2A, 0x61, 0xB8, 0x34, 0x32, 0xFD, 0xFB, 0x17, 0x40, 0xE6, 0x51, 0x1D, 0x41, 0x8F, 0x29, 0xDD, 0x04, 0x80, 0xDE, 0xE7, 0x31, 0x7F, 0x01, 0xA2, 0xF7, 0x39, 0xDA, 0x6F, 0x23, 0xFE, 0x3A, 0xD0, 0x1C, 0xD1, 0x30, 0x3E, 0x12, 0xCD, 0x0F, 0xE0, 0xA8, 0xAF, 0x82, 0x59, 0x2C, 0x7D, 0xAD, 0xB2, 0xEF, 0xC2, 0x87, 0xCE, 0x75, 0x13, 0x02, 0x90, 0x4F, 0x2E, 0x72, 0x33, 0x85, 0x8D, 0xCF, 0xA9, 0x81, 0xE2, 0xC4, 0x27, 0x2F, 0x7A, 0x9F, 0x52, 0xE1, 0x15, 0x38, 0x2B, 0xFC, 0x42, 0xC7, 0x08, 0xE4, 0x09, 0x55, 0x5E, 0x8C, 0x76, 0x60, 0xFF, 0xDF, 0xD7, 0x98, 0xFA, 0x0B, 0x00, 0x1A, 0xF9, 0xA6, 0xB9, 0xE8, 0x9E, 0x62, 0xD9, 0x91, 0x50, 0xD2, 0xEE, 0x18, 0xB4, 0x07, 0xEA, 0x5B, 0xA4, 0xC8, 0x0E, 0xCB, 0x48, 0x69, 0x4E, 0x9C, 0x35, 0x79, 0x45, 0x4D, 0x54, 0xE5, 0x3C, 0x0C, 0x4A, 0x8B, 0x3F, 0xCC, 0xA7, 0xDB }; const byte KEY_INDEX[208] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x09, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, 0x01, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x09, 0x0A, 0x0B, 0x05, 0x06, 0x07, 0x08, 0x00, 0x01, 0x02, 0x03, 0x0F, 0x10, 0x11, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x07, 0x08, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x11, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x09, 0x0A, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, 0x01, 0x02, 0x0E, 0x0F, 0x10, 0x11, 0x09, 0x0A, 0x0B, 0x0C, 0x06, 0x07, 0x08, 0x00, 0x01, 0x02, 0x03, 0x04, 0x10, 0x11, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x08, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x09, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, 0x01, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x09, 0x0A, 0x0B, 0x05, 0x06, 0x07, 0x08, 0x00, 0x01, 0x02, 0x03, 0x0F, 0x10, 0x11, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x07, 0x08, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x11, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }; SecureVector KB(18); for(size_t i = 0; i != 8; ++i) { KB[ 8] ^= KB[i] = rotate_left(key[i], 5); KB[17] ^= KB[i+9] = EK[i] = key[i+8]; } for(size_t i = 0; i != get_rounds(); ++i) { for(size_t j = 0; j != 18; ++j) KB[j] = rotate_left(KB[j], 6); for(size_t j = 0; j != 16; ++j) EK[16*i+j+8] = KB[KEY_INDEX[16*i+j]] + BIAS[16*i+j]; } } /* * Return the name of this type */ std::string SAFER_SK::name() const { return "SAFER-SK(" + to_string(get_rounds()) + ")"; } /* * Return a clone of this object */ BlockCipher* SAFER_SK::clone() const { return new SAFER_SK(get_rounds()); } /* * SAFER-SK Constructor */ SAFER_SK::SAFER_SK(size_t rounds) { if(rounds > 13 || rounds == 0) throw Invalid_Argument(name() + ": Invalid number of rounds"); EK.resize(16 * rounds + 8); } } /* * SEED * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { /* * SEED G Function */ u32bit SEED::G_FUNC::operator()(u32bit X) const { return (S0[get_byte(3, X)] ^ S1[get_byte(2, X)] ^ S2[get_byte(1, X)] ^ S3[get_byte(0, X)]); } /* * SEED Encryption */ void SEED::encrypt_n(const byte in[], byte out[], size_t blocks) const { for(size_t i = 0; i != blocks; ++i) { u32bit B0 = load_be(in, 0); u32bit B1 = load_be(in, 1); u32bit B2 = load_be(in, 2); u32bit B3 = load_be(in, 3); G_FUNC G; for(size_t 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; } } /* * SEED Decryption */ void SEED::decrypt_n(const byte in[], byte out[], size_t blocks) const { for(size_t i = 0; i != blocks; ++i) { u32bit B0 = load_be(in, 0); u32bit B1 = load_be(in, 1); u32bit B2 = load_be(in, 2); u32bit B3 = load_be(in, 3); G_FUNC G; for(size_t 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; } } /* * SEED Key Schedule */ void SEED::key_schedule(const byte key[], size_t) { const u32bit RC[16] = { 0x9E3779B9, 0x3C6EF373, 0x78DDE6E6, 0xF1BBCDCC, 0xE3779B99, 0xC6EF3733, 0x8DDE6E67, 0x1BBCDCCF, 0x3779B99E, 0x6EF3733C, 0xDDE6E678, 0xBBCDCCF1, 0x779B99E3, 0xEF3733C6, 0xDE6E678D, 0xBCDCCF1B }; SecureVector WK(4); for(size_t i = 0; i != 4; ++i) WK[i] = load_be(key, i); G_FUNC G; for(size_t i = 0; i != 16; i += 2) { K[2*i ] = G(WK[0] + WK[2] - RC[i]); K[2*i+1] = G(WK[1] - WK[3] + RC[i]) ^ K[2*i]; byte T = get_byte(3, WK[0]); WK[0] = (WK[0] >> 8) | (get_byte(3, WK[1]) << 24); WK[1] = (WK[1] >> 8) | (T << 24); K[2*i+2] = G(WK[0] + WK[2] - RC[i+1]); K[2*i+3] = G(WK[1] - WK[3] + RC[i+1]) ^ K[2*i+2]; T = get_byte(0, WK[3]); WK[3] = (WK[3] << 8) | get_byte(0, WK[2]); WK[2] = (WK[2] << 8) | T; } } } /* * S-Box Tables for SEED * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { const u32bit SEED::G_FUNC::S0[256] = { 0x2989A1A8, 0x05858184, 0x16C6D2D4, 0x13C3D3D0, 0x14445054, 0x1D0D111C, 0x2C8CA0AC, 0x25052124, 0x1D4D515C, 0x03434340, 0x18081018, 0x1E0E121C, 0x11415150, 0x3CCCF0FC, 0x0ACAC2C8, 0x23436360, 0x28082028, 0x04444044, 0x20002020, 0x1D8D919C, 0x20C0E0E0, 0x22C2E2E0, 0x08C8C0C8, 0x17071314, 0x2585A1A4, 0x0F8F838C, 0x03030300, 0x3B4B7378, 0x3B8BB3B8, 0x13031310, 0x12C2D2D0, 0x2ECEE2EC, 0x30407070, 0x0C8C808C, 0x3F0F333C, 0x2888A0A8, 0x32023230, 0x1DCDD1DC, 0x36C6F2F4, 0x34447074, 0x2CCCE0EC, 0x15859194, 0x0B0B0308, 0x17475354, 0x1C4C505C, 0x1B4B5358, 0x3D8DB1BC, 0x01010100, 0x24042024, 0x1C0C101C, 0x33437370, 0x18889098, 0x10001010, 0x0CCCC0CC, 0x32C2F2F0, 0x19C9D1D8, 0x2C0C202C, 0x27C7E3E4, 0x32427270, 0x03838380, 0x1B8B9398, 0x11C1D1D0, 0x06868284, 0x09C9C1C8, 0x20406060, 0x10405050, 0x2383A3A0, 0x2BCBE3E8, 0x0D0D010C, 0x3686B2B4, 0x1E8E929C, 0x0F4F434C, 0x3787B3B4, 0x1A4A5258, 0x06C6C2C4, 0x38487078, 0x2686A2A4, 0x12021210, 0x2F8FA3AC, 0x15C5D1D4, 0x21416160, 0x03C3C3C0, 0x3484B0B4, 0x01414140, 0x12425250, 0x3D4D717C, 0x0D8D818C, 0x08080008, 0x1F0F131C, 0x19899198, 0x00000000, 0x19091118, 0x04040004, 0x13435350, 0x37C7F3F4, 0x21C1E1E0, 0x3DCDF1FC, 0x36467274, 0x2F0F232C, 0x27072324, 0x3080B0B0, 0x0B8B8388, 0x0E0E020C, 0x2B8BA3A8, 0x2282A2A0, 0x2E4E626C, 0x13839390, 0x0D4D414C, 0x29496168, 0x3C4C707C, 0x09090108, 0x0A0A0208, 0x3F8FB3BC, 0x2FCFE3EC, 0x33C3F3F0, 0x05C5C1C4, 0x07878384, 0x14041014, 0x3ECEF2FC, 0x24446064, 0x1ECED2DC, 0x2E0E222C, 0x0B4B4348, 0x1A0A1218, 0x06060204, 0x21012120, 0x2B4B6368, 0x26466264, 0x02020200, 0x35C5F1F4, 0x12829290, 0x0A8A8288, 0x0C0C000C, 0x3383B3B0, 0x3E4E727C, 0x10C0D0D0, 0x3A4A7278, 0x07474344, 0x16869294, 0x25C5E1E4, 0x26062224, 0x00808080, 0x2D8DA1AC, 0x1FCFD3DC, 0x2181A1A0, 0x30003030, 0x37073334, 0x2E8EA2AC, 0x36063234, 0x15051114, 0x22022220, 0x38083038, 0x34C4F0F4, 0x2787A3A4, 0x05454144, 0x0C4C404C, 0x01818180, 0x29C9E1E8, 0x04848084, 0x17879394, 0x35053134, 0x0BCBC3C8, 0x0ECEC2CC, 0x3C0C303C, 0x31417170, 0x11011110, 0x07C7C3C4, 0x09898188, 0x35457174, 0x3BCBF3F8, 0x1ACAD2D8, 0x38C8F0F8, 0x14849094, 0x19495158, 0x02828280, 0x04C4C0C4, 0x3FCFF3FC, 0x09494148, 0x39093138, 0x27476364, 0x00C0C0C0, 0x0FCFC3CC, 0x17C7D3D4, 0x3888B0B8, 0x0F0F030C, 0x0E8E828C, 0x02424240, 0x23032320, 0x11819190, 0x2C4C606C, 0x1BCBD3D8, 0x2484A0A4, 0x34043034, 0x31C1F1F0, 0x08484048, 0x02C2C2C0, 0x2F4F636C, 0x3D0D313C, 0x2D0D212C, 0x00404040, 0x3E8EB2BC, 0x3E0E323C, 0x3C8CB0BC, 0x01C1C1C0, 0x2A8AA2A8, 0x3A8AB2B8, 0x0E4E424C, 0x15455154, 0x3B0B3338, 0x1CCCD0DC, 0x28486068, 0x3F4F737C, 0x1C8C909C, 0x18C8D0D8, 0x0A4A4248, 0x16465254, 0x37477374, 0x2080A0A0, 0x2DCDE1EC, 0x06464244, 0x3585B1B4, 0x2B0B2328, 0x25456164, 0x3ACAF2F8, 0x23C3E3E0, 0x3989B1B8, 0x3181B1B0, 0x1F8F939C, 0x1E4E525C, 0x39C9F1F8, 0x26C6E2E4, 0x3282B2B0, 0x31013130, 0x2ACAE2E8, 0x2D4D616C, 0x1F4F535C, 0x24C4E0E4, 0x30C0F0F0, 0x0DCDC1CC, 0x08888088, 0x16061214, 0x3A0A3238, 0x18485058, 0x14C4D0D4, 0x22426260, 0x29092128, 0x07070304, 0x33033330, 0x28C8E0E8, 0x1B0B1318, 0x05050104, 0x39497178, 0x10809090, 0x2A4A6268, 0x2A0A2228, 0x1A8A9298 }; const u32bit SEED::G_FUNC::S1[256] = { 0x38380830, 0xE828C8E0, 0x2C2D0D21, 0xA42686A2, 0xCC0FCFC3, 0xDC1ECED2, 0xB03383B3, 0xB83888B0, 0xAC2F8FA3, 0x60204060, 0x54154551, 0xC407C7C3, 0x44044440, 0x6C2F4F63, 0x682B4B63, 0x581B4B53, 0xC003C3C3, 0x60224262, 0x30330333, 0xB43585B1, 0x28290921, 0xA02080A0, 0xE022C2E2, 0xA42787A3, 0xD013C3D3, 0x90118191, 0x10110111, 0x04060602, 0x1C1C0C10, 0xBC3C8CB0, 0x34360632, 0x480B4B43, 0xEC2FCFE3, 0x88088880, 0x6C2C4C60, 0xA82888A0, 0x14170713, 0xC404C4C0, 0x14160612, 0xF434C4F0, 0xC002C2C2, 0x44054541, 0xE021C1E1, 0xD416C6D2, 0x3C3F0F33, 0x3C3D0D31, 0x8C0E8E82, 0x98188890, 0x28280820, 0x4C0E4E42, 0xF436C6F2, 0x3C3E0E32, 0xA42585A1, 0xF839C9F1, 0x0C0D0D01, 0xDC1FCFD3, 0xD818C8D0, 0x282B0B23, 0x64264662, 0x783A4A72, 0x24270723, 0x2C2F0F23, 0xF031C1F1, 0x70324272, 0x40024242, 0xD414C4D0, 0x40014141, 0xC000C0C0, 0x70334373, 0x64274763, 0xAC2C8CA0, 0x880B8B83, 0xF437C7F3, 0xAC2D8DA1, 0x80008080, 0x1C1F0F13, 0xC80ACAC2, 0x2C2C0C20, 0xA82A8AA2, 0x34340430, 0xD012C2D2, 0x080B0B03, 0xEC2ECEE2, 0xE829C9E1, 0x5C1D4D51, 0x94148490, 0x18180810, 0xF838C8F0, 0x54174753, 0xAC2E8EA2, 0x08080800, 0xC405C5C1, 0x10130313, 0xCC0DCDC1, 0x84068682, 0xB83989B1, 0xFC3FCFF3, 0x7C3D4D71, 0xC001C1C1, 0x30310131, 0xF435C5F1, 0x880A8A82, 0x682A4A62, 0xB03181B1, 0xD011C1D1, 0x20200020, 0xD417C7D3, 0x00020202, 0x20220222, 0x04040400, 0x68284860, 0x70314171, 0x04070703, 0xD81BCBD3, 0x9C1D8D91, 0x98198991, 0x60214161, 0xBC3E8EB2, 0xE426C6E2, 0x58194951, 0xDC1DCDD1, 0x50114151, 0x90108090, 0xDC1CCCD0, 0x981A8A92, 0xA02383A3, 0xA82B8BA3, 0xD010C0D0, 0x80018181, 0x0C0F0F03, 0x44074743, 0x181A0A12, 0xE023C3E3, 0xEC2CCCE0, 0x8C0D8D81, 0xBC3F8FB3, 0x94168692, 0x783B4B73, 0x5C1C4C50, 0xA02282A2, 0xA02181A1, 0x60234363, 0x20230323, 0x4C0D4D41, 0xC808C8C0, 0x9C1E8E92, 0x9C1C8C90, 0x383A0A32, 0x0C0C0C00, 0x2C2E0E22, 0xB83A8AB2, 0x6C2E4E62, 0x9C1F8F93, 0x581A4A52, 0xF032C2F2, 0x90128292, 0xF033C3F3, 0x48094941, 0x78384870, 0xCC0CCCC0, 0x14150511, 0xF83BCBF3, 0x70304070, 0x74354571, 0x7C3F4F73, 0x34350531, 0x10100010, 0x00030303, 0x64244460, 0x6C2D4D61, 0xC406C6C2, 0x74344470, 0xD415C5D1, 0xB43484B0, 0xE82ACAE2, 0x08090901, 0x74364672, 0x18190911, 0xFC3ECEF2, 0x40004040, 0x10120212, 0xE020C0E0, 0xBC3D8DB1, 0x04050501, 0xF83ACAF2, 0x00010101, 0xF030C0F0, 0x282A0A22, 0x5C1E4E52, 0xA82989A1, 0x54164652, 0x40034343, 0x84058581, 0x14140410, 0x88098981, 0x981B8B93, 0xB03080B0, 0xE425C5E1, 0x48084840, 0x78394971, 0x94178793, 0xFC3CCCF0, 0x1C1E0E12, 0x80028282, 0x20210121, 0x8C0C8C80, 0x181B0B13, 0x5C1F4F53, 0x74374773, 0x54144450, 0xB03282B2, 0x1C1D0D11, 0x24250521, 0x4C0F4F43, 0x00000000, 0x44064642, 0xEC2DCDE1, 0x58184850, 0x50124252, 0xE82BCBE3, 0x7C3E4E72, 0xD81ACAD2, 0xC809C9C1, 0xFC3DCDF1, 0x30300030, 0x94158591, 0x64254561, 0x3C3C0C30, 0xB43686B2, 0xE424C4E0, 0xB83B8BB3, 0x7C3C4C70, 0x0C0E0E02, 0x50104050, 0x38390931, 0x24260622, 0x30320232, 0x84048480, 0x68294961, 0x90138393, 0x34370733, 0xE427C7E3, 0x24240420, 0xA42484A0, 0xC80BCBC3, 0x50134353, 0x080A0A02, 0x84078783, 0xD819C9D1, 0x4C0C4C40, 0x80038383, 0x8C0F8F83, 0xCC0ECEC2, 0x383B0B33, 0x480A4A42, 0xB43787B3 }; const u32bit SEED::G_FUNC::S2[256] = { 0xA1A82989, 0x81840585, 0xD2D416C6, 0xD3D013C3, 0x50541444, 0x111C1D0D, 0xA0AC2C8C, 0x21242505, 0x515C1D4D, 0x43400343, 0x10181808, 0x121C1E0E, 0x51501141, 0xF0FC3CCC, 0xC2C80ACA, 0x63602343, 0x20282808, 0x40440444, 0x20202000, 0x919C1D8D, 0xE0E020C0, 0xE2E022C2, 0xC0C808C8, 0x13141707, 0xA1A42585, 0x838C0F8F, 0x03000303, 0x73783B4B, 0xB3B83B8B, 0x13101303, 0xD2D012C2, 0xE2EC2ECE, 0x70703040, 0x808C0C8C, 0x333C3F0F, 0xA0A82888, 0x32303202, 0xD1DC1DCD, 0xF2F436C6, 0x70743444, 0xE0EC2CCC, 0x91941585, 0x03080B0B, 0x53541747, 0x505C1C4C, 0x53581B4B, 0xB1BC3D8D, 0x01000101, 0x20242404, 0x101C1C0C, 0x73703343, 0x90981888, 0x10101000, 0xC0CC0CCC, 0xF2F032C2, 0xD1D819C9, 0x202C2C0C, 0xE3E427C7, 0x72703242, 0x83800383, 0x93981B8B, 0xD1D011C1, 0x82840686, 0xC1C809C9, 0x60602040, 0x50501040, 0xA3A02383, 0xE3E82BCB, 0x010C0D0D, 0xB2B43686, 0x929C1E8E, 0x434C0F4F, 0xB3B43787, 0x52581A4A, 0xC2C406C6, 0x70783848, 0xA2A42686, 0x12101202, 0xA3AC2F8F, 0xD1D415C5, 0x61602141, 0xC3C003C3, 0xB0B43484, 0x41400141, 0x52501242, 0x717C3D4D, 0x818C0D8D, 0x00080808, 0x131C1F0F, 0x91981989, 0x00000000, 0x11181909, 0x00040404, 0x53501343, 0xF3F437C7, 0xE1E021C1, 0xF1FC3DCD, 0x72743646, 0x232C2F0F, 0x23242707, 0xB0B03080, 0x83880B8B, 0x020C0E0E, 0xA3A82B8B, 0xA2A02282, 0x626C2E4E, 0x93901383, 0x414C0D4D, 0x61682949, 0x707C3C4C, 0x01080909, 0x02080A0A, 0xB3BC3F8F, 0xE3EC2FCF, 0xF3F033C3, 0xC1C405C5, 0x83840787, 0x10141404, 0xF2FC3ECE, 0x60642444, 0xD2DC1ECE, 0x222C2E0E, 0x43480B4B, 0x12181A0A, 0x02040606, 0x21202101, 0x63682B4B, 0x62642646, 0x02000202, 0xF1F435C5, 0x92901282, 0x82880A8A, 0x000C0C0C, 0xB3B03383, 0x727C3E4E, 0xD0D010C0, 0x72783A4A, 0x43440747, 0x92941686, 0xE1E425C5, 0x22242606, 0x80800080, 0xA1AC2D8D, 0xD3DC1FCF, 0xA1A02181, 0x30303000, 0x33343707, 0xA2AC2E8E, 0x32343606, 0x11141505, 0x22202202, 0x30383808, 0xF0F434C4, 0xA3A42787, 0x41440545, 0x404C0C4C, 0x81800181, 0xE1E829C9, 0x80840484, 0x93941787, 0x31343505, 0xC3C80BCB, 0xC2CC0ECE, 0x303C3C0C, 0x71703141, 0x11101101, 0xC3C407C7, 0x81880989, 0x71743545, 0xF3F83BCB, 0xD2D81ACA, 0xF0F838C8, 0x90941484, 0x51581949, 0x82800282, 0xC0C404C4, 0xF3FC3FCF, 0x41480949, 0x31383909, 0x63642747, 0xC0C000C0, 0xC3CC0FCF, 0xD3D417C7, 0xB0B83888, 0x030C0F0F, 0x828C0E8E, 0x42400242, 0x23202303, 0x91901181, 0x606C2C4C, 0xD3D81BCB, 0xA0A42484, 0x30343404, 0xF1F031C1, 0x40480848, 0xC2C002C2, 0x636C2F4F, 0x313C3D0D, 0x212C2D0D, 0x40400040, 0xB2BC3E8E, 0x323C3E0E, 0xB0BC3C8C, 0xC1C001C1, 0xA2A82A8A, 0xB2B83A8A, 0x424C0E4E, 0x51541545, 0x33383B0B, 0xD0DC1CCC, 0x60682848, 0x737C3F4F, 0x909C1C8C, 0xD0D818C8, 0x42480A4A, 0x52541646, 0x73743747, 0xA0A02080, 0xE1EC2DCD, 0x42440646, 0xB1B43585, 0x23282B0B, 0x61642545, 0xF2F83ACA, 0xE3E023C3, 0xB1B83989, 0xB1B03181, 0x939C1F8F, 0x525C1E4E, 0xF1F839C9, 0xE2E426C6, 0xB2B03282, 0x31303101, 0xE2E82ACA, 0x616C2D4D, 0x535C1F4F, 0xE0E424C4, 0xF0F030C0, 0xC1CC0DCD, 0x80880888, 0x12141606, 0x32383A0A, 0x50581848, 0xD0D414C4, 0x62602242, 0x21282909, 0x03040707, 0x33303303, 0xE0E828C8, 0x13181B0B, 0x01040505, 0x71783949, 0x90901080, 0x62682A4A, 0x22282A0A, 0x92981A8A }; const u32bit SEED::G_FUNC::S3[256] = { 0x08303838, 0xC8E0E828, 0x0D212C2D, 0x86A2A426, 0xCFC3CC0F, 0xCED2DC1E, 0x83B3B033, 0x88B0B838, 0x8FA3AC2F, 0x40606020, 0x45515415, 0xC7C3C407, 0x44404404, 0x4F636C2F, 0x4B63682B, 0x4B53581B, 0xC3C3C003, 0x42626022, 0x03333033, 0x85B1B435, 0x09212829, 0x80A0A020, 0xC2E2E022, 0x87A3A427, 0xC3D3D013, 0x81919011, 0x01111011, 0x06020406, 0x0C101C1C, 0x8CB0BC3C, 0x06323436, 0x4B43480B, 0xCFE3EC2F, 0x88808808, 0x4C606C2C, 0x88A0A828, 0x07131417, 0xC4C0C404, 0x06121416, 0xC4F0F434, 0xC2C2C002, 0x45414405, 0xC1E1E021, 0xC6D2D416, 0x0F333C3F, 0x0D313C3D, 0x8E828C0E, 0x88909818, 0x08202828, 0x4E424C0E, 0xC6F2F436, 0x0E323C3E, 0x85A1A425, 0xC9F1F839, 0x0D010C0D, 0xCFD3DC1F, 0xC8D0D818, 0x0B23282B, 0x46626426, 0x4A72783A, 0x07232427, 0x0F232C2F, 0xC1F1F031, 0x42727032, 0x42424002, 0xC4D0D414, 0x41414001, 0xC0C0C000, 0x43737033, 0x47636427, 0x8CA0AC2C, 0x8B83880B, 0xC7F3F437, 0x8DA1AC2D, 0x80808000, 0x0F131C1F, 0xCAC2C80A, 0x0C202C2C, 0x8AA2A82A, 0x04303434, 0xC2D2D012, 0x0B03080B, 0xCEE2EC2E, 0xC9E1E829, 0x4D515C1D, 0x84909414, 0x08101818, 0xC8F0F838, 0x47535417, 0x8EA2AC2E, 0x08000808, 0xC5C1C405, 0x03131013, 0xCDC1CC0D, 0x86828406, 0x89B1B839, 0xCFF3FC3F, 0x4D717C3D, 0xC1C1C001, 0x01313031, 0xC5F1F435, 0x8A82880A, 0x4A62682A, 0x81B1B031, 0xC1D1D011, 0x00202020, 0xC7D3D417, 0x02020002, 0x02222022, 0x04000404, 0x48606828, 0x41717031, 0x07030407, 0xCBD3D81B, 0x8D919C1D, 0x89919819, 0x41616021, 0x8EB2BC3E, 0xC6E2E426, 0x49515819, 0xCDD1DC1D, 0x41515011, 0x80909010, 0xCCD0DC1C, 0x8A92981A, 0x83A3A023, 0x8BA3A82B, 0xC0D0D010, 0x81818001, 0x0F030C0F, 0x47434407, 0x0A12181A, 0xC3E3E023, 0xCCE0EC2C, 0x8D818C0D, 0x8FB3BC3F, 0x86929416, 0x4B73783B, 0x4C505C1C, 0x82A2A022, 0x81A1A021, 0x43636023, 0x03232023, 0x4D414C0D, 0xC8C0C808, 0x8E929C1E, 0x8C909C1C, 0x0A32383A, 0x0C000C0C, 0x0E222C2E, 0x8AB2B83A, 0x4E626C2E, 0x8F939C1F, 0x4A52581A, 0xC2F2F032, 0x82929012, 0xC3F3F033, 0x49414809, 0x48707838, 0xCCC0CC0C, 0x05111415, 0xCBF3F83B, 0x40707030, 0x45717435, 0x4F737C3F, 0x05313435, 0x00101010, 0x03030003, 0x44606424, 0x4D616C2D, 0xC6C2C406, 0x44707434, 0xC5D1D415, 0x84B0B434, 0xCAE2E82A, 0x09010809, 0x46727436, 0x09111819, 0xCEF2FC3E, 0x40404000, 0x02121012, 0xC0E0E020, 0x8DB1BC3D, 0x05010405, 0xCAF2F83A, 0x01010001, 0xC0F0F030, 0x0A22282A, 0x4E525C1E, 0x89A1A829, 0x46525416, 0x43434003, 0x85818405, 0x04101414, 0x89818809, 0x8B93981B, 0x80B0B030, 0xC5E1E425, 0x48404808, 0x49717839, 0x87939417, 0xCCF0FC3C, 0x0E121C1E, 0x82828002, 0x01212021, 0x8C808C0C, 0x0B13181B, 0x4F535C1F, 0x47737437, 0x44505414, 0x82B2B032, 0x0D111C1D, 0x05212425, 0x4F434C0F, 0x00000000, 0x46424406, 0xCDE1EC2D, 0x48505818, 0x42525012, 0xCBE3E82B, 0x4E727C3E, 0xCAD2D81A, 0xC9C1C809, 0xCDF1FC3D, 0x00303030, 0x85919415, 0x45616425, 0x0C303C3C, 0x86B2B436, 0xC4E0E424, 0x8BB3B83B, 0x4C707C3C, 0x0E020C0E, 0x40505010, 0x09313839, 0x06222426, 0x02323032, 0x84808404, 0x49616829, 0x83939013, 0x07333437, 0xC7E3E427, 0x04202424, 0x84A0A424, 0xCBC3C80B, 0x43535013, 0x0A02080A, 0x87838407, 0xC9D1D819, 0x4C404C0C, 0x83838003, 0x8F838C0F, 0xCEC2CC0E, 0x0B33383B, 0x4A42480A, 0x87B3B437 }; } /* * Serpent * (C) 1999-2007 Jack Lloyd * * The sbox expressions used here were discovered by Dag Arne Osvik and * are described in his paper "Speeding Up Serpent". * * Distributed under the terms of the Botan license */ namespace Botan { namespace { /* * Serpent Encryption S-Box 1 */ inline void SBoxE1(u32bit& B0, u32bit& B1, u32bit& B2, u32bit& B3) { u32bit T0 = B0, T1 = B1, T2 = B2, T3 = B3, T4; T3 ^= T0; T4 = T1; T1 &= T3; T4 ^= T2; T1 ^= T0; T0 |= T3; T0 ^= T4; T4 ^= T3; T3 ^= T2; T2 |= T1; T2 ^= T4; T4 = ~T4; T4 |= T1; T1 ^= T3; T1 ^= T4; T3 |= T0; T1 ^= T3; T4 ^= T3; B0 = T1; B1 = T4; B2 = T2; B3 = T0; } /* * Serpent Encryption S-Box 2 */ inline void SBoxE2(u32bit& B0, u32bit& B1, u32bit& B2, u32bit& B3) { u32bit T0 = B0, T1 = B1, T2 = B2, T3 = B3, T4; T0 = ~T0; T2 = ~T2; T4 = T0; T0 &= T1; T2 ^= T0; T0 |= T3; T3 ^= T2; T1 ^= T0; T0 ^= T4; T4 |= T1; T1 ^= T3; T2 |= T0; T2 &= T4; T0 ^= T1; T1 &= T2; T1 ^= T0; T0 &= T2; T0 ^= T4; B0 = T2; B1 = T0; B2 = T3; B3 = T1; } /* * Serpent Encryption S-Box 3 */ inline void SBoxE3(u32bit& B0, u32bit& B1, u32bit& B2, u32bit& B3) { u32bit T0 = B0, T1 = B1, T2 = B2, T3 = B3, T4; T4 = T0; T0 &= T2; T0 ^= T3; T2 ^= T1; T2 ^= T0; T3 |= T4; T3 ^= T1; T4 ^= T2; T1 = T3; T3 |= T4; T3 ^= T0; T0 &= T1; T4 ^= T0; T1 ^= T3; T1 ^= T4; T4 = ~T4; B0 = T2; B1 = T3; B2 = T1; B3 = T4; } /* * Serpent Encryption S-Box 4 */ inline void SBoxE4(u32bit& B0, u32bit& B1, u32bit& B2, u32bit& B3) { u32bit T0 = B0, T1 = B1, T2 = B2, T3 = B3, T4; T4 = T0; T0 |= T3; T3 ^= T1; T1 &= T4; T4 ^= T2; T2 ^= T3; T3 &= T0; T4 |= T1; T3 ^= T4; T0 ^= T1; T4 &= T0; T1 ^= T3; T4 ^= T2; T1 |= T0; T1 ^= T2; T0 ^= T3; T2 = T1; T1 |= T3; T1 ^= T0; B0 = T1; B1 = T2; B2 = T3; B3 = T4; } /* * Serpent Encryption S-Box 5 */ inline void SBoxE5(u32bit& B0, u32bit& B1, u32bit& B2, u32bit& B3) { u32bit T0 = B0, T1 = B1, T2 = B2, T3 = B3, T4; T1 ^= T3; T3 = ~T3; T2 ^= T3; T3 ^= T0; T4 = T1; T1 &= T3; T1 ^= T2; T4 ^= T3; T0 ^= T4; T2 &= T4; T2 ^= T0; T0 &= T1; T3 ^= T0; T4 |= T1; T4 ^= T0; T0 |= T3; T0 ^= T2; T2 &= T3; T0 = ~T0; T4 ^= T2; B0 = T1; B1 = T4; B2 = T0; B3 = T3; } /* * Serpent Encryption S-Box 6 */ inline void SBoxE6(u32bit& B0, u32bit& B1, u32bit& B2, u32bit& B3) { u32bit T0 = B0, T1 = B1, T2 = B2, T3 = B3, T4; T0 ^= T1; T1 ^= T3; T3 = ~T3; T4 = T1; T1 &= T0; T2 ^= T3; T1 ^= T2; T2 |= T4; T4 ^= T3; T3 &= T1; T3 ^= T0; T4 ^= T1; T4 ^= T2; T2 ^= T0; T0 &= T3; T2 = ~T2; T0 ^= T4; T4 |= T3; T2 ^= T4; B0 = T1; B1 = T3; B2 = T0; B3 = T2; } /* * Serpent Encryption S-Box 7 */ inline void SBoxE7(u32bit& B0, u32bit& B1, u32bit& B2, u32bit& B3) { u32bit T0 = B0, T1 = B1, T2 = B2, T3 = B3, T4; T2 = ~T2; T4 = T3; T3 &= T0; T0 ^= T4; T3 ^= T2; T2 |= T4; T1 ^= T3; T2 ^= T0; T0 |= T1; T2 ^= T1; T4 ^= T0; T0 |= T3; T0 ^= T2; T4 ^= T3; T4 ^= T0; T3 = ~T3; T2 &= T4; T2 ^= T3; B0 = T0; B1 = T1; B2 = T4; B3 = T2; } /* * Serpent Encryption S-Box 8 */ inline void SBoxE8(u32bit& B0, u32bit& B1, u32bit& B2, u32bit& B3) { u32bit T0 = B0, T1 = B1, T2 = B2, T3 = B3, T4; T4 = T1; T1 |= T2; T1 ^= T3; T4 ^= T2; T2 ^= T1; T3 |= T4; T3 &= T0; T4 ^= T2; T3 ^= T1; T1 |= T4; T1 ^= T0; T0 |= T4; T0 ^= T2; T1 ^= T4; T2 ^= T1; T1 &= T0; T1 ^= T4; T2 = ~T2; T2 |= T0; T4 ^= T2; B0 = T4; B1 = T3; B2 = T1; B3 = T0; } /* * Serpent Decryption S-Box 1 */ inline void SBoxD1(u32bit& B0, u32bit& B1, u32bit& B2, u32bit& B3) { u32bit T0 = B0, T1 = B1, T2 = B2, T3 = B3, T4; T2 = ~T2; T4 = T1; T1 |= T0; T4 = ~T4; T1 ^= T2; T2 |= T4; T1 ^= T3; T0 ^= T4; T2 ^= T0; T0 &= T3; T4 ^= T0; T0 |= T1; T0 ^= T2; T3 ^= T4; T2 ^= T1; T3 ^= T0; T3 ^= T1; T2 &= T3; T4 ^= T2; B0 = T0; B1 = T4; B2 = T1; B3 = T3; } /* * Serpent Decryption S-Box 2 */ inline void SBoxD2(u32bit& B0, u32bit& B1, u32bit& B2, u32bit& B3) { u32bit T0 = B0, T1 = B1, T2 = B2, T3 = B3, T4; T4 = T1; T1 ^= T3; T3 &= T1; T4 ^= T2; T3 ^= T0; T0 |= T1; T2 ^= T3; T0 ^= T4; T0 |= T2; T1 ^= T3; T0 ^= T1; T1 |= T3; T1 ^= T0; T4 = ~T4; T4 ^= T1; T1 |= T0; T1 ^= T0; T1 |= T4; T3 ^= T1; B0 = T4; B1 = T0; B2 = T3; B3 = T2; } /* * Serpent Decryption S-Box 3 */ inline void SBoxD3(u32bit& B0, u32bit& B1, u32bit& B2, u32bit& B3) { u32bit T0 = B0, T1 = B1, T2 = B2, T3 = B3, T4; T2 ^= T3; T3 ^= T0; T4 = T3; T3 &= T2; T3 ^= T1; T1 |= T2; T1 ^= T4; T4 &= T3; T2 ^= T3; T4 &= T0; T4 ^= T2; T2 &= T1; T2 |= T0; T3 = ~T3; T2 ^= T3; T0 ^= T3; T0 &= T1; T3 ^= T4; T3 ^= T0; B0 = T1; B1 = T4; B2 = T2; B3 = T3; } /* * Serpent Decryption S-Box 4 */ inline void SBoxD4(u32bit& B0, u32bit& B1, u32bit& B2, u32bit& B3) { u32bit T0 = B0, T1 = B1, T2 = B2, T3 = B3, T4; T4 = T2; T2 ^= T1; T0 ^= T2; T4 &= T2; T4 ^= T0; T0 &= T1; T1 ^= T3; T3 |= T4; T2 ^= T3; T0 ^= T3; T1 ^= T4; T3 &= T2; T3 ^= T1; T1 ^= T0; T1 |= T2; T0 ^= T3; T1 ^= T4; T0 ^= T1; B0 = T2; B1 = T1; B2 = T3; B3 = T0; } /* * Serpent Decryption S-Box 5 */ inline void SBoxD5(u32bit& B0, u32bit& B1, u32bit& B2, u32bit& B3) { u32bit T0 = B0, T1 = B1, T2 = B2, T3 = B3, T4; T4 = T2; T2 &= T3; T2 ^= T1; T1 |= T3; T1 &= T0; T4 ^= T2; T4 ^= T1; T1 &= T2; T0 = ~T0; T3 ^= T4; T1 ^= T3; T3 &= T0; T3 ^= T2; T0 ^= T1; T2 &= T0; T3 ^= T0; T2 ^= T4; T2 |= T3; T3 ^= T0; T2 ^= T1; B0 = T0; B1 = T3; B2 = T2; B3 = T4; } /* * Serpent Decryption S-Box 6 */ inline void SBoxD6(u32bit& B0, u32bit& B1, u32bit& B2, u32bit& B3) { u32bit T0 = B0, T1 = B1, T2 = B2, T3 = B3, T4; T1 = ~T1; T4 = T3; T2 ^= T1; T3 |= T0; T3 ^= T2; T2 |= T1; T2 &= T0; T4 ^= T3; T2 ^= T4; T4 |= T0; T4 ^= T1; T1 &= T2; T1 ^= T3; T4 ^= T2; T3 &= T4; T4 ^= T1; T3 ^= T4; T4 = ~T4; T3 ^= T0; B0 = T1; B1 = T4; B2 = T3; B3 = T2; } /* * Serpent Decryption S-Box 7 */ inline void SBoxD7(u32bit& B0, u32bit& B1, u32bit& B2, u32bit& B3) { u32bit T0 = B0, T1 = B1, T2 = B2, T3 = B3, T4; T0 ^= T2; T4 = T2; T2 &= T0; T4 ^= T3; T2 = ~T2; T3 ^= T1; T2 ^= T3; T4 |= T0; T0 ^= T2; T3 ^= T4; T4 ^= T1; T1 &= T3; T1 ^= T0; T0 ^= T3; T0 |= T2; T3 ^= T1; T4 ^= T0; B0 = T1; B1 = T2; B2 = T4; B3 = T3; } /* * Serpent Decryption S-Box 8 */ inline void SBoxD8(u32bit& B0, u32bit& B1, u32bit& B2, u32bit& B3) { u32bit T0 = B0, T1 = B1, T2 = B2, T3 = B3, T4; T4 = T2; T2 ^= T0; T0 &= T3; T4 |= T3; T2 = ~T2; T3 ^= T1; T1 |= T0; T0 ^= T2; T2 &= T4; T3 &= T4; T1 ^= T2; T2 ^= T0; T0 |= T2; T4 ^= T1; T0 ^= T3; T3 ^= T4; T4 |= T0; T3 ^= T2; T4 ^= T2; B0 = T3; B1 = T0; B2 = T1; B3 = T4; } /* * Serpent's Linear Transformation */ inline void transform(u32bit& B0, u32bit& B1, u32bit& B2, u32bit& B3) { B0 = rotate_left(B0, 13); B2 = rotate_left(B2, 3); B1 ^= B0 ^ B2; B3 ^= B2 ^ (B0 << 3); B1 = rotate_left(B1, 1); B3 = rotate_left(B3, 7); B0 ^= B1 ^ B3; B2 ^= B3 ^ (B1 << 7); B0 = rotate_left(B0, 5); B2 = rotate_left(B2, 22); } /* * Serpent's Inverse Linear Transformation */ inline void i_transform(u32bit& B0, u32bit& B1, u32bit& B2, u32bit& B3) { B2 = rotate_right(B2, 22); B0 = rotate_right(B0, 5); B2 ^= B3 ^ (B1 << 7); B0 ^= B1 ^ B3; B3 = rotate_right(B3, 7); B1 = rotate_right(B1, 1); B3 ^= B2 ^ (B0 << 3); B1 ^= B0 ^ B2; B2 = rotate_right(B2, 3); B0 = rotate_right(B0, 13); } } /* * XOR a key block with a data block */ #define key_xor(round, B0, B1, B2, B3) \ B0 ^= round_key[4*round ]; \ B1 ^= round_key[4*round+1]; \ B2 ^= round_key[4*round+2]; \ B3 ^= round_key[4*round+3]; /* * Serpent Encryption */ void Serpent::encrypt_n(const byte in[], byte out[], size_t blocks) const { for(size_t i = 0; i != blocks; ++i) { u32bit B0 = load_le(in, 0); u32bit B1 = load_le(in, 1); u32bit B2 = load_le(in, 2); u32bit B3 = load_le(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::decrypt_n(const byte in[], byte out[], size_t blocks) const { for(size_t i = 0; i != blocks; ++i) { u32bit B0 = load_le(in, 0); u32bit B1 = load_le(in, 1); u32bit B2 = load_le(in, 2); u32bit B3 = load_le(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; } } #undef key_xor #undef transform #undef i_transform /* * Serpent Key Schedule */ void Serpent::key_schedule(const byte key[], size_t length) { const u32bit PHI = 0x9E3779B9; SecureVector W(140); for(size_t i = 0; i != length / 4; ++i) W[i] = load_le(key, i); W[length / 4] |= u32bit(1) << ((length%4)*8); for(size_t i = 8; i != 140; ++i) { u32bit wi = W[i-8] ^ W[i-5] ^ W[i-3] ^ W[i-1] ^ PHI ^ u32bit(i-8); W[i] = rotate_left(wi, 11); } SBoxE4(W[ 8],W[ 9],W[ 10],W[ 11]); SBoxE3(W[ 12],W[ 13],W[ 14],W[ 15]); SBoxE2(W[ 16],W[ 17],W[ 18],W[ 19]); SBoxE1(W[ 20],W[ 21],W[ 22],W[ 23]); SBoxE8(W[ 24],W[ 25],W[ 26],W[ 27]); SBoxE7(W[ 28],W[ 29],W[ 30],W[ 31]); SBoxE6(W[ 32],W[ 33],W[ 34],W[ 35]); SBoxE5(W[ 36],W[ 37],W[ 38],W[ 39]); SBoxE4(W[ 40],W[ 41],W[ 42],W[ 43]); SBoxE3(W[ 44],W[ 45],W[ 46],W[ 47]); SBoxE2(W[ 48],W[ 49],W[ 50],W[ 51]); SBoxE1(W[ 52],W[ 53],W[ 54],W[ 55]); SBoxE8(W[ 56],W[ 57],W[ 58],W[ 59]); SBoxE7(W[ 60],W[ 61],W[ 62],W[ 63]); SBoxE6(W[ 64],W[ 65],W[ 66],W[ 67]); SBoxE5(W[ 68],W[ 69],W[ 70],W[ 71]); SBoxE4(W[ 72],W[ 73],W[ 74],W[ 75]); SBoxE3(W[ 76],W[ 77],W[ 78],W[ 79]); SBoxE2(W[ 80],W[ 81],W[ 82],W[ 83]); SBoxE1(W[ 84],W[ 85],W[ 86],W[ 87]); SBoxE8(W[ 88],W[ 89],W[ 90],W[ 91]); SBoxE7(W[ 92],W[ 93],W[ 94],W[ 95]); SBoxE6(W[ 96],W[ 97],W[ 98],W[ 99]); SBoxE5(W[100],W[101],W[102],W[103]); SBoxE4(W[104],W[105],W[106],W[107]); SBoxE3(W[108],W[109],W[110],W[111]); SBoxE2(W[112],W[113],W[114],W[115]); SBoxE1(W[116],W[117],W[118],W[119]); SBoxE8(W[120],W[121],W[122],W[123]); SBoxE7(W[124],W[125],W[126],W[127]); SBoxE6(W[128],W[129],W[130],W[131]); SBoxE5(W[132],W[133],W[134],W[135]); SBoxE4(W[136],W[137],W[138],W[139]); round_key.copy(&W[8], 132); } } /* * Serpent (SIMD) * (C) 2009 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { namespace { #define SBoxE1(B0, B1, B2, B3) \ do { \ B3 ^= B0; \ SIMD_32 B4 = B1; \ B1 &= B3; \ B4 ^= B2; \ B1 ^= B0; \ B0 |= B3; \ B0 ^= B4; \ B4 ^= B3; \ B3 ^= B2; \ B2 |= B1; \ B2 ^= B4; \ B4 = ~B4; \ B4 |= B1; \ B1 ^= B3; \ B1 ^= B4; \ B3 |= B0; \ B1 ^= B3; \ B4 ^= B3; \ B3 = B0; \ B0 = B1; \ B1 = B4; \ } while(0); #define SBoxE2(B0, B1, B2, B3) \ do { \ B0 = ~B0; \ B2 = ~B2; \ SIMD_32 B4 = B0; \ B0 &= B1; \ B2 ^= B0; \ B0 |= B3; \ B3 ^= B2; \ B1 ^= B0; \ B0 ^= B4; \ B4 |= B1; \ B1 ^= B3; \ B2 |= B0; \ B2 &= B4; \ B0 ^= B1; \ B1 &= B2; \ B1 ^= B0; \ B0 &= B2; \ B4 ^= B0; \ B0 = B2; \ B2 = B3; \ B3 = B1; \ B1 = B4; \ } while(0); #define SBoxE3(B0, B1, B2, B3) \ do { \ SIMD_32 B4 = B0; \ B0 &= B2; \ B0 ^= B3; \ B2 ^= B1; \ B2 ^= B0; \ B3 |= B4; \ B3 ^= B1; \ B4 ^= B2; \ B1 = B3; \ B3 |= B4; \ B3 ^= B0; \ B0 &= B1; \ B4 ^= B0; \ B1 ^= B3; \ B1 ^= B4; \ B0 = B2; \ B2 = B1; \ B1 = B3; \ B3 = ~B4; \ } while(0); #define SBoxE4(B0, B1, B2, B3) \ do { \ SIMD_32 B4 = B0; \ B0 |= B3; \ B3 ^= B1; \ B1 &= B4; \ B4 ^= B2; \ B2 ^= B3; \ B3 &= B0; \ B4 |= B1; \ B3 ^= B4; \ B0 ^= B1; \ B4 &= B0; \ B1 ^= B3; \ B4 ^= B2; \ B1 |= B0; \ B1 ^= B2; \ B0 ^= B3; \ B2 = B1; \ B1 |= B3; \ B0 ^= B1; \ B1 = B2; \ B2 = B3; \ B3 = B4; \ } while(0); #define SBoxE5(B0, B1, B2, B3) \ do { \ B1 ^= B3; \ B3 = ~B3; \ B2 ^= B3; \ B3 ^= B0; \ SIMD_32 B4 = B1; \ B1 &= B3; \ B1 ^= B2; \ B4 ^= B3; \ B0 ^= B4; \ B2 &= B4; \ B2 ^= B0; \ B0 &= B1; \ B3 ^= B0; \ B4 |= B1; \ B4 ^= B0; \ B0 |= B3; \ B0 ^= B2; \ B2 &= B3; \ B0 = ~B0; \ B4 ^= B2; \ B2 = B0; \ B0 = B1; \ B1 = B4; \ } while(0); #define SBoxE6(B0, B1, B2, B3) \ do { \ B0 ^= B1; \ B1 ^= B3; \ B3 = ~B3; \ SIMD_32 B4 = B1; \ B1 &= B0; \ B2 ^= B3; \ B1 ^= B2; \ B2 |= B4; \ B4 ^= B3; \ B3 &= B1; \ B3 ^= B0; \ B4 ^= B1; \ B4 ^= B2; \ B2 ^= B0; \ B0 &= B3; \ B2 = ~B2; \ B0 ^= B4; \ B4 |= B3; \ B4 ^= B2; \ B2 = B0; \ B0 = B1; \ B1 = B3; \ B3 = B4; \ } while(0); #define SBoxE7(B0, B1, B2, B3) \ do { \ B2 = ~B2; \ SIMD_32 B4 = B3; \ B3 &= B0; \ B0 ^= B4; \ B3 ^= B2; \ B2 |= B4; \ B1 ^= B3; \ B2 ^= B0; \ B0 |= B1; \ B2 ^= B1; \ B4 ^= B0; \ B0 |= B3; \ B0 ^= B2; \ B4 ^= B3; \ B4 ^= B0; \ B3 = ~B3; \ B2 &= B4; \ B3 ^= B2; \ B2 = B4; \ } while(0); #define SBoxE8(B0, B1, B2, B3) \ do { \ SIMD_32 B4 = B1; \ B1 |= B2; \ B1 ^= B3; \ B4 ^= B2; \ B2 ^= B1; \ B3 |= B4; \ B3 &= B0; \ B4 ^= B2; \ B3 ^= B1; \ B1 |= B4; \ B1 ^= B0; \ B0 |= B4; \ B0 ^= B2; \ B1 ^= B4; \ B2 ^= B1; \ B1 &= B0; \ B1 ^= B4; \ B2 = ~B2; \ B2 |= B0; \ B4 ^= B2; \ B2 = B1; \ B1 = B3; \ B3 = B0; \ B0 = B4; \ } while(0); #define SBoxD1(B0, B1, B2, B3) \ do { \ B2 = ~B2; \ SIMD_32 B4 = B1; \ B1 |= B0; \ B4 = ~B4; \ B1 ^= B2; \ B2 |= B4; \ B1 ^= B3; \ B0 ^= B4; \ B2 ^= B0; \ B0 &= B3; \ B4 ^= B0; \ B0 |= B1; \ B0 ^= B2; \ B3 ^= B4; \ B2 ^= B1; \ B3 ^= B0; \ B3 ^= B1; \ B2 &= B3; \ B4 ^= B2; \ B2 = B1; \ B1 = B4; \ } while(0); #define SBoxD2(B0, B1, B2, B3) \ do { \ SIMD_32 B4 = B1; \ B1 ^= B3; \ B3 &= B1; \ B4 ^= B2; \ B3 ^= B0; \ B0 |= B1; \ B2 ^= B3; \ B0 ^= B4; \ B0 |= B2; \ B1 ^= B3; \ B0 ^= B1; \ B1 |= B3; \ B1 ^= B0; \ B4 = ~B4; \ B4 ^= B1; \ B1 |= B0; \ B1 ^= B0; \ B1 |= B4; \ B3 ^= B1; \ B1 = B0; \ B0 = B4; \ B4 = B2; \ B2 = B3; \ B3 = B4; \ } while(0); #define SBoxD3(B0, B1, B2, B3) \ do { \ B2 ^= B3; \ B3 ^= B0; \ SIMD_32 B4 = B3; \ B3 &= B2; \ B3 ^= B1; \ B1 |= B2; \ B1 ^= B4; \ B4 &= B3; \ B2 ^= B3; \ B4 &= B0; \ B4 ^= B2; \ B2 &= B1; \ B2 |= B0; \ B3 = ~B3; \ B2 ^= B3; \ B0 ^= B3; \ B0 &= B1; \ B3 ^= B4; \ B3 ^= B0; \ B0 = B1; \ B1 = B4; \ } while(0); #define SBoxD4(B0, B1, B2, B3) \ do { \ SIMD_32 B4 = B2; \ B2 ^= B1; \ B0 ^= B2; \ B4 &= B2; \ B4 ^= B0; \ B0 &= B1; \ B1 ^= B3; \ B3 |= B4; \ B2 ^= B3; \ B0 ^= B3; \ B1 ^= B4; \ B3 &= B2; \ B3 ^= B1; \ B1 ^= B0; \ B1 |= B2; \ B0 ^= B3; \ B1 ^= B4; \ B0 ^= B1; \ B4 = B0; \ B0 = B2; \ B2 = B3; \ B3 = B4; \ } while(0); #define SBoxD5(B0, B1, B2, B3) \ do { \ SIMD_32 B4 = B2; \ B2 &= B3; \ B2 ^= B1; \ B1 |= B3; \ B1 &= B0; \ B4 ^= B2; \ B4 ^= B1; \ B1 &= B2; \ B0 = ~B0; \ B3 ^= B4; \ B1 ^= B3; \ B3 &= B0; \ B3 ^= B2; \ B0 ^= B1; \ B2 &= B0; \ B3 ^= B0; \ B2 ^= B4; \ B2 |= B3; \ B3 ^= B0; \ B2 ^= B1; \ B1 = B3; \ B3 = B4; \ } while(0); #define SBoxD6(B0, B1, B2, B3) \ do { \ B1 = ~B1; \ SIMD_32 B4 = B3; \ B2 ^= B1; \ B3 |= B0; \ B3 ^= B2; \ B2 |= B1; \ B2 &= B0; \ B4 ^= B3; \ B2 ^= B4; \ B4 |= B0; \ B4 ^= B1; \ B1 &= B2; \ B1 ^= B3; \ B4 ^= B2; \ B3 &= B4; \ B4 ^= B1; \ B3 ^= B4; \ B4 = ~B4; \ B3 ^= B0; \ B0 = B1; \ B1 = B4; \ B4 = B3; \ B3 = B2; \ B2 = B4; \ } while(0); #define SBoxD7(B0, B1, B2, B3) \ do { \ B0 ^= B2; \ SIMD_32 B4 = B2; \ B2 &= B0; \ B4 ^= B3; \ B2 = ~B2; \ B3 ^= B1; \ B2 ^= B3; \ B4 |= B0; \ B0 ^= B2; \ B3 ^= B4; \ B4 ^= B1; \ B1 &= B3; \ B1 ^= B0; \ B0 ^= B3; \ B0 |= B2; \ B3 ^= B1; \ B4 ^= B0; \ B0 = B1; \ B1 = B2; \ B2 = B4; \ } while(0); #define SBoxD8(B0, B1, B2, B3) \ do { \ SIMD_32 B4 = B2; \ B2 ^= B0; \ B0 &= B3; \ B4 |= B3; \ B2 = ~B2; \ B3 ^= B1; \ B1 |= B0; \ B0 ^= B2; \ B2 &= B4; \ B3 &= B4; \ B1 ^= B2; \ B2 ^= B0; \ B0 |= B2; \ B4 ^= B1; \ B0 ^= B3; \ B3 ^= B4; \ B4 |= B0; \ B3 ^= B2; \ B4 ^= B2; \ B2 = B1; \ B1 = B0; \ B0 = B3; \ B3 = B4; \ } while(0); #define key_xor(round, B0, B1, B2, B3) \ do { \ B0 ^= SIMD_32(keys[4*round ]); \ B1 ^= SIMD_32(keys[4*round+1]); \ B2 ^= SIMD_32(keys[4*round+2]); \ B3 ^= SIMD_32(keys[4*round+3]); \ } while(0); /* * Serpent's linear transformations */ #define transform(B0, B1, B2, B3) \ do { \ B0.rotate_left(13); \ B2.rotate_left(3); \ B1 ^= B0 ^ B2; \ B3 ^= B2 ^ (B0 << 3); \ B1.rotate_left(1); \ B3.rotate_left(7); \ B0 ^= B1 ^ B3; \ B2 ^= B3 ^ (B1 << 7); \ B0.rotate_left(5); \ B2.rotate_left(22); \ } while(0); #define i_transform(B0, B1, B2, B3) \ do { \ B2.rotate_right(22); \ B0.rotate_right(5); \ B2 ^= B3 ^ (B1 << 7); \ B0 ^= B1 ^ B3; \ B3.rotate_right(7); \ B1.rotate_right(1); \ B3 ^= B2 ^ (B0 << 3); \ B1 ^= B0 ^ B2; \ B2.rotate_right(3); \ B0.rotate_right(13); \ } while(0); /* * SIMD Serpent Encryption of 4 blocks in parallel */ void serpent_encrypt_4(const byte in[64], byte out[64], const u32bit keys[132]) { SIMD_32 B0 = SIMD_32::load_le(in); SIMD_32 B1 = SIMD_32::load_le(in + 16); SIMD_32 B2 = SIMD_32::load_le(in + 32); SIMD_32 B3 = SIMD_32::load_le(in + 48); SIMD_32::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); SIMD_32::transpose(B0, B1, B2, B3); B0.store_le(out); B1.store_le(out + 16); B2.store_le(out + 32); B3.store_le(out + 48); } /* * SIMD Serpent Decryption of 4 blocks in parallel */ void serpent_decrypt_4(const byte in[64], byte out[64], const u32bit keys[132]) { SIMD_32 B0 = SIMD_32::load_le(in); SIMD_32 B1 = SIMD_32::load_le(in + 16); SIMD_32 B2 = SIMD_32::load_le(in + 32); SIMD_32 B3 = SIMD_32::load_le(in + 48); SIMD_32::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); SIMD_32::transpose(B0, B1, B2, B3); B0.store_le(out); B1.store_le(out + 16); B2.store_le(out + 32); B3.store_le(out + 48); } } #undef key_xor #undef transform #undef i_transform #undef SBoxE1 #undef SBoxE2 #undef SBoxE3 #undef SBoxE4 #undef SBoxE5 #undef SBoxE6 #undef SBoxE7 #undef SBoxE8 #undef SBoxD1 #undef SBoxD2 #undef SBoxD3 #undef SBoxD4 #undef SBoxD5 #undef SBoxD6 #undef SBoxD7 #undef SBoxD8 /* * Serpent Encryption */ void Serpent_SIMD::encrypt_n(const byte in[], byte out[], size_t blocks) const { const u32bit* KS = &(this->get_round_keys()[0]); while(blocks >= 4) { serpent_encrypt_4(in, out, KS); in += 4 * BLOCK_SIZE; out += 4 * BLOCK_SIZE; blocks -= 4; } if(blocks) Serpent::encrypt_n(in, out, blocks); } /* * Serpent Decryption */ void Serpent_SIMD::decrypt_n(const byte in[], byte out[], size_t blocks) const { const u32bit* KS = &(this->get_round_keys()[0]); while(blocks >= 4) { serpent_decrypt_4(in, out, KS); in += 4 * BLOCK_SIZE; out += 4 * BLOCK_SIZE; blocks -= 4; } if(blocks) Serpent::decrypt_n(in, out, blocks); } } /* * Skipjack * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { namespace { /* * Skipjack Stepping Rule 'A' */ void step_A(u16bit& W1, u16bit& W4, size_t round, const byte FTAB[]) { byte G1 = get_byte(0, W1), G2 = get_byte(1, W1), G3; G3 = FTAB[((4*round-4)%10)*256 + G2] ^ G1; G1 = FTAB[((4*round-3)%10)*256 + G3] ^ G2; G2 = FTAB[((4*round-2)%10)*256 + G1] ^ G3; G3 = FTAB[((4*round-1)%10)*256 + G2] ^ G1; W1 = make_u16bit(G2, G3); W4 ^= W1 ^ round; } /* * Skipjack Stepping Rule 'B' */ void step_B(u16bit& W1, u16bit& W2, size_t round, const byte FTAB[]) { W2 ^= W1 ^ round; byte G1 = get_byte(0, W1), G2 = get_byte(1, W1), G3; G3 = FTAB[((4*round-4)%10)*256 + G2] ^ G1; G1 = FTAB[((4*round-3)%10)*256 + G3] ^ G2; G2 = FTAB[((4*round-2)%10)*256 + G1] ^ G3; G3 = FTAB[((4*round-1)%10)*256 + G2] ^ G1; W1 = make_u16bit(G2, G3); } /* * Skipjack Invserse Stepping Rule 'A' */ void step_Ai(u16bit& W1, u16bit& W2, size_t round, const byte FTAB[]) { W1 ^= W2 ^ round; byte G1 = get_byte(1, W2), G2 = get_byte(0, W2), G3; G3 = FTAB[((4 * round - 1) % 10)*256 + G2] ^ G1; G1 = FTAB[((4 * round - 2) % 10)*256 + G3] ^ G2; G2 = FTAB[((4 * round - 3) % 10)*256 + G1] ^ G3; G3 = FTAB[((4 * round - 4) % 10)*256 + G2] ^ G1; W2 = make_u16bit(G3, G2); } /* * Skipjack Invserse Stepping Rule 'B' */ void step_Bi(u16bit& W2, u16bit& W3, size_t round, const byte FTAB[]) { byte G1 = get_byte(1, W2), G2 = get_byte(0, W2), G3; G3 = FTAB[((4 * round - 1) % 10)*256 + G2] ^ G1; G1 = FTAB[((4 * round - 2) % 10)*256 + G3] ^ G2; G2 = FTAB[((4 * round - 3) % 10)*256 + G1] ^ G3; G3 = FTAB[((4 * round - 4) % 10)*256 + G2] ^ G1; W2 = make_u16bit(G3, G2); W3 ^= W2 ^ round; } } /* * Skipjack Encryption */ void Skipjack::encrypt_n(const byte in[], byte out[], size_t blocks) const { const byte* ftab = &FTAB[0]; for(size_t i = 0; i != blocks; ++i) { u16bit W1 = load_le(in, 3); u16bit W2 = load_le(in, 2); u16bit W3 = load_le(in, 1); u16bit W4 = load_le(in, 0); step_A(W1, W4, 1, ftab); step_A(W4, W3, 2, ftab); step_A(W3, W2, 3, ftab); step_A(W2, W1, 4, ftab); step_A(W1, W4, 5, ftab); step_A(W4, W3, 6, ftab); step_A(W3, W2, 7, ftab); step_A(W2, W1, 8, ftab); step_B(W1, W2, 9, ftab); step_B(W4, W1, 10, ftab); step_B(W3, W4, 11, ftab); step_B(W2, W3, 12, ftab); step_B(W1, W2, 13, ftab); step_B(W4, W1, 14, ftab); step_B(W3, W4, 15, ftab); step_B(W2, W3, 16, ftab); step_A(W1, W4, 17, ftab); step_A(W4, W3, 18, ftab); step_A(W3, W2, 19, ftab); step_A(W2, W1, 20, ftab); step_A(W1, W4, 21, ftab); step_A(W4, W3, 22, ftab); step_A(W3, W2, 23, ftab); step_A(W2, W1, 24, ftab); step_B(W1, W2, 25, ftab); step_B(W4, W1, 26, ftab); step_B(W3, W4, 27, ftab); step_B(W2, W3, 28, ftab); step_B(W1, W2, 29, ftab); step_B(W4, W1, 30, ftab); step_B(W3, W4, 31, ftab); step_B(W2, W3, 32, ftab); store_le(out, W4, W3, W2, W1); in += BLOCK_SIZE; out += BLOCK_SIZE; } } /* * Skipjack Decryption */ void Skipjack::decrypt_n(const byte in[], byte out[], size_t blocks) const { const byte* ftab = &FTAB[0]; for(size_t i = 0; i != blocks; ++i) { u16bit W1 = load_le(in, 3); u16bit W2 = load_le(in, 2); u16bit W3 = load_le(in, 1); u16bit W4 = load_le(in, 0); step_Bi(W2, W3, 32, ftab); step_Bi(W3, W4, 31, ftab); step_Bi(W4, W1, 30, ftab); step_Bi(W1, W2, 29, ftab); step_Bi(W2, W3, 28, ftab); step_Bi(W3, W4, 27, ftab); step_Bi(W4, W1, 26, ftab); step_Bi(W1, W2, 25, ftab); step_Ai(W1, W2, 24, ftab); step_Ai(W2, W3, 23, ftab); step_Ai(W3, W4, 22, ftab); step_Ai(W4, W1, 21, ftab); step_Ai(W1, W2, 20, ftab); step_Ai(W2, W3, 19, ftab); step_Ai(W3, W4, 18, ftab); step_Ai(W4, W1, 17, ftab); step_Bi(W2, W3, 16, ftab); step_Bi(W3, W4, 15, ftab); step_Bi(W4, W1, 14, ftab); step_Bi(W1, W2, 13, ftab); step_Bi(W2, W3, 12, ftab); step_Bi(W3, W4, 11, ftab); step_Bi(W4, W1, 10, ftab); step_Bi(W1, W2, 9, ftab); step_Ai(W1, W2, 8, ftab); step_Ai(W2, W3, 7, ftab); step_Ai(W3, W4, 6, ftab); step_Ai(W4, W1, 5, ftab); step_Ai(W1, W2, 4, ftab); step_Ai(W2, W3, 3, ftab); step_Ai(W3, W4, 2, ftab); step_Ai(W4, W1, 1, ftab); store_le(out, W4, W3, W2, W1); in += BLOCK_SIZE; out += BLOCK_SIZE; } } /* * Skipjack Key Schedule */ void Skipjack::key_schedule(const byte key[], size_t) { static const byte F[256] = { 0xA3, 0xD7, 0x09, 0x83, 0xF8, 0x48, 0xF6, 0xF4, 0xB3, 0x21, 0x15, 0x78, 0x99, 0xB1, 0xAF, 0xF9, 0xE7, 0x2D, 0x4D, 0x8A, 0xCE, 0x4C, 0xCA, 0x2E, 0x52, 0x95, 0xD9, 0x1E, 0x4E, 0x38, 0x44, 0x28, 0x0A, 0xDF, 0x02, 0xA0, 0x17, 0xF1, 0x60, 0x68, 0x12, 0xB7, 0x7A, 0xC3, 0xE9, 0xFA, 0x3D, 0x53, 0x96, 0x84, 0x6B, 0xBA, 0xF2, 0x63, 0x9A, 0x19, 0x7C, 0xAE, 0xE5, 0xF5, 0xF7, 0x16, 0x6A, 0xA2, 0x39, 0xB6, 0x7B, 0x0F, 0xC1, 0x93, 0x81, 0x1B, 0xEE, 0xB4, 0x1A, 0xEA, 0xD0, 0x91, 0x2F, 0xB8, 0x55, 0xB9, 0xDA, 0x85, 0x3F, 0x41, 0xBF, 0xE0, 0x5A, 0x58, 0x80, 0x5F, 0x66, 0x0B, 0xD8, 0x90, 0x35, 0xD5, 0xC0, 0xA7, 0x33, 0x06, 0x65, 0x69, 0x45, 0x00, 0x94, 0x56, 0x6D, 0x98, 0x9B, 0x76, 0x97, 0xFC, 0xB2, 0xC2, 0xB0, 0xFE, 0xDB, 0x20, 0xE1, 0xEB, 0xD6, 0xE4, 0xDD, 0x47, 0x4A, 0x1D, 0x42, 0xED, 0x9E, 0x6E, 0x49, 0x3C, 0xCD, 0x43, 0x27, 0xD2, 0x07, 0xD4, 0xDE, 0xC7, 0x67, 0x18, 0x89, 0xCB, 0x30, 0x1F, 0x8D, 0xC6, 0x8F, 0xAA, 0xC8, 0x74, 0xDC, 0xC9, 0x5D, 0x5C, 0x31, 0xA4, 0x70, 0x88, 0x61, 0x2C, 0x9F, 0x0D, 0x2B, 0x87, 0x50, 0x82, 0x54, 0x64, 0x26, 0x7D, 0x03, 0x40, 0x34, 0x4B, 0x1C, 0x73, 0xD1, 0xC4, 0xFD, 0x3B, 0xCC, 0xFB, 0x7F, 0xAB, 0xE6, 0x3E, 0x5B, 0xA5, 0xAD, 0x04, 0x23, 0x9C, 0x14, 0x51, 0x22, 0xF0, 0x29, 0x79, 0x71, 0x7E, 0xFF, 0x8C, 0x0E, 0xE2, 0x0C, 0xEF, 0xBC, 0x72, 0x75, 0x6F, 0x37, 0xA1, 0xEC, 0xD3, 0x8E, 0x62, 0x8B, 0x86, 0x10, 0xE8, 0x08, 0x77, 0x11, 0xBE, 0x92, 0x4F, 0x24, 0xC5, 0x32, 0x36, 0x9D, 0xCF, 0xF3, 0xA6, 0xBB, 0xAC, 0x5E, 0x6C, 0xA9, 0x13, 0x57, 0x25, 0xB5, 0xE3, 0xBD, 0xA8, 0x3A, 0x01, 0x05, 0x59, 0x2A, 0x46 }; for(size_t i = 0; i != 10; ++i) for(size_t j = 0; j != 256; ++j) FTAB[256*i+j] = F[j ^ key[9-i]]; } /* * Clear memory of sensitive data */ void Skipjack::clear() { zeroise(FTAB); } } /* * S-Box and Diffusion Tables for Square * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { const byte Square::SE[256] = { 0xB1, 0xCE, 0xC3, 0x95, 0x5A, 0xAD, 0xE7, 0x02, 0x4D, 0x44, 0xFB, 0x91, 0x0C, 0x87, 0xA1, 0x50, 0xCB, 0x67, 0x54, 0xDD, 0x46, 0x8F, 0xE1, 0x4E, 0xF0, 0xFD, 0xFC, 0xEB, 0xF9, 0xC4, 0x1A, 0x6E, 0x5E, 0xF5, 0xCC, 0x8D, 0x1C, 0x56, 0x43, 0xFE, 0x07, 0x61, 0xF8, 0x75, 0x59, 0xFF, 0x03, 0x22, 0x8A, 0xD1, 0x13, 0xEE, 0x88, 0x00, 0x0E, 0x34, 0x15, 0x80, 0x94, 0xE3, 0xED, 0xB5, 0x53, 0x23, 0x4B, 0x47, 0x17, 0xA7, 0x90, 0x35, 0xAB, 0xD8, 0xB8, 0xDF, 0x4F, 0x57, 0x9A, 0x92, 0xDB, 0x1B, 0x3C, 0xC8, 0x99, 0x04, 0x8E, 0xE0, 0xD7, 0x7D, 0x85, 0xBB, 0x40, 0x2C, 0x3A, 0x45, 0xF1, 0x42, 0x65, 0x20, 0x41, 0x18, 0x72, 0x25, 0x93, 0x70, 0x36, 0x05, 0xF2, 0x0B, 0xA3, 0x79, 0xEC, 0x08, 0x27, 0x31, 0x32, 0xB6, 0x7C, 0xB0, 0x0A, 0x73, 0x5B, 0x7B, 0xB7, 0x81, 0xD2, 0x0D, 0x6A, 0x26, 0x9E, 0x58, 0x9C, 0x83, 0x74, 0xB3, 0xAC, 0x30, 0x7A, 0x69, 0x77, 0x0F, 0xAE, 0x21, 0xDE, 0xD0, 0x2E, 0x97, 0x10, 0xA4, 0x98, 0xA8, 0xD4, 0x68, 0x2D, 0x62, 0x29, 0x6D, 0x16, 0x49, 0x76, 0xC7, 0xE8, 0xC1, 0x96, 0x37, 0xE5, 0xCA, 0xF4, 0xE9, 0x63, 0x12, 0xC2, 0xA6, 0x14, 0xBC, 0xD3, 0x28, 0xAF, 0x2F, 0xE6, 0x24, 0x52, 0xC6, 0xA0, 0x09, 0xBD, 0x8C, 0xCF, 0x5D, 0x11, 0x5F, 0x01, 0xC5, 0x9F, 0x3D, 0xA2, 0x9B, 0xC9, 0x3B, 0xBE, 0x51, 0x19, 0x1F, 0x3F, 0x5C, 0xB2, 0xEF, 0x4A, 0xCD, 0xBF, 0xBA, 0x6F, 0x64, 0xD9, 0xF3, 0x3E, 0xB4, 0xAA, 0xDC, 0xD5, 0x06, 0xC0, 0x7E, 0xF6, 0x66, 0x6C, 0x84, 0x71, 0x38, 0xB9, 0x1D, 0x7F, 0x9D, 0x48, 0x8B, 0x2A, 0xDA, 0xA5, 0x33, 0x82, 0x39, 0xD6, 0x78, 0x86, 0xFA, 0xE4, 0x2B, 0xA9, 0x1E, 0x89, 0x60, 0x6B, 0xEA, 0x55, 0x4C, 0xF7, 0xE2 }; const byte Square::SD[256] = { 0x35, 0xBE, 0x07, 0x2E, 0x53, 0x69, 0xDB, 0x28, 0x6F, 0xB7, 0x76, 0x6B, 0x0C, 0x7D, 0x36, 0x8B, 0x92, 0xBC, 0xA9, 0x32, 0xAC, 0x38, 0x9C, 0x42, 0x63, 0xC8, 0x1E, 0x4F, 0x24, 0xE5, 0xF7, 0xC9, 0x61, 0x8D, 0x2F, 0x3F, 0xB3, 0x65, 0x7F, 0x70, 0xAF, 0x9A, 0xEA, 0xF5, 0x5B, 0x98, 0x90, 0xB1, 0x87, 0x71, 0x72, 0xED, 0x37, 0x45, 0x68, 0xA3, 0xE3, 0xEF, 0x5C, 0xC5, 0x50, 0xC1, 0xD6, 0xCA, 0x5A, 0x62, 0x5F, 0x26, 0x09, 0x5D, 0x14, 0x41, 0xE8, 0x9D, 0xCE, 0x40, 0xFD, 0x08, 0x17, 0x4A, 0x0F, 0xC7, 0xB4, 0x3E, 0x12, 0xFC, 0x25, 0x4B, 0x81, 0x2C, 0x04, 0x78, 0xCB, 0xBB, 0x20, 0xBD, 0xF9, 0x29, 0x99, 0xA8, 0xD3, 0x60, 0xDF, 0x11, 0x97, 0x89, 0x7E, 0xFA, 0xE0, 0x9B, 0x1F, 0xD2, 0x67, 0xE2, 0x64, 0x77, 0x84, 0x2B, 0x9E, 0x8A, 0xF1, 0x6D, 0x88, 0x79, 0x74, 0x57, 0xDD, 0xE6, 0x39, 0x7B, 0xEE, 0x83, 0xE1, 0x58, 0xF2, 0x0D, 0x34, 0xF8, 0x30, 0xE9, 0xB9, 0x23, 0x54, 0x15, 0x44, 0x0B, 0x4D, 0x66, 0x3A, 0x03, 0xA2, 0x91, 0x94, 0x52, 0x4C, 0xC3, 0x82, 0xE7, 0x80, 0xC0, 0xB6, 0x0E, 0xC2, 0x6C, 0x93, 0xEC, 0xAB, 0x43, 0x95, 0xF6, 0xD8, 0x46, 0x86, 0x05, 0x8C, 0xB0, 0x75, 0x00, 0xCC, 0x85, 0xD7, 0x3D, 0x73, 0x7A, 0x48, 0xE4, 0xD1, 0x59, 0xAD, 0xB8, 0xC6, 0xD0, 0xDC, 0xA1, 0xAA, 0x02, 0x1D, 0xBF, 0xB5, 0x9F, 0x51, 0xC4, 0xA5, 0x10, 0x22, 0xCF, 0x01, 0xBA, 0x8F, 0x31, 0x7C, 0xAE, 0x96, 0xDA, 0xF0, 0x56, 0x47, 0xD4, 0xEB, 0x4E, 0xD9, 0x13, 0x8E, 0x49, 0x55, 0x16, 0xFF, 0x3B, 0xF4, 0xA4, 0xB2, 0x06, 0xA0, 0xA7, 0xFB, 0x1B, 0x6E, 0x3C, 0x33, 0xCD, 0x18, 0x5E, 0x6A, 0xD5, 0xA6, 0x21, 0xDE, 0xFE, 0x2A, 0x1C, 0xF3, 0x0A, 0x1A, 0x19, 0x27, 0x2D }; const byte Square::Log[256] = { 0x00, 0x00, 0x01, 0x86, 0x02, 0x0D, 0x87, 0x4C, 0x03, 0xD2, 0x0E, 0xAE, 0x88, 0x22, 0x4D, 0x93, 0x04, 0x1A, 0xD3, 0xCB, 0x0F, 0x98, 0xAF, 0xA8, 0x89, 0xF0, 0x23, 0x59, 0x4E, 0x35, 0x94, 0x09, 0x05, 0x8F, 0x1B, 0x6E, 0xD4, 0x39, 0xCC, 0xBB, 0x10, 0x68, 0x99, 0x77, 0xB0, 0xDF, 0xA9, 0x72, 0x8A, 0xFA, 0xF1, 0xA0, 0x24, 0x52, 0x5A, 0x60, 0x4F, 0x2F, 0x36, 0xDC, 0x95, 0x32, 0x0A, 0x1F, 0x06, 0xA5, 0x90, 0x49, 0x1C, 0x5D, 0x6F, 0xB8, 0xD5, 0xC1, 0x3A, 0xB5, 0xCD, 0x63, 0xBC, 0x3D, 0x11, 0x44, 0x69, 0x81, 0x9A, 0x27, 0x78, 0xC4, 0xB1, 0xE6, 0xE0, 0xEA, 0xAA, 0x55, 0x73, 0xD8, 0x8B, 0xF6, 0xFB, 0x16, 0xF2, 0xF4, 0xA1, 0x40, 0x25, 0x42, 0x53, 0xE4, 0x5B, 0xA3, 0x61, 0xBF, 0x50, 0xF8, 0x30, 0x2D, 0x37, 0x8D, 0xDD, 0x66, 0x96, 0x18, 0x33, 0xEE, 0x0B, 0xFD, 0x20, 0xD0, 0x07, 0x57, 0xA6, 0xC9, 0x91, 0xAC, 0x4A, 0x84, 0x1D, 0xDA, 0x5E, 0x9E, 0x70, 0x75, 0xB9, 0x6C, 0xD6, 0xE8, 0xC2, 0x7F, 0x3B, 0xB3, 0xB6, 0x47, 0xCE, 0xEC, 0x64, 0x2B, 0xBD, 0xE2, 0x3E, 0x14, 0x12, 0x29, 0x45, 0x7D, 0x6A, 0x9C, 0x82, 0xC7, 0x9B, 0xC6, 0x28, 0x7C, 0x79, 0x7A, 0xC5, 0x7B, 0xB2, 0x46, 0xE7, 0x7E, 0xE1, 0x13, 0xEB, 0x2A, 0xAB, 0x83, 0x56, 0xC8, 0x74, 0x6B, 0xD9, 0x9D, 0x8C, 0x65, 0xF7, 0x2C, 0xFC, 0xCF, 0x17, 0xED, 0xF3, 0x3F, 0xF5, 0x15, 0xA2, 0xBE, 0x41, 0xE3, 0x26, 0xC3, 0x43, 0x80, 0x54, 0xD7, 0xE5, 0xE9, 0x5C, 0xB7, 0xA4, 0x48, 0x62, 0x3C, 0xC0, 0xB4, 0x51, 0x5F, 0xF9, 0x9F, 0x31, 0x1E, 0x2E, 0xDB, 0x38, 0xBA, 0x8E, 0x6D, 0xDE, 0x71, 0x67, 0x76, 0x97, 0xA7, 0x19, 0xCA, 0x34, 0x08, 0xEF, 0x58, 0x0C, 0x4B, 0xFE, 0x85, 0x21, 0x92, 0xD1, 0xAD }; const byte Square::ALog[255] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0xF5, 0x1F, 0x3E, 0x7C, 0xF8, 0x05, 0x0A, 0x14, 0x28, 0x50, 0xA0, 0xB5, 0x9F, 0xCB, 0x63, 0xC6, 0x79, 0xF2, 0x11, 0x22, 0x44, 0x88, 0xE5, 0x3F, 0x7E, 0xFC, 0x0D, 0x1A, 0x34, 0x68, 0xD0, 0x55, 0xAA, 0xA1, 0xB7, 0x9B, 0xC3, 0x73, 0xE6, 0x39, 0x72, 0xE4, 0x3D, 0x7A, 0xF4, 0x1D, 0x3A, 0x74, 0xE8, 0x25, 0x4A, 0x94, 0xDD, 0x4F, 0x9E, 0xC9, 0x67, 0xCE, 0x69, 0xD2, 0x51, 0xA2, 0xB1, 0x97, 0xDB, 0x43, 0x86, 0xF9, 0x07, 0x0E, 0x1C, 0x38, 0x70, 0xE0, 0x35, 0x6A, 0xD4, 0x5D, 0xBA, 0x81, 0xF7, 0x1B, 0x36, 0x6C, 0xD8, 0x45, 0x8A, 0xE1, 0x37, 0x6E, 0xDC, 0x4D, 0x9A, 0xC1, 0x77, 0xEE, 0x29, 0x52, 0xA4, 0xBD, 0x8F, 0xEB, 0x23, 0x46, 0x8C, 0xED, 0x2F, 0x5E, 0xBC, 0x8D, 0xEF, 0x2B, 0x56, 0xAC, 0xAD, 0xAF, 0xAB, 0xA3, 0xB3, 0x93, 0xD3, 0x53, 0xA6, 0xB9, 0x87, 0xFB, 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0x75, 0xEA, 0x21, 0x42, 0x84, 0xFD, 0x0F, 0x1E, 0x3C, 0x78, 0xF0, 0x15, 0x2A, 0x54, 0xA8, 0xA5, 0xBF, 0x8B, 0xE3, 0x33, 0x66, 0xCC, 0x6D, 0xDA, 0x41, 0x82, 0xF1, 0x17, 0x2E, 0x5C, 0xB8, 0x85, 0xFF, 0x0B, 0x16, 0x2C, 0x58, 0xB0, 0x95, 0xDF, 0x4B, 0x96, 0xD9, 0x47, 0x8E, 0xE9, 0x27, 0x4E, 0x9C, 0xCD, 0x6F, 0xDE, 0x49, 0x92, 0xD1, 0x57, 0xAE, 0xA9, 0xA7, 0xBB, 0x83, 0xF3, 0x13, 0x26, 0x4C, 0x98, 0xC5, 0x7F, 0xFE, 0x09, 0x12, 0x24, 0x48, 0x90, 0xD5, 0x5F, 0xBE, 0x89, 0xE7, 0x3B, 0x76, 0xEC, 0x2D, 0x5A, 0xB4, 0x9D, 0xCF, 0x6B, 0xD6, 0x59, 0xB2, 0x91, 0xD7, 0x5B, 0xB6, 0x99, 0xC7, 0x7B, 0xF6, 0x19, 0x32, 0x64, 0xC8, 0x65, 0xCA, 0x61, 0xC2, 0x71, 0xE2, 0x31, 0x62, 0xC4, 0x7D, 0xFA }; const u32bit Square::TE0[256] = { 0x97B1B126, 0x69CECEA7, 0x73C3C3B0, 0xDF95954A, 0xB45A5AEE, 0xAFADAD02, 0x3BE7E7DC, 0x04020206, 0x9A4D4DD7, 0x884444CC, 0x03FBFBF8, 0xD7919146, 0x180C0C14, 0xFB87877C, 0xB7A1A116, 0xA05050F0, 0x63CBCBA8, 0xCE6767A9, 0xA85454FC, 0x4FDDDD92, 0x8C4646CA, 0xEB8F8F64, 0x37E1E1D6, 0x9C4E4ED2, 0x15F0F0E5, 0x0FFDFDF2, 0x0DFCFCF1, 0x23EBEBC8, 0x07F9F9FE, 0x7DC4C4B9, 0x341A1A2E, 0xDC6E6EB2, 0xBC5E5EE2, 0x1FF5F5EA, 0x6DCCCCA1, 0xEF8D8D62, 0x381C1C24, 0xAC5656FA, 0x864343C5, 0x09FEFEF7, 0x0E070709, 0xC26161A3, 0x05F8F8FD, 0xEA75759F, 0xB25959EB, 0x0BFFFFF4, 0x06030305, 0x44222266, 0xE18A8A6B, 0x57D1D186, 0x26131335, 0x29EEEEC7, 0xE588886D, 0x00000000, 0x1C0E0E12, 0x6834345C, 0x2A15153F, 0xF5808075, 0xDD949449, 0x33E3E3D0, 0x2FEDEDC2, 0x9FB5B52A, 0xA65353F5, 0x46232365, 0x964B4BDD, 0x8E4747C9, 0x2E171739, 0xBBA7A71C, 0xD5909045, 0x6A35355F, 0xA3ABAB08, 0x45D8D89D, 0x85B8B83D, 0x4BDFDF94, 0x9E4F4FD1, 0xAE5757F9, 0xC19A9A5B, 0xD1929243, 0x43DBDB98, 0x361B1B2D, 0x783C3C44, 0x65C8C8AD, 0xC799995E, 0x0804040C, 0xE98E8E67, 0x35E0E0D5, 0x5BD7D78C, 0xFA7D7D87, 0xFF85857A, 0x83BBBB38, 0x804040C0, 0x582C2C74, 0x743A3A4E, 0x8A4545CF, 0x17F1F1E6, 0x844242C6, 0xCA6565AF, 0x40202060, 0x824141C3, 0x30181828, 0xE4727296, 0x4A25256F, 0xD3939340, 0xE0707090, 0x6C36365A, 0x0A05050F, 0x11F2F2E3, 0x160B0B1D, 0xB3A3A310, 0xF279798B, 0x2DECECC1, 0x10080818, 0x4E272769, 0x62313153, 0x64323256, 0x99B6B62F, 0xF87C7C84, 0x95B0B025, 0x140A0A1E, 0xE6737395, 0xB65B5BED, 0xF67B7B8D, 0x9BB7B72C, 0xF7818176, 0x51D2D283, 0x1A0D0D17, 0xD46A6ABE, 0x4C26266A, 0xC99E9E57, 0xB05858E8, 0xCD9C9C51, 0xF3838370, 0xE874749C, 0x93B3B320, 0xADACAC01, 0x60303050, 0xF47A7A8E, 0xD26969BB, 0xEE777799, 0x1E0F0F11, 0xA9AEAE07, 0x42212163, 0x49DEDE97, 0x55D0D085, 0x5C2E2E72, 0xDB97974C, 0x20101030, 0xBDA4A419, 0xC598985D, 0xA5A8A80D, 0x5DD4D489, 0xD06868B8, 0x5A2D2D77, 0xC46262A6, 0x5229297B, 0xDA6D6DB7, 0x2C16163A, 0x924949DB, 0xEC76769A, 0x7BC7C7BC, 0x25E8E8CD, 0x77C1C1B6, 0xD996964F, 0x6E373759, 0x3FE5E5DA, 0x61CACAAB, 0x1DF4F4E9, 0x27E9E9CE, 0xC66363A5, 0x24121236, 0x71C2C2B3, 0xB9A6A61F, 0x2814143C, 0x8DBCBC31, 0x53D3D380, 0x50282878, 0xABAFAF04, 0x5E2F2F71, 0x39E6E6DF, 0x4824246C, 0xA45252F6, 0x79C6C6BF, 0xB5A0A015, 0x1209091B, 0x8FBDBD32, 0xED8C8C61, 0x6BCFCFA4, 0xBA5D5DE7, 0x22111133, 0xBE5F5FE1, 0x02010103, 0x7FC5C5BA, 0xCB9F9F54, 0x7A3D3D47, 0xB1A2A213, 0xC39B9B58, 0x67C9C9AE, 0x763B3B4D, 0x89BEBE37, 0xA25151F3, 0x3219192B, 0x3E1F1F21, 0x7E3F3F41, 0xB85C5CE4, 0x91B2B223, 0x2BEFEFC4, 0x944A4ADE, 0x6FCDCDA2, 0x8BBFBF34, 0x81BABA3B, 0xDE6F6FB1, 0xC86464AC, 0x47D9D99E, 0x13F3F3E0, 0x7C3E3E42, 0x9DB4B429, 0xA1AAAA0B, 0x4DDCDC91, 0x5FD5D58A, 0x0C06060A, 0x75C0C0B5, 0xFC7E7E82, 0x19F6F6EF, 0xCC6666AA, 0xD86C6CB4, 0xFD848479, 0xE2717193, 0x70383848, 0x87B9B93E, 0x3A1D1D27, 0xFE7F7F81, 0xCF9D9D52, 0x904848D8, 0xE38B8B68, 0x542A2A7E, 0x41DADA9B, 0xBFA5A51A, 0x66333355, 0xF1828273, 0x7239394B, 0x59D6D68F, 0xF0787888, 0xF986867F, 0x01FAFAFB, 0x3DE4E4D9, 0x562B2B7D, 0xA7A9A90E, 0x3C1E1E22, 0xE789896E, 0xC06060A0, 0xD66B6BBD, 0x21EAEACB, 0xAA5555FF, 0x984C4CD4, 0x1BF7F7EC, 0x31E2E2D3 }; const u32bit Square::TE1[256] = { 0x2697B1B1, 0xA769CECE, 0xB073C3C3, 0x4ADF9595, 0xEEB45A5A, 0x02AFADAD, 0xDC3BE7E7, 0x06040202, 0xD79A4D4D, 0xCC884444, 0xF803FBFB, 0x46D79191, 0x14180C0C, 0x7CFB8787, 0x16B7A1A1, 0xF0A05050, 0xA863CBCB, 0xA9CE6767, 0xFCA85454, 0x924FDDDD, 0xCA8C4646, 0x64EB8F8F, 0xD637E1E1, 0xD29C4E4E, 0xE515F0F0, 0xF20FFDFD, 0xF10DFCFC, 0xC823EBEB, 0xFE07F9F9, 0xB97DC4C4, 0x2E341A1A, 0xB2DC6E6E, 0xE2BC5E5E, 0xEA1FF5F5, 0xA16DCCCC, 0x62EF8D8D, 0x24381C1C, 0xFAAC5656, 0xC5864343, 0xF709FEFE, 0x090E0707, 0xA3C26161, 0xFD05F8F8, 0x9FEA7575, 0xEBB25959, 0xF40BFFFF, 0x05060303, 0x66442222, 0x6BE18A8A, 0x8657D1D1, 0x35261313, 0xC729EEEE, 0x6DE58888, 0x00000000, 0x121C0E0E, 0x5C683434, 0x3F2A1515, 0x75F58080, 0x49DD9494, 0xD033E3E3, 0xC22FEDED, 0x2A9FB5B5, 0xF5A65353, 0x65462323, 0xDD964B4B, 0xC98E4747, 0x392E1717, 0x1CBBA7A7, 0x45D59090, 0x5F6A3535, 0x08A3ABAB, 0x9D45D8D8, 0x3D85B8B8, 0x944BDFDF, 0xD19E4F4F, 0xF9AE5757, 0x5BC19A9A, 0x43D19292, 0x9843DBDB, 0x2D361B1B, 0x44783C3C, 0xAD65C8C8, 0x5EC79999, 0x0C080404, 0x67E98E8E, 0xD535E0E0, 0x8C5BD7D7, 0x87FA7D7D, 0x7AFF8585, 0x3883BBBB, 0xC0804040, 0x74582C2C, 0x4E743A3A, 0xCF8A4545, 0xE617F1F1, 0xC6844242, 0xAFCA6565, 0x60402020, 0xC3824141, 0x28301818, 0x96E47272, 0x6F4A2525, 0x40D39393, 0x90E07070, 0x5A6C3636, 0x0F0A0505, 0xE311F2F2, 0x1D160B0B, 0x10B3A3A3, 0x8BF27979, 0xC12DECEC, 0x18100808, 0x694E2727, 0x53623131, 0x56643232, 0x2F99B6B6, 0x84F87C7C, 0x2595B0B0, 0x1E140A0A, 0x95E67373, 0xEDB65B5B, 0x8DF67B7B, 0x2C9BB7B7, 0x76F78181, 0x8351D2D2, 0x171A0D0D, 0xBED46A6A, 0x6A4C2626, 0x57C99E9E, 0xE8B05858, 0x51CD9C9C, 0x70F38383, 0x9CE87474, 0x2093B3B3, 0x01ADACAC, 0x50603030, 0x8EF47A7A, 0xBBD26969, 0x99EE7777, 0x111E0F0F, 0x07A9AEAE, 0x63422121, 0x9749DEDE, 0x8555D0D0, 0x725C2E2E, 0x4CDB9797, 0x30201010, 0x19BDA4A4, 0x5DC59898, 0x0DA5A8A8, 0x895DD4D4, 0xB8D06868, 0x775A2D2D, 0xA6C46262, 0x7B522929, 0xB7DA6D6D, 0x3A2C1616, 0xDB924949, 0x9AEC7676, 0xBC7BC7C7, 0xCD25E8E8, 0xB677C1C1, 0x4FD99696, 0x596E3737, 0xDA3FE5E5, 0xAB61CACA, 0xE91DF4F4, 0xCE27E9E9, 0xA5C66363, 0x36241212, 0xB371C2C2, 0x1FB9A6A6, 0x3C281414, 0x318DBCBC, 0x8053D3D3, 0x78502828, 0x04ABAFAF, 0x715E2F2F, 0xDF39E6E6, 0x6C482424, 0xF6A45252, 0xBF79C6C6, 0x15B5A0A0, 0x1B120909, 0x328FBDBD, 0x61ED8C8C, 0xA46BCFCF, 0xE7BA5D5D, 0x33221111, 0xE1BE5F5F, 0x03020101, 0xBA7FC5C5, 0x54CB9F9F, 0x477A3D3D, 0x13B1A2A2, 0x58C39B9B, 0xAE67C9C9, 0x4D763B3B, 0x3789BEBE, 0xF3A25151, 0x2B321919, 0x213E1F1F, 0x417E3F3F, 0xE4B85C5C, 0x2391B2B2, 0xC42BEFEF, 0xDE944A4A, 0xA26FCDCD, 0x348BBFBF, 0x3B81BABA, 0xB1DE6F6F, 0xACC86464, 0x9E47D9D9, 0xE013F3F3, 0x427C3E3E, 0x299DB4B4, 0x0BA1AAAA, 0x914DDCDC, 0x8A5FD5D5, 0x0A0C0606, 0xB575C0C0, 0x82FC7E7E, 0xEF19F6F6, 0xAACC6666, 0xB4D86C6C, 0x79FD8484, 0x93E27171, 0x48703838, 0x3E87B9B9, 0x273A1D1D, 0x81FE7F7F, 0x52CF9D9D, 0xD8904848, 0x68E38B8B, 0x7E542A2A, 0x9B41DADA, 0x1ABFA5A5, 0x55663333, 0x73F18282, 0x4B723939, 0x8F59D6D6, 0x88F07878, 0x7FF98686, 0xFB01FAFA, 0xD93DE4E4, 0x7D562B2B, 0x0EA7A9A9, 0x223C1E1E, 0x6EE78989, 0xA0C06060, 0xBDD66B6B, 0xCB21EAEA, 0xFFAA5555, 0xD4984C4C, 0xEC1BF7F7, 0xD331E2E2 }; const u32bit Square::TE2[256] = { 0xB12697B1, 0xCEA769CE, 0xC3B073C3, 0x954ADF95, 0x5AEEB45A, 0xAD02AFAD, 0xE7DC3BE7, 0x02060402, 0x4DD79A4D, 0x44CC8844, 0xFBF803FB, 0x9146D791, 0x0C14180C, 0x877CFB87, 0xA116B7A1, 0x50F0A050, 0xCBA863CB, 0x67A9CE67, 0x54FCA854, 0xDD924FDD, 0x46CA8C46, 0x8F64EB8F, 0xE1D637E1, 0x4ED29C4E, 0xF0E515F0, 0xFDF20FFD, 0xFCF10DFC, 0xEBC823EB, 0xF9FE07F9, 0xC4B97DC4, 0x1A2E341A, 0x6EB2DC6E, 0x5EE2BC5E, 0xF5EA1FF5, 0xCCA16DCC, 0x8D62EF8D, 0x1C24381C, 0x56FAAC56, 0x43C58643, 0xFEF709FE, 0x07090E07, 0x61A3C261, 0xF8FD05F8, 0x759FEA75, 0x59EBB259, 0xFFF40BFF, 0x03050603, 0x22664422, 0x8A6BE18A, 0xD18657D1, 0x13352613, 0xEEC729EE, 0x886DE588, 0x00000000, 0x0E121C0E, 0x345C6834, 0x153F2A15, 0x8075F580, 0x9449DD94, 0xE3D033E3, 0xEDC22FED, 0xB52A9FB5, 0x53F5A653, 0x23654623, 0x4BDD964B, 0x47C98E47, 0x17392E17, 0xA71CBBA7, 0x9045D590, 0x355F6A35, 0xAB08A3AB, 0xD89D45D8, 0xB83D85B8, 0xDF944BDF, 0x4FD19E4F, 0x57F9AE57, 0x9A5BC19A, 0x9243D192, 0xDB9843DB, 0x1B2D361B, 0x3C44783C, 0xC8AD65C8, 0x995EC799, 0x040C0804, 0x8E67E98E, 0xE0D535E0, 0xD78C5BD7, 0x7D87FA7D, 0x857AFF85, 0xBB3883BB, 0x40C08040, 0x2C74582C, 0x3A4E743A, 0x45CF8A45, 0xF1E617F1, 0x42C68442, 0x65AFCA65, 0x20604020, 0x41C38241, 0x18283018, 0x7296E472, 0x256F4A25, 0x9340D393, 0x7090E070, 0x365A6C36, 0x050F0A05, 0xF2E311F2, 0x0B1D160B, 0xA310B3A3, 0x798BF279, 0xECC12DEC, 0x08181008, 0x27694E27, 0x31536231, 0x32566432, 0xB62F99B6, 0x7C84F87C, 0xB02595B0, 0x0A1E140A, 0x7395E673, 0x5BEDB65B, 0x7B8DF67B, 0xB72C9BB7, 0x8176F781, 0xD28351D2, 0x0D171A0D, 0x6ABED46A, 0x266A4C26, 0x9E57C99E, 0x58E8B058, 0x9C51CD9C, 0x8370F383, 0x749CE874, 0xB32093B3, 0xAC01ADAC, 0x30506030, 0x7A8EF47A, 0x69BBD269, 0x7799EE77, 0x0F111E0F, 0xAE07A9AE, 0x21634221, 0xDE9749DE, 0xD08555D0, 0x2E725C2E, 0x974CDB97, 0x10302010, 0xA419BDA4, 0x985DC598, 0xA80DA5A8, 0xD4895DD4, 0x68B8D068, 0x2D775A2D, 0x62A6C462, 0x297B5229, 0x6DB7DA6D, 0x163A2C16, 0x49DB9249, 0x769AEC76, 0xC7BC7BC7, 0xE8CD25E8, 0xC1B677C1, 0x964FD996, 0x37596E37, 0xE5DA3FE5, 0xCAAB61CA, 0xF4E91DF4, 0xE9CE27E9, 0x63A5C663, 0x12362412, 0xC2B371C2, 0xA61FB9A6, 0x143C2814, 0xBC318DBC, 0xD38053D3, 0x28785028, 0xAF04ABAF, 0x2F715E2F, 0xE6DF39E6, 0x246C4824, 0x52F6A452, 0xC6BF79C6, 0xA015B5A0, 0x091B1209, 0xBD328FBD, 0x8C61ED8C, 0xCFA46BCF, 0x5DE7BA5D, 0x11332211, 0x5FE1BE5F, 0x01030201, 0xC5BA7FC5, 0x9F54CB9F, 0x3D477A3D, 0xA213B1A2, 0x9B58C39B, 0xC9AE67C9, 0x3B4D763B, 0xBE3789BE, 0x51F3A251, 0x192B3219, 0x1F213E1F, 0x3F417E3F, 0x5CE4B85C, 0xB22391B2, 0xEFC42BEF, 0x4ADE944A, 0xCDA26FCD, 0xBF348BBF, 0xBA3B81BA, 0x6FB1DE6F, 0x64ACC864, 0xD99E47D9, 0xF3E013F3, 0x3E427C3E, 0xB4299DB4, 0xAA0BA1AA, 0xDC914DDC, 0xD58A5FD5, 0x060A0C06, 0xC0B575C0, 0x7E82FC7E, 0xF6EF19F6, 0x66AACC66, 0x6CB4D86C, 0x8479FD84, 0x7193E271, 0x38487038, 0xB93E87B9, 0x1D273A1D, 0x7F81FE7F, 0x9D52CF9D, 0x48D89048, 0x8B68E38B, 0x2A7E542A, 0xDA9B41DA, 0xA51ABFA5, 0x33556633, 0x8273F182, 0x394B7239, 0xD68F59D6, 0x7888F078, 0x867FF986, 0xFAFB01FA, 0xE4D93DE4, 0x2B7D562B, 0xA90EA7A9, 0x1E223C1E, 0x896EE789, 0x60A0C060, 0x6BBDD66B, 0xEACB21EA, 0x55FFAA55, 0x4CD4984C, 0xF7EC1BF7, 0xE2D331E2 }; const u32bit Square::TE3[256] = { 0xB1B12697, 0xCECEA769, 0xC3C3B073, 0x95954ADF, 0x5A5AEEB4, 0xADAD02AF, 0xE7E7DC3B, 0x02020604, 0x4D4DD79A, 0x4444CC88, 0xFBFBF803, 0x919146D7, 0x0C0C1418, 0x87877CFB, 0xA1A116B7, 0x5050F0A0, 0xCBCBA863, 0x6767A9CE, 0x5454FCA8, 0xDDDD924F, 0x4646CA8C, 0x8F8F64EB, 0xE1E1D637, 0x4E4ED29C, 0xF0F0E515, 0xFDFDF20F, 0xFCFCF10D, 0xEBEBC823, 0xF9F9FE07, 0xC4C4B97D, 0x1A1A2E34, 0x6E6EB2DC, 0x5E5EE2BC, 0xF5F5EA1F, 0xCCCCA16D, 0x8D8D62EF, 0x1C1C2438, 0x5656FAAC, 0x4343C586, 0xFEFEF709, 0x0707090E, 0x6161A3C2, 0xF8F8FD05, 0x75759FEA, 0x5959EBB2, 0xFFFFF40B, 0x03030506, 0x22226644, 0x8A8A6BE1, 0xD1D18657, 0x13133526, 0xEEEEC729, 0x88886DE5, 0x00000000, 0x0E0E121C, 0x34345C68, 0x15153F2A, 0x808075F5, 0x949449DD, 0xE3E3D033, 0xEDEDC22F, 0xB5B52A9F, 0x5353F5A6, 0x23236546, 0x4B4BDD96, 0x4747C98E, 0x1717392E, 0xA7A71CBB, 0x909045D5, 0x35355F6A, 0xABAB08A3, 0xD8D89D45, 0xB8B83D85, 0xDFDF944B, 0x4F4FD19E, 0x5757F9AE, 0x9A9A5BC1, 0x929243D1, 0xDBDB9843, 0x1B1B2D36, 0x3C3C4478, 0xC8C8AD65, 0x99995EC7, 0x04040C08, 0x8E8E67E9, 0xE0E0D535, 0xD7D78C5B, 0x7D7D87FA, 0x85857AFF, 0xBBBB3883, 0x4040C080, 0x2C2C7458, 0x3A3A4E74, 0x4545CF8A, 0xF1F1E617, 0x4242C684, 0x6565AFCA, 0x20206040, 0x4141C382, 0x18182830, 0x727296E4, 0x25256F4A, 0x939340D3, 0x707090E0, 0x36365A6C, 0x05050F0A, 0xF2F2E311, 0x0B0B1D16, 0xA3A310B3, 0x79798BF2, 0xECECC12D, 0x08081810, 0x2727694E, 0x31315362, 0x32325664, 0xB6B62F99, 0x7C7C84F8, 0xB0B02595, 0x0A0A1E14, 0x737395E6, 0x5B5BEDB6, 0x7B7B8DF6, 0xB7B72C9B, 0x818176F7, 0xD2D28351, 0x0D0D171A, 0x6A6ABED4, 0x26266A4C, 0x9E9E57C9, 0x5858E8B0, 0x9C9C51CD, 0x838370F3, 0x74749CE8, 0xB3B32093, 0xACAC01AD, 0x30305060, 0x7A7A8EF4, 0x6969BBD2, 0x777799EE, 0x0F0F111E, 0xAEAE07A9, 0x21216342, 0xDEDE9749, 0xD0D08555, 0x2E2E725C, 0x97974CDB, 0x10103020, 0xA4A419BD, 0x98985DC5, 0xA8A80DA5, 0xD4D4895D, 0x6868B8D0, 0x2D2D775A, 0x6262A6C4, 0x29297B52, 0x6D6DB7DA, 0x16163A2C, 0x4949DB92, 0x76769AEC, 0xC7C7BC7B, 0xE8E8CD25, 0xC1C1B677, 0x96964FD9, 0x3737596E, 0xE5E5DA3F, 0xCACAAB61, 0xF4F4E91D, 0xE9E9CE27, 0x6363A5C6, 0x12123624, 0xC2C2B371, 0xA6A61FB9, 0x14143C28, 0xBCBC318D, 0xD3D38053, 0x28287850, 0xAFAF04AB, 0x2F2F715E, 0xE6E6DF39, 0x24246C48, 0x5252F6A4, 0xC6C6BF79, 0xA0A015B5, 0x09091B12, 0xBDBD328F, 0x8C8C61ED, 0xCFCFA46B, 0x5D5DE7BA, 0x11113322, 0x5F5FE1BE, 0x01010302, 0xC5C5BA7F, 0x9F9F54CB, 0x3D3D477A, 0xA2A213B1, 0x9B9B58C3, 0xC9C9AE67, 0x3B3B4D76, 0xBEBE3789, 0x5151F3A2, 0x19192B32, 0x1F1F213E, 0x3F3F417E, 0x5C5CE4B8, 0xB2B22391, 0xEFEFC42B, 0x4A4ADE94, 0xCDCDA26F, 0xBFBF348B, 0xBABA3B81, 0x6F6FB1DE, 0x6464ACC8, 0xD9D99E47, 0xF3F3E013, 0x3E3E427C, 0xB4B4299D, 0xAAAA0BA1, 0xDCDC914D, 0xD5D58A5F, 0x06060A0C, 0xC0C0B575, 0x7E7E82FC, 0xF6F6EF19, 0x6666AACC, 0x6C6CB4D8, 0x848479FD, 0x717193E2, 0x38384870, 0xB9B93E87, 0x1D1D273A, 0x7F7F81FE, 0x9D9D52CF, 0x4848D890, 0x8B8B68E3, 0x2A2A7E54, 0xDADA9B41, 0xA5A51ABF, 0x33335566, 0x828273F1, 0x39394B72, 0xD6D68F59, 0x787888F0, 0x86867FF9, 0xFAFAFB01, 0xE4E4D93D, 0x2B2B7D56, 0xA9A90EA7, 0x1E1E223C, 0x89896EE7, 0x6060A0C0, 0x6B6BBDD6, 0xEAEACB21, 0x5555FFAA, 0x4C4CD498, 0xF7F7EC1B, 0xE2E2D331 }; const u32bit Square::TD0[256] = { 0xE368BC02, 0x5585620C, 0x2A3F2331, 0x61AB13F7, 0x98D46D72, 0x21CB9A19, 0x3C22A461, 0x459D3DCD, 0x05FDB423, 0x2BC4075F, 0x9B2C01C0, 0x3DD9800F, 0x486C5C74, 0xF97F7E85, 0xF173AB1F, 0xB6EDDE0E, 0x283C6BED, 0x4997781A, 0x9F2A918D, 0xC9579F33, 0xA907A8AA, 0xA50DED7D, 0x7C422D8F, 0x764DB0C9, 0x4D91E857, 0xCEA963CC, 0xB4EE96D2, 0x3028E1B6, 0x0DF161B9, 0xBD196726, 0x419BAD80, 0xC0A06EC7, 0x5183F241, 0x92DBF034, 0x6FA21EFC, 0x8F32CE4C, 0x13E03373, 0x69A7C66D, 0xE56D6493, 0xBF1A2FFA, 0xBB1CBFB7, 0x587403B5, 0xE76E2C4F, 0x5D89B796, 0xE89C052A, 0x446619A3, 0x342E71FB, 0x0FF22965, 0xFE81827A, 0xB11322F1, 0xA30835EC, 0xCD510F7E, 0xFF7AA614, 0x5C7293F8, 0x2FC29712, 0xF370E3C3, 0x992F491C, 0xD1431568, 0xC2A3261B, 0x88CC32B3, 0x8ACF7A6F, 0xB0E8069F, 0x7A47F51E, 0xD2BB79DA, 0xE6950821, 0x4398E55C, 0xD0B83106, 0x11E37BAF, 0x7E416553, 0xCCAA2B10, 0xD8B4E49C, 0x6456A7D4, 0xFB7C3659, 0x724B2084, 0xEA9F4DF6, 0x6A5FAADF, 0x2DC1DFCE, 0x70486858, 0xCAAFF381, 0x0605D891, 0x5A774B69, 0x94DE28A5, 0x39DF1042, 0x813BC347, 0xFC82CAA6, 0x23C8D2C5, 0x03F86CB2, 0x080CD59A, 0xDAB7AC40, 0x7DB909E1, 0x3824342C, 0xCF5247A2, 0xDCB274D1, 0x63A85B2B, 0x35D55595, 0x479E7511, 0x15E5EBE2, 0x4B9430C6, 0x4A6F14A8, 0x91239C86, 0x4C6ACC39, 0x5F8AFF4A, 0x0406904D, 0xEE99DDBB, 0x1E1152CA, 0xAAFFC418, 0xEB646998, 0x07FEFCFF, 0x8B345E01, 0x567D0EBE, 0xBAE79BD9, 0x4263C132, 0x75B5DC7B, 0x97264417, 0x67AECB66, 0x95250CCB, 0xEC9A9567, 0x57862AD0, 0x60503799, 0xB8E4D305, 0x65AD83BA, 0x19EFAE35, 0xA4F6C913, 0xC15B4AA9, 0x873E1BD6, 0xA0F0595E, 0x18148A5B, 0xAF02703B, 0xAB04E076, 0xDD4950BF, 0xDF4A1863, 0xC6A5B656, 0x853D530A, 0xFA871237, 0x77B694A7, 0x4665517F, 0xED61B109, 0x1BECE6E9, 0xD5458525, 0xF5753B52, 0x7FBA413D, 0x27CE4288, 0xB2EB4E43, 0xD6BDE997, 0x527B9EF3, 0x62537F45, 0x2C3AFBA0, 0x7BBCD170, 0xB91FF76B, 0x121B171D, 0xFD79EEC8, 0x3A277CF0, 0x0C0A45D7, 0x96DD6079, 0x2233F6AB, 0xACFA1C89, 0xC8ACBB5D, 0xA10B7D30, 0xD4BEA14B, 0xBEE10B94, 0x25CD0A54, 0x547E4662, 0xA2F31182, 0x17E6A33E, 0x263566E6, 0xC3580275, 0x83388B9B, 0x7844BDC2, 0x020348DC, 0x4F92A08B, 0x2E39B37C, 0x4E6984E5, 0xF0888F71, 0x362D3927, 0x9CD2FD3F, 0x01FB246E, 0x893716DD, 0x00000000, 0xF68D57E0, 0xE293986C, 0x744EF815, 0x9320D45A, 0xAD0138E7, 0xD3405DB4, 0x1A17C287, 0xB3106A2D, 0x5078D62F, 0xF48E1F3C, 0xA70EA5A1, 0x71B34C36, 0x9AD725AE, 0x5E71DB24, 0x161D8750, 0xEF62F9D5, 0x8D318690, 0x1C121A16, 0xA6F581CF, 0x5B8C6F07, 0x37D61D49, 0x6E593A92, 0x84C67764, 0x86C53FB8, 0xD746CDF9, 0xE090D0B0, 0x29C74F83, 0xE49640FD, 0x0E090D0B, 0x6DA15620, 0x8EC9EA22, 0xDB4C882E, 0xF776738E, 0xB515B2BC, 0x10185FC1, 0x322BA96A, 0x6BA48EB1, 0xAEF95455, 0x406089EE, 0x6655EF08, 0xE9672144, 0x3E21ECBD, 0x2030BE77, 0xF28BC7AD, 0x80C0E729, 0x141ECF8C, 0xBCE24348, 0xC4A6FE8A, 0x31D3C5D8, 0xB716FA60, 0x5380BA9D, 0xD94FC0F2, 0x1DE93E78, 0x24362E3A, 0xE16BF4DE, 0xCB54D7EF, 0x09F7F1F4, 0x82C3AFF5, 0x0BF4B928, 0x9D29D951, 0xC75E9238, 0xF8845AEB, 0x90D8B8E8, 0xDEB13C0D, 0x33D08D04, 0x685CE203, 0xC55DDAE4, 0x3BDC589E, 0x0A0F9D46, 0x3FDAC8D3, 0x598F27DB, 0xA8FC8CC4, 0x79BF99AC, 0x6C5A724E, 0x8CCAA2FE, 0x9ED1B5E3, 0x1FEA76A4, 0x73B004EA }; const u32bit Square::TD1[256] = { 0x02E368BC, 0x0C558562, 0x312A3F23, 0xF761AB13, 0x7298D46D, 0x1921CB9A, 0x613C22A4, 0xCD459D3D, 0x2305FDB4, 0x5F2BC407, 0xC09B2C01, 0x0F3DD980, 0x74486C5C, 0x85F97F7E, 0x1FF173AB, 0x0EB6EDDE, 0xED283C6B, 0x1A499778, 0x8D9F2A91, 0x33C9579F, 0xAAA907A8, 0x7DA50DED, 0x8F7C422D, 0xC9764DB0, 0x574D91E8, 0xCCCEA963, 0xD2B4EE96, 0xB63028E1, 0xB90DF161, 0x26BD1967, 0x80419BAD, 0xC7C0A06E, 0x415183F2, 0x3492DBF0, 0xFC6FA21E, 0x4C8F32CE, 0x7313E033, 0x6D69A7C6, 0x93E56D64, 0xFABF1A2F, 0xB7BB1CBF, 0xB5587403, 0x4FE76E2C, 0x965D89B7, 0x2AE89C05, 0xA3446619, 0xFB342E71, 0x650FF229, 0x7AFE8182, 0xF1B11322, 0xECA30835, 0x7ECD510F, 0x14FF7AA6, 0xF85C7293, 0x122FC297, 0xC3F370E3, 0x1C992F49, 0x68D14315, 0x1BC2A326, 0xB388CC32, 0x6F8ACF7A, 0x9FB0E806, 0x1E7A47F5, 0xDAD2BB79, 0x21E69508, 0x5C4398E5, 0x06D0B831, 0xAF11E37B, 0x537E4165, 0x10CCAA2B, 0x9CD8B4E4, 0xD46456A7, 0x59FB7C36, 0x84724B20, 0xF6EA9F4D, 0xDF6A5FAA, 0xCE2DC1DF, 0x58704868, 0x81CAAFF3, 0x910605D8, 0x695A774B, 0xA594DE28, 0x4239DF10, 0x47813BC3, 0xA6FC82CA, 0xC523C8D2, 0xB203F86C, 0x9A080CD5, 0x40DAB7AC, 0xE17DB909, 0x2C382434, 0xA2CF5247, 0xD1DCB274, 0x2B63A85B, 0x9535D555, 0x11479E75, 0xE215E5EB, 0xC64B9430, 0xA84A6F14, 0x8691239C, 0x394C6ACC, 0x4A5F8AFF, 0x4D040690, 0xBBEE99DD, 0xCA1E1152, 0x18AAFFC4, 0x98EB6469, 0xFF07FEFC, 0x018B345E, 0xBE567D0E, 0xD9BAE79B, 0x324263C1, 0x7B75B5DC, 0x17972644, 0x6667AECB, 0xCB95250C, 0x67EC9A95, 0xD057862A, 0x99605037, 0x05B8E4D3, 0xBA65AD83, 0x3519EFAE, 0x13A4F6C9, 0xA9C15B4A, 0xD6873E1B, 0x5EA0F059, 0x5B18148A, 0x3BAF0270, 0x76AB04E0, 0xBFDD4950, 0x63DF4A18, 0x56C6A5B6, 0x0A853D53, 0x37FA8712, 0xA777B694, 0x7F466551, 0x09ED61B1, 0xE91BECE6, 0x25D54585, 0x52F5753B, 0x3D7FBA41, 0x8827CE42, 0x43B2EB4E, 0x97D6BDE9, 0xF3527B9E, 0x4562537F, 0xA02C3AFB, 0x707BBCD1, 0x6BB91FF7, 0x1D121B17, 0xC8FD79EE, 0xF03A277C, 0xD70C0A45, 0x7996DD60, 0xAB2233F6, 0x89ACFA1C, 0x5DC8ACBB, 0x30A10B7D, 0x4BD4BEA1, 0x94BEE10B, 0x5425CD0A, 0x62547E46, 0x82A2F311, 0x3E17E6A3, 0xE6263566, 0x75C35802, 0x9B83388B, 0xC27844BD, 0xDC020348, 0x8B4F92A0, 0x7C2E39B3, 0xE54E6984, 0x71F0888F, 0x27362D39, 0x3F9CD2FD, 0x6E01FB24, 0xDD893716, 0x00000000, 0xE0F68D57, 0x6CE29398, 0x15744EF8, 0x5A9320D4, 0xE7AD0138, 0xB4D3405D, 0x871A17C2, 0x2DB3106A, 0x2F5078D6, 0x3CF48E1F, 0xA1A70EA5, 0x3671B34C, 0xAE9AD725, 0x245E71DB, 0x50161D87, 0xD5EF62F9, 0x908D3186, 0x161C121A, 0xCFA6F581, 0x075B8C6F, 0x4937D61D, 0x926E593A, 0x6484C677, 0xB886C53F, 0xF9D746CD, 0xB0E090D0, 0x8329C74F, 0xFDE49640, 0x0B0E090D, 0x206DA156, 0x228EC9EA, 0x2EDB4C88, 0x8EF77673, 0xBCB515B2, 0xC110185F, 0x6A322BA9, 0xB16BA48E, 0x55AEF954, 0xEE406089, 0x086655EF, 0x44E96721, 0xBD3E21EC, 0x772030BE, 0xADF28BC7, 0x2980C0E7, 0x8C141ECF, 0x48BCE243, 0x8AC4A6FE, 0xD831D3C5, 0x60B716FA, 0x9D5380BA, 0xF2D94FC0, 0x781DE93E, 0x3A24362E, 0xDEE16BF4, 0xEFCB54D7, 0xF409F7F1, 0xF582C3AF, 0x280BF4B9, 0x519D29D9, 0x38C75E92, 0xEBF8845A, 0xE890D8B8, 0x0DDEB13C, 0x0433D08D, 0x03685CE2, 0xE4C55DDA, 0x9E3BDC58, 0x460A0F9D, 0xD33FDAC8, 0xDB598F27, 0xC4A8FC8C, 0xAC79BF99, 0x4E6C5A72, 0xFE8CCAA2, 0xE39ED1B5, 0xA41FEA76, 0xEA73B004 }; const u32bit Square::TD2[256] = { 0xBC02E368, 0x620C5585, 0x23312A3F, 0x13F761AB, 0x6D7298D4, 0x9A1921CB, 0xA4613C22, 0x3DCD459D, 0xB42305FD, 0x075F2BC4, 0x01C09B2C, 0x800F3DD9, 0x5C74486C, 0x7E85F97F, 0xAB1FF173, 0xDE0EB6ED, 0x6BED283C, 0x781A4997, 0x918D9F2A, 0x9F33C957, 0xA8AAA907, 0xED7DA50D, 0x2D8F7C42, 0xB0C9764D, 0xE8574D91, 0x63CCCEA9, 0x96D2B4EE, 0xE1B63028, 0x61B90DF1, 0x6726BD19, 0xAD80419B, 0x6EC7C0A0, 0xF2415183, 0xF03492DB, 0x1EFC6FA2, 0xCE4C8F32, 0x337313E0, 0xC66D69A7, 0x6493E56D, 0x2FFABF1A, 0xBFB7BB1C, 0x03B55874, 0x2C4FE76E, 0xB7965D89, 0x052AE89C, 0x19A34466, 0x71FB342E, 0x29650FF2, 0x827AFE81, 0x22F1B113, 0x35ECA308, 0x0F7ECD51, 0xA614FF7A, 0x93F85C72, 0x97122FC2, 0xE3C3F370, 0x491C992F, 0x1568D143, 0x261BC2A3, 0x32B388CC, 0x7A6F8ACF, 0x069FB0E8, 0xF51E7A47, 0x79DAD2BB, 0x0821E695, 0xE55C4398, 0x3106D0B8, 0x7BAF11E3, 0x65537E41, 0x2B10CCAA, 0xE49CD8B4, 0xA7D46456, 0x3659FB7C, 0x2084724B, 0x4DF6EA9F, 0xAADF6A5F, 0xDFCE2DC1, 0x68587048, 0xF381CAAF, 0xD8910605, 0x4B695A77, 0x28A594DE, 0x104239DF, 0xC347813B, 0xCAA6FC82, 0xD2C523C8, 0x6CB203F8, 0xD59A080C, 0xAC40DAB7, 0x09E17DB9, 0x342C3824, 0x47A2CF52, 0x74D1DCB2, 0x5B2B63A8, 0x559535D5, 0x7511479E, 0xEBE215E5, 0x30C64B94, 0x14A84A6F, 0x9C869123, 0xCC394C6A, 0xFF4A5F8A, 0x904D0406, 0xDDBBEE99, 0x52CA1E11, 0xC418AAFF, 0x6998EB64, 0xFCFF07FE, 0x5E018B34, 0x0EBE567D, 0x9BD9BAE7, 0xC1324263, 0xDC7B75B5, 0x44179726, 0xCB6667AE, 0x0CCB9525, 0x9567EC9A, 0x2AD05786, 0x37996050, 0xD305B8E4, 0x83BA65AD, 0xAE3519EF, 0xC913A4F6, 0x4AA9C15B, 0x1BD6873E, 0x595EA0F0, 0x8A5B1814, 0x703BAF02, 0xE076AB04, 0x50BFDD49, 0x1863DF4A, 0xB656C6A5, 0x530A853D, 0x1237FA87, 0x94A777B6, 0x517F4665, 0xB109ED61, 0xE6E91BEC, 0x8525D545, 0x3B52F575, 0x413D7FBA, 0x428827CE, 0x4E43B2EB, 0xE997D6BD, 0x9EF3527B, 0x7F456253, 0xFBA02C3A, 0xD1707BBC, 0xF76BB91F, 0x171D121B, 0xEEC8FD79, 0x7CF03A27, 0x45D70C0A, 0x607996DD, 0xF6AB2233, 0x1C89ACFA, 0xBB5DC8AC, 0x7D30A10B, 0xA14BD4BE, 0x0B94BEE1, 0x0A5425CD, 0x4662547E, 0x1182A2F3, 0xA33E17E6, 0x66E62635, 0x0275C358, 0x8B9B8338, 0xBDC27844, 0x48DC0203, 0xA08B4F92, 0xB37C2E39, 0x84E54E69, 0x8F71F088, 0x3927362D, 0xFD3F9CD2, 0x246E01FB, 0x16DD8937, 0x00000000, 0x57E0F68D, 0x986CE293, 0xF815744E, 0xD45A9320, 0x38E7AD01, 0x5DB4D340, 0xC2871A17, 0x6A2DB310, 0xD62F5078, 0x1F3CF48E, 0xA5A1A70E, 0x4C3671B3, 0x25AE9AD7, 0xDB245E71, 0x8750161D, 0xF9D5EF62, 0x86908D31, 0x1A161C12, 0x81CFA6F5, 0x6F075B8C, 0x1D4937D6, 0x3A926E59, 0x776484C6, 0x3FB886C5, 0xCDF9D746, 0xD0B0E090, 0x4F8329C7, 0x40FDE496, 0x0D0B0E09, 0x56206DA1, 0xEA228EC9, 0x882EDB4C, 0x738EF776, 0xB2BCB515, 0x5FC11018, 0xA96A322B, 0x8EB16BA4, 0x5455AEF9, 0x89EE4060, 0xEF086655, 0x2144E967, 0xECBD3E21, 0xBE772030, 0xC7ADF28B, 0xE72980C0, 0xCF8C141E, 0x4348BCE2, 0xFE8AC4A6, 0xC5D831D3, 0xFA60B716, 0xBA9D5380, 0xC0F2D94F, 0x3E781DE9, 0x2E3A2436, 0xF4DEE16B, 0xD7EFCB54, 0xF1F409F7, 0xAFF582C3, 0xB9280BF4, 0xD9519D29, 0x9238C75E, 0x5AEBF884, 0xB8E890D8, 0x3C0DDEB1, 0x8D0433D0, 0xE203685C, 0xDAE4C55D, 0x589E3BDC, 0x9D460A0F, 0xC8D33FDA, 0x27DB598F, 0x8CC4A8FC, 0x99AC79BF, 0x724E6C5A, 0xA2FE8CCA, 0xB5E39ED1, 0x76A41FEA, 0x04EA73B0 }; const u32bit Square::TD3[256] = { 0x68BC02E3, 0x85620C55, 0x3F23312A, 0xAB13F761, 0xD46D7298, 0xCB9A1921, 0x22A4613C, 0x9D3DCD45, 0xFDB42305, 0xC4075F2B, 0x2C01C09B, 0xD9800F3D, 0x6C5C7448, 0x7F7E85F9, 0x73AB1FF1, 0xEDDE0EB6, 0x3C6BED28, 0x97781A49, 0x2A918D9F, 0x579F33C9, 0x07A8AAA9, 0x0DED7DA5, 0x422D8F7C, 0x4DB0C976, 0x91E8574D, 0xA963CCCE, 0xEE96D2B4, 0x28E1B630, 0xF161B90D, 0x196726BD, 0x9BAD8041, 0xA06EC7C0, 0x83F24151, 0xDBF03492, 0xA21EFC6F, 0x32CE4C8F, 0xE0337313, 0xA7C66D69, 0x6D6493E5, 0x1A2FFABF, 0x1CBFB7BB, 0x7403B558, 0x6E2C4FE7, 0x89B7965D, 0x9C052AE8, 0x6619A344, 0x2E71FB34, 0xF229650F, 0x81827AFE, 0x1322F1B1, 0x0835ECA3, 0x510F7ECD, 0x7AA614FF, 0x7293F85C, 0xC297122F, 0x70E3C3F3, 0x2F491C99, 0x431568D1, 0xA3261BC2, 0xCC32B388, 0xCF7A6F8A, 0xE8069FB0, 0x47F51E7A, 0xBB79DAD2, 0x950821E6, 0x98E55C43, 0xB83106D0, 0xE37BAF11, 0x4165537E, 0xAA2B10CC, 0xB4E49CD8, 0x56A7D464, 0x7C3659FB, 0x4B208472, 0x9F4DF6EA, 0x5FAADF6A, 0xC1DFCE2D, 0x48685870, 0xAFF381CA, 0x05D89106, 0x774B695A, 0xDE28A594, 0xDF104239, 0x3BC34781, 0x82CAA6FC, 0xC8D2C523, 0xF86CB203, 0x0CD59A08, 0xB7AC40DA, 0xB909E17D, 0x24342C38, 0x5247A2CF, 0xB274D1DC, 0xA85B2B63, 0xD5559535, 0x9E751147, 0xE5EBE215, 0x9430C64B, 0x6F14A84A, 0x239C8691, 0x6ACC394C, 0x8AFF4A5F, 0x06904D04, 0x99DDBBEE, 0x1152CA1E, 0xFFC418AA, 0x646998EB, 0xFEFCFF07, 0x345E018B, 0x7D0EBE56, 0xE79BD9BA, 0x63C13242, 0xB5DC7B75, 0x26441797, 0xAECB6667, 0x250CCB95, 0x9A9567EC, 0x862AD057, 0x50379960, 0xE4D305B8, 0xAD83BA65, 0xEFAE3519, 0xF6C913A4, 0x5B4AA9C1, 0x3E1BD687, 0xF0595EA0, 0x148A5B18, 0x02703BAF, 0x04E076AB, 0x4950BFDD, 0x4A1863DF, 0xA5B656C6, 0x3D530A85, 0x871237FA, 0xB694A777, 0x65517F46, 0x61B109ED, 0xECE6E91B, 0x458525D5, 0x753B52F5, 0xBA413D7F, 0xCE428827, 0xEB4E43B2, 0xBDE997D6, 0x7B9EF352, 0x537F4562, 0x3AFBA02C, 0xBCD1707B, 0x1FF76BB9, 0x1B171D12, 0x79EEC8FD, 0x277CF03A, 0x0A45D70C, 0xDD607996, 0x33F6AB22, 0xFA1C89AC, 0xACBB5DC8, 0x0B7D30A1, 0xBEA14BD4, 0xE10B94BE, 0xCD0A5425, 0x7E466254, 0xF31182A2, 0xE6A33E17, 0x3566E626, 0x580275C3, 0x388B9B83, 0x44BDC278, 0x0348DC02, 0x92A08B4F, 0x39B37C2E, 0x6984E54E, 0x888F71F0, 0x2D392736, 0xD2FD3F9C, 0xFB246E01, 0x3716DD89, 0x00000000, 0x8D57E0F6, 0x93986CE2, 0x4EF81574, 0x20D45A93, 0x0138E7AD, 0x405DB4D3, 0x17C2871A, 0x106A2DB3, 0x78D62F50, 0x8E1F3CF4, 0x0EA5A1A7, 0xB34C3671, 0xD725AE9A, 0x71DB245E, 0x1D875016, 0x62F9D5EF, 0x3186908D, 0x121A161C, 0xF581CFA6, 0x8C6F075B, 0xD61D4937, 0x593A926E, 0xC6776484, 0xC53FB886, 0x46CDF9D7, 0x90D0B0E0, 0xC74F8329, 0x9640FDE4, 0x090D0B0E, 0xA156206D, 0xC9EA228E, 0x4C882EDB, 0x76738EF7, 0x15B2BCB5, 0x185FC110, 0x2BA96A32, 0xA48EB16B, 0xF95455AE, 0x6089EE40, 0x55EF0866, 0x672144E9, 0x21ECBD3E, 0x30BE7720, 0x8BC7ADF2, 0xC0E72980, 0x1ECF8C14, 0xE24348BC, 0xA6FE8AC4, 0xD3C5D831, 0x16FA60B7, 0x80BA9D53, 0x4FC0F2D9, 0xE93E781D, 0x362E3A24, 0x6BF4DEE1, 0x54D7EFCB, 0xF7F1F409, 0xC3AFF582, 0xF4B9280B, 0x29D9519D, 0x5E9238C7, 0x845AEBF8, 0xD8B8E890, 0xB13C0DDE, 0xD08D0433, 0x5CE20368, 0x5DDAE4C5, 0xDC589E3B, 0x0F9D460A, 0xDAC8D33F, 0x8F27DB59, 0xFC8CC4A8, 0xBF99AC79, 0x5A724E6C, 0xCAA2FE8C, 0xD1B5E39E, 0xEA76A41F, 0xB004EA73 }; } /* * Square * (C) 1999-2007 Jack Lloyd * * Based on the public domain reference implemenation * * Distributed under the terms of the Botan license */ namespace Botan { /* * Square Encryption */ void Square::encrypt_n(const byte in[], byte out[], size_t blocks) const { for(size_t i = 0; i != blocks; ++i) { u32bit 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(size_t j = 1; j != 7; j += 2) { u32bit T0, T1, T2, T3; 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; } } /* * Square Decryption */ void Square::decrypt_n(const byte in[], byte out[], size_t blocks) const { for(size_t i = 0; i != blocks; ++i) { u32bit 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(size_t j = 1; j != 7; j += 2) { u32bit T0, T1, T2, T3; 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; } } /* * Square Key Schedule */ void Square::key_schedule(const byte key[], size_t) { SecureVector XEK(36), XDK(36); for(size_t i = 0; i != 4; ++i) XEK[i] = load_be(key, i); for(size_t i = 0; i != 8; ++i) { XEK[4*i+4] = XEK[4*i ] ^ rotate_left(XEK[4*i+3], 8) ^ (0x01000000 << i); XEK[4*i+5] = XEK[4*i+1] ^ XEK[4*i+4]; XEK[4*i+6] = XEK[4*i+2] ^ XEK[4*i+5]; XEK[4*i+7] = XEK[4*i+3] ^ XEK[4*i+6]; for(size_t j = 0; j != 4; ++j) XDK[28 - 4*i + j] = XEK[4*(i+1)+j]; transform(&XEK[4*i]); } for(size_t i = 0; i != 4; ++i) for(size_t j = 0; j != 4; ++j) { ME[4*i+j ] = get_byte(j, XEK[i ]); ME[4*i+j+16] = get_byte(j, XEK[i+32]); MD[4*i+j ] = get_byte(j, XDK[i ]); MD[4*i+j+16] = get_byte(j, XEK[i ]); } EK.copy(&XEK[4], 28); DK.copy(&XDK[4], 28); } /* * Square's Inverse Linear Transformation */ void Square::transform(u32bit round_key[4]) { static const byte G[4][4] = { { 2, 1, 1, 3 }, { 3, 2, 1, 1 }, { 1, 3, 2, 1 }, { 1, 1, 3, 2 } }; for(size_t i = 0; i != 4; ++i) { byte A[4] = { 0 }, B[4] = { 0 }; store_be(round_key[i], A); for(size_t j = 0; j != 4; ++j) for(size_t k = 0; k != 4; ++k) { const byte a = A[k]; const byte b = G[k][j]; if(a && b) B[j] ^= ALog[(Log[a] + Log[b]) % 255]; } round_key[i] = load_be(B, 0); } } /* * Clear memory of sensitive data */ void Square::clear() { zeroise(EK); zeroise(DK); zeroise(ME); zeroise(MD); } } /* * TEA * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { /* * TEA Encryption */ void TEA::encrypt_n(const byte in[], byte out[], size_t blocks) const { for(size_t i = 0; i != blocks; ++i) { u32bit L = load_be(in, 0); u32bit R = load_be(in, 1); u32bit S = 0; for(size_t 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); in += BLOCK_SIZE; out += BLOCK_SIZE; } } /* * TEA Decryption */ void TEA::decrypt_n(const byte in[], byte out[], size_t blocks) const { for(size_t i = 0; i != blocks; ++i) { u32bit L = load_be(in, 0); u32bit R = load_be(in, 1); u32bit S = 0xC6EF3720; for(size_t 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); in += BLOCK_SIZE; out += BLOCK_SIZE; } } /* * TEA Key Schedule */ void TEA::key_schedule(const byte key[], size_t) { for(size_t i = 0; i != 4; ++i) K[i] = load_be(key, i); } } /* * S-Box and MDS Tables for Twofish * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { const byte Twofish::Q0[256] = { 0xA9, 0x67, 0xB3, 0xE8, 0x04, 0xFD, 0xA3, 0x76, 0x9A, 0x92, 0x80, 0x78, 0xE4, 0xDD, 0xD1, 0x38, 0x0D, 0xC6, 0x35, 0x98, 0x18, 0xF7, 0xEC, 0x6C, 0x43, 0x75, 0x37, 0x26, 0xFA, 0x13, 0x94, 0x48, 0xF2, 0xD0, 0x8B, 0x30, 0x84, 0x54, 0xDF, 0x23, 0x19, 0x5B, 0x3D, 0x59, 0xF3, 0xAE, 0xA2, 0x82, 0x63, 0x01, 0x83, 0x2E, 0xD9, 0x51, 0x9B, 0x7C, 0xA6, 0xEB, 0xA5, 0xBE, 0x16, 0x0C, 0xE3, 0x61, 0xC0, 0x8C, 0x3A, 0xF5, 0x73, 0x2C, 0x25, 0x0B, 0xBB, 0x4E, 0x89, 0x6B, 0x53, 0x6A, 0xB4, 0xF1, 0xE1, 0xE6, 0xBD, 0x45, 0xE2, 0xF4, 0xB6, 0x66, 0xCC, 0x95, 0x03, 0x56, 0xD4, 0x1C, 0x1E, 0xD7, 0xFB, 0xC3, 0x8E, 0xB5, 0xE9, 0xCF, 0xBF, 0xBA, 0xEA, 0x77, 0x39, 0xAF, 0x33, 0xC9, 0x62, 0x71, 0x81, 0x79, 0x09, 0xAD, 0x24, 0xCD, 0xF9, 0xD8, 0xE5, 0xC5, 0xB9, 0x4D, 0x44, 0x08, 0x86, 0xE7, 0xA1, 0x1D, 0xAA, 0xED, 0x06, 0x70, 0xB2, 0xD2, 0x41, 0x7B, 0xA0, 0x11, 0x31, 0xC2, 0x27, 0x90, 0x20, 0xF6, 0x60, 0xFF, 0x96, 0x5C, 0xB1, 0xAB, 0x9E, 0x9C, 0x52, 0x1B, 0x5F, 0x93, 0x0A, 0xEF, 0x91, 0x85, 0x49, 0xEE, 0x2D, 0x4F, 0x8F, 0x3B, 0x47, 0x87, 0x6D, 0x46, 0xD6, 0x3E, 0x69, 0x64, 0x2A, 0xCE, 0xCB, 0x2F, 0xFC, 0x97, 0x05, 0x7A, 0xAC, 0x7F, 0xD5, 0x1A, 0x4B, 0x0E, 0xA7, 0x5A, 0x28, 0x14, 0x3F, 0x29, 0x88, 0x3C, 0x4C, 0x02, 0xB8, 0xDA, 0xB0, 0x17, 0x55, 0x1F, 0x8A, 0x7D, 0x57, 0xC7, 0x8D, 0x74, 0xB7, 0xC4, 0x9F, 0x72, 0x7E, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34, 0x6E, 0x50, 0xDE, 0x68, 0x65, 0xBC, 0xDB, 0xF8, 0xC8, 0xA8, 0x2B, 0x40, 0xDC, 0xFE, 0x32, 0xA4, 0xCA, 0x10, 0x21, 0xF0, 0xD3, 0x5D, 0x0F, 0x00, 0x6F, 0x9D, 0x36, 0x42, 0x4A, 0x5E, 0xC1, 0xE0 }; const byte Twofish::Q1[256] = { 0x75, 0xF3, 0xC6, 0xF4, 0xDB, 0x7B, 0xFB, 0xC8, 0x4A, 0xD3, 0xE6, 0x6B, 0x45, 0x7D, 0xE8, 0x4B, 0xD6, 0x32, 0xD8, 0xFD, 0x37, 0x71, 0xF1, 0xE1, 0x30, 0x0F, 0xF8, 0x1B, 0x87, 0xFA, 0x06, 0x3F, 0x5E, 0xBA, 0xAE, 0x5B, 0x8A, 0x00, 0xBC, 0x9D, 0x6D, 0xC1, 0xB1, 0x0E, 0x80, 0x5D, 0xD2, 0xD5, 0xA0, 0x84, 0x07, 0x14, 0xB5, 0x90, 0x2C, 0xA3, 0xB2, 0x73, 0x4C, 0x54, 0x92, 0x74, 0x36, 0x51, 0x38, 0xB0, 0xBD, 0x5A, 0xFC, 0x60, 0x62, 0x96, 0x6C, 0x42, 0xF7, 0x10, 0x7C, 0x28, 0x27, 0x8C, 0x13, 0x95, 0x9C, 0xC7, 0x24, 0x46, 0x3B, 0x70, 0xCA, 0xE3, 0x85, 0xCB, 0x11, 0xD0, 0x93, 0xB8, 0xA6, 0x83, 0x20, 0xFF, 0x9F, 0x77, 0xC3, 0xCC, 0x03, 0x6F, 0x08, 0xBF, 0x40, 0xE7, 0x2B, 0xE2, 0x79, 0x0C, 0xAA, 0x82, 0x41, 0x3A, 0xEA, 0xB9, 0xE4, 0x9A, 0xA4, 0x97, 0x7E, 0xDA, 0x7A, 0x17, 0x66, 0x94, 0xA1, 0x1D, 0x3D, 0xF0, 0xDE, 0xB3, 0x0B, 0x72, 0xA7, 0x1C, 0xEF, 0xD1, 0x53, 0x3E, 0x8F, 0x33, 0x26, 0x5F, 0xEC, 0x76, 0x2A, 0x49, 0x81, 0x88, 0xEE, 0x21, 0xC4, 0x1A, 0xEB, 0xD9, 0xC5, 0x39, 0x99, 0xCD, 0xAD, 0x31, 0x8B, 0x01, 0x18, 0x23, 0xDD, 0x1F, 0x4E, 0x2D, 0xF9, 0x48, 0x4F, 0xF2, 0x65, 0x8E, 0x78, 0x5C, 0x58, 0x19, 0x8D, 0xE5, 0x98, 0x57, 0x67, 0x7F, 0x05, 0x64, 0xAF, 0x63, 0xB6, 0xFE, 0xF5, 0xB7, 0x3C, 0xA5, 0xCE, 0xE9, 0x68, 0x44, 0xE0, 0x4D, 0x43, 0x69, 0x29, 0x2E, 0xAC, 0x15, 0x59, 0xA8, 0x0A, 0x9E, 0x6E, 0x47, 0xDF, 0x34, 0x35, 0x6A, 0xCF, 0xDC, 0x22, 0xC9, 0xC0, 0x9B, 0x89, 0xD4, 0xED, 0xAB, 0x12, 0xA2, 0x0D, 0x52, 0xBB, 0x02, 0x2F, 0xA9, 0xD7, 0x61, 0x1E, 0xB4, 0x50, 0x04, 0xF6, 0xC2, 0x16, 0x25, 0x86, 0x56, 0x55, 0x09, 0xBE, 0x91 }; const byte Twofish::RS[32] = { 0x01, 0xA4, 0x02, 0xA4, 0xA4, 0x56, 0xA1, 0x55, 0x55, 0x82, 0xFC, 0x87, 0x87, 0xF3, 0xC1, 0x5A, 0x5A, 0x1E, 0x47, 0x58, 0x58, 0xC6, 0xAE, 0xDB, 0xDB, 0x68, 0x3D, 0x9E, 0x9E, 0xE5, 0x19, 0x03 }; const byte Twofish::EXP_TO_POLY[255] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x4D, 0x9A, 0x79, 0xF2, 0xA9, 0x1F, 0x3E, 0x7C, 0xF8, 0xBD, 0x37, 0x6E, 0xDC, 0xF5, 0xA7, 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0xCD, 0xD7, 0xE3, 0x8B, 0x5B, 0xB6, 0x21, 0x42, 0x84, 0x45, 0x8A, 0x59, 0xB2, 0x29, 0x52, 0xA4, 0x05, 0x0A, 0x14, 0x28, 0x50, 0xA0, 0x0D, 0x1A, 0x34, 0x68, 0xD0, 0xED, 0x97, 0x63, 0xC6, 0xC1, 0xCF, 0xD3, 0xEB, 0x9B, 0x7B, 0xF6, 0xA1, 0x0F, 0x1E, 0x3C, 0x78, 0xF0, 0xAD, 0x17, 0x2E, 0x5C, 0xB8, 0x3D, 0x7A, 0xF4, 0xA5, 0x07, 0x0E, 0x1C, 0x38, 0x70, 0xE0, 0x8D, 0x57, 0xAE, 0x11, 0x22, 0x44, 0x88, 0x5D, 0xBA, 0x39, 0x72, 0xE4, 0x85, 0x47, 0x8E, 0x51, 0xA2, 0x09, 0x12, 0x24, 0x48, 0x90, 0x6D, 0xDA, 0xF9, 0xBF, 0x33, 0x66, 0xCC, 0xD5, 0xE7, 0x83, 0x4B, 0x96, 0x61, 0xC2, 0xC9, 0xDF, 0xF3, 0xAB, 0x1B, 0x36, 0x6C, 0xD8, 0xFD, 0xB7, 0x23, 0x46, 0x8C, 0x55, 0xAA, 0x19, 0x32, 0x64, 0xC8, 0xDD, 0xF7, 0xA3, 0x0B, 0x16, 0x2C, 0x58, 0xB0, 0x2D, 0x5A, 0xB4, 0x25, 0x4A, 0x94, 0x65, 0xCA, 0xD9, 0xFF, 0xB3, 0x2B, 0x56, 0xAC, 0x15, 0x2A, 0x54, 0xA8, 0x1D, 0x3A, 0x74, 0xE8, 0x9D, 0x77, 0xEE, 0x91, 0x6F, 0xDE, 0xF1, 0xAF, 0x13, 0x26, 0x4C, 0x98, 0x7D, 0xFA, 0xB9, 0x3F, 0x7E, 0xFC, 0xB5, 0x27, 0x4E, 0x9C, 0x75, 0xEA, 0x99, 0x7F, 0xFE, 0xB1, 0x2F, 0x5E, 0xBC, 0x35, 0x6A, 0xD4, 0xE5, 0x87, 0x43, 0x86, 0x41, 0x82, 0x49, 0x92, 0x69, 0xD2, 0xE9, 0x9F, 0x73, 0xE6, 0x81, 0x4F, 0x9E, 0x71, 0xE2, 0x89, 0x5F, 0xBE, 0x31, 0x62, 0xC4, 0xC5, 0xC7, 0xC3, 0xCB, 0xDB, 0xFB, 0xBB, 0x3B, 0x76, 0xEC, 0x95, 0x67, 0xCE, 0xD1, 0xEF, 0x93, 0x6B, 0xD6, 0xE1, 0x8F, 0x53, 0xA6 }; const byte Twofish::POLY_TO_EXP[255] = { 0x00, 0x01, 0x17, 0x02, 0x2E, 0x18, 0x53, 0x03, 0x6A, 0x2F, 0x93, 0x19, 0x34, 0x54, 0x45, 0x04, 0x5C, 0x6B, 0xB6, 0x30, 0xA6, 0x94, 0x4B, 0x1A, 0x8C, 0x35, 0x81, 0x55, 0xAA, 0x46, 0x0D, 0x05, 0x24, 0x5D, 0x87, 0x6C, 0x9B, 0xB7, 0xC1, 0x31, 0x2B, 0xA7, 0xA3, 0x95, 0x98, 0x4C, 0xCA, 0x1B, 0xE6, 0x8D, 0x73, 0x36, 0xCD, 0x82, 0x12, 0x56, 0x62, 0xAB, 0xF0, 0x47, 0x4F, 0x0E, 0xBD, 0x06, 0xD4, 0x25, 0xD2, 0x5E, 0x27, 0x88, 0x66, 0x6D, 0xD6, 0x9C, 0x79, 0xB8, 0x08, 0xC2, 0xDF, 0x32, 0x68, 0x2C, 0xFD, 0xA8, 0x8A, 0xA4, 0x5A, 0x96, 0x29, 0x99, 0x22, 0x4D, 0x60, 0xCB, 0xE4, 0x1C, 0x7B, 0xE7, 0x3B, 0x8E, 0x9E, 0x74, 0xF4, 0x37, 0xD8, 0xCE, 0xF9, 0x83, 0x6F, 0x13, 0xB2, 0x57, 0xE1, 0x63, 0xDC, 0xAC, 0xC4, 0xF1, 0xAF, 0x48, 0x0A, 0x50, 0x42, 0x0F, 0xBA, 0xBE, 0xC7, 0x07, 0xDE, 0xD5, 0x78, 0x26, 0x65, 0xD3, 0xD1, 0x5F, 0xE3, 0x28, 0x21, 0x89, 0x59, 0x67, 0xFC, 0x6E, 0xB1, 0xD7, 0xF8, 0x9D, 0xF3, 0x7A, 0x3A, 0xB9, 0xC6, 0x09, 0x41, 0xC3, 0xAE, 0xE0, 0xDB, 0x33, 0x44, 0x69, 0x92, 0x2D, 0x52, 0xFE, 0x16, 0xA9, 0x0C, 0x8B, 0x80, 0xA5, 0x4A, 0x5B, 0xB5, 0x97, 0xC9, 0x2A, 0xA2, 0x9A, 0xC0, 0x23, 0x86, 0x4E, 0xBC, 0x61, 0xEF, 0xCC, 0x11, 0xE5, 0x72, 0x1D, 0x3D, 0x7C, 0xEB, 0xE8, 0xE9, 0x3C, 0xEA, 0x8F, 0x7D, 0x9F, 0xEC, 0x75, 0x1E, 0xF5, 0x3E, 0x38, 0xF6, 0xD9, 0x3F, 0xCF, 0x76, 0xFA, 0x1F, 0x84, 0xA0, 0x70, 0xED, 0x14, 0x90, 0xB3, 0x7E, 0x58, 0xFB, 0xE2, 0x20, 0x64, 0xD0, 0xDD, 0x77, 0xAD, 0xDA, 0xC5, 0x40, 0xF2, 0x39, 0xB0, 0xF7, 0x49, 0xB4, 0x0B, 0x7F, 0x51, 0x15, 0x43, 0x91, 0x10, 0x71, 0xBB, 0xEE, 0xBF, 0x85, 0xC8, 0xA1 }; const u32bit Twofish::MDS0[256] = { 0xBCBC3275, 0xECEC21F3, 0x202043C6, 0xB3B3C9F4, 0xDADA03DB, 0x02028B7B, 0xE2E22BFB, 0x9E9EFAC8, 0xC9C9EC4A, 0xD4D409D3, 0x18186BE6, 0x1E1E9F6B, 0x98980E45, 0xB2B2387D, 0xA6A6D2E8, 0x2626B74B, 0x3C3C57D6, 0x93938A32, 0x8282EED8, 0x525298FD, 0x7B7BD437, 0xBBBB3771, 0x5B5B97F1, 0x474783E1, 0x24243C30, 0x5151E20F, 0xBABAC6F8, 0x4A4AF31B, 0xBFBF4887, 0x0D0D70FA, 0xB0B0B306, 0x7575DE3F, 0xD2D2FD5E, 0x7D7D20BA, 0x666631AE, 0x3A3AA35B, 0x59591C8A, 0x00000000, 0xCDCD93BC, 0x1A1AE09D, 0xAEAE2C6D, 0x7F7FABC1, 0x2B2BC7B1, 0xBEBEB90E, 0xE0E0A080, 0x8A8A105D, 0x3B3B52D2, 0x6464BAD5, 0xD8D888A0, 0xE7E7A584, 0x5F5FE807, 0x1B1B1114, 0x2C2CC2B5, 0xFCFCB490, 0x3131272C, 0x808065A3, 0x73732AB2, 0x0C0C8173, 0x79795F4C, 0x6B6B4154, 0x4B4B0292, 0x53536974, 0x94948F36, 0x83831F51, 0x2A2A3638, 0xC4C49CB0, 0x2222C8BD, 0xD5D5F85A, 0xBDBDC3FC, 0x48487860, 0xFFFFCE62, 0x4C4C0796, 0x4141776C, 0xC7C7E642, 0xEBEB24F7, 0x1C1C1410, 0x5D5D637C, 0x36362228, 0x6767C027, 0xE9E9AF8C, 0x4444F913, 0x1414EA95, 0xF5F5BB9C, 0xCFCF18C7, 0x3F3F2D24, 0xC0C0E346, 0x7272DB3B, 0x54546C70, 0x29294CCA, 0xF0F035E3, 0x0808FE85, 0xC6C617CB, 0xF3F34F11, 0x8C8CE4D0, 0xA4A45993, 0xCACA96B8, 0x68683BA6, 0xB8B84D83, 0x38382820, 0xE5E52EFF, 0xADAD569F, 0x0B0B8477, 0xC8C81DC3, 0x9999FFCC, 0x5858ED03, 0x19199A6F, 0x0E0E0A08, 0x95957EBF, 0x70705040, 0xF7F730E7, 0x6E6ECF2B, 0x1F1F6EE2, 0xB5B53D79, 0x09090F0C, 0x616134AA, 0x57571682, 0x9F9F0B41, 0x9D9D803A, 0x111164EA, 0x2525CDB9, 0xAFAFDDE4, 0x4545089A, 0xDFDF8DA4, 0xA3A35C97, 0xEAEAD57E, 0x353558DA, 0xEDEDD07A, 0x4343FC17, 0xF8F8CB66, 0xFBFBB194, 0x3737D3A1, 0xFAFA401D, 0xC2C2683D, 0xB4B4CCF0, 0x32325DDE, 0x9C9C71B3, 0x5656E70B, 0xE3E3DA72, 0x878760A7, 0x15151B1C, 0xF9F93AEF, 0x6363BFD1, 0x3434A953, 0x9A9A853E, 0xB1B1428F, 0x7C7CD133, 0x88889B26, 0x3D3DA65F, 0xA1A1D7EC, 0xE4E4DF76, 0x8181942A, 0x91910149, 0x0F0FFB81, 0xEEEEAA88, 0x161661EE, 0xD7D77321, 0x9797F5C4, 0xA5A5A81A, 0xFEFE3FEB, 0x6D6DB5D9, 0x7878AEC5, 0xC5C56D39, 0x1D1DE599, 0x7676A4CD, 0x3E3EDCAD, 0xCBCB6731, 0xB6B6478B, 0xEFEF5B01, 0x12121E18, 0x6060C523, 0x6A6AB0DD, 0x4D4DF61F, 0xCECEE94E, 0xDEDE7C2D, 0x55559DF9, 0x7E7E5A48, 0x2121B24F, 0x03037AF2, 0xA0A02665, 0x5E5E198E, 0x5A5A6678, 0x65654B5C, 0x62624E58, 0xFDFD4519, 0x0606F48D, 0x404086E5, 0xF2F2BE98, 0x3333AC57, 0x17179067, 0x05058E7F, 0xE8E85E05, 0x4F4F7D64, 0x89896AAF, 0x10109563, 0x74742FB6, 0x0A0A75FE, 0x5C5C92F5, 0x9B9B74B7, 0x2D2D333C, 0x3030D6A5, 0x2E2E49CE, 0x494989E9, 0x46467268, 0x77775544, 0xA8A8D8E0, 0x9696044D, 0x2828BD43, 0xA9A92969, 0xD9D97929, 0x8686912E, 0xD1D187AC, 0xF4F44A15, 0x8D8D1559, 0xD6D682A8, 0xB9B9BC0A, 0x42420D9E, 0xF6F6C16E, 0x2F2FB847, 0xDDDD06DF, 0x23233934, 0xCCCC6235, 0xF1F1C46A, 0xC1C112CF, 0x8585EBDC, 0x8F8F9E22, 0x7171A1C9, 0x9090F0C0, 0xAAAA539B, 0x0101F189, 0x8B8BE1D4, 0x4E4E8CED, 0x8E8E6FAB, 0xABABA212, 0x6F6F3EA2, 0xE6E6540D, 0xDBDBF252, 0x92927BBB, 0xB7B7B602, 0x6969CA2F, 0x3939D9A9, 0xD3D30CD7, 0xA7A72361, 0xA2A2AD1E, 0xC3C399B4, 0x6C6C4450, 0x07070504, 0x04047FF6, 0x272746C2, 0xACACA716, 0xD0D07625, 0x50501386, 0xDCDCF756, 0x84841A55, 0xE1E15109, 0x7A7A25BE, 0x1313EF91 }; const u32bit Twofish::MDS1[256] = { 0xA9D93939, 0x67901717, 0xB3719C9C, 0xE8D2A6A6, 0x04050707, 0xFD985252, 0xA3658080, 0x76DFE4E4, 0x9A084545, 0x92024B4B, 0x80A0E0E0, 0x78665A5A, 0xE4DDAFAF, 0xDDB06A6A, 0xD1BF6363, 0x38362A2A, 0x0D54E6E6, 0xC6432020, 0x3562CCCC, 0x98BEF2F2, 0x181E1212, 0xF724EBEB, 0xECD7A1A1, 0x6C774141, 0x43BD2828, 0x7532BCBC, 0x37D47B7B, 0x269B8888, 0xFA700D0D, 0x13F94444, 0x94B1FBFB, 0x485A7E7E, 0xF27A0303, 0xD0E48C8C, 0x8B47B6B6, 0x303C2424, 0x84A5E7E7, 0x54416B6B, 0xDF06DDDD, 0x23C56060, 0x1945FDFD, 0x5BA33A3A, 0x3D68C2C2, 0x59158D8D, 0xF321ECEC, 0xAE316666, 0xA23E6F6F, 0x82165757, 0x63951010, 0x015BEFEF, 0x834DB8B8, 0x2E918686, 0xD9B56D6D, 0x511F8383, 0x9B53AAAA, 0x7C635D5D, 0xA63B6868, 0xEB3FFEFE, 0xA5D63030, 0xBE257A7A, 0x16A7ACAC, 0x0C0F0909, 0xE335F0F0, 0x6123A7A7, 0xC0F09090, 0x8CAFE9E9, 0x3A809D9D, 0xF5925C5C, 0x73810C0C, 0x2C273131, 0x2576D0D0, 0x0BE75656, 0xBB7B9292, 0x4EE9CECE, 0x89F10101, 0x6B9F1E1E, 0x53A93434, 0x6AC4F1F1, 0xB499C3C3, 0xF1975B5B, 0xE1834747, 0xE66B1818, 0xBDC82222, 0x450E9898, 0xE26E1F1F, 0xF4C9B3B3, 0xB62F7474, 0x66CBF8F8, 0xCCFF9999, 0x95EA1414, 0x03ED5858, 0x56F7DCDC, 0xD4E18B8B, 0x1C1B1515, 0x1EADA2A2, 0xD70CD3D3, 0xFB2BE2E2, 0xC31DC8C8, 0x8E195E5E, 0xB5C22C2C, 0xE9894949, 0xCF12C1C1, 0xBF7E9595, 0xBA207D7D, 0xEA641111, 0x77840B0B, 0x396DC5C5, 0xAF6A8989, 0x33D17C7C, 0xC9A17171, 0x62CEFFFF, 0x7137BBBB, 0x81FB0F0F, 0x793DB5B5, 0x0951E1E1, 0xADDC3E3E, 0x242D3F3F, 0xCDA47676, 0xF99D5555, 0xD8EE8282, 0xE5864040, 0xC5AE7878, 0xB9CD2525, 0x4D049696, 0x44557777, 0x080A0E0E, 0x86135050, 0xE730F7F7, 0xA1D33737, 0x1D40FAFA, 0xAA346161, 0xED8C4E4E, 0x06B3B0B0, 0x706C5454, 0xB22A7373, 0xD2523B3B, 0x410B9F9F, 0x7B8B0202, 0xA088D8D8, 0x114FF3F3, 0x3167CBCB, 0xC2462727, 0x27C06767, 0x90B4FCFC, 0x20283838, 0xF67F0404, 0x60784848, 0xFF2EE5E5, 0x96074C4C, 0x5C4B6565, 0xB1C72B2B, 0xAB6F8E8E, 0x9E0D4242, 0x9CBBF5F5, 0x52F2DBDB, 0x1BF34A4A, 0x5FA63D3D, 0x9359A4A4, 0x0ABCB9B9, 0xEF3AF9F9, 0x91EF1313, 0x85FE0808, 0x49019191, 0xEE611616, 0x2D7CDEDE, 0x4FB22121, 0x8F42B1B1, 0x3BDB7272, 0x47B82F2F, 0x8748BFBF, 0x6D2CAEAE, 0x46E3C0C0, 0xD6573C3C, 0x3E859A9A, 0x6929A9A9, 0x647D4F4F, 0x2A948181, 0xCE492E2E, 0xCB17C6C6, 0x2FCA6969, 0xFCC3BDBD, 0x975CA3A3, 0x055EE8E8, 0x7AD0EDED, 0xAC87D1D1, 0x7F8E0505, 0xD5BA6464, 0x1AA8A5A5, 0x4BB72626, 0x0EB9BEBE, 0xA7608787, 0x5AF8D5D5, 0x28223636, 0x14111B1B, 0x3FDE7575, 0x2979D9D9, 0x88AAEEEE, 0x3C332D2D, 0x4C5F7979, 0x02B6B7B7, 0xB896CACA, 0xDA583535, 0xB09CC4C4, 0x17FC4343, 0x551A8484, 0x1FF64D4D, 0x8A1C5959, 0x7D38B2B2, 0x57AC3333, 0xC718CFCF, 0x8DF40606, 0x74695353, 0xB7749B9B, 0xC4F59797, 0x9F56ADAD, 0x72DAE3E3, 0x7ED5EAEA, 0x154AF4F4, 0x229E8F8F, 0x12A2ABAB, 0x584E6262, 0x07E85F5F, 0x99E51D1D, 0x34392323, 0x6EC1F6F6, 0x50446C6C, 0xDE5D3232, 0x68724646, 0x6526A0A0, 0xBC93CDCD, 0xDB03DADA, 0xF8C6BABA, 0xC8FA9E9E, 0xA882D6D6, 0x2BCF6E6E, 0x40507070, 0xDCEB8585, 0xFE750A0A, 0x328A9393, 0xA48DDFDF, 0xCA4C2929, 0x10141C1C, 0x2173D7D7, 0xF0CCB4B4, 0xD309D4D4, 0x5D108A8A, 0x0FE25151, 0x00000000, 0x6F9A1919, 0x9DE01A1A, 0x368F9494, 0x42E6C7C7, 0x4AECC9C9, 0x5EFDD2D2, 0xC1AB7F7F, 0xE0D8A8A8 }; const u32bit Twofish::MDS2[256] = { 0xBC75BC32, 0xECF3EC21, 0x20C62043, 0xB3F4B3C9, 0xDADBDA03, 0x027B028B, 0xE2FBE22B, 0x9EC89EFA, 0xC94AC9EC, 0xD4D3D409, 0x18E6186B, 0x1E6B1E9F, 0x9845980E, 0xB27DB238, 0xA6E8A6D2, 0x264B26B7, 0x3CD63C57, 0x9332938A, 0x82D882EE, 0x52FD5298, 0x7B377BD4, 0xBB71BB37, 0x5BF15B97, 0x47E14783, 0x2430243C, 0x510F51E2, 0xBAF8BAC6, 0x4A1B4AF3, 0xBF87BF48, 0x0DFA0D70, 0xB006B0B3, 0x753F75DE, 0xD25ED2FD, 0x7DBA7D20, 0x66AE6631, 0x3A5B3AA3, 0x598A591C, 0x00000000, 0xCDBCCD93, 0x1A9D1AE0, 0xAE6DAE2C, 0x7FC17FAB, 0x2BB12BC7, 0xBE0EBEB9, 0xE080E0A0, 0x8A5D8A10, 0x3BD23B52, 0x64D564BA, 0xD8A0D888, 0xE784E7A5, 0x5F075FE8, 0x1B141B11, 0x2CB52CC2, 0xFC90FCB4, 0x312C3127, 0x80A38065, 0x73B2732A, 0x0C730C81, 0x794C795F, 0x6B546B41, 0x4B924B02, 0x53745369, 0x9436948F, 0x8351831F, 0x2A382A36, 0xC4B0C49C, 0x22BD22C8, 0xD55AD5F8, 0xBDFCBDC3, 0x48604878, 0xFF62FFCE, 0x4C964C07, 0x416C4177, 0xC742C7E6, 0xEBF7EB24, 0x1C101C14, 0x5D7C5D63, 0x36283622, 0x672767C0, 0xE98CE9AF, 0x441344F9, 0x149514EA, 0xF59CF5BB, 0xCFC7CF18, 0x3F243F2D, 0xC046C0E3, 0x723B72DB, 0x5470546C, 0x29CA294C, 0xF0E3F035, 0x088508FE, 0xC6CBC617, 0xF311F34F, 0x8CD08CE4, 0xA493A459, 0xCAB8CA96, 0x68A6683B, 0xB883B84D, 0x38203828, 0xE5FFE52E, 0xAD9FAD56, 0x0B770B84, 0xC8C3C81D, 0x99CC99FF, 0x580358ED, 0x196F199A, 0x0E080E0A, 0x95BF957E, 0x70407050, 0xF7E7F730, 0x6E2B6ECF, 0x1FE21F6E, 0xB579B53D, 0x090C090F, 0x61AA6134, 0x57825716, 0x9F419F0B, 0x9D3A9D80, 0x11EA1164, 0x25B925CD, 0xAFE4AFDD, 0x459A4508, 0xDFA4DF8D, 0xA397A35C, 0xEA7EEAD5, 0x35DA3558, 0xED7AEDD0, 0x431743FC, 0xF866F8CB, 0xFB94FBB1, 0x37A137D3, 0xFA1DFA40, 0xC23DC268, 0xB4F0B4CC, 0x32DE325D, 0x9CB39C71, 0x560B56E7, 0xE372E3DA, 0x87A78760, 0x151C151B, 0xF9EFF93A, 0x63D163BF, 0x345334A9, 0x9A3E9A85, 0xB18FB142, 0x7C337CD1, 0x8826889B, 0x3D5F3DA6, 0xA1ECA1D7, 0xE476E4DF, 0x812A8194, 0x91499101, 0x0F810FFB, 0xEE88EEAA, 0x16EE1661, 0xD721D773, 0x97C497F5, 0xA51AA5A8, 0xFEEBFE3F, 0x6DD96DB5, 0x78C578AE, 0xC539C56D, 0x1D991DE5, 0x76CD76A4, 0x3EAD3EDC, 0xCB31CB67, 0xB68BB647, 0xEF01EF5B, 0x1218121E, 0x602360C5, 0x6ADD6AB0, 0x4D1F4DF6, 0xCE4ECEE9, 0xDE2DDE7C, 0x55F9559D, 0x7E487E5A, 0x214F21B2, 0x03F2037A, 0xA065A026, 0x5E8E5E19, 0x5A785A66, 0x655C654B, 0x6258624E, 0xFD19FD45, 0x068D06F4, 0x40E54086, 0xF298F2BE, 0x335733AC, 0x17671790, 0x057F058E, 0xE805E85E, 0x4F644F7D, 0x89AF896A, 0x10631095, 0x74B6742F, 0x0AFE0A75, 0x5CF55C92, 0x9BB79B74, 0x2D3C2D33, 0x30A530D6, 0x2ECE2E49, 0x49E94989, 0x46684672, 0x77447755, 0xA8E0A8D8, 0x964D9604, 0x284328BD, 0xA969A929, 0xD929D979, 0x862E8691, 0xD1ACD187, 0xF415F44A, 0x8D598D15, 0xD6A8D682, 0xB90AB9BC, 0x429E420D, 0xF66EF6C1, 0x2F472FB8, 0xDDDFDD06, 0x23342339, 0xCC35CC62, 0xF16AF1C4, 0xC1CFC112, 0x85DC85EB, 0x8F228F9E, 0x71C971A1, 0x90C090F0, 0xAA9BAA53, 0x018901F1, 0x8BD48BE1, 0x4EED4E8C, 0x8EAB8E6F, 0xAB12ABA2, 0x6FA26F3E, 0xE60DE654, 0xDB52DBF2, 0x92BB927B, 0xB702B7B6, 0x692F69CA, 0x39A939D9, 0xD3D7D30C, 0xA761A723, 0xA21EA2AD, 0xC3B4C399, 0x6C506C44, 0x07040705, 0x04F6047F, 0x27C22746, 0xAC16ACA7, 0xD025D076, 0x50865013, 0xDC56DCF7, 0x8455841A, 0xE109E151, 0x7ABE7A25, 0x139113EF }; const u32bit Twofish::MDS3[256] = { 0xD939A9D9, 0x90176790, 0x719CB371, 0xD2A6E8D2, 0x05070405, 0x9852FD98, 0x6580A365, 0xDFE476DF, 0x08459A08, 0x024B9202, 0xA0E080A0, 0x665A7866, 0xDDAFE4DD, 0xB06ADDB0, 0xBF63D1BF, 0x362A3836, 0x54E60D54, 0x4320C643, 0x62CC3562, 0xBEF298BE, 0x1E12181E, 0x24EBF724, 0xD7A1ECD7, 0x77416C77, 0xBD2843BD, 0x32BC7532, 0xD47B37D4, 0x9B88269B, 0x700DFA70, 0xF94413F9, 0xB1FB94B1, 0x5A7E485A, 0x7A03F27A, 0xE48CD0E4, 0x47B68B47, 0x3C24303C, 0xA5E784A5, 0x416B5441, 0x06DDDF06, 0xC56023C5, 0x45FD1945, 0xA33A5BA3, 0x68C23D68, 0x158D5915, 0x21ECF321, 0x3166AE31, 0x3E6FA23E, 0x16578216, 0x95106395, 0x5BEF015B, 0x4DB8834D, 0x91862E91, 0xB56DD9B5, 0x1F83511F, 0x53AA9B53, 0x635D7C63, 0x3B68A63B, 0x3FFEEB3F, 0xD630A5D6, 0x257ABE25, 0xA7AC16A7, 0x0F090C0F, 0x35F0E335, 0x23A76123, 0xF090C0F0, 0xAFE98CAF, 0x809D3A80, 0x925CF592, 0x810C7381, 0x27312C27, 0x76D02576, 0xE7560BE7, 0x7B92BB7B, 0xE9CE4EE9, 0xF10189F1, 0x9F1E6B9F, 0xA93453A9, 0xC4F16AC4, 0x99C3B499, 0x975BF197, 0x8347E183, 0x6B18E66B, 0xC822BDC8, 0x0E98450E, 0x6E1FE26E, 0xC9B3F4C9, 0x2F74B62F, 0xCBF866CB, 0xFF99CCFF, 0xEA1495EA, 0xED5803ED, 0xF7DC56F7, 0xE18BD4E1, 0x1B151C1B, 0xADA21EAD, 0x0CD3D70C, 0x2BE2FB2B, 0x1DC8C31D, 0x195E8E19, 0xC22CB5C2, 0x8949E989, 0x12C1CF12, 0x7E95BF7E, 0x207DBA20, 0x6411EA64, 0x840B7784, 0x6DC5396D, 0x6A89AF6A, 0xD17C33D1, 0xA171C9A1, 0xCEFF62CE, 0x37BB7137, 0xFB0F81FB, 0x3DB5793D, 0x51E10951, 0xDC3EADDC, 0x2D3F242D, 0xA476CDA4, 0x9D55F99D, 0xEE82D8EE, 0x8640E586, 0xAE78C5AE, 0xCD25B9CD, 0x04964D04, 0x55774455, 0x0A0E080A, 0x13508613, 0x30F7E730, 0xD337A1D3, 0x40FA1D40, 0x3461AA34, 0x8C4EED8C, 0xB3B006B3, 0x6C54706C, 0x2A73B22A, 0x523BD252, 0x0B9F410B, 0x8B027B8B, 0x88D8A088, 0x4FF3114F, 0x67CB3167, 0x4627C246, 0xC06727C0, 0xB4FC90B4, 0x28382028, 0x7F04F67F, 0x78486078, 0x2EE5FF2E, 0x074C9607, 0x4B655C4B, 0xC72BB1C7, 0x6F8EAB6F, 0x0D429E0D, 0xBBF59CBB, 0xF2DB52F2, 0xF34A1BF3, 0xA63D5FA6, 0x59A49359, 0xBCB90ABC, 0x3AF9EF3A, 0xEF1391EF, 0xFE0885FE, 0x01914901, 0x6116EE61, 0x7CDE2D7C, 0xB2214FB2, 0x42B18F42, 0xDB723BDB, 0xB82F47B8, 0x48BF8748, 0x2CAE6D2C, 0xE3C046E3, 0x573CD657, 0x859A3E85, 0x29A96929, 0x7D4F647D, 0x94812A94, 0x492ECE49, 0x17C6CB17, 0xCA692FCA, 0xC3BDFCC3, 0x5CA3975C, 0x5EE8055E, 0xD0ED7AD0, 0x87D1AC87, 0x8E057F8E, 0xBA64D5BA, 0xA8A51AA8, 0xB7264BB7, 0xB9BE0EB9, 0x6087A760, 0xF8D55AF8, 0x22362822, 0x111B1411, 0xDE753FDE, 0x79D92979, 0xAAEE88AA, 0x332D3C33, 0x5F794C5F, 0xB6B702B6, 0x96CAB896, 0x5835DA58, 0x9CC4B09C, 0xFC4317FC, 0x1A84551A, 0xF64D1FF6, 0x1C598A1C, 0x38B27D38, 0xAC3357AC, 0x18CFC718, 0xF4068DF4, 0x69537469, 0x749BB774, 0xF597C4F5, 0x56AD9F56, 0xDAE372DA, 0xD5EA7ED5, 0x4AF4154A, 0x9E8F229E, 0xA2AB12A2, 0x4E62584E, 0xE85F07E8, 0xE51D99E5, 0x39233439, 0xC1F66EC1, 0x446C5044, 0x5D32DE5D, 0x72466872, 0x26A06526, 0x93CDBC93, 0x03DADB03, 0xC6BAF8C6, 0xFA9EC8FA, 0x82D6A882, 0xCF6E2BCF, 0x50704050, 0xEB85DCEB, 0x750AFE75, 0x8A93328A, 0x8DDFA48D, 0x4C29CA4C, 0x141C1014, 0x73D72173, 0xCCB4F0CC, 0x09D4D309, 0x108A5D10, 0xE2510FE2, 0x00000000, 0x9A196F9A, 0xE01A9DE0, 0x8F94368F, 0xE6C742E6, 0xECC94AEC, 0xFDD25EFD, 0xAB7FC1AB, 0xD8A8E0D8 }; } /* * Twofish * (C) 1999-2007 Jack Lloyd * * The key schedule implemenation is based on a public domain * implementation by Matthew Skala * * Distributed under the terms of the Botan license */ namespace Botan { /* * Twofish Encryption */ void Twofish::encrypt_n(const byte in[], byte out[], size_t blocks) const { for(size_t i = 0; i != blocks; ++i) { u32bit A = load_le(in, 0) ^ RK[0]; u32bit B = load_le(in, 1) ^ RK[1]; u32bit C = load_le(in, 2) ^ RK[2]; u32bit D = load_le(in, 3) ^ RK[3]; for(size_t j = 0; j != 16; j += 2) { u32bit X, Y; X = SB[ get_byte(3, A)] ^ SB[256+get_byte(2, A)] ^ SB[512+get_byte(1, A)] ^ SB[768+get_byte(0, A)]; Y = SB[ get_byte(0, B)] ^ SB[256+get_byte(3, B)] ^ SB[512+get_byte(2, B)] ^ SB[768+get_byte(1, B)]; X += Y; Y += X + RK[2*j + 9]; X += RK[2*j + 8]; C = rotate_right(C ^ X, 1); D = rotate_left(D, 1) ^ Y; X = SB[ get_byte(3, C)] ^ SB[256+get_byte(2, C)] ^ SB[512+get_byte(1, C)] ^ SB[768+get_byte(0, C)]; Y = SB[ get_byte(0, D)] ^ SB[256+get_byte(3, D)] ^ SB[512+get_byte(2, D)] ^ SB[768+get_byte(1, D)]; X += Y; Y += X + RK[2*j + 11]; X += RK[2*j + 10]; A = rotate_right(A ^ X, 1); B = rotate_left(B, 1) ^ Y; } C ^= RK[4]; D ^= RK[5]; A ^= RK[6]; B ^= RK[7]; store_le(out, C, D, A, B); in += BLOCK_SIZE; out += BLOCK_SIZE; } } /* * Twofish Decryption */ void Twofish::decrypt_n(const byte in[], byte out[], size_t blocks) const { for(size_t i = 0; i != blocks; ++i) { u32bit A = load_le(in, 0) ^ RK[4]; u32bit B = load_le(in, 1) ^ RK[5]; u32bit C = load_le(in, 2) ^ RK[6]; u32bit D = load_le(in, 3) ^ RK[7]; for(size_t j = 0; j != 16; j += 2) { u32bit X, Y; X = SB[ get_byte(3, A)] ^ SB[256+get_byte(2, A)] ^ SB[512+get_byte(1, A)] ^ SB[768+get_byte(0, A)]; Y = SB[ get_byte(0, B)] ^ SB[256+get_byte(3, B)] ^ SB[512+get_byte(2, B)] ^ SB[768+get_byte(1, B)]; X += Y; Y += X + RK[39 - 2*j]; X += RK[38 - 2*j]; C = rotate_left(C, 1) ^ X; D = rotate_right(D ^ Y, 1); X = SB[ get_byte(3, C)] ^ SB[256+get_byte(2, C)] ^ SB[512+get_byte(1, C)] ^ SB[768+get_byte(0, C)]; Y = SB[ get_byte(0, D)] ^ SB[256+get_byte(3, D)] ^ SB[512+get_byte(2, D)] ^ SB[768+get_byte(1, D)]; X += Y; Y += X + RK[37 - 2*j]; X += RK[36 - 2*j]; A = rotate_left(A, 1) ^ X; B = rotate_right(B ^ Y, 1); } C ^= RK[0]; D ^= RK[1]; A ^= RK[2]; B ^= RK[3]; store_le(out, C, D, A, B); in += BLOCK_SIZE; out += BLOCK_SIZE; } } /* * Twofish Key Schedule */ void Twofish::key_schedule(const byte key[], size_t length) { SecureVector S(16); for(size_t i = 0; i != length; ++i) rs_mul(&S[4*(i/8)], key[i], i); if(length == 16) { for(size_t i = 0; i != 256; ++i) { SB[ i] = MDS0[Q0[Q0[i]^S[ 0]]^S[ 4]]; SB[256+i] = MDS1[Q0[Q1[i]^S[ 1]]^S[ 5]]; SB[512+i] = MDS2[Q1[Q0[i]^S[ 2]]^S[ 6]]; SB[768+i] = MDS3[Q1[Q1[i]^S[ 3]]^S[ 7]]; } for(size_t i = 0; i != 40; i += 2) { u32bit X = MDS0[Q0[Q0[i ]^key[ 8]]^key[ 0]] ^ MDS1[Q0[Q1[i ]^key[ 9]]^key[ 1]] ^ MDS2[Q1[Q0[i ]^key[10]]^key[ 2]] ^ MDS3[Q1[Q1[i ]^key[11]]^key[ 3]]; u32bit Y = MDS0[Q0[Q0[i+1]^key[12]]^key[ 4]] ^ MDS1[Q0[Q1[i+1]^key[13]]^key[ 5]] ^ MDS2[Q1[Q0[i+1]^key[14]]^key[ 6]] ^ MDS3[Q1[Q1[i+1]^key[15]]^key[ 7]]; Y = rotate_left(Y, 8); X += Y; Y += X; RK[i] = X; RK[i+1] = rotate_left(Y, 9); } } else if(length == 24) { for(size_t i = 0; i != 256; ++i) { SB[ i] = MDS0[Q0[Q0[Q1[i]^S[ 0]]^S[ 4]]^S[ 8]]; SB[256+i] = MDS1[Q0[Q1[Q1[i]^S[ 1]]^S[ 5]]^S[ 9]]; SB[512+i] = MDS2[Q1[Q0[Q0[i]^S[ 2]]^S[ 6]]^S[10]]; SB[768+i] = MDS3[Q1[Q1[Q0[i]^S[ 3]]^S[ 7]]^S[11]]; } for(size_t i = 0; i != 40; i += 2) { u32bit X = MDS0[Q0[Q0[Q1[i ]^key[16]]^key[ 8]]^key[ 0]] ^ MDS1[Q0[Q1[Q1[i ]^key[17]]^key[ 9]]^key[ 1]] ^ MDS2[Q1[Q0[Q0[i ]^key[18]]^key[10]]^key[ 2]] ^ MDS3[Q1[Q1[Q0[i ]^key[19]]^key[11]]^key[ 3]]; u32bit Y = MDS0[Q0[Q0[Q1[i+1]^key[20]]^key[12]]^key[ 4]] ^ MDS1[Q0[Q1[Q1[i+1]^key[21]]^key[13]]^key[ 5]] ^ MDS2[Q1[Q0[Q0[i+1]^key[22]]^key[14]]^key[ 6]] ^ MDS3[Q1[Q1[Q0[i+1]^key[23]]^key[15]]^key[ 7]]; Y = rotate_left(Y, 8); X += Y; Y += X; RK[i] = X; RK[i+1] = rotate_left(Y, 9); } } else if(length == 32) { for(size_t i = 0; i != 256; ++i) { SB[ i] = MDS0[Q0[Q0[Q1[Q1[i]^S[ 0]]^S[ 4]]^S[ 8]]^S[12]]; SB[256+i] = MDS1[Q0[Q1[Q1[Q0[i]^S[ 1]]^S[ 5]]^S[ 9]]^S[13]]; SB[512+i] = MDS2[Q1[Q0[Q0[Q0[i]^S[ 2]]^S[ 6]]^S[10]]^S[14]]; SB[768+i] = MDS3[Q1[Q1[Q0[Q1[i]^S[ 3]]^S[ 7]]^S[11]]^S[15]]; } for(size_t i = 0; i != 40; i += 2) { u32bit X = MDS0[Q0[Q0[Q1[Q1[i ]^key[24]]^key[16]]^key[ 8]]^key[ 0]] ^ MDS1[Q0[Q1[Q1[Q0[i ]^key[25]]^key[17]]^key[ 9]]^key[ 1]] ^ MDS2[Q1[Q0[Q0[Q0[i ]^key[26]]^key[18]]^key[10]]^key[ 2]] ^ MDS3[Q1[Q1[Q0[Q1[i ]^key[27]]^key[19]]^key[11]]^key[ 3]]; u32bit Y = MDS0[Q0[Q0[Q1[Q1[i+1]^key[28]]^key[20]]^key[12]]^key[ 4]] ^ MDS1[Q0[Q1[Q1[Q0[i+1]^key[29]]^key[21]]^key[13]]^key[ 5]] ^ MDS2[Q1[Q0[Q0[Q0[i+1]^key[30]]^key[22]]^key[14]]^key[ 6]] ^ MDS3[Q1[Q1[Q0[Q1[i+1]^key[31]]^key[23]]^key[15]]^key[ 7]]; Y = rotate_left(Y, 8); X += Y; Y += X; RK[i] = X; RK[i+1] = rotate_left(Y, 9); } } } /* * Do one column of the RS matrix multiplcation */ void Twofish::rs_mul(byte S[4], byte key, size_t offset) { if(key) { byte X = POLY_TO_EXP[key - 1]; byte RS1 = RS[(4*offset ) % 32]; byte RS2 = RS[(4*offset+1) % 32]; byte RS3 = RS[(4*offset+2) % 32]; byte RS4 = RS[(4*offset+3) % 32]; S[0] ^= EXP_TO_POLY[(X + POLY_TO_EXP[RS1 - 1]) % 255]; S[1] ^= EXP_TO_POLY[(X + POLY_TO_EXP[RS2 - 1]) % 255]; S[2] ^= EXP_TO_POLY[(X + POLY_TO_EXP[RS3 - 1]) % 255]; S[3] ^= EXP_TO_POLY[(X + POLY_TO_EXP[RS4 - 1]) % 255]; } } /* * Clear memory of sensitive data */ void Twofish::clear() { zeroise(SB); zeroise(RK); } } /* * XTEA * (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { namespace { void xtea_encrypt_4(const byte in[32], byte out[32], const u32bit EK[64]) { u32bit L0, R0, L1, R1, L2, R2, L3, R3; load_be(in, L0, R0, L1, R1, L2, R2, L3, R3); for(size_t i = 0; i != 32; ++i) { L0 += (((R0 << 4) ^ (R0 >> 5)) + R0) ^ EK[2*i]; L1 += (((R1 << 4) ^ (R1 >> 5)) + R1) ^ EK[2*i]; L2 += (((R2 << 4) ^ (R2 >> 5)) + R2) ^ EK[2*i]; L3 += (((R3 << 4) ^ (R3 >> 5)) + R3) ^ EK[2*i]; R0 += (((L0 << 4) ^ (L0 >> 5)) + L0) ^ EK[2*i+1]; R1 += (((L1 << 4) ^ (L1 >> 5)) + L1) ^ EK[2*i+1]; R2 += (((L2 << 4) ^ (L2 >> 5)) + L2) ^ EK[2*i+1]; R3 += (((L3 << 4) ^ (L3 >> 5)) + L3) ^ EK[2*i+1]; } store_be(out, L0, R0, L1, R1, L2, R2, L3, R3); } void xtea_decrypt_4(const byte in[32], byte out[32], const u32bit EK[64]) { u32bit L0, R0, L1, R1, L2, R2, L3, R3; load_be(in, L0, R0, L1, R1, L2, R2, L3, R3); for(size_t i = 0; i != 32; ++i) { R0 -= (((L0 << 4) ^ (L0 >> 5)) + L0) ^ EK[63 - 2*i]; R1 -= (((L1 << 4) ^ (L1 >> 5)) + L1) ^ EK[63 - 2*i]; R2 -= (((L2 << 4) ^ (L2 >> 5)) + L2) ^ EK[63 - 2*i]; R3 -= (((L3 << 4) ^ (L3 >> 5)) + L3) ^ EK[63 - 2*i]; L0 -= (((R0 << 4) ^ (R0 >> 5)) + R0) ^ EK[62 - 2*i]; L1 -= (((R1 << 4) ^ (R1 >> 5)) + R1) ^ EK[62 - 2*i]; L2 -= (((R2 << 4) ^ (R2 >> 5)) + R2) ^ EK[62 - 2*i]; L3 -= (((R3 << 4) ^ (R3 >> 5)) + R3) ^ EK[62 - 2*i]; } store_be(out, L0, R0, L1, R1, L2, R2, L3, R3); } } /* * XTEA Encryption */ void XTEA::encrypt_n(const byte in[], byte out[], size_t blocks) const { while(blocks >= 4) { xtea_encrypt_4(in, out, &(this->EK[0])); in += 4 * BLOCK_SIZE; out += 4 * BLOCK_SIZE; blocks -= 4; } for(size_t i = 0; i != blocks; ++i) { u32bit L = load_be(in, 0); u32bit R = load_be(in, 1); for(size_t 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); in += BLOCK_SIZE; out += BLOCK_SIZE; } } /* * XTEA Decryption */ void XTEA::decrypt_n(const byte in[], byte out[], size_t blocks) const { while(blocks >= 4) { xtea_decrypt_4(in, out, &(this->EK[0])); in += 4 * BLOCK_SIZE; out += 4 * BLOCK_SIZE; blocks -= 4; } for(size_t i = 0; i != blocks; ++i) { u32bit L = load_be(in, 0); u32bit R = load_be(in, 1); for(size_t 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); in += BLOCK_SIZE; out += BLOCK_SIZE; } } /* * XTEA Key Schedule */ void XTEA::key_schedule(const byte key[], size_t) { SecureVector UK(4); for(size_t i = 0; i != 4; ++i) UK[i] = load_be(key, i); u32bit D = 0; for(size_t i = 0; i != 64; i += 2) { EK[i ] = D + UK[D % 4]; D += 0x9E3779B9; EK[i+1] = D + UK[(D >> 11) % 4]; } } } /* * XTEA in SIMD * (C) 2009 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { namespace { void xtea_encrypt_8(const byte in[64], byte out[64], const u32bit EK[64]) { SIMD_32 L0 = SIMD_32::load_be(in ); SIMD_32 R0 = SIMD_32::load_be(in + 16); SIMD_32 L1 = SIMD_32::load_be(in + 32); SIMD_32 R1 = SIMD_32::load_be(in + 48); SIMD_32::transpose(L0, R0, L1, R1); for(size_t i = 0; i != 32; i += 2) { SIMD_32 K0(EK[2*i ]); SIMD_32 K1(EK[2*i+1]); SIMD_32 K2(EK[2*i+2]); SIMD_32 K3(EK[2*i+3]); L0 += (((R0 << 4) ^ (R0 >> 5)) + R0) ^ K0; L1 += (((R1 << 4) ^ (R1 >> 5)) + R1) ^ K0; R0 += (((L0 << 4) ^ (L0 >> 5)) + L0) ^ K1; R1 += (((L1 << 4) ^ (L1 >> 5)) + L1) ^ K1; L0 += (((R0 << 4) ^ (R0 >> 5)) + R0) ^ K2; L1 += (((R1 << 4) ^ (R1 >> 5)) + R1) ^ K2; R0 += (((L0 << 4) ^ (L0 >> 5)) + L0) ^ K3; R1 += (((L1 << 4) ^ (L1 >> 5)) + L1) ^ K3; } SIMD_32::transpose(L0, R0, L1, R1); L0.store_be(out); R0.store_be(out + 16); L1.store_be(out + 32); R1.store_be(out + 48); } void xtea_decrypt_8(const byte in[64], byte out[64], const u32bit EK[64]) { SIMD_32 L0 = SIMD_32::load_be(in ); SIMD_32 R0 = SIMD_32::load_be(in + 16); SIMD_32 L1 = SIMD_32::load_be(in + 32); SIMD_32 R1 = SIMD_32::load_be(in + 48); SIMD_32::transpose(L0, R0, L1, R1); for(size_t i = 0; i != 32; i += 2) { SIMD_32 K0(EK[63 - 2*i]); SIMD_32 K1(EK[62 - 2*i]); SIMD_32 K2(EK[61 - 2*i]); SIMD_32 K3(EK[60 - 2*i]); R0 -= (((L0 << 4) ^ (L0 >> 5)) + L0) ^ K0; R1 -= (((L1 << 4) ^ (L1 >> 5)) + L1) ^ K0; L0 -= (((R0 << 4) ^ (R0 >> 5)) + R0) ^ K1; L1 -= (((R1 << 4) ^ (R1 >> 5)) + R1) ^ K1; R0 -= (((L0 << 4) ^ (L0 >> 5)) + L0) ^ K2; R1 -= (((L1 << 4) ^ (L1 >> 5)) + L1) ^ K2; L0 -= (((R0 << 4) ^ (R0 >> 5)) + R0) ^ K3; L1 -= (((R1 << 4) ^ (R1 >> 5)) + R1) ^ K3; } SIMD_32::transpose(L0, R0, L1, R1); L0.store_be(out); R0.store_be(out + 16); L1.store_be(out + 32); R1.store_be(out + 48); } } /* * XTEA Encryption */ void XTEA_SIMD::encrypt_n(const byte in[], byte out[], size_t blocks) const { const u32bit* KS = &(this->get_EK()[0]); while(blocks >= 8) { xtea_encrypt_8(in, out, KS); in += 8 * BLOCK_SIZE; out += 8 * BLOCK_SIZE; blocks -= 8; } if(blocks) XTEA::encrypt_n(in, out, blocks); } /* * XTEA Decryption */ void XTEA_SIMD::decrypt_n(const byte in[], byte out[], size_t blocks) const { const u32bit* KS = &(this->get_EK()[0]); while(blocks >= 8) { xtea_decrypt_8(in, out, KS); in += 8 * BLOCK_SIZE; out += 8 * BLOCK_SIZE; blocks -= 8; } if(blocks) XTEA::decrypt_n(in, out, blocks); } } /* * Certificate Store * (C) 1999-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { Certificate_Store* Certificate_Store_Memory::clone() const { return new Certificate_Store_Memory(*this); } void Certificate_Store_Memory::add_certificate(const X509_Certificate& cert) { for(size_t i = 0; i != certs.size(); ++i) { if(certs[i] == cert) return; } certs.push_back(cert); } std::vector Certificate_Store_Memory::find_cert_by_subject_and_key_id( const X509_DN& subject_dn, const MemoryRegion& key_id) const { std::vector result; for(size_t i = 0; i != certs.size(); ++i) { // Only compare key ids if set in both call and in the cert if(key_id.size()) { MemoryVector skid = certs[i].subject_key_id(); if(skid.size() && skid != key_id) // no match continue; } if(certs[i].subject_dn() == subject_dn) result.push_back(certs[i]); } return result; } void Certificate_Store_Memory::add_crl(const X509_CRL& crl) { X509_DN crl_issuer = crl.issuer_dn(); for(size_t i = 0; i != crls.size(); ++i) { // Found an update of a previously existing one; replace it if(crls[i].issuer_dn() == crl_issuer) { if(crls[i].this_update() < crl.this_update()) { crls[i] = crl; return; } } } // Totally new CRL, add to the list crls.push_back(crl); } std::vector Certificate_Store_Memory::find_crl_by_subject_and_key_id( const X509_DN& issuer_dn, const MemoryRegion& key_id) const { std::vector result; for(size_t i = 0; i != crls.size(); ++i) { // Only compare key ids if set in both call and in the CRL if(key_id.size()) { MemoryVector akid = crls[i].authority_key_id(); if(akid.size() && akid != key_id) // no match continue; } if(crls[i].issuer_dn() == issuer_dn) result.push_back(crls[i]); } return result; } } /* * PKCS #10 * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { /* * PKCS10_Request Constructor */ PKCS10_Request::PKCS10_Request(DataSource& in) : X509_Object(in, "CERTIFICATE REQUEST/NEW CERTIFICATE REQUEST") { do_decode(); } /* * PKCS10_Request Constructor */ PKCS10_Request::PKCS10_Request(const std::string& in) : X509_Object(in, "CERTIFICATE REQUEST/NEW CERTIFICATE REQUEST") { do_decode(); } /* * Deocde the CertificateRequestInfo */ void PKCS10_Request::force_decode() { BER_Decoder cert_req_info(tbs_bits); size_t version; cert_req_info.decode(version); if(version != 0) throw Decoding_Error("Unknown version code in PKCS #10 request: " + to_string(version)); X509_DN dn_subject; cert_req_info.decode(dn_subject); info.add(dn_subject.contents()); BER_Object public_key = cert_req_info.get_next_object(); if(public_key.type_tag != SEQUENCE || public_key.class_tag != CONSTRUCTED) throw BER_Bad_Tag("PKCS10_Request: Unexpected tag for public key", public_key.type_tag, public_key.class_tag); info.add("X509.Certificate.public_key", PEM_Code::encode( ASN1::put_in_sequence(public_key.value), "PUBLIC KEY" ) ); BER_Object attr_bits = cert_req_info.get_next_object(); if(attr_bits.type_tag == 0 && attr_bits.class_tag == ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC)) { BER_Decoder attributes(attr_bits.value); while(attributes.more_items()) { Attribute attr; attributes.decode(attr); handle_attribute(attr); } attributes.verify_end(); } else if(attr_bits.type_tag != NO_OBJECT) throw BER_Bad_Tag("PKCS10_Request: Unexpected tag for attributes", attr_bits.type_tag, attr_bits.class_tag); cert_req_info.verify_end(); if(!this->check_signature(subject_public_key())) throw Decoding_Error("PKCS #10 request: Bad signature detected"); } /* * Handle attributes in a PKCS #10 request */ void PKCS10_Request::handle_attribute(const Attribute& attr) { BER_Decoder value(attr.parameters); if(attr.oid == OIDS::lookup("PKCS9.EmailAddress")) { ASN1_String email; value.decode(email); info.add("RFC822", email.value()); } else if(attr.oid == OIDS::lookup("PKCS9.ChallengePassword")) { ASN1_String challenge_password; value.decode(challenge_password); info.add("PKCS9.ChallengePassword", challenge_password.value()); } else if(attr.oid == OIDS::lookup("PKCS9.ExtensionRequest")) { Extensions extensions; value.decode(extensions).verify_end(); Data_Store issuer_info; extensions.contents_to(info, issuer_info); } } /* * Return the challenge password (if any) */ std::string PKCS10_Request::challenge_password() const { return info.get1("PKCS9.ChallengePassword"); } /* * Return the name of the requestor */ X509_DN PKCS10_Request::subject_dn() const { return create_dn(info); } /* * Return the public key of the requestor */ MemoryVector PKCS10_Request::raw_public_key() const { DataSource_Memory source(info.get1("X509.Certificate.public_key")); return PEM_Code::decode_check_label(source, "PUBLIC KEY"); } /* * Return the public key of the requestor */ Public_Key* PKCS10_Request::subject_public_key() const { DataSource_Memory source(info.get1("X509.Certificate.public_key")); return X509::load_key(source); } /* * Return the alternative names of the requestor */ AlternativeName PKCS10_Request::subject_alt_name() const { return create_alt_name(info); } /* * Return the key constraints (if any) */ Key_Constraints PKCS10_Request::constraints() const { return Key_Constraints(info.get1_u32bit("X509v3.KeyUsage", NO_CONSTRAINTS)); } /* * Return the extendend key constraints (if any) */ std::vector PKCS10_Request::ex_constraints() const { std::vector oids = info.get("X509v3.ExtendedKeyUsage"); std::vector result; for(size_t i = 0; i != oids.size(); ++i) result.push_back(OID(oids[i])); return result; } /* * Return is a CA certificate is requested */ bool PKCS10_Request::is_CA() const { return (info.get1_u32bit("X509v3.BasicConstraints.is_ca") > 0); } /* * Return the desired path limit (if any) */ u32bit PKCS10_Request::path_limit() const { return info.get1_u32bit("X509v3.BasicConstraints.path_constraint", 0); } } /* * X.509 Certificate Authority * (C) 1999-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ #include #include #include #include #include namespace Botan { /* * Load the certificate and private key */ X509_CA::X509_CA(const X509_Certificate& c, const Private_Key& key, const std::string& hash_fn) : cert(c) { if(!cert.is_CA_cert()) throw Invalid_Argument("X509_CA: This certificate is not for a CA"); signer = choose_sig_format(key, hash_fn, ca_sig_algo); } /* * X509_CA Destructor */ X509_CA::~X509_CA() { delete signer; } /* * Sign a PKCS #10 certificate request */ X509_Certificate X509_CA::sign_request(const PKCS10_Request& req, RandomNumberGenerator& rng, const X509_Time& not_before, const X509_Time& not_after) { Key_Constraints constraints; if(req.is_CA()) constraints = Key_Constraints(KEY_CERT_SIGN | CRL_SIGN); else { std::unique_ptr key(req.subject_public_key()); constraints = X509::find_constraints(*key, req.constraints()); } Extensions extensions; extensions.add( new Cert_Extension::Basic_Constraints(req.is_CA(), req.path_limit()), true); extensions.add(new Cert_Extension::Key_Usage(constraints), true); extensions.add(new Cert_Extension::Authority_Key_ID(cert.subject_key_id())); extensions.add(new Cert_Extension::Subject_Key_ID(req.raw_public_key())); extensions.add( new Cert_Extension::Subject_Alternative_Name(req.subject_alt_name())); extensions.add( new Cert_Extension::Extended_Key_Usage(req.ex_constraints())); return make_cert(signer, rng, ca_sig_algo, req.raw_public_key(), not_before, not_after, cert.subject_dn(), req.subject_dn(), extensions); } /* * Create a new certificate */ X509_Certificate X509_CA::make_cert(PK_Signer* signer, RandomNumberGenerator& rng, const AlgorithmIdentifier& sig_algo, const MemoryRegion& pub_key, const X509_Time& not_before, const X509_Time& not_after, const X509_DN& issuer_dn, const X509_DN& subject_dn, const Extensions& extensions) { const size_t X509_CERT_VERSION = 3; const size_t SERIAL_BITS = 128; BigInt serial_no(rng, SERIAL_BITS); DataSource_Memory source(X509_Object::make_signed(signer, rng, sig_algo, DER_Encoder().start_cons(SEQUENCE) .start_explicit(0) .encode(X509_CERT_VERSION-1) .end_explicit() .encode(serial_no) .encode(sig_algo) .encode(issuer_dn) .start_cons(SEQUENCE) .encode(not_before) .encode(not_after) .end_cons() .encode(subject_dn) .raw_bytes(pub_key) .start_explicit(3) .start_cons(SEQUENCE) .encode(extensions) .end_cons() .end_explicit() .end_cons() .get_contents() )); return X509_Certificate(source); } /* * Create a new, empty CRL */ X509_CRL X509_CA::new_crl(RandomNumberGenerator& rng, u32bit next_update) const { std::vector empty; return make_crl(empty, 1, next_update, rng); } /* * Update a CRL with new entries */ X509_CRL X509_CA::update_crl(const X509_CRL& crl, const std::vector& new_revoked, RandomNumberGenerator& rng, u32bit next_update) const { std::vector revoked = crl.get_revoked(); std::copy(new_revoked.begin(), new_revoked.end(), std::back_inserter(revoked)); return make_crl(revoked, crl.crl_number() + 1, next_update, rng); } /* * Create a CRL */ X509_CRL X509_CA::make_crl(const std::vector& revoked, u32bit crl_number, u32bit next_update, RandomNumberGenerator& rng) const { const size_t X509_CRL_VERSION = 2; if(next_update == 0) next_update = timespec_to_u32bit("7d"); // Totally stupid: ties encoding logic to the return of std::time!! const u64bit current_time = system_time(); Extensions extensions; extensions.add( new Cert_Extension::Authority_Key_ID(cert.subject_key_id())); extensions.add(new Cert_Extension::CRL_Number(crl_number)); DataSource_Memory source(X509_Object::make_signed(signer, rng, ca_sig_algo, DER_Encoder().start_cons(SEQUENCE) .encode(X509_CRL_VERSION-1) .encode(ca_sig_algo) .encode(cert.issuer_dn()) .encode(X509_Time(current_time)) .encode(X509_Time(current_time + next_update)) .encode_if(revoked.size() > 0, DER_Encoder() .start_cons(SEQUENCE) .encode_list(revoked) .end_cons() ) .start_explicit(0) .start_cons(SEQUENCE) .encode(extensions) .end_cons() .end_explicit() .end_cons() .get_contents() )); return X509_CRL(source); } /* * Return the CA's certificate */ X509_Certificate X509_CA::ca_certificate() const { return cert; } /* * Choose a signing format for the key */ PK_Signer* choose_sig_format(const Private_Key& key, const std::string& hash_fn, AlgorithmIdentifier& sig_algo) { std::string padding; const std::string algo_name = key.algo_name(); const HashFunction* proto_hash = retrieve_hash(hash_fn); if(!proto_hash) throw Algorithm_Not_Found(hash_fn); if(key.max_input_bits() < proto_hash->output_length()*8) throw Invalid_Argument("Key is too small for chosen hash function"); if(algo_name == "RSA") padding = "EMSA3"; else if(algo_name == "DSA") padding = "EMSA1"; else if(algo_name == "ECDSA") padding = "EMSA1_BSI"; else throw Invalid_Argument("Unknown X.509 signing key type: " + algo_name); Signature_Format format = (key.message_parts() > 1) ? DER_SEQUENCE : IEEE_1363; padding = padding + '(' + proto_hash->name() + ')'; sig_algo.oid = OIDS::lookup(algo_name + "/" + padding); sig_algo.parameters = key.algorithm_identifier().parameters; return new PK_Signer(key, padding, format); } } /* * X.509 Certificate Extensions * (C) 1999-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ #include #include namespace Botan { /* * List of X.509 Certificate Extensions */ Certificate_Extension* Extensions::get_extension(const OID& oid) { #define X509_EXTENSION(NAME, TYPE) \ if(OIDS::name_of(oid, NAME)) \ return new Cert_Extension::TYPE(); X509_EXTENSION("X509v3.KeyUsage", Key_Usage); X509_EXTENSION("X509v3.BasicConstraints", Basic_Constraints); X509_EXTENSION("X509v3.SubjectKeyIdentifier", Subject_Key_ID); X509_EXTENSION("X509v3.AuthorityKeyIdentifier", Authority_Key_ID); X509_EXTENSION("X509v3.ExtendedKeyUsage", Extended_Key_Usage); X509_EXTENSION("X509v3.IssuerAlternativeName", Issuer_Alternative_Name); X509_EXTENSION("X509v3.SubjectAlternativeName", Subject_Alternative_Name); X509_EXTENSION("X509v3.CRLNumber", CRL_Number); X509_EXTENSION("X509v3.CertificatePolicies", Certificate_Policies); X509_EXTENSION("X509v3.ReasonCode", CRL_ReasonCode); return 0; } /* * Extensions Copy Constructor */ Extensions::Extensions(const Extensions& extensions) : ASN1_Object() { *this = extensions; } /* * Extensions Assignment Operator */ Extensions& Extensions::operator=(const Extensions& other) { for(size_t i = 0; i != extensions.size(); ++i) delete extensions[i].first; extensions.clear(); for(size_t i = 0; i != other.extensions.size(); ++i) extensions.push_back( std::make_pair(other.extensions[i].first->copy(), other.extensions[i].second)); return (*this); } /* * Return the OID of this extension */ OID Certificate_Extension::oid_of() const { return OIDS::lookup(oid_name()); } void Extensions::add(Certificate_Extension* extn, bool critical) { extensions.push_back(std::make_pair(extn, critical)); } /* * Encode an Extensions list */ void Extensions::encode_into(DER_Encoder& to_object) const { for(size_t i = 0; i != extensions.size(); ++i) { const Certificate_Extension* ext = extensions[i].first; const bool is_critical = extensions[i].second; const bool should_encode = ext->should_encode(); if(should_encode) { to_object.start_cons(SEQUENCE) .encode(ext->oid_of()) .encode_optional(is_critical, false) .encode(ext->encode_inner(), OCTET_STRING) .end_cons(); } } } /* * Decode a list of Extensions */ void Extensions::decode_from(BER_Decoder& from_source) { for(size_t i = 0; i != extensions.size(); ++i) delete extensions[i].first; extensions.clear(); BER_Decoder sequence = from_source.start_cons(SEQUENCE); while(sequence.more_items()) { OID oid; MemoryVector value; bool critical; sequence.start_cons(SEQUENCE) .decode(oid) .decode_optional(critical, BOOLEAN, UNIVERSAL, false) .decode(value, OCTET_STRING) .verify_end() .end_cons(); Certificate_Extension* ext = get_extension(oid); if(!ext) { if(!critical || !should_throw) continue; throw Decoding_Error("Encountered unknown X.509 extension marked " "as critical; OID = " + oid.as_string()); } ext->decode_inner(value); extensions.push_back(std::make_pair(ext, critical)); } sequence.verify_end(); } /* * Write the extensions to an info store */ void Extensions::contents_to(Data_Store& subject_info, Data_Store& issuer_info) const { for(size_t i = 0; i != extensions.size(); ++i) extensions[i].first->contents_to(subject_info, issuer_info); } /* * Delete an Extensions list */ Extensions::~Extensions() { for(size_t i = 0; i != extensions.size(); ++i) delete extensions[i].first; } namespace Cert_Extension { /* * Checked accessor for the path_limit member */ size_t Basic_Constraints::get_path_limit() const { if(!is_ca) throw Invalid_State("Basic_Constraints::get_path_limit: Not a CA"); return path_limit; } /* * Encode the extension */ MemoryVector Basic_Constraints::encode_inner() const { return DER_Encoder() .start_cons(SEQUENCE) .encode_if(is_ca, DER_Encoder() .encode(is_ca) .encode_optional(path_limit, NO_CERT_PATH_LIMIT) ) .end_cons() .get_contents(); } /* * Decode the extension */ void Basic_Constraints::decode_inner(const MemoryRegion& in) { BER_Decoder(in) .start_cons(SEQUENCE) .decode_optional(is_ca, BOOLEAN, UNIVERSAL, false) .decode_optional(path_limit, INTEGER, UNIVERSAL, NO_CERT_PATH_LIMIT) .verify_end() .end_cons(); if(is_ca == false) path_limit = 0; } /* * Return a textual representation */ void Basic_Constraints::contents_to(Data_Store& subject, Data_Store&) const { subject.add("X509v3.BasicConstraints.is_ca", (is_ca ? 1 : 0)); subject.add("X509v3.BasicConstraints.path_constraint", path_limit); } /* * Encode the extension */ MemoryVector Key_Usage::encode_inner() const { if(constraints == NO_CONSTRAINTS) throw Encoding_Error("Cannot encode zero usage constraints"); const size_t unused_bits = low_bit(constraints) - 1; MemoryVector der; der.push_back(BIT_STRING); der.push_back(2 + ((unused_bits < 8) ? 1 : 0)); der.push_back(unused_bits % 8); der.push_back((constraints >> 8) & 0xFF); if(constraints & 0xFF) der.push_back(constraints & 0xFF); return der; } /* * Decode the extension */ void Key_Usage::decode_inner(const MemoryRegion& in) { BER_Decoder ber(in); BER_Object obj = ber.get_next_object(); if(obj.type_tag != BIT_STRING || obj.class_tag != UNIVERSAL) throw BER_Bad_Tag("Bad tag for usage constraint", obj.type_tag, obj.class_tag); if(obj.value.size() != 2 && obj.value.size() != 3) throw BER_Decoding_Error("Bad size for BITSTRING in usage constraint"); if(obj.value[0] >= 8) throw BER_Decoding_Error("Invalid unused bits in usage constraint"); obj.value[obj.value.size()-1] &= (0xFF << obj.value[0]); u16bit usage = 0; for(size_t i = 1; i != obj.value.size(); ++i) usage = (obj.value[i] << 8) | usage; constraints = Key_Constraints(usage); } /* * Return a textual representation */ void Key_Usage::contents_to(Data_Store& subject, Data_Store&) const { subject.add("X509v3.KeyUsage", constraints); } /* * Encode the extension */ MemoryVector Subject_Key_ID::encode_inner() const { return DER_Encoder().encode(key_id, OCTET_STRING).get_contents(); } /* * Decode the extension */ void Subject_Key_ID::decode_inner(const MemoryRegion& in) { BER_Decoder(in).decode(key_id, OCTET_STRING).verify_end(); } /* * Return a textual representation */ void Subject_Key_ID::contents_to(Data_Store& subject, Data_Store&) const { subject.add("X509v3.SubjectKeyIdentifier", key_id); } /* * Subject_Key_ID Constructor */ Subject_Key_ID::Subject_Key_ID(const MemoryRegion& pub_key) { SHA_160 hash; key_id = hash.process(pub_key); } /* * Encode the extension */ MemoryVector Authority_Key_ID::encode_inner() const { return DER_Encoder() .start_cons(SEQUENCE) .encode(key_id, OCTET_STRING, ASN1_Tag(0), CONTEXT_SPECIFIC) .end_cons() .get_contents(); } /* * Decode the extension */ void Authority_Key_ID::decode_inner(const MemoryRegion& in) { BER_Decoder(in) .start_cons(SEQUENCE) .decode_optional_string(key_id, OCTET_STRING, 0); } /* * Return a textual representation */ void Authority_Key_ID::contents_to(Data_Store&, Data_Store& issuer) const { if(key_id.size()) issuer.add("X509v3.AuthorityKeyIdentifier", key_id); } /* * Encode the extension */ MemoryVector Alternative_Name::encode_inner() const { return DER_Encoder().encode(alt_name).get_contents(); } /* * Decode the extension */ void Alternative_Name::decode_inner(const MemoryRegion& in) { BER_Decoder(in).decode(alt_name); } /* * Return a textual representation */ void Alternative_Name::contents_to(Data_Store& subject_info, Data_Store& issuer_info) const { std::multimap contents = get_alt_name().contents(); if(oid_name_str == "X509v3.SubjectAlternativeName") subject_info.add(contents); else if(oid_name_str == "X509v3.IssuerAlternativeName") issuer_info.add(contents); else throw Internal_Error("In Alternative_Name, unknown type " + oid_name_str); } /* * Alternative_Name Constructor */ Alternative_Name::Alternative_Name(const AlternativeName& alt_name, const std::string& oid_name_str, const std::string& config_name_str) { this->alt_name = alt_name; this->oid_name_str = oid_name_str; this->config_name_str = config_name_str; } /* * Subject_Alternative_Name Constructor */ Subject_Alternative_Name::Subject_Alternative_Name( const AlternativeName& name) : Alternative_Name(name, "X509v3.SubjectAlternativeName", "subject_alternative_name") { } /* * Issuer_Alternative_Name Constructor */ Issuer_Alternative_Name::Issuer_Alternative_Name(const AlternativeName& name) : Alternative_Name(name, "X509v3.IssuerAlternativeName", "issuer_alternative_name") { } /* * Encode the extension */ MemoryVector Extended_Key_Usage::encode_inner() const { return DER_Encoder() .start_cons(SEQUENCE) .encode_list(oids) .end_cons() .get_contents(); } /* * Decode the extension */ void Extended_Key_Usage::decode_inner(const MemoryRegion& in) { BER_Decoder(in) .start_cons(SEQUENCE) .decode_list(oids) .end_cons(); } /* * Return a textual representation */ void Extended_Key_Usage::contents_to(Data_Store& subject, Data_Store&) const { for(size_t i = 0; i != oids.size(); ++i) subject.add("X509v3.ExtendedKeyUsage", oids[i].as_string()); } /* * A policy specifier */ class Policy_Information : public ASN1_Object { public: OID oid; Policy_Information() {} Policy_Information(const OID& oid) : oid(oid) {} void encode_into(DER_Encoder& codec) const { codec.start_cons(SEQUENCE) .encode(oid) .end_cons(); } void decode_from(BER_Decoder& codec) { codec.start_cons(SEQUENCE) .decode(oid) .discard_remaining() .end_cons(); } }; /* * Encode the extension */ MemoryVector Certificate_Policies::encode_inner() const { std::vector policies; for(size_t i = 0; i != oids.size(); ++i) policies.push_back(oids[i]); return DER_Encoder() .start_cons(SEQUENCE) .encode_list(policies) .end_cons() .get_contents(); } /* * Decode the extension */ void Certificate_Policies::decode_inner(const MemoryRegion& in) { std::vector policies; BER_Decoder(in) .start_cons(SEQUENCE) .decode_list(policies) .end_cons(); oids.clear(); for(size_t i = 0; i != policies.size(); ++i) oids.push_back(policies[i].oid); } /* * Return a textual representation */ void Certificate_Policies::contents_to(Data_Store& info, Data_Store&) const { for(size_t i = 0; i != oids.size(); ++i) info.add("X509v3.ExtendedKeyUsage", oids[i].as_string()); } /* * Checked accessor for the crl_number member */ size_t CRL_Number::get_crl_number() const { if(!has_value) throw Invalid_State("CRL_Number::get_crl_number: Not set"); return crl_number; } /* * Copy a CRL_Number extension */ CRL_Number* CRL_Number::copy() const { if(!has_value) throw Invalid_State("CRL_Number::copy: Not set"); return new CRL_Number(crl_number); } /* * Encode the extension */ MemoryVector CRL_Number::encode_inner() const { return DER_Encoder().encode(crl_number).get_contents(); } /* * Decode the extension */ void CRL_Number::decode_inner(const MemoryRegion& in) { BER_Decoder(in).decode(crl_number); } /* * Return a textual representation */ void CRL_Number::contents_to(Data_Store& info, Data_Store&) const { info.add("X509v3.CRLNumber", crl_number); } /* * Encode the extension */ MemoryVector CRL_ReasonCode::encode_inner() const { return DER_Encoder() .encode(static_cast(reason), ENUMERATED, UNIVERSAL) .get_contents(); } /* * Decode the extension */ void CRL_ReasonCode::decode_inner(const MemoryRegion& in) { size_t reason_code = 0; BER_Decoder(in).decode(reason_code, ENUMERATED, UNIVERSAL); reason = static_cast(reason_code); } /* * Return a textual representation */ void CRL_ReasonCode::contents_to(Data_Store& info, Data_Store&) const { info.add("X509v3.CRLReasonCode", reason); } } } /* * X.509 SIGNED Object * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ #include #include namespace Botan { /* * Create a generic X.509 object */ X509_Object::X509_Object(DataSource& stream, const std::string& labels) { init(stream, labels); } /* * Createa a generic X.509 object */ X509_Object::X509_Object(const std::string& file, const std::string& labels) { DataSource_Stream stream(file, true); init(stream, labels); } /* * Read a PEM or BER X.509 object */ void X509_Object::init(DataSource& in, const std::string& labels) { PEM_labels_allowed = split_on(labels, '/'); if(PEM_labels_allowed.size() < 1) throw Invalid_Argument("Bad labels argument to X509_Object"); PEM_label_pref = PEM_labels_allowed[0]; std::sort(PEM_labels_allowed.begin(), PEM_labels_allowed.end()); try { if(ASN1::maybe_BER(in) && !PEM_Code::matches(in)) decode_info(in); else { std::string got_label; DataSource_Memory ber(PEM_Code::decode(in, got_label)); if(!std::binary_search(PEM_labels_allowed.begin(), PEM_labels_allowed.end(), got_label)) throw Decoding_Error("Invalid PEM label: " + got_label); decode_info(ber); } } catch(Decoding_Error& e) { throw Decoding_Error(PEM_label_pref + " decoding failed: " + e.what()); } } /* * Read a BER encoded X.509 object */ void X509_Object::decode_info(DataSource& source) { BER_Decoder(source) .start_cons(SEQUENCE) .start_cons(SEQUENCE) .raw_bytes(tbs_bits) .end_cons() .decode(sig_algo) .decode(sig, BIT_STRING) .verify_end() .end_cons(); } /* * Return a BER or PEM encoded X.509 object */ void X509_Object::encode(Pipe& out, X509_Encoding encoding) const { if(encoding == PEM) out.write(this->PEM_encode()); else out.write(this->BER_encode()); } /* * Return a BER encoded X.509 object */ MemoryVector X509_Object::BER_encode() const { return DER_Encoder() .start_cons(SEQUENCE) .start_cons(SEQUENCE) .raw_bytes(tbs_bits) .end_cons() .encode(sig_algo) .encode(sig, BIT_STRING) .end_cons() .get_contents(); } /* * Return a PEM encoded X.509 object */ std::string X509_Object::PEM_encode() const { return PEM_Code::encode(BER_encode(), PEM_label_pref); } /* * Return the TBS data */ MemoryVector X509_Object::tbs_data() const { return ASN1::put_in_sequence(tbs_bits); } /* * Return the signature of this object */ MemoryVector X509_Object::signature() const { return sig; } /* * Return the algorithm used to sign this object */ AlgorithmIdentifier X509_Object::signature_algorithm() const { return sig_algo; } /* * Return the hash used in generating the signature */ std::string X509_Object::hash_used_for_signature() const { std::vector sig_info = split_on(OIDS::lookup(sig_algo.oid), '/'); if(sig_info.size() != 2) throw Internal_Error("Invalid name format found for " + sig_algo.oid.as_string()); std::vector pad_and_hash = parse_algorithm_name(sig_info[1]); if(pad_and_hash.size() != 2) throw Internal_Error("Invalid name format " + sig_info[1]); return pad_and_hash[1]; } /* * Check the signature on an object */ bool X509_Object::check_signature(Public_Key* pub_key) const { std::unique_ptr key(pub_key); return check_signature(*key); } /* * Check the signature on an object */ bool X509_Object::check_signature(Public_Key& pub_key) const { try { std::vector sig_info = split_on(OIDS::lookup(sig_algo.oid), '/'); if(sig_info.size() != 2 || sig_info[0] != pub_key.algo_name()) return false; std::string padding = sig_info[1]; Signature_Format format = (pub_key.message_parts() >= 2) ? DER_SEQUENCE : IEEE_1363; PK_Verifier verifier(pub_key, padding, format); return verifier.verify_message(tbs_data(), signature()); } catch(...) { return false; } } /* * Apply the X.509 SIGNED macro */ MemoryVector X509_Object::make_signed(PK_Signer* signer, RandomNumberGenerator& rng, const AlgorithmIdentifier& algo, const MemoryRegion& tbs_bits) { return DER_Encoder() .start_cons(SEQUENCE) .raw_bytes(tbs_bits) .encode(algo) .encode(signer->sign_message(tbs_bits, rng), BIT_STRING) .end_cons() .get_contents(); } /* * Try to decode the actual information */ void X509_Object::do_decode() { try { force_decode(); } catch(Decoding_Error& e) { throw Decoding_Error(PEM_label_pref + " decoding failed (" + e.what() + ")"); } catch(Invalid_Argument& e) { throw Decoding_Error(PEM_label_pref + " decoding failed (" + e.what() + ")"); } } } /* * X.509 Certificates * (C) 1999-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ #include #include #include namespace Botan { namespace { /* * Lookup each OID in the vector */ std::vector lookup_oids(const std::vector& in) { std::vector out; std::vector::const_iterator i = in.begin(); while(i != in.end()) { out.push_back(OIDS::lookup(OID(*i))); ++i; } return out; } } /* * X509_Certificate Constructor */ X509_Certificate::X509_Certificate(DataSource& in) : X509_Object(in, "CERTIFICATE/X509 CERTIFICATE") { self_signed = false; do_decode(); } /* * X509_Certificate Constructor */ X509_Certificate::X509_Certificate(const std::string& in) : X509_Object(in, "CERTIFICATE/X509 CERTIFICATE") { self_signed = false; do_decode(); } /* * Decode the TBSCertificate data */ void X509_Certificate::force_decode() { size_t version; BigInt serial_bn; AlgorithmIdentifier sig_algo_inner; X509_DN dn_issuer, dn_subject; X509_Time start, end; BER_Decoder tbs_cert(tbs_bits); tbs_cert.decode_optional(version, ASN1_Tag(0), ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC)) .decode(serial_bn) .decode(sig_algo_inner) .decode(dn_issuer) .start_cons(SEQUENCE) .decode(start) .decode(end) .verify_end() .end_cons() .decode(dn_subject); if(version > 2) throw Decoding_Error("Unknown X.509 cert version " + Botan::to_string(version)); if(sig_algo != sig_algo_inner) throw Decoding_Error("Algorithm identifier mismatch"); self_signed = (dn_subject == dn_issuer); subject.add(dn_subject.contents()); issuer.add(dn_issuer.contents()); BER_Object public_key = tbs_cert.get_next_object(); if(public_key.type_tag != SEQUENCE || public_key.class_tag != CONSTRUCTED) throw BER_Bad_Tag("X509_Certificate: Unexpected tag for public key", public_key.type_tag, public_key.class_tag); MemoryVector v2_issuer_key_id, v2_subject_key_id; tbs_cert.decode_optional_string(v2_issuer_key_id, BIT_STRING, 1); tbs_cert.decode_optional_string(v2_subject_key_id, BIT_STRING, 2); BER_Object v3_exts_data = tbs_cert.get_next_object(); if(v3_exts_data.type_tag == 3 && v3_exts_data.class_tag == ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC)) { Extensions extensions; BER_Decoder(v3_exts_data.value).decode(extensions).verify_end(); extensions.contents_to(subject, issuer); } else if(v3_exts_data.type_tag != NO_OBJECT) throw BER_Bad_Tag("Unknown tag in X.509 cert", v3_exts_data.type_tag, v3_exts_data.class_tag); if(tbs_cert.more_items()) throw Decoding_Error("TBSCertificate has more items that expected"); subject.add("X509.Certificate.version", version); subject.add("X509.Certificate.serial", BigInt::encode(serial_bn)); subject.add("X509.Certificate.start", start.readable_string()); subject.add("X509.Certificate.end", end.readable_string()); issuer.add("X509.Certificate.v2.key_id", v2_issuer_key_id); subject.add("X509.Certificate.v2.key_id", v2_subject_key_id); subject.add("X509.Certificate.public_key", PEM_Code::encode( ASN1::put_in_sequence(public_key.value), "PUBLIC KEY" ) ); if(is_CA_cert() && !subject.has_value("X509v3.BasicConstraints.path_constraint")) { const size_t limit = (x509_version() < 3) ? Cert_Extension::NO_CERT_PATH_LIMIT : 0; subject.add("X509v3.BasicConstraints.path_constraint", limit); } } /* * Return the X.509 version in use */ u32bit X509_Certificate::x509_version() const { return (subject.get1_u32bit("X509.Certificate.version") + 1); } /* * Return the time this cert becomes valid */ std::string X509_Certificate::start_time() const { return subject.get1("X509.Certificate.start"); } /* * Return the time this cert becomes invalid */ std::string X509_Certificate::end_time() const { return subject.get1("X509.Certificate.end"); } /* * Return information about the subject */ std::vector X509_Certificate::subject_info(const std::string& what) const { return subject.get(X509_DN::deref_info_field(what)); } /* * Return information about the issuer */ std::vector X509_Certificate::issuer_info(const std::string& what) const { return issuer.get(X509_DN::deref_info_field(what)); } /* * Return the public key in this certificate */ Public_Key* X509_Certificate::subject_public_key() const { DataSource_Memory source(subject.get1("X509.Certificate.public_key")); return X509::load_key(source); } /* * Check if the certificate is for a CA */ bool X509_Certificate::is_CA_cert() const { if(!subject.get1_u32bit("X509v3.BasicConstraints.is_ca")) return false; if((constraints() & KEY_CERT_SIGN) || (constraints() == NO_CONSTRAINTS)) return true; return false; } /* * Return the path length constraint */ u32bit X509_Certificate::path_limit() const { return subject.get1_u32bit("X509v3.BasicConstraints.path_constraint", 0); } /* * Return the key usage constraints */ Key_Constraints X509_Certificate::constraints() const { return Key_Constraints(subject.get1_u32bit("X509v3.KeyUsage", NO_CONSTRAINTS)); } /* * Return the list of extended key usage OIDs */ std::vector X509_Certificate::ex_constraints() const { return lookup_oids(subject.get("X509v3.ExtendedKeyUsage")); } /* * Return the list of certificate policies */ std::vector X509_Certificate::policies() const { return lookup_oids(subject.get("X509v3.CertificatePolicies")); } /* * Return the authority key id */ MemoryVector X509_Certificate::authority_key_id() const { return issuer.get1_memvec("X509v3.AuthorityKeyIdentifier"); } /* * Return the subject key id */ MemoryVector X509_Certificate::subject_key_id() const { return subject.get1_memvec("X509v3.SubjectKeyIdentifier"); } /* * Return the certificate serial number */ MemoryVector X509_Certificate::serial_number() const { return subject.get1_memvec("X509.Certificate.serial"); } /* * Return the distinguished name of the issuer */ X509_DN X509_Certificate::issuer_dn() const { return create_dn(issuer); } /* * Return the distinguished name of the subject */ X509_DN X509_Certificate::subject_dn() const { return create_dn(subject); } /* * Compare two certificates for equality */ bool X509_Certificate::operator==(const X509_Certificate& other) const { return (sig == other.sig && sig_algo == other.sig_algo && self_signed == other.self_signed && issuer == other.issuer && subject == other.subject); } /* * X.509 Certificate Comparison */ bool operator!=(const X509_Certificate& cert1, const X509_Certificate& cert2) { return !(cert1 == cert2); } std::string X509_Certificate::to_string() const { const char* dn_fields[] = { "Name", "Email", "Organization", "Organizational Unit", "Locality", "State", "Country", "IP", "DNS", "URI", "PKIX.XMPPAddr", 0 }; std::ostringstream out; for(size_t i = 0; dn_fields[i]; ++i) { const std::vector vals = this->subject_info(dn_fields[i]); if(vals.empty()) continue; out << "Subject " << dn_fields[i] << ":"; for(size_t j = 0; j != vals.size(); ++j) out << " " << vals[j]; out << "\n"; } for(size_t i = 0; dn_fields[i]; ++i) { const std::vector vals = this->issuer_info(dn_fields[i]); if(vals.empty()) continue; out << "Issuer " << dn_fields[i] << ":"; for(size_t j = 0; j != vals.size(); ++j) out << " " << vals[j]; out << "\n"; } out << "Version: " << this->x509_version() << "\n"; out << "Not valid before: " << this->start_time() << "\n"; out << "Not valid after: " << this->end_time() << "\n"; out << "Constraints:\n"; Key_Constraints constraints = this->constraints(); if(constraints == NO_CONSTRAINTS) out << " None\n"; else { if(constraints & DIGITAL_SIGNATURE) out << " Digital Signature\n"; if(constraints & NON_REPUDIATION) out << " Non-Repuidation\n"; if(constraints & KEY_ENCIPHERMENT) out << " Key Encipherment\n"; if(constraints & DATA_ENCIPHERMENT) out << " Data Encipherment\n"; if(constraints & KEY_AGREEMENT) out << " Key Agreement\n"; if(constraints & KEY_CERT_SIGN) out << " Cert Sign\n"; if(constraints & CRL_SIGN) out << " CRL Sign\n"; } std::vector policies = this->policies(); if(policies.size()) { out << "Policies: " << "\n"; for(size_t i = 0; i != policies.size(); i++) out << " " << policies[i] << "\n"; } std::vector ex_constraints = this->ex_constraints(); if(ex_constraints.size()) { out << "Extended Constraints:\n"; for(size_t i = 0; i != ex_constraints.size(); i++) out << " " << ex_constraints[i] << "\n"; } out << "Signature algorithm: " << OIDS::lookup(this->signature_algorithm().oid) << "\n"; out << "Serial number: " << hex_encode(this->serial_number()) << "\n"; if(this->authority_key_id().size()) out << "Authority keyid: " << hex_encode(this->authority_key_id()) << "\n"; if(this->subject_key_id().size()) out << "Subject keyid: " << hex_encode(this->subject_key_id()) << "\n"; X509_PublicKey* pubkey = this->subject_public_key(); out << "Public Key:\n" << X509::PEM_encode(*pubkey); delete pubkey; return out.str(); } /* * Create and populate a X509_DN */ X509_DN create_dn(const Data_Store& info) { class DN_Matcher : public Data_Store::Matcher { public: bool operator()(const std::string& key, const std::string&) const { if(key.find("X520.") != std::string::npos) return true; return false; } }; std::multimap names = info.search_with(DN_Matcher()); X509_DN dn; std::multimap::iterator i; for(i = names.begin(); i != names.end(); ++i) dn.add_attribute(i->first, i->second); return dn; } /* * Create and populate an AlternativeName */ AlternativeName create_alt_name(const Data_Store& info) { class AltName_Matcher : public Data_Store::Matcher { public: bool operator()(const std::string& key, const std::string&) const { for(size_t i = 0; i != matches.size(); ++i) if(key.compare(matches[i]) == 0) return true; return false; } AltName_Matcher(const std::string& match_any_of) { matches = split_on(match_any_of, '/'); } private: std::vector matches; }; std::multimap names = info.search_with(AltName_Matcher("RFC822/DNS/URI/IP")); AlternativeName alt_name; std::multimap::iterator i; for(i = names.begin(); i != names.end(); ++i) alt_name.add_attribute(i->first, i->second); return alt_name; } } /* * CRL Entry * (C) 1999-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { /* * Create a CRL_Entry */ CRL_Entry::CRL_Entry(bool t_on_unknown_crit) : throw_on_unknown_critical(t_on_unknown_crit) { reason = UNSPECIFIED; } /* * Create a CRL_Entry */ CRL_Entry::CRL_Entry(const X509_Certificate& cert, CRL_Code why) : throw_on_unknown_critical(false) { serial = cert.serial_number(); time = X509_Time(system_time()); reason = why; } /* * Compare two CRL_Entrys for equality */ bool operator==(const CRL_Entry& a1, const CRL_Entry& a2) { if(a1.serial_number() != a2.serial_number()) return false; if(a1.expire_time() != a2.expire_time()) return false; if(a1.reason_code() != a2.reason_code()) return false; return true; } /* * Compare two CRL_Entrys for inequality */ bool operator!=(const CRL_Entry& a1, const CRL_Entry& a2) { return !(a1 == a2); } /* * DER encode a CRL_Entry */ void CRL_Entry::encode_into(DER_Encoder& der) const { Extensions extensions; extensions.add(new Cert_Extension::CRL_ReasonCode(reason)); der.start_cons(SEQUENCE) .encode(BigInt::decode(serial)) .encode(time) .start_cons(SEQUENCE) .encode(extensions) .end_cons() .end_cons(); } /* * Decode a BER encoded CRL_Entry */ void CRL_Entry::decode_from(BER_Decoder& source) { BigInt serial_number_bn; reason = UNSPECIFIED; BER_Decoder entry = source.start_cons(SEQUENCE); entry.decode(serial_number_bn).decode(time); if(entry.more_items()) { Extensions extensions(throw_on_unknown_critical); entry.decode(extensions); Data_Store info; extensions.contents_to(info, info); reason = CRL_Code(info.get1_u32bit("X509v3.CRLReasonCode")); } entry.end_cons(); serial = BigInt::encode(serial_number_bn); } } /* * X.509 CRL * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { /* * Load a X.509 CRL */ X509_CRL::X509_CRL(DataSource& in, bool touc) : X509_Object(in, "X509 CRL/CRL"), throw_on_unknown_critical(touc) { do_decode(); } /* * Load a X.509 CRL */ X509_CRL::X509_CRL(const std::string& in, bool touc) : X509_Object(in, "CRL/X509 CRL"), throw_on_unknown_critical(touc) { do_decode(); } /* * Decode the TBSCertList data */ void X509_CRL::force_decode() { BER_Decoder tbs_crl(tbs_bits); size_t version; tbs_crl.decode_optional(version, INTEGER, UNIVERSAL); if(version != 0 && version != 1) throw X509_CRL_Error("Unknown X.509 CRL version " + to_string(version+1)); AlgorithmIdentifier sig_algo_inner; tbs_crl.decode(sig_algo_inner); if(sig_algo != sig_algo_inner) throw X509_CRL_Error("Algorithm identifier mismatch"); X509_DN dn_issuer; tbs_crl.decode(dn_issuer); info.add(dn_issuer.contents()); X509_Time start, end; tbs_crl.decode(start).decode(end); info.add("X509.CRL.start", start.readable_string()); info.add("X509.CRL.end", end.readable_string()); BER_Object next = tbs_crl.get_next_object(); if(next.type_tag == SEQUENCE && next.class_tag == CONSTRUCTED) { BER_Decoder cert_list(next.value); while(cert_list.more_items()) { CRL_Entry entry(throw_on_unknown_critical); cert_list.decode(entry); revoked.push_back(entry); } next = tbs_crl.get_next_object(); } if(next.type_tag == 0 && next.class_tag == ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC)) { BER_Decoder crl_options(next.value); Extensions extensions(throw_on_unknown_critical); crl_options.decode(extensions).verify_end(); extensions.contents_to(info, info); next = tbs_crl.get_next_object(); } if(next.type_tag != NO_OBJECT) throw X509_CRL_Error("Unknown tag in CRL"); tbs_crl.verify_end(); } /* * Return the list of revoked certificates */ std::vector X509_CRL::get_revoked() const { return revoked; } /* * Return the distinguished name of the issuer */ X509_DN X509_CRL::issuer_dn() const { return create_dn(info); } /* * Return the key identifier of the issuer */ MemoryVector X509_CRL::authority_key_id() const { return info.get1_memvec("X509v3.AuthorityKeyIdentifier"); } /* * Return the CRL number of this CRL */ u32bit X509_CRL::crl_number() const { return info.get1_u32bit("X509v3.CRLNumber"); } /* * Return the issue data of the CRL */ X509_Time X509_CRL::this_update() const { return info.get1("X509.CRL.start"); } /* * Return the date when a new CRL will be issued */ X509_Time X509_CRL::next_update() const { return info.get1("X509.CRL.end"); } } /* * X.509 Certificate Options * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { /* * Set when the certificate should become valid */ void X509_Cert_Options::not_before(const std::string& time_string) { start = X509_Time(time_string); } /* * Set when the certificate should expire */ void X509_Cert_Options::not_after(const std::string& time_string) { end = X509_Time(time_string); } /* * Set key constraint information */ void X509_Cert_Options::add_constraints(Key_Constraints usage) { constraints = usage; } /* * Set key constraint information */ void X509_Cert_Options::add_ex_constraint(const OID& oid) { ex_constraints.push_back(oid); } /* * Set key constraint information */ void X509_Cert_Options::add_ex_constraint(const std::string& oid_str) { ex_constraints.push_back(OIDS::lookup(oid_str)); } /* * Mark this certificate for CA usage */ void X509_Cert_Options::CA_key(size_t limit) { is_CA = true; path_limit = limit; } /* * Do basic sanity checks */ void X509_Cert_Options::sanity_check() const { if(common_name == "" || country == "") throw Encoding_Error("X.509 certificate: name and country MUST be set"); if(country.size() != 2) throw Encoding_Error("Invalid ISO country code: " + country); if(start >= end) throw Encoding_Error("X509_Cert_Options: invalid time constraints"); } /* * Initialize the certificate options */ X509_Cert_Options::X509_Cert_Options(const std::string& initial_opts, u32bit expiration_time_in_seconds) { is_CA = false; path_limit = 0; constraints = NO_CONSTRAINTS; const u64bit now = system_time(); start = X509_Time(now); end = X509_Time(now + expiration_time_in_seconds); if(initial_opts == "") return; std::vector parsed = split_on(initial_opts, '/'); if(parsed.size() > 4) throw Invalid_Argument("X.509 cert options: Too many names: " + initial_opts); if(parsed.size() >= 1) common_name = parsed[0]; if(parsed.size() >= 2) country = parsed[1]; if(parsed.size() >= 3) organization = parsed[2]; if(parsed.size() == 4) org_unit = parsed[3]; } } /* * PKCS #10/Self Signed Cert Creation * (C) 1999-2008 Jack Lloyd * * Distributed under the terms of the Botan license */ #include namespace Botan { namespace { /* * Load information from the X509_Cert_Options */ void load_info(const X509_Cert_Options& opts, X509_DN& subject_dn, AlternativeName& subject_alt) { subject_dn.add_attribute("X520.CommonName", opts.common_name); subject_dn.add_attribute("X520.Country", opts.country); subject_dn.add_attribute("X520.State", opts.state); subject_dn.add_attribute("X520.Locality", opts.locality); subject_dn.add_attribute("X520.Organization", opts.organization); subject_dn.add_attribute("X520.OrganizationalUnit", opts.org_unit); subject_dn.add_attribute("X520.SerialNumber", opts.serial_number); subject_alt = AlternativeName(opts.email, opts.uri, opts.dns, opts.ip); subject_alt.add_othername(OIDS::lookup("PKIX.XMPPAddr"), opts.xmpp, UTF8_STRING); } } namespace X509 { /* * Create a new self-signed X.509 certificate */ X509_Certificate create_self_signed_cert(const X509_Cert_Options& opts, const Private_Key& key, const std::string& hash_fn, RandomNumberGenerator& rng) { AlgorithmIdentifier sig_algo; X509_DN subject_dn; AlternativeName subject_alt; opts.sanity_check(); MemoryVector pub_key = X509::BER_encode(key); std::unique_ptr signer(choose_sig_format(key, hash_fn, sig_algo)); load_info(opts, subject_dn, subject_alt); Key_Constraints constraints; if(opts.is_CA) constraints = Key_Constraints(KEY_CERT_SIGN | CRL_SIGN); else constraints = find_constraints(key, opts.constraints); Extensions extensions; extensions.add( new Cert_Extension::Basic_Constraints(opts.is_CA, opts.path_limit), true); extensions.add(new Cert_Extension::Key_Usage(constraints), true); extensions.add(new Cert_Extension::Subject_Key_ID(pub_key)); extensions.add( new Cert_Extension::Subject_Alternative_Name(subject_alt)); extensions.add( new Cert_Extension::Extended_Key_Usage(opts.ex_constraints)); return X509_CA::make_cert(signer.get(), rng, sig_algo, pub_key, opts.start, opts.end, subject_dn, subject_dn, extensions); } /* * Create a PKCS #10 certificate request */ PKCS10_Request create_cert_req(const X509_Cert_Options& opts, const Private_Key& key, const std::string& hash_fn, RandomNumberGenerator& rng) { AlgorithmIdentifier sig_algo; X509_DN subject_dn; AlternativeName subject_alt; opts.sanity_check(); MemoryVector pub_key = X509::BER_encode(key); std::unique_ptr signer(choose_sig_format(key, hash_fn, sig_algo)); load_info(opts, subject_dn, subject_alt); const size_t PKCS10_VERSION = 0; Extensions extensions; extensions.add( new Cert_Extension::Basic_Constraints(opts.is_CA, opts.path_limit)); extensions.add( new Cert_Extension::Key_Usage( opts.is_CA ? Key_Constraints(KEY_CERT_SIGN | CRL_SIGN) : find_constraints(key, opts.constraints) ) ); extensions.add( new Cert_Extension::Extended_Key_Usage(opts.ex_constraints)); extensions.add( new Cert_Extension::Subject_Alternative_Name(subject_alt)); DER_Encoder tbs_req; tbs_req.start_cons(SEQUENCE) .encode(PKCS10_VERSION) .encode(subject_dn) .raw_bytes(pub_key) .start_explicit(0); if(opts.challenge != "") { ASN1_String challenge(opts.challenge, DIRECTORY_STRING); tbs_req.encode( Attribute("PKCS9.ChallengePassword", DER_Encoder().encode(challenge).get_contents() ) ); } tbs_req.encode( Attribute("PKCS9.ExtensionRequest", DER_Encoder() .start_cons(SEQUENCE) .encode(extensions) .end_cons() .get_contents() ) ) .end_explicit() .end_cons(); DataSource_Memory source( X509_Object::make_signed(signer.get(), rng, sig_algo, tbs_req.get_contents()) ); return PKCS10_Request(source); } } } /* * X.509 Certificate Store * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ #include #include namespace Botan { namespace { /* * Do a validity check */ s32bit validity_check(const X509_Time& start, const X509_Time& end, u64bit current_time, u32bit slack) { const s32bit NOT_YET_VALID = -1, VALID_TIME = 0, EXPIRED = 1; if(start.cmp(current_time + slack) > 0) return NOT_YET_VALID; if(end.cmp(current_time - slack) < 0) return EXPIRED; return VALID_TIME; } /* * Compare the value of unique ID fields */ bool compare_ids(const MemoryVector& id1, const MemoryVector& id2) { if(!id1.size() || !id2.size()) return true; return (id1 == id2); } /* * Check a particular usage restriction */ bool check_usage(const X509_Certificate& cert, X509_Store::Cert_Usage usage, X509_Store::Cert_Usage check_for, Key_Constraints constraints) { if((usage & check_for) == 0) return true; if(cert.constraints() == NO_CONSTRAINTS) return true; if(cert.constraints() & constraints) return true; return false; } /* * Check a particular usage restriction */ bool check_usage(const X509_Certificate& cert, X509_Store::Cert_Usage usage, X509_Store::Cert_Usage check_for, const std::string& usage_oid) { if((usage & check_for) == 0) return true; const std::vector constraints = cert.ex_constraints(); if(constraints.empty()) return true; return std::binary_search(constraints.begin(), constraints.end(), usage_oid); } /* * Check the usage restrictions */ X509_Code usage_check(const X509_Certificate& cert, X509_Store::Cert_Usage usage) { if(usage == X509_Store::ANY) return VERIFIED; if(!check_usage(cert, usage, X509_Store::CRL_SIGNING, CRL_SIGN)) return CA_CERT_NOT_FOR_CRL_ISSUER; if(!check_usage(cert, usage, X509_Store::TLS_SERVER, "PKIX.ServerAuth")) return INVALID_USAGE; if(!check_usage(cert, usage, X509_Store::TLS_CLIENT, "PKIX.ClientAuth")) return INVALID_USAGE; if(!check_usage(cert, usage, X509_Store::CODE_SIGNING, "PKIX.CodeSigning")) return INVALID_USAGE; if(!check_usage(cert, usage, X509_Store::EMAIL_PROTECTION, "PKIX.EmailProtection")) return INVALID_USAGE; if(!check_usage(cert, usage, X509_Store::TIME_STAMPING, "PKIX.TimeStamping")) return INVALID_USAGE; return VERIFIED; } } /* * Define equality for revocation data */ bool X509_Store::CRL_Data::operator==(const CRL_Data& other) const { if(issuer != other.issuer) return false; if(serial != other.serial) return false; return compare_ids(auth_key_id, other.auth_key_id); } /* * Define inequality for revocation data */ bool X509_Store::CRL_Data::operator!=(const CRL_Data& other) const { return !((*this) == other); } /* * Define an ordering for revocation data */ bool X509_Store::CRL_Data::operator<(const X509_Store::CRL_Data& other) const { if(*this == other) return false; const MemoryVector& serial1 = serial; const MemoryVector& key_id1 = auth_key_id; const MemoryVector& serial2 = other.serial; const MemoryVector& key_id2 = other.auth_key_id; if(compare_ids(key_id1, key_id2) == false) { if(std::lexicographical_compare(key_id1.begin(), key_id1.end(), key_id2.begin(), key_id2.end())) return true; if(std::lexicographical_compare(key_id2.begin(), key_id2.end(), key_id1.begin(), key_id1.end())) return false; } if(compare_ids(serial1, serial2) == false) { if(std::lexicographical_compare(serial1.begin(), serial1.end(), serial2.begin(), serial2.end())) return true; if(std::lexicographical_compare(serial2.begin(), serial2.end(), serial1.begin(), serial1.end())) return false; } return (issuer < other.issuer); } /* * X509_Store Constructor */ X509_Store::X509_Store(u32bit slack, u32bit cache_timeout) { revoked_info_valid = true; validation_cache_timeout = cache_timeout; time_slack = slack; } /* * X509_Store Copy Constructor */ X509_Store::X509_Store(const X509_Store& other) { certs = other.certs; revoked = other.revoked; revoked_info_valid = other.revoked_info_valid; for(size_t j = 0; j != other.stores.size(); ++j) stores[j] = other.stores[j]->clone(); time_slack = other.time_slack; } /* * X509_Store Destructor */ X509_Store::~X509_Store() { for(size_t j = 0; j != stores.size(); ++j) delete stores[j]; } /* * Verify a certificate's authenticity */ X509_Code X509_Store::validate_cert(const X509_Certificate& cert, Cert_Usage cert_usage) { recompute_revoked_info(); std::vector indexes; X509_Code chaining_result = construct_cert_chain(cert, indexes); if(chaining_result != VERIFIED) return chaining_result; const u64bit current_time = system_time(); s32bit time_check = validity_check(cert.start_time(), cert.end_time(), current_time, time_slack); if(time_check < 0) return CERT_NOT_YET_VALID; else if(time_check > 0) return CERT_HAS_EXPIRED; X509_Code sig_check_result = check_sig(cert, certs[indexes[0]]); if(sig_check_result != VERIFIED) return sig_check_result; if(is_revoked(cert)) return CERT_IS_REVOKED; for(size_t j = 0; j != indexes.size() - 1; ++j) { const X509_Certificate& current_cert = certs[indexes[j]].cert; time_check = validity_check(current_cert.start_time(), current_cert.end_time(), current_time, time_slack); if(time_check < 0) return CERT_NOT_YET_VALID; else if(time_check > 0) return CERT_HAS_EXPIRED; sig_check_result = check_sig(certs[indexes[j]], certs[indexes[j+1]]); if(sig_check_result != VERIFIED) return sig_check_result; } return usage_check(cert, cert_usage); } /* * Find this certificate */ size_t X509_Store::find_cert(const X509_DN& subject_dn, const MemoryRegion& subject_key_id) const { for(size_t j = 0; j != certs.size(); ++j) { const X509_Certificate& this_cert = certs[j].cert; if(compare_ids(this_cert.subject_key_id(), subject_key_id) && this_cert.subject_dn() == subject_dn) return j; } return NO_CERT_FOUND; } /* * Find the parent of this certificate */ size_t X509_Store::find_parent_of(const X509_Certificate& cert) { const X509_DN issuer_dn = cert.issuer_dn(); const MemoryVector auth_key_id = cert.authority_key_id(); size_t index = find_cert(issuer_dn, auth_key_id); if(index != NO_CERT_FOUND) return index; for(size_t j = 0; j != stores.size(); ++j) { std::vector got = stores[j]->find_cert_by_subject_and_key_id(issuer_dn, auth_key_id); for(size_t k = 0; k != got.size(); ++k) add_cert(got[k]); } return find_cert(issuer_dn, auth_key_id); } /* * Construct a chain of certificate relationships */ X509_Code X509_Store::construct_cert_chain(const X509_Certificate& end_cert, std::vector& indexes, bool need_full_chain) { size_t parent = find_parent_of(end_cert); while(true) { if(parent == NO_CERT_FOUND) return CERT_ISSUER_NOT_FOUND; indexes.push_back(parent); if(certs[parent].is_verified(validation_cache_timeout)) if(certs[parent].verify_result() != VERIFIED) return certs[parent].verify_result(); const X509_Certificate& parent_cert = certs[parent].cert; if(!parent_cert.is_CA_cert()) return CA_CERT_NOT_FOR_CERT_ISSUER; if(certs[parent].is_trusted()) break; if(parent_cert.is_self_signed()) return CANNOT_ESTABLISH_TRUST; if(parent_cert.path_limit() < indexes.size() - 1) return CERT_CHAIN_TOO_LONG; parent = find_parent_of(parent_cert); } if(need_full_chain) return VERIFIED; while(true) { if(indexes.size() < 2) break; const size_t cert = indexes.back(); if(certs[cert].is_verified(validation_cache_timeout)) { if(certs[cert].verify_result() != VERIFIED) throw Internal_Error("X509_Store::construct_cert_chain"); indexes.pop_back(); } else break; } const size_t last_cert = indexes.back(); const size_t parent_of_last_cert = find_parent_of(certs[last_cert].cert); if(parent_of_last_cert == NO_CERT_FOUND) return CERT_ISSUER_NOT_FOUND; indexes.push_back(parent_of_last_cert); return VERIFIED; } /* * Check the CAs signature on a certificate */ X509_Code X509_Store::check_sig(const Cert_Info& cert_info, const Cert_Info& ca_cert_info) const { if(cert_info.is_verified(validation_cache_timeout)) return cert_info.verify_result(); const X509_Certificate& cert = cert_info.cert; const X509_Certificate& ca_cert = ca_cert_info.cert; X509_Code verify_code = check_sig(cert, ca_cert.subject_public_key()); cert_info.set_result(verify_code); return verify_code; } /* * Check a CA's signature */ X509_Code X509_Store::check_sig(const X509_Object& object, Public_Key* key) { std::unique_ptr pub_key(key); try { std::vector sig_info = split_on(OIDS::lookup(object.signature_algorithm().oid), '/'); if(sig_info.size() != 2 || sig_info[0] != pub_key->algo_name()) return SIGNATURE_ERROR; std::string padding = sig_info[1]; Signature_Format format; if(key->message_parts() >= 2) format = DER_SEQUENCE; else format = IEEE_1363; PK_Verifier verifier(*pub_key.get(), padding, format); bool valid = verifier.verify_message(object.tbs_data(), object.signature()); if(valid) return VERIFIED; else return SIGNATURE_ERROR; } catch(Lookup_Error) { return CA_CERT_CANNOT_SIGN; } catch(Decoding_Error) { return CERT_FORMAT_ERROR; } catch(Exception) {} return UNKNOWN_X509_ERROR; } /* * Recompute the revocation status of the certs */ void X509_Store::recompute_revoked_info() const { if(revoked_info_valid) return; for(size_t j = 0; j != certs.size(); ++j) { if((certs[j].is_verified(validation_cache_timeout)) && (certs[j].verify_result() != VERIFIED)) continue; if(is_revoked(certs[j].cert)) certs[j].set_result(CERT_IS_REVOKED); } revoked_info_valid = true; } /* * Check if a certificate is revoked */ bool X509_Store::is_revoked(const X509_Certificate& cert) const { CRL_Data revoked_info; revoked_info.issuer = cert.issuer_dn(); revoked_info.serial = cert.serial_number(); revoked_info.auth_key_id = cert.authority_key_id(); if(std::binary_search(revoked.begin(), revoked.end(), revoked_info)) return true; return false; } /* * Construct a path back to a root for this cert */ std::vector X509_Store::get_cert_chain(const X509_Certificate& cert) { std::vector result; std::vector indexes; X509_Code chaining_result = construct_cert_chain(cert, indexes, true); if(chaining_result != VERIFIED) throw Invalid_State("X509_Store::get_cert_chain: Can't construct chain"); for(size_t j = 0; j != indexes.size(); ++j) result.push_back(certs[indexes[j]].cert); return result; } /* * Add a certificate store to the list of stores */ void X509_Store::add_new_certstore(Certificate_Store* certstore) { stores.push_back(certstore); } /* * Add a certificate to the store */ void X509_Store::add_cert(const X509_Certificate& cert, bool trusted) { if(trusted && !cert.is_self_signed()) throw Invalid_Argument("X509_Store: Trusted certs must be self-signed"); if(find_cert(cert.subject_dn(), cert.subject_key_id()) == NO_CERT_FOUND) { revoked_info_valid = false; Cert_Info info(cert, trusted); certs.push_back(info); } else if(trusted) { for(size_t j = 0; j != certs.size(); ++j) { const X509_Certificate& this_cert = certs[j].cert; if(this_cert == cert) certs[j].trusted = trusted; } } } /* * Add one or more certificates to the store */ void X509_Store::do_add_certs(DataSource& source, bool trusted) { while(!source.end_of_data()) { try { X509_Certificate cert(source); add_cert(cert, trusted); } catch(Decoding_Error) {} catch(Invalid_Argument) {} } } /* * Add one or more certificates to the store */ void X509_Store::add_certs(DataSource& source) { do_add_certs(source, false); } /* * Add one or more certificates to the store */ void X509_Store::add_trusted_certs(DataSource& source) { do_add_certs(source, true); } /* * Add one or more certificates to the store */ X509_Code X509_Store::add_crl(const X509_CRL& crl) { s32bit time_check = validity_check(crl.this_update(), crl.next_update(), system_time(), time_slack); if(time_check < 0) return CRL_NOT_YET_VALID; else if(time_check > 0) return CRL_HAS_EXPIRED; size_t cert_index = NO_CERT_FOUND; for(size_t j = 0; j != certs.size(); ++j) { const X509_Certificate& this_cert = certs[j].cert; if(compare_ids(this_cert.subject_key_id(), crl.authority_key_id())) { if(this_cert.subject_dn() == crl.issuer_dn()) cert_index = j; } } if(cert_index == NO_CERT_FOUND) return CRL_ISSUER_NOT_FOUND; const X509_Certificate& ca_cert = certs[cert_index].cert; X509_Code verify_result = validate_cert(ca_cert, CRL_SIGNING); if(verify_result != VERIFIED) return verify_result; verify_result = check_sig(crl, ca_cert.subject_public_key()); if(verify_result != VERIFIED) return verify_result; std::vector revoked_certs = crl.get_revoked(); for(size_t j = 0; j != revoked_certs.size(); ++j) { CRL_Data revoked_info; revoked_info.issuer = crl.issuer_dn(); revoked_info.serial = revoked_certs[j].serial_number(); revoked_info.auth_key_id = crl.authority_key_id(); std::vector::iterator p = std::find(revoked.begin(), revoked.end(), revoked_info); if(revoked_certs[j].reason_code() == REMOVE_FROM_CRL) { if(p == revoked.end()) continue; revoked.erase(p); } else { if(p != revoked.end()) continue; revoked.push_back(revoked_info); } } std::sort(revoked.begin(), revoked.end()); revoked_info_valid = false; return VERIFIED; } /* * PEM encode the set of certificates */ std::string X509_Store::PEM_encode() const { std::string cert_store; for(size_t j = 0; j != certs.size(); ++j) cert_store += certs[j].cert.PEM_encode(); return cert_store; } /* * Create a Cert_Info structure */ X509_Store::Cert_Info::Cert_Info(const X509_Certificate& c, bool t) : cert(c), trusted(t) { checked = false; result = UNKNOWN_X509_ERROR; last_checked = 0; } /* * Return the verification results */ X509_Code X509_Store::Cert_Info::verify_result() const { if(!checked) throw Invalid_State("Cert_Info::verify_result() called; not checked"); return result; } /* * Set the verification results */ void X509_Store::Cert_Info::set_result(X509_Code code) const { result = code; last_checked = system_time(); checked = true; } /* * Check if this certificate can be trusted */ bool X509_Store::Cert_Info::is_trusted() const { return trusted; } /* * Check if this certificate has been verified */ bool X509_Store::Cert_Info::is_verified(u32bit timeout) const { if(!checked) return false; if(result != VERIFIED && result != CERT_NOT_YET_VALID) return true; const u64bit current_time = system_time(); if(current_time > last_checked + timeout) checked = false; return checked; } } /* * Adler32 * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { namespace { void adler32_update(const byte input[], size_t length, u16bit& S1, u16bit& S2) { u32bit S1x = S1; u32bit S2x = S2; while(length >= 16) { S1x += input[ 0]; S2x += S1x; S1x += input[ 1]; S2x += S1x; S1x += input[ 2]; S2x += S1x; S1x += input[ 3]; S2x += S1x; S1x += input[ 4]; S2x += S1x; S1x += input[ 5]; S2x += S1x; S1x += input[ 6]; S2x += S1x; S1x += input[ 7]; S2x += S1x; S1x += input[ 8]; S2x += S1x; S1x += input[ 9]; S2x += S1x; S1x += input[10]; S2x += S1x; S1x += input[11]; S2x += S1x; S1x += input[12]; S2x += S1x; S1x += input[13]; S2x += S1x; S1x += input[14]; S2x += S1x; S1x += input[15]; S2x += S1x; input += 16; length -= 16; } for(size_t j = 0; j != length; ++j) { S1x += input[j]; S2x += S1x; } S1 = S1x % 65521; S2 = S2x % 65521; } } /* * Update an Adler32 Checksum */ void Adler32::add_data(const byte input[], size_t length) { const size_t PROCESS_AMOUNT = 5552; while(length >= PROCESS_AMOUNT) { adler32_update(input, PROCESS_AMOUNT, S1, S2); input += PROCESS_AMOUNT; length -= PROCESS_AMOUNT; } adler32_update(input, length, S1, S2); } /* * Finalize an Adler32 Checksum */ void Adler32::final_result(byte output[]) { store_be(output, S2, S1); clear(); } } /* * CRC24 * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { /* * Update a CRC24 Checksum */ void CRC24::add_data(const byte input[], size_t length) { const u32bit TABLE[256] = { 0x00000000, 0x00864CFB, 0x008AD50D, 0x000C99F6, 0x0093E6E1, 0x0015AA1A, 0x001933EC, 0x009F7F17, 0x00A18139, 0x0027CDC2, 0x002B5434, 0x00AD18CF, 0x003267D8, 0x00B42B23, 0x00B8B2D5, 0x003EFE2E, 0x00C54E89, 0x00430272, 0x004F9B84, 0x00C9D77F, 0x0056A868, 0x00D0E493, 0x00DC7D65, 0x005A319E, 0x0064CFB0, 0x00E2834B, 0x00EE1ABD, 0x00685646, 0x00F72951, 0x007165AA, 0x007DFC5C, 0x00FBB0A7, 0x000CD1E9, 0x008A9D12, 0x008604E4, 0x0000481F, 0x009F3708, 0x00197BF3, 0x0015E205, 0x0093AEFE, 0x00AD50D0, 0x002B1C2B, 0x002785DD, 0x00A1C926, 0x003EB631, 0x00B8FACA, 0x00B4633C, 0x00322FC7, 0x00C99F60, 0x004FD39B, 0x00434A6D, 0x00C50696, 0x005A7981, 0x00DC357A, 0x00D0AC8C, 0x0056E077, 0x00681E59, 0x00EE52A2, 0x00E2CB54, 0x006487AF, 0x00FBF8B8, 0x007DB443, 0x00712DB5, 0x00F7614E, 0x0019A3D2, 0x009FEF29, 0x009376DF, 0x00153A24, 0x008A4533, 0x000C09C8, 0x0000903E, 0x0086DCC5, 0x00B822EB, 0x003E6E10, 0x0032F7E6, 0x00B4BB1D, 0x002BC40A, 0x00AD88F1, 0x00A11107, 0x00275DFC, 0x00DCED5B, 0x005AA1A0, 0x00563856, 0x00D074AD, 0x004F0BBA, 0x00C94741, 0x00C5DEB7, 0x0043924C, 0x007D6C62, 0x00FB2099, 0x00F7B96F, 0x0071F594, 0x00EE8A83, 0x0068C678, 0x00645F8E, 0x00E21375, 0x0015723B, 0x00933EC0, 0x009FA736, 0x0019EBCD, 0x008694DA, 0x0000D821, 0x000C41D7, 0x008A0D2C, 0x00B4F302, 0x0032BFF9, 0x003E260F, 0x00B86AF4, 0x002715E3, 0x00A15918, 0x00ADC0EE, 0x002B8C15, 0x00D03CB2, 0x00567049, 0x005AE9BF, 0x00DCA544, 0x0043DA53, 0x00C596A8, 0x00C90F5E, 0x004F43A5, 0x0071BD8B, 0x00F7F170, 0x00FB6886, 0x007D247D, 0x00E25B6A, 0x00641791, 0x00688E67, 0x00EEC29C, 0x003347A4, 0x00B50B5F, 0x00B992A9, 0x003FDE52, 0x00A0A145, 0x0026EDBE, 0x002A7448, 0x00AC38B3, 0x0092C69D, 0x00148A66, 0x00181390, 0x009E5F6B, 0x0001207C, 0x00876C87, 0x008BF571, 0x000DB98A, 0x00F6092D, 0x007045D6, 0x007CDC20, 0x00FA90DB, 0x0065EFCC, 0x00E3A337, 0x00EF3AC1, 0x0069763A, 0x00578814, 0x00D1C4EF, 0x00DD5D19, 0x005B11E2, 0x00C46EF5, 0x0042220E, 0x004EBBF8, 0x00C8F703, 0x003F964D, 0x00B9DAB6, 0x00B54340, 0x00330FBB, 0x00AC70AC, 0x002A3C57, 0x0026A5A1, 0x00A0E95A, 0x009E1774, 0x00185B8F, 0x0014C279, 0x00928E82, 0x000DF195, 0x008BBD6E, 0x00872498, 0x00016863, 0x00FAD8C4, 0x007C943F, 0x00700DC9, 0x00F64132, 0x00693E25, 0x00EF72DE, 0x00E3EB28, 0x0065A7D3, 0x005B59FD, 0x00DD1506, 0x00D18CF0, 0x0057C00B, 0x00C8BF1C, 0x004EF3E7, 0x00426A11, 0x00C426EA, 0x002AE476, 0x00ACA88D, 0x00A0317B, 0x00267D80, 0x00B90297, 0x003F4E6C, 0x0033D79A, 0x00B59B61, 0x008B654F, 0x000D29B4, 0x0001B042, 0x0087FCB9, 0x001883AE, 0x009ECF55, 0x009256A3, 0x00141A58, 0x00EFAAFF, 0x0069E604, 0x00657FF2, 0x00E33309, 0x007C4C1E, 0x00FA00E5, 0x00F69913, 0x0070D5E8, 0x004E2BC6, 0x00C8673D, 0x00C4FECB, 0x0042B230, 0x00DDCD27, 0x005B81DC, 0x0057182A, 0x00D154D1, 0x0026359F, 0x00A07964, 0x00ACE092, 0x002AAC69, 0x00B5D37E, 0x00339F85, 0x003F0673, 0x00B94A88, 0x0087B4A6, 0x0001F85D, 0x000D61AB, 0x008B2D50, 0x00145247, 0x00921EBC, 0x009E874A, 0x0018CBB1, 0x00E37B16, 0x006537ED, 0x0069AE1B, 0x00EFE2E0, 0x00709DF7, 0x00F6D10C, 0x00FA48FA, 0x007C0401, 0x0042FA2F, 0x00C4B6D4, 0x00C82F22, 0x004E63D9, 0x00D11CCE, 0x00575035, 0x005BC9C3, 0x00DD8538 }; u32bit tmp = crc; while(length >= 16) { tmp = TABLE[((tmp >> 16) ^ input[ 0]) & 0xFF] ^ (tmp << 8); tmp = TABLE[((tmp >> 16) ^ input[ 1]) & 0xFF] ^ (tmp << 8); tmp = TABLE[((tmp >> 16) ^ input[ 2]) & 0xFF] ^ (tmp << 8); tmp = TABLE[((tmp >> 16) ^ input[ 3]) & 0xFF] ^ (tmp << 8); tmp = TABLE[((tmp >> 16) ^ input[ 4]) & 0xFF] ^ (tmp << 8); tmp = TABLE[((tmp >> 16) ^ input[ 5]) & 0xFF] ^ (tmp << 8); tmp = TABLE[((tmp >> 16) ^ input[ 6]) & 0xFF] ^ (tmp << 8); tmp = TABLE[((tmp >> 16) ^ input[ 7]) & 0xFF] ^ (tmp << 8); tmp = TABLE[((tmp >> 16) ^ input[ 8]) & 0xFF] ^ (tmp << 8); tmp = TABLE[((tmp >> 16) ^ input[ 9]) & 0xFF] ^ (tmp << 8); tmp = TABLE[((tmp >> 16) ^ input[10]) & 0xFF] ^ (tmp << 8); tmp = TABLE[((tmp >> 16) ^ input[11]) & 0xFF] ^ (tmp << 8); tmp = TABLE[((tmp >> 16) ^ input[12]) & 0xFF] ^ (tmp << 8); tmp = TABLE[((tmp >> 16) ^ input[13]) & 0xFF] ^ (tmp << 8); tmp = TABLE[((tmp >> 16) ^ input[14]) & 0xFF] ^ (tmp << 8); tmp = TABLE[((tmp >> 16) ^ input[15]) & 0xFF] ^ (tmp << 8); input += 16; length -= 16; } for(size_t i = 0; i != length; ++i) tmp = TABLE[((tmp >> 16) ^ input[i]) & 0xFF] ^ (tmp << 8); crc = tmp; } /* * Finalize a CRC24 Checksum */ void CRC24::final_result(byte output[]) { for(size_t i = 0; i != 3; ++i) output[i] = get_byte(i+1, crc); clear(); } } /* * CRC32 * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { /* * Update a CRC32 Checksum */ void CRC32::add_data(const byte input[], size_t length) { const u32bit TABLE[256] = { 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D }; u32bit tmp = crc; while(length >= 16) { tmp = TABLE[(tmp ^ input[ 0]) & 0xFF] ^ (tmp >> 8); tmp = TABLE[(tmp ^ input[ 1]) & 0xFF] ^ (tmp >> 8); tmp = TABLE[(tmp ^ input[ 2]) & 0xFF] ^ (tmp >> 8); tmp = TABLE[(tmp ^ input[ 3]) & 0xFF] ^ (tmp >> 8); tmp = TABLE[(tmp ^ input[ 4]) & 0xFF] ^ (tmp >> 8); tmp = TABLE[(tmp ^ input[ 5]) & 0xFF] ^ (tmp >> 8); tmp = TABLE[(tmp ^ input[ 6]) & 0xFF] ^ (tmp >> 8); tmp = TABLE[(tmp ^ input[ 7]) & 0xFF] ^ (tmp >> 8); tmp = TABLE[(tmp ^ input[ 8]) & 0xFF] ^ (tmp >> 8); tmp = TABLE[(tmp ^ input[ 9]) & 0xFF] ^ (tmp >> 8); tmp = TABLE[(tmp ^ input[10]) & 0xFF] ^ (tmp >> 8); tmp = TABLE[(tmp ^ input[11]) & 0xFF] ^ (tmp >> 8); tmp = TABLE[(tmp ^ input[12]) & 0xFF] ^ (tmp >> 8); tmp = TABLE[(tmp ^ input[13]) & 0xFF] ^ (tmp >> 8); tmp = TABLE[(tmp ^ input[14]) & 0xFF] ^ (tmp >> 8); tmp = TABLE[(tmp ^ input[15]) & 0xFF] ^ (tmp >> 8); input += 16; length -= 16; } for(size_t i = 0; i != length; ++i) tmp = TABLE[(tmp ^ input[i]) & 0xFF] ^ (tmp >> 8); crc = tmp; } /* * Finalize a CRC32 Checksum */ void CRC32::final_result(byte output[]) { crc ^= 0xFFFFFFFF; store_be(crc, output); clear(); } } /* * Base64 Encoding and Decoding * (C) 2010 Jack Lloyd * * Distributed under the terms of the Botan license */ #include namespace Botan { namespace { static const byte BIN_TO_BASE64[64] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' }; void do_base64_encode(char out[4], const byte in[3]) { out[0] = BIN_TO_BASE64[((in[0] & 0xFC) >> 2)]; out[1] = BIN_TO_BASE64[((in[0] & 0x03) << 4) | (in[1] >> 4)]; out[2] = BIN_TO_BASE64[((in[1] & 0x0F) << 2) | (in[2] >> 6)]; out[3] = BIN_TO_BASE64[((in[2] & 0x3F) )]; } } size_t base64_encode(char out[], const byte in[], size_t input_length, size_t& input_consumed, bool final_inputs) { input_consumed = 0; size_t input_remaining = input_length; size_t output_produced = 0; while(input_remaining >= 3) { do_base64_encode(out + output_produced, in + input_consumed); input_consumed += 3; output_produced += 4; input_remaining -= 3; } if(final_inputs && input_remaining) { byte remainder[3] = { 0 }; for(size_t i = 0; i != input_remaining; ++i) remainder[i] = in[input_consumed + i]; do_base64_encode(out + output_produced, remainder); size_t empty_bits = 8 * (3 - input_remaining); size_t index = output_produced + 4 - 1; while(empty_bits >= 8) { out[index--] = '='; empty_bits -= 6; } input_consumed += input_remaining; output_produced += 4; } return output_produced; } std::string base64_encode(const byte input[], size_t input_length) { std::string output((round_up(input_length, 3) / 3) * 4, 0); size_t consumed = 0; size_t produced = base64_encode(&output[0], input, input_length, consumed, true); BOTAN_ASSERT_EQUAL(consumed, input_length, "Did not consume all input"); BOTAN_ASSERT_EQUAL(produced, output.size(), "Did not produce right amount"); return output; } std::string base64_encode(const MemoryRegion& input) { return base64_encode(&input[0], input.size()); } size_t base64_decode(byte output[], const char input[], size_t input_length, size_t& input_consumed, bool final_inputs, bool ignore_ws) { /* * Base64 Decoder Lookup Table * Warning: assumes ASCII encodings */ static const byte BASE64_TO_BIN[256] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x80, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3E, 0xFF, 0xFF, 0xFF, 0x3F, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0xFF, 0xFF, 0xFF, 0x81, 0xFF, 0xFF, 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; byte* out_ptr = output; byte decode_buf[4]; size_t decode_buf_pos = 0; size_t final_truncate = 0; clear_mem(output, input_length * 3 / 4); for(size_t i = 0; i != input_length; ++i) { const byte bin = BASE64_TO_BIN[static_cast(input[i])]; if(bin <= 0x3F) { decode_buf[decode_buf_pos] = bin; decode_buf_pos += 1; } else if(!(bin == 0x81 || (bin == 0x80 && ignore_ws))) { std::string bad_char(1, input[i]); if(bad_char == "\t") bad_char = "\\t"; else if(bad_char == "\n") bad_char = "\\n"; else if(bad_char == "\r") bad_char = "\\r"; throw std::invalid_argument( std::string("base64_decode: invalid base64 character '") + bad_char + "'"); } /* * If we're at the end of the input, pad with 0s and truncate */ if(final_inputs && (i == input_length - 1)) { if(decode_buf_pos) { for(size_t i = decode_buf_pos; i != 4; ++i) decode_buf[i] = 0; final_truncate = (4 - decode_buf_pos); decode_buf_pos = 4; } } if(decode_buf_pos == 4) { out_ptr[0] = (decode_buf[0] << 2) | (decode_buf[1] >> 4); out_ptr[1] = (decode_buf[1] << 4) | (decode_buf[2] >> 2); out_ptr[2] = (decode_buf[2] << 6) | decode_buf[3]; out_ptr += 3; decode_buf_pos = 0; input_consumed = i+1; } } while(input_consumed < input_length && BASE64_TO_BIN[static_cast(input[input_consumed])] == 0x80) { ++input_consumed; } size_t written = (out_ptr - output) - final_truncate; return written; } size_t base64_decode(byte output[], const char input[], size_t input_length, bool ignore_ws) { size_t consumed = 0; size_t written = base64_decode(output, input, input_length, consumed, true, ignore_ws); if(consumed != input_length) throw std::invalid_argument("base64_decode: input did not have full bytes"); return written; } size_t base64_decode(byte output[], const std::string& input, bool ignore_ws) { return base64_decode(output, &input[0], input.length(), ignore_ws); } SecureVector base64_decode(const char input[], size_t input_length, bool ignore_ws) { SecureVector bin((round_up(input_length, 4) * 3) / 4); size_t written = base64_decode(&bin[0], input, input_length, ignore_ws); bin.resize(written); return bin; } SecureVector base64_decode(const std::string& input, bool ignore_ws) { return base64_decode(&input[0], input.size(), ignore_ws); } } /* * Hex Encoding and Decoding * (C) 2010 Jack Lloyd * * Distributed under the terms of the Botan license */ #include namespace Botan { void hex_encode(char output[], const byte input[], size_t input_length, bool uppercase) { static const byte BIN_TO_HEX_UPPER[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; static const byte BIN_TO_HEX_LOWER[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; const byte* tbl = uppercase ? BIN_TO_HEX_UPPER : BIN_TO_HEX_LOWER; for(size_t i = 0; i != input_length; ++i) { byte x = input[i]; output[2*i ] = tbl[(x >> 4) & 0x0F]; output[2*i+1] = tbl[(x ) & 0x0F]; } } std::string hex_encode(const MemoryRegion& input, bool uppercase) { return hex_encode(&input[0], input.size(), uppercase); } std::string hex_encode(const byte input[], size_t input_length, bool uppercase) { std::string output(2 * input_length, 0); if(input_length) hex_encode(&output[0], input, input_length, uppercase); return output; } size_t hex_decode(byte output[], const char input[], size_t input_length, size_t& input_consumed, bool ignore_ws) { /* * Mapping of hex characters to either their binary equivalent * or to an error code. * If valid hex (0-9 A-F a-f), the value. * If whitespace, then 0x80 * Otherwise 0xFF * Warning: this table assumes ASCII character encodings */ static const byte HEX_TO_BIN[256] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; byte* out_ptr = output; bool top_nibble = true; clear_mem(output, input_length / 2); for(size_t i = 0; i != input_length; ++i) { const byte bin = HEX_TO_BIN[static_cast(input[i])]; if(bin >= 0x10) { if(bin == 0x80 && ignore_ws) continue; std::string bad_char(1, input[i]); if(bad_char == "\t") bad_char = "\\t"; else if(bad_char == "\n") bad_char = "\\n"; throw std::invalid_argument( std::string("hex_decode: invalid hex character '") + bad_char + "'"); } *out_ptr |= bin << (top_nibble*4); top_nibble = !top_nibble; if(top_nibble) ++out_ptr; } input_consumed = input_length; size_t written = (out_ptr - output); /* * We only got half of a byte at the end; zap the half-written * output and mark it as unread */ if(!top_nibble) { *out_ptr = 0; input_consumed -= 1; } return written; } size_t hex_decode(byte output[], const char input[], size_t input_length, bool ignore_ws) { size_t consumed = 0; size_t written = hex_decode(output, input, input_length, consumed, ignore_ws); if(consumed != input_length) throw std::invalid_argument("hex_decode: input did not have full bytes"); return written; } size_t hex_decode(byte output[], const std::string& input, bool ignore_ws) { return hex_decode(output, &input[0], input.length(), ignore_ws); } SecureVector hex_decode(const char input[], size_t input_length, bool ignore_ws) { SecureVector bin(1 + input_length / 2); size_t written = hex_decode(&bin[0], input, input_length, ignore_ws); bin.resize(written); return bin; } SecureVector hex_decode(const std::string& input, bool ignore_ws) { return hex_decode(&input[0], input.size(), ignore_ws); } } /* * OpenPGP Codec * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { /* * OpenPGP Base64 encoding */ std::string PGP_encode( const byte input[], size_t length, const std::string& label, const std::map& headers) { const std::string PGP_HEADER = "-----BEGIN PGP " + label + "-----\n"; const std::string PGP_TRAILER = "-----END PGP " + label + "-----\n"; const size_t PGP_WIDTH = 64; std::string pgp_encoded = PGP_HEADER; if(headers.find("Version") != headers.end()) pgp_encoded += "Version: " + headers.find("Version")->second + '\n'; std::map::const_iterator i = headers.begin(); while(i != headers.end()) { if(i->first != "Version") pgp_encoded += i->first + ": " + i->second + '\n'; ++i; } pgp_encoded += '\n'; Pipe pipe(new Fork( new Base64_Encoder(true, PGP_WIDTH), new Chain(new Hash_Filter(new CRC24), new Base64_Encoder) ) ); pipe.process_msg(input, length); pgp_encoded += pipe.read_all_as_string(0); pgp_encoded += '=' + pipe.read_all_as_string(1) + '\n'; pgp_encoded += PGP_TRAILER; return pgp_encoded; } /* * OpenPGP Base64 encoding */ std::string PGP_encode(const byte input[], size_t length, const std::string& type) { std::map empty; return PGP_encode(input, length, type, empty); } /* * OpenPGP Base64 decoding */ SecureVector PGP_decode(DataSource& source, std::string& label, std::map& headers) { const size_t RANDOM_CHAR_LIMIT = 5; const std::string PGP_HEADER1 = "-----BEGIN PGP "; const std::string PGP_HEADER2 = "-----"; size_t position = 0; while(position != PGP_HEADER1.length()) { byte b; if(!source.read_byte(b)) throw Decoding_Error("PGP: No PGP header found"); if(b == PGP_HEADER1[position]) ++position; else if(position >= RANDOM_CHAR_LIMIT) throw Decoding_Error("PGP: Malformed PGP header"); else position = 0; } position = 0; while(position != PGP_HEADER2.length()) { byte b; if(!source.read_byte(b)) throw Decoding_Error("PGP: No PGP header found"); if(b == PGP_HEADER2[position]) ++position; else if(position) throw Decoding_Error("PGP: Malformed PGP header"); if(position == 0) label += static_cast(b); } headers.clear(); bool end_of_headers = false; while(!end_of_headers) { std::string this_header; byte b = 0; while(b != '\n') { if(!source.read_byte(b)) throw Decoding_Error("PGP: Bad armor header"); if(b != '\n') this_header += static_cast(b); } end_of_headers = true; for(size_t j = 0; j != this_header.length(); ++j) if(!Charset::is_space(this_header[j])) end_of_headers = false; if(!end_of_headers) { std::string::size_type pos = this_header.find(": "); if(pos == std::string::npos) throw Decoding_Error("OpenPGP: Bad headers"); std::string key = this_header.substr(0, pos); std::string value = this_header.substr(pos + 2, std::string::npos); headers[key] = value; } } Pipe base64(new Base64_Decoder, new Fork(0, new Chain(new Hash_Filter(new CRC24), new Base64_Encoder) ) ); base64.start_msg(); const std::string PGP_TRAILER = "-----END PGP " + label + "-----"; position = 0; bool newline_seen = 0; std::string crc; while(position != PGP_TRAILER.length()) { byte b; if(!source.read_byte(b)) throw Decoding_Error("PGP: No PGP trailer found"); if(b == PGP_TRAILER[position]) ++position; else if(position) throw Decoding_Error("PGP: Malformed PGP trailer"); if(b == '=' && newline_seen) { while(b != '\n') { if(!source.read_byte(b)) throw Decoding_Error("PGP: Bad CRC tail"); if(b != '\n') crc += static_cast(b); } } else if(b == '\n') newline_seen = true; else if(position == 0) { base64.write(b); newline_seen = false; } } base64.end_msg(); if(crc != "" && crc != base64.read_all_as_string(1)) throw Decoding_Error("PGP: Corrupt CRC"); return base64.read_all(); } /* * OpenPGP Base64 decoding */ SecureVector PGP_decode(DataSource& source, std::string& label) { std::map ignored; return PGP_decode(source, label, ignored); } } /* * PEM Encoding/Decoding * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { namespace PEM_Code { /* * PEM encode BER/DER-encoded objects */ std::string encode(const byte der[], size_t length, const std::string& label, size_t width) { const std::string PEM_HEADER = "-----BEGIN " + label + "-----\n"; const std::string PEM_TRAILER = "-----END " + label + "-----\n"; Pipe pipe(new Base64_Encoder(true, width)); pipe.process_msg(der, length); return (PEM_HEADER + pipe.read_all_as_string() + PEM_TRAILER); } /* * PEM encode BER/DER-encoded objects */ std::string encode(const MemoryRegion& data, const std::string& label, size_t width) { return encode(&data[0], data.size(), label, width); } /* * Decode PEM down to raw BER/DER */ SecureVector decode_check_label(DataSource& source, const std::string& label_want) { std::string label_got; SecureVector ber = decode(source, label_got); if(label_got != label_want) throw Decoding_Error("PEM: Label mismatch, wanted " + label_want + ", got " + label_got); return ber; } /* * Decode PEM down to raw BER/DER */ SecureVector decode(DataSource& source, std::string& label) { const size_t RANDOM_CHAR_LIMIT = 8; const std::string PEM_HEADER1 = "-----BEGIN "; const std::string PEM_HEADER2 = "-----"; size_t position = 0; while(position != PEM_HEADER1.length()) { byte b; if(!source.read_byte(b)) throw Decoding_Error("PEM: No PEM header found"); if(b == PEM_HEADER1[position]) ++position; else if(position >= RANDOM_CHAR_LIMIT) throw Decoding_Error("PEM: Malformed PEM header"); else position = 0; } position = 0; while(position != PEM_HEADER2.length()) { byte b; if(!source.read_byte(b)) throw Decoding_Error("PEM: No PEM header found"); if(b == PEM_HEADER2[position]) ++position; else if(position) throw Decoding_Error("PEM: Malformed PEM header"); if(position == 0) label += static_cast(b); } Pipe base64(new Base64_Decoder); base64.start_msg(); const std::string PEM_TRAILER = "-----END " + label + "-----"; position = 0; while(position != PEM_TRAILER.length()) { byte b; if(!source.read_byte(b)) throw Decoding_Error("PEM: No PEM trailer found"); if(b == PEM_TRAILER[position]) ++position; else if(position) throw Decoding_Error("PEM: Malformed PEM trailer"); if(position == 0) base64.write(b); } base64.end_msg(); return base64.read_all(); } /* * Search for a PEM signature */ bool matches(DataSource& source, const std::string& extra, size_t search_range) { const std::string PEM_HEADER = "-----BEGIN " + extra; SecureVector search_buf(search_range); size_t got = source.peek(&search_buf[0], search_buf.size(), 0); if(got < PEM_HEADER.length()) return false; size_t index = 0; for(size_t j = 0; j != got; ++j) { if(search_buf[j] == PEM_HEADER[index]) ++index; else index = 0; if(index == PEM_HEADER.size()) return true; } return false; } } } /* * Rivest's Package Tranform * * (C) 2009 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { void aont_package(RandomNumberGenerator& rng, BlockCipher* cipher, const byte input[], size_t input_len, byte output[]) { const size_t BLOCK_SIZE = cipher->block_size(); if(!cipher->valid_keylength(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(BLOCK_SIZE*2, '0'); SymmetricKey package_key(rng, BLOCK_SIZE); Pipe pipe(new StreamCipher_Filter(new CTR_BE(cipher), package_key)); pipe.process_msg(input, input_len); pipe.read(output, pipe.remaining()); // Set K0 (the all zero key) cipher->set_key(SymmetricKey(all_zeros)); SecureVector buf(BLOCK_SIZE); const size_t blocks = (input_len + BLOCK_SIZE - 1) / BLOCK_SIZE; byte* final_block = output + input_len; clear_mem(final_block, BLOCK_SIZE); // XOR the hash blocks into the final block for(size_t i = 0; i != blocks; ++i) { const size_t left = std::min(BLOCK_SIZE, input_len - BLOCK_SIZE * i); zeroise(buf); copy_mem(&buf[0], output + (BLOCK_SIZE * i), left); for(size_t j = 0; j != sizeof(i); ++j) buf[BLOCK_SIZE - 1 - j] ^= get_byte(sizeof(i)-1-j, i); cipher->encrypt(buf); xor_buf(final_block, buf, BLOCK_SIZE); } // XOR the random package key into the final block xor_buf(final_block, package_key.begin(), BLOCK_SIZE); } void aont_unpackage(BlockCipher* cipher, const byte input[], size_t input_len, byte output[]) { const size_t BLOCK_SIZE = cipher->block_size(); if(!cipher->valid_keylength(BLOCK_SIZE)) throw Invalid_Argument("AONT::unpackage: Invalid cipher"); if(input_len < 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(BLOCK_SIZE*2, '0'); cipher->set_key(SymmetricKey(all_zeros)); SecureVector package_key(BLOCK_SIZE); SecureVector buf(BLOCK_SIZE); // Copy the package key (masked with the block hashes) copy_mem(&package_key[0], input + (input_len - BLOCK_SIZE), BLOCK_SIZE); const size_t blocks = ((input_len - 1) / BLOCK_SIZE); // XOR the blocks into the package key bits for(size_t i = 0; i != blocks; ++i) { const size_t left = std::min(BLOCK_SIZE, input_len - BLOCK_SIZE * (i+1)); zeroise(buf); copy_mem(&buf[0], input + (BLOCK_SIZE * i), left); for(size_t j = 0; j != sizeof(i); ++j) buf[BLOCK_SIZE - 1 - j] ^= get_byte(sizeof(i)-1-j, i); cipher->encrypt(buf); xor_buf(&package_key[0], buf, BLOCK_SIZE); } Pipe pipe(new StreamCipher_Filter(new CTR_BE(cipher), package_key)); pipe.process_msg(input, input_len - BLOCK_SIZE); pipe.read(output, pipe.remaining()); } } /* * Cryptobox Message Routines * (C) 2009 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { namespace CryptoBox { namespace { /* First 24 bits of SHA-256("Botan Cryptobox"), followed by 8 0 bits for later use as flags, etc if needed */ const u32bit CRYPTOBOX_VERSION_CODE = 0xEFC22400; const size_t VERSION_CODE_LEN = 4; const size_t CIPHER_KEY_LEN = 32; const size_t CIPHER_IV_LEN = 16; const size_t MAC_KEY_LEN = 32; const size_t MAC_OUTPUT_LEN = 20; const size_t PBKDF_SALT_LEN = 10; const size_t PBKDF_ITERATIONS = 8 * 1024; const size_t PBKDF_OUTPUT_LEN = CIPHER_KEY_LEN + CIPHER_IV_LEN + MAC_KEY_LEN; } std::string encrypt(const byte input[], size_t input_len, const std::string& passphrase, RandomNumberGenerator& rng) { SecureVector pbkdf_salt(PBKDF_SALT_LEN); rng.randomize(&pbkdf_salt[0], pbkdf_salt.size()); PKCS5_PBKDF2 pbkdf(new HMAC(new SHA_512)); OctetString master_key = pbkdf.derive_key( PBKDF_OUTPUT_LEN, passphrase, &pbkdf_salt[0], pbkdf_salt.size(), PBKDF_ITERATIONS); const byte* mk = master_key.begin(); SymmetricKey cipher_key(&mk[0], CIPHER_KEY_LEN); SymmetricKey mac_key(&mk[CIPHER_KEY_LEN], MAC_KEY_LEN); InitializationVector iv(&mk[CIPHER_KEY_LEN + MAC_KEY_LEN], CIPHER_IV_LEN); Pipe pipe(get_cipher("Serpent/CTR-BE", cipher_key, iv, ENCRYPTION), new Fork( 0, new MAC_Filter(new HMAC(new SHA_512), mac_key, MAC_OUTPUT_LEN))); pipe.process_msg(input, input_len); /* Output format is: version # (4 bytes) salt (10 bytes) mac (20 bytes) ciphertext */ const size_t ciphertext_len = pipe.remaining(0); SecureVector out_buf(VERSION_CODE_LEN + PBKDF_SALT_LEN + MAC_OUTPUT_LEN + ciphertext_len); for(size_t i = 0; i != VERSION_CODE_LEN; ++i) out_buf[i] = get_byte(i, CRYPTOBOX_VERSION_CODE); copy_mem(&out_buf[VERSION_CODE_LEN], &pbkdf_salt[0], PBKDF_SALT_LEN); pipe.read(&out_buf[VERSION_CODE_LEN + PBKDF_SALT_LEN], MAC_OUTPUT_LEN, 1); pipe.read(&out_buf[VERSION_CODE_LEN + PBKDF_SALT_LEN + MAC_OUTPUT_LEN], ciphertext_len, 0); return PEM_Code::encode(out_buf, "BOTAN CRYPTOBOX MESSAGE"); } std::string decrypt(const byte input[], size_t input_len, const std::string& passphrase) { DataSource_Memory input_src(input, input_len); SecureVector ciphertext = PEM_Code::decode_check_label(input_src, "BOTAN CRYPTOBOX MESSAGE"); if(ciphertext.size() < (VERSION_CODE_LEN + PBKDF_SALT_LEN + MAC_OUTPUT_LEN)) throw Decoding_Error("Invalid CryptoBox input"); for(size_t i = 0; i != VERSION_CODE_LEN; ++i) if(ciphertext[i] != get_byte(i, CRYPTOBOX_VERSION_CODE)) throw Decoding_Error("Bad CryptoBox version"); const byte* pbkdf_salt = &ciphertext[VERSION_CODE_LEN]; PKCS5_PBKDF2 pbkdf(new HMAC(new SHA_512)); OctetString master_key = pbkdf.derive_key( PBKDF_OUTPUT_LEN, passphrase, pbkdf_salt, PBKDF_SALT_LEN, PBKDF_ITERATIONS); const byte* mk = master_key.begin(); SymmetricKey cipher_key(&mk[0], CIPHER_KEY_LEN); SymmetricKey mac_key(&mk[CIPHER_KEY_LEN], MAC_KEY_LEN); InitializationVector iv(&mk[CIPHER_KEY_LEN + MAC_KEY_LEN], CIPHER_IV_LEN); Pipe pipe(new Fork( get_cipher("Serpent/CTR-BE", cipher_key, iv, DECRYPTION), new MAC_Filter(new HMAC(new SHA_512), mac_key, MAC_OUTPUT_LEN))); const size_t ciphertext_offset = VERSION_CODE_LEN + PBKDF_SALT_LEN + MAC_OUTPUT_LEN; pipe.process_msg(&ciphertext[ciphertext_offset], ciphertext.size() - ciphertext_offset); byte computed_mac[MAC_OUTPUT_LEN]; pipe.read(computed_mac, MAC_OUTPUT_LEN, 1); if(!same_mem(computed_mac, &ciphertext[VERSION_CODE_LEN + PBKDF_SALT_LEN], MAC_OUTPUT_LEN)) throw Decoding_Error("CryptoBox integrity failure"); return pipe.read_all_as_string(0); } std::string decrypt(const std::string& input, const std::string& passphrase) { return decrypt(reinterpret_cast(&input[0]), input.size(), passphrase); } } } /* * Format Preserving Encryption using the scheme FE1 from the paper * "Format-Preserving Encryption" by Bellare, Rogaway, et al * (http://eprint.iacr.org/2009/251) * * (C) 2009 Jack Lloyd * * Distributed under the terms of the Botan license */ #include namespace Botan { namespace FPE { namespace { // Normally FPE is for SSNs, CC#s, etc, nothing too big const size_t MAX_N_BYTES = 128/8; /* * Factor n into a and b which are as close together as possible. * Assumes n is composed mostly of small factors which is the case for * typical uses of FPE (typically, n is a power of 10) * * Want a >= b since the safe number of rounds is 2+log_a(b); if a >= b * then this is always 3 */ void factor(BigInt n, BigInt& a, BigInt& b) { a = 1; b = 1; size_t n_low_zero = low_zero_bits(n); a <<= (n_low_zero / 2); b <<= n_low_zero - (n_low_zero / 2); n >>= n_low_zero; for(size_t i = 0; i != PRIME_TABLE_SIZE; ++i) { while(n % PRIMES[i] == 0) { a *= PRIMES[i]; if(a > b) std::swap(a, b); n /= PRIMES[i]; } } if(a > b) std::swap(a, b); a *= n; if(a < b) std::swap(a, b); if(a <= 1 || b <= 1) throw std::runtime_error("Could not factor n for use in FPE"); } /* * According to a paper by Rogaway, Bellare, etc, the min safe number * of rounds to use for FPE is 2+log_a(b). If a >= b then log_a(b) <= 1 * so 3 rounds is safe. The FPE factorization routine should always * return a >= b, so just confirm that and return 3. */ size_t rounds(const BigInt& a, const BigInt& b) { if(a < b) throw std::logic_error("FPE rounds: a < b"); return 3; } /* * A simple round function based on HMAC(SHA-256) */ class FPE_Encryptor { public: FPE_Encryptor(const SymmetricKey& key, const BigInt& n, const MemoryRegion& tweak); ~FPE_Encryptor() { delete mac; } BigInt operator()(size_t i, const BigInt& R); private: MessageAuthenticationCode* mac; SecureVector mac_n_t; }; FPE_Encryptor::FPE_Encryptor(const SymmetricKey& key, const BigInt& n, const MemoryRegion& tweak) { mac = new HMAC(new SHA_256); mac->set_key(key); SecureVector n_bin = BigInt::encode(n); if(n_bin.size() > MAX_N_BYTES) throw std::runtime_error("N is too large for FPE encryption"); mac->update_be(static_cast(n_bin.size())); mac->update(&n_bin[0], n_bin.size()); mac->update_be(static_cast(tweak.size())); mac->update(&tweak[0], tweak.size()); mac_n_t = mac->final(); } BigInt FPE_Encryptor::operator()(size_t round_no, const BigInt& R) { SecureVector r_bin = BigInt::encode(R); mac->update(mac_n_t); mac->update_be(static_cast(round_no)); mac->update_be(static_cast(r_bin.size())); mac->update(&r_bin[0], r_bin.size()); SecureVector X = mac->final(); return BigInt(&X[0], X.size()); } } /* * Generic Z_n FPE encryption, FE1 scheme */ BigInt fe1_encrypt(const BigInt& n, const BigInt& X0, const SymmetricKey& key, const MemoryRegion& tweak) { FPE_Encryptor F(key, n, tweak); BigInt a, b; factor(n, a, b); const size_t r = rounds(a, b); BigInt X = X0; for(size_t i = 0; i != r; ++i) { BigInt L = X / b; BigInt R = X % b; BigInt W = (L + F(i, R)) % a; X = a * R + W; } return X; } /* * Generic Z_n FPE decryption, FD1 scheme */ BigInt fe1_decrypt(const BigInt& n, const BigInt& X0, const SymmetricKey& key, const MemoryRegion& tweak) { FPE_Encryptor F(key, n, tweak); BigInt a, b; factor(n, a, b); const size_t r = rounds(a, b); BigInt X = X0; for(size_t i = 0; i != r; ++i) { BigInt W = X % a; BigInt R = X / a; BigInt L = (W - F(r-i-1, R)) % a; X = b * L + R; } return X; } } } /* * AES Key Wrap (RFC 3394) * (C) 2011 Jack Lloyd * * Distributed under the terms of the Botan license */ #include namespace Botan { namespace { BlockCipher* make_aes(size_t keylength, Algorithm_Factory& af) { if(keylength == 16) return af.make_block_cipher("AES-128"); else if(keylength == 24) return af.make_block_cipher("AES-192"); else if(keylength == 32) return af.make_block_cipher("AES-256"); else throw std::invalid_argument("Bad KEK length for NIST keywrap"); } } SecureVector rfc3394_keywrap(const MemoryRegion& key, const SymmetricKey& kek, Algorithm_Factory& af) { if(key.size() % 8 != 0) throw std::invalid_argument("Bad input key size for NIST key wrap"); std::unique_ptr aes(make_aes(kek.length(), af)); aes->set_key(kek); const size_t n = key.size() / 8; SecureVector R((n + 1) * 8); SecureVector A(16); for(size_t i = 0; i != 8; ++i) A[i] = 0xA6; copy_mem(&R[8], key.begin(), key.size()); for(size_t j = 0; j <= 5; ++j) { for(size_t i = 1; i <= n; ++i) { const u32bit t = (n * j) + i; copy_mem(&A[8], &R[8*i], 8); aes->encrypt(&A[0]); copy_mem(&R[8*i], &A[8], 8); byte t_buf[4] = { 0 }; store_be(t, t_buf); xor_buf(&A[4], &t_buf[0], 4); } } copy_mem(&R[0], &A[0], 8); return R; } SecureVector rfc3394_keyunwrap(const MemoryRegion& key, const SymmetricKey& kek, Algorithm_Factory& af) { if(key.size() < 16 || key.size() % 8 != 0) throw std::invalid_argument("Bad input key size for NIST key unwrap"); std::unique_ptr aes(make_aes(kek.length(), af)); aes->set_key(kek); const size_t n = (key.size() - 8) / 8; SecureVector R(n * 8); SecureVector A(16); for(size_t i = 0; i != 8; ++i) A[i] = key[i]; copy_mem(&R[0], key.begin() + 8, key.size() - 8); for(size_t j = 0; j <= 5; ++j) { for(size_t i = n; i != 0; --i) { const u32bit t = (5 - j) * n + i; byte t_buf[4] = { 0 }; store_be(t, t_buf); xor_buf(&A[4], &t_buf[0], 4); copy_mem(&A[8], &R[8*(i-1)], 8); aes->decrypt(&A[0]); copy_mem(&R[8*(i-1)], &A[8], 8); } } if(load_be(&A[0], 0) != 0xA6A6A6A6A6A6A6A6ULL) throw Integrity_Failure("NIST key unwrap failed"); return R; } } /* * SRP-6a (RFC 5054 compatatible) * (C) 2011,2012 Jack Lloyd * * Distributed under the terms of the Botan license */ #include namespace Botan { namespace { BigInt hash_seq(const std::string& hash_id, size_t pad_to, const BigInt& in1, const BigInt& in2) { std::unique_ptr hash_fn( global_state().algorithm_factory().make_hash_function(hash_id)); hash_fn->update(BigInt::encode_1363(in1, pad_to)); hash_fn->update(BigInt::encode_1363(in2, pad_to)); return BigInt::decode(hash_fn->final()); } BigInt compute_x(const std::string& hash_id, const std::string& identifier, const std::string& password, const MemoryRegion& salt) { std::unique_ptr hash_fn( global_state().algorithm_factory().make_hash_function(hash_id)); hash_fn->update(identifier); hash_fn->update(":"); hash_fn->update(password); SecureVector inner_h = hash_fn->final(); hash_fn->update(salt); hash_fn->update(inner_h); SecureVector outer_h = hash_fn->final(); return BigInt::decode(outer_h); } } std::string srp6_group_identifier(const BigInt& N, const BigInt& g) { /* This function assumes that only one 'standard' SRP parameter set has been defined for a particular bitsize. As of this writing that is the case. */ try { const std::string group_name = "modp/srp/" + to_string(N.bits()); DL_Group group(group_name); if(group.get_p() == N && group.get_g() == g) return group_name; throw std::runtime_error("Unknown SRP params"); } catch(...) { throw Invalid_Argument("Bad SRP group parameters"); } } std::pair srp6_client_agree(const std::string& identifier, const std::string& password, const std::string& group_id, const std::string& hash_id, const MemoryRegion& salt, const BigInt& B, RandomNumberGenerator& rng) { DL_Group group(group_id); const BigInt& g = group.get_g(); const BigInt& p = group.get_p(); const size_t p_bytes = group.get_p().bytes(); if(B % p == 0) throw std::runtime_error("Invalid SRP parameter from server"); BigInt k = hash_seq(hash_id, p_bytes, p, g); BigInt a(rng, 256); BigInt A = power_mod(g, a, p); BigInt u = hash_seq(hash_id, p_bytes, A, B); const BigInt x = compute_x(hash_id, identifier, password, salt); BigInt S = power_mod((B - (k * power_mod(g, x, p))) % p, (a + (u * x)), p); SymmetricKey Sk(BigInt::encode_1363(S, p_bytes)); return std::make_pair(A, Sk); } BigInt generate_srp6_verifier(const std::string& identifier, const std::string& password, const MemoryRegion& salt, const std::string& group_id, const std::string& hash_id) { const BigInt x = compute_x(hash_id, identifier, password, salt); DL_Group group(group_id); return power_mod(group.get_g(), x, group.get_p()); } BigInt SRP6_Server_Session::step1(const BigInt& v, const std::string& group_id, const std::string& hash_id, RandomNumberGenerator& rng) { DL_Group group(group_id); const BigInt& g = group.get_g(); const BigInt& p = group.get_p(); p_bytes = p.bytes(); BigInt k = hash_seq(hash_id, p_bytes, p, g); BigInt b(rng, 256); B = (v*k + power_mod(g, b, p)) % p; this->v = v; this->b = b; this->p = p; this->hash_id = hash_id; return B; } SymmetricKey SRP6_Server_Session::step2(const BigInt& A) { if(A % p == 0) throw std::runtime_error("Invalid SRP parameter from client"); BigInt u = hash_seq(hash_id, p_bytes, A, B); BigInt S = power_mod(A * power_mod(v, u, p), b, p); return BigInt::encode_1363(S, p_bytes); } } /* * RTSS (threshold secret sharing) * (C) 2009 Jack Lloyd * * Distributed under the terms of the Botan license */ #include namespace Botan { namespace { /** Table for GF(2^8) arithmetic (exponentials) */ const byte RTSS_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 RTSS_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 RTSS_EXP[(RTSS_LOG[x] + RTSS_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) { contents = hex_decode(hex_input); } 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 { return hex_encode(&contents[0], contents.size()); } std::vector 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 shares(N); // Create RTSS header in each share for(byte i = 0; i != N; ++i) { shares[i].contents += std::make_pair(identifier, 16); shares[i].contents += rtss_hash_id(hash.name()); shares[i].contents += M; shares[i].contents += get_byte(0, S_len); shares[i].contents += get_byte(1, S_len); } // Choose sequential values for X starting from 1 for(byte i = 0; i != N; ++i) shares[i].contents.push_back(i+1); // secret = S || H(S) SecureVector secret(S, S_len); secret += hash.process(S, S_len); for(size_t i = 0; i != secret.size(); ++i) { std::vector 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.push_back(sum); } } return shares; } SecureVector RTSS_Share::reconstruct(const std::vector& shares) { const size_t 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[0], &shares[i].contents[0], 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::unique_ptr 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 V(shares.size()); SecureVector 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 = RTSS_EXP[(255 + RTSS_LOG[share_l] - RTSS_LOG[share_k ^ share_l]) % 255]; r2 = gfp_mul(r2, div); } r ^= gfp_mul(V[k], r2); } secret.push_back(r); } if(secret.size() != secret_len + hash->output_length()) throw Decoding_Error("Bad length in RTSS output"); hash->update(&secret[0], secret_len); SecureVector hash_check = hash->final(); if(!same_mem(&hash_check[0], &secret[secret_len], hash->output_length())) throw Decoding_Error("RTSS hash check failed"); return SecureVector(&secret[0], secret_len); } } /* * Core Engine * (C) 1999-2007,2011 Jack Lloyd * * Distributed under the terms of the Botan license */ #include #if defined(BOTAN_HAS_ECB) #endif #if defined(BOTAN_HAS_CBC) #endif #if defined(BOTAN_HAS_CTS) #endif #if defined(BOTAN_HAS_CFB) #endif #if defined(BOTAN_HAS_OFB) #endif #if defined(BOTAN_HAS_CTR_BE) #endif #if defined(BOTAN_HAS_EAX) #endif #if defined(BOTAN_HAS_XTS) #endif namespace Botan { namespace { /** * Get a block cipher padding method by name */ BlockCipherModePaddingMethod* get_bc_pad(const std::string& algo_spec, const std::string& def_if_empty) { #if defined(BOTAN_HAS_CIPHER_MODE_PADDING) 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(algo_spec == "OneAndZeros") return new OneAndZeros_Padding; if(algo_spec == "X9.23") return new ANSI_X923_Padding; #endif throw Algorithm_Not_Found(algo_spec); } } Keyed_Filter* get_cipher_mode(const BlockCipher* block_cipher, Cipher_Dir direction, const std::string& mode, const std::string& padding) { #if defined(BOTAN_HAS_OFB) if(mode == "OFB") return new StreamCipher_Filter(new OFB(block_cipher->clone())); #endif #if defined(BOTAN_HAS_CTR_BE) if(mode == "CTR-BE") return new StreamCipher_Filter(new CTR_BE(block_cipher->clone())); #endif #if defined(BOTAN_HAS_ECB) if(mode == "ECB" || mode == "") { if(direction == ENCRYPTION) return new ECB_Encryption(block_cipher->clone(), get_bc_pad(padding, "NoPadding")); else return new ECB_Decryption(block_cipher->clone(), get_bc_pad(padding, "NoPadding")); } #endif if(mode == "CBC") { if(padding == "CTS") { #if defined(BOTAN_HAS_CTS) if(direction == ENCRYPTION) return new CTS_Encryption(block_cipher->clone()); else return new CTS_Decryption(block_cipher->clone()); #else return 0; #endif } #if defined(BOTAN_HAS_CBC) if(direction == ENCRYPTION) return new CBC_Encryption(block_cipher->clone(), get_bc_pad(padding, "PKCS7")); else return new CBC_Decryption(block_cipher->clone(), get_bc_pad(padding, "PKCS7")); #else return 0; #endif } #if defined(BOTAN_HAS_XTS) if(mode == "XTS") { if(direction == ENCRYPTION) return new XTS_Encryption(block_cipher->clone()); else return new XTS_Decryption(block_cipher->clone()); } #endif if(mode.find("CFB") != std::string::npos || mode.find("EAX") != std::string::npos) { size_t bits = 0; std::vector 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* Core_Engine::get_cipher(const std::string& algo_spec, Cipher_Dir direction, Algorithm_Factory& af) { std::vector 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() >= 4) return 0; // 4 part mode, not something we know about if(algo_parts.size() < 2) throw Lookup_Error("Cipher specification '" + algo_spec + "' is missing mode identifier"); 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(cipher_name + "/" + mode + "/" + padding); } } /* * PK Operations * (C) 1999-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ #if defined(BOTAN_HAS_RSA) #endif #if defined(BOTAN_HAS_RW) #endif #if defined(BOTAN_HAS_DSA) #endif #if defined(BOTAN_HAS_ECDSA) #endif #if defined(BOTAN_HAS_ELGAMAL) #endif #if defined(BOTAN_HAS_GOST_34_10_2001) #endif #if defined(BOTAN_HAS_NYBERG_RUEPPEL) #endif #if defined(BOTAN_HAS_DIFFIE_HELLMAN) #endif #if defined(BOTAN_HAS_ECDH) #endif namespace Botan { PK_Ops::Encryption* Core_Engine::get_encryption_op(const Public_Key& key) const { #if defined(BOTAN_HAS_RSA) if(const RSA_PublicKey* s = dynamic_cast(&key)) return new RSA_Public_Operation(*s); #endif #if defined(BOTAN_HAS_ELGAMAL) if(const ElGamal_PublicKey* s = dynamic_cast(&key)) return new ElGamal_Encryption_Operation(*s); #endif return 0; } PK_Ops::Decryption* Core_Engine::get_decryption_op(const Private_Key& key) const { #if defined(BOTAN_HAS_RSA) if(const RSA_PrivateKey* s = dynamic_cast(&key)) return new RSA_Private_Operation(*s); #endif #if defined(BOTAN_HAS_ELGAMAL) if(const ElGamal_PrivateKey* s = dynamic_cast(&key)) return new ElGamal_Decryption_Operation(*s); #endif return 0; } PK_Ops::Key_Agreement* Core_Engine::get_key_agreement_op(const Private_Key& key) const { #if defined(BOTAN_HAS_DIFFIE_HELLMAN) if(const DH_PrivateKey* dh = dynamic_cast(&key)) return new DH_KA_Operation(*dh); #endif #if defined(BOTAN_HAS_ECDH) if(const ECDH_PrivateKey* ecdh = dynamic_cast(&key)) return new ECDH_KA_Operation(*ecdh); #endif return 0; } PK_Ops::Signature* Core_Engine::get_signature_op(const Private_Key& key) const { #if defined(BOTAN_HAS_RSA) if(const RSA_PrivateKey* s = dynamic_cast(&key)) return new RSA_Private_Operation(*s); #endif #if defined(BOTAN_HAS_RW) if(const RW_PrivateKey* s = dynamic_cast(&key)) return new RW_Signature_Operation(*s); #endif #if defined(BOTAN_HAS_DSA) if(const DSA_PrivateKey* s = dynamic_cast(&key)) return new DSA_Signature_Operation(*s); #endif #if defined(BOTAN_HAS_ECDSA) if(const ECDSA_PrivateKey* s = dynamic_cast(&key)) return new ECDSA_Signature_Operation(*s); #endif #if defined(BOTAN_HAS_GOST_34_10_2001) if(const GOST_3410_PrivateKey* s = dynamic_cast(&key)) return new GOST_3410_Signature_Operation(*s); #endif #if defined(BOTAN_HAS_NYBERG_RUEPPEL) if(const NR_PrivateKey* s = dynamic_cast(&key)) return new NR_Signature_Operation(*s); #endif return 0; } PK_Ops::Verification* Core_Engine::get_verify_op(const Public_Key& key) const { #if defined(BOTAN_HAS_RSA) if(const RSA_PublicKey* s = dynamic_cast(&key)) return new RSA_Public_Operation(*s); #endif #if defined(BOTAN_HAS_RW) if(const RW_PublicKey* s = dynamic_cast(&key)) return new RW_Verification_Operation(*s); #endif #if defined(BOTAN_HAS_DSA) if(const DSA_PublicKey* s = dynamic_cast(&key)) return new DSA_Verification_Operation(*s); #endif #if defined(BOTAN_HAS_ECDSA) if(const ECDSA_PublicKey* s = dynamic_cast(&key)) return new ECDSA_Verification_Operation(*s); #endif #if defined(BOTAN_HAS_GOST_34_10_2001) if(const GOST_3410_PublicKey* s = dynamic_cast(&key)) return new GOST_3410_Verification_Operation(*s); #endif #if defined(BOTAN_HAS_NYBERG_RUEPPEL) if(const NR_PublicKey* s = dynamic_cast(&key)) return new NR_Verification_Operation(*s); #endif return 0; } } /* * Modular Exponentiation * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { /* * Choose a modular exponentation algorithm */ Modular_Exponentiator* Core_Engine::mod_exp(const BigInt& n, Power_Mod::Usage_Hints hints) const { if(n.is_odd()) return new Montgomery_Exponentiator(n, hints); return new Fixed_Window_Exponentiator(n, hints); } } /* * Block Cipher Lookup * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ #if defined(BOTAN_HAS_AES) #endif #if defined(BOTAN_HAS_BLOWFISH) #endif #if defined(BOTAN_HAS_CAMELLIA) #endif #if defined(BOTAN_HAS_CAST) #endif #if defined(BOTAN_HAS_CASCADE) #endif #if defined(BOTAN_HAS_DES) #endif #if defined(BOTAN_HAS_GOST_28147_89) #endif #if defined(BOTAN_HAS_IDEA) #endif #if defined(BOTAN_HAS_KASUMI) #endif #if defined(BOTAN_HAS_LION) #endif #if defined(BOTAN_HAS_LUBY_RACKOFF) #endif #if defined(BOTAN_HAS_MARS) #endif #if defined(BOTAN_HAS_MISTY1) #endif #if defined(BOTAN_HAS_NOEKEON) #endif #if defined(BOTAN_HAS_RC2) #endif #if defined(BOTAN_HAS_RC5) #endif #if defined(BOTAN_HAS_RC6) #endif #if defined(BOTAN_HAS_SAFER) #endif #if defined(BOTAN_HAS_SEED) #endif #if defined(BOTAN_HAS_SERPENT) #endif #if defined(BOTAN_HAS_SKIPJACK) #endif #if defined(BOTAN_HAS_SQUARE) #endif #if defined(BOTAN_HAS_TEA) #endif #if defined(BOTAN_HAS_TWOFISH) #endif #if defined(BOTAN_HAS_XTEA) #endif namespace Botan { /* * Look for an algorithm with this name */ BlockCipher* Core_Engine::find_block_cipher(const SCAN_Name& request, Algorithm_Factory& af) const { #if defined(BOTAN_HAS_AES) if(request.algo_name() == "AES-128") return new AES_128; if(request.algo_name() == "AES-192") return new AES_192; if(request.algo_name() == "AES-256") return new AES_256; #endif #if defined(BOTAN_HAS_BLOWFISH) if(request.algo_name() == "Blowfish") return new Blowfish; #endif #if defined(BOTAN_HAS_CAMELLIA) if(request.algo_name() == "Camellia-128") return new Camellia_128; if(request.algo_name() == "Camellia-192") return new Camellia_192; if(request.algo_name() == "Camellia-256") return new Camellia_256; #endif #if defined(BOTAN_HAS_CAST) if(request.algo_name() == "CAST-128") return new CAST_128; if(request.algo_name() == "CAST-256") return new CAST_256; #endif #if defined(BOTAN_HAS_DES) if(request.algo_name() == "DES") return new DES; if(request.algo_name() == "DESX") return new DESX; if(request.algo_name() == "TripleDES") return new TripleDES; #endif #if defined(BOTAN_HAS_GOST_28147_89) if(request.algo_name() == "GOST-28147-89") return new GOST_28147_89(request.arg(0, "R3411_94_TestParam")); #endif #if defined(BOTAN_HAS_IDEA) if(request.algo_name() == "IDEA") return new IDEA; #endif #if defined(BOTAN_HAS_KASUMI) if(request.algo_name() == "KASUMI") return new KASUMI; #endif #if defined(BOTAN_HAS_MARS) if(request.algo_name() == "MARS") return new MARS; #endif #if defined(BOTAN_HAS_MISTY1) if(request.algo_name() == "MISTY1") return new MISTY1(request.arg_as_integer(0, 8)); #endif #if defined(BOTAN_HAS_NOEKEON) if(request.algo_name() == "Noekeon") return new Noekeon; #endif #if defined(BOTAN_HAS_RC2) if(request.algo_name() == "RC2") return new RC2; #endif #if defined(BOTAN_HAS_RC5) if(request.algo_name() == "RC5") return new RC5(request.arg_as_integer(0, 12)); #endif #if defined(BOTAN_HAS_RC6) if(request.algo_name() == "RC6") return new RC6; #endif #if defined(BOTAN_HAS_SAFER) if(request.algo_name() == "SAFER-SK") return new SAFER_SK(request.arg_as_integer(0, 10)); #endif #if defined(BOTAN_HAS_SEED) if(request.algo_name() == "SEED") return new SEED; #endif #if defined(BOTAN_HAS_SERPENT) if(request.algo_name() == "Serpent") return new Serpent; #endif #if defined(BOTAN_HAS_SKIPJACK) if(request.algo_name() == "Skipjack") return new Skipjack; #endif #if defined(BOTAN_HAS_SQUARE) if(request.algo_name() == "Square") return new Square; #endif #if defined(BOTAN_HAS_TEA) if(request.algo_name() == "TEA") return new TEA; #endif #if defined(BOTAN_HAS_TWOFISH) if(request.algo_name() == "Twofish") return new Twofish; #endif #if defined(BOTAN_HAS_XTEA) if(request.algo_name() == "XTEA") return new XTEA; #endif #if defined(BOTAN_HAS_LUBY_RACKOFF) if(request.algo_name() == "Luby-Rackoff" && request.arg_count() == 1) { const HashFunction* hash = af.prototype_hash_function(request.arg(0)); if(hash) return new LubyRackoff(hash->clone()); } #endif #if defined(BOTAN_HAS_CASCADE) if(request.algo_name() == "Cascade" && request.arg_count() == 2) { const BlockCipher* c1 = af.prototype_block_cipher(request.arg(0)); const BlockCipher* c2 = af.prototype_block_cipher(request.arg(1)); if(c1 && c2) return new Cascade_Cipher(c1->clone(), c2->clone()); } #endif #if defined(BOTAN_HAS_LION) if(request.algo_name() == "Lion" && request.arg_count_between(2, 3)) { const size_t block_size = request.arg_as_integer(2, 1024); const HashFunction* hash = af.prototype_hash_function(request.arg(0)); const StreamCipher* stream_cipher = af.prototype_stream_cipher(request.arg(1)); if(!hash || !stream_cipher) return 0; return new Lion(hash->clone(), stream_cipher->clone(), block_size); } #endif return 0; } } /* * Hash Algorithms Lookup * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ #include #if defined(BOTAN_HAS_ADLER32) #endif #if defined(BOTAN_HAS_CRC24) #endif #if defined(BOTAN_HAS_CRC32) #endif #if defined(BOTAN_HAS_BMW_512) #endif #if defined(BOTAN_HAS_GOST_34_11) #endif #if defined(BOTAN_HAS_HAS_160) #endif #if defined(BOTAN_HAS_KECCAK) #endif #if defined(BOTAN_HAS_MD2) #endif #if defined(BOTAN_HAS_MD4) #endif #if defined(BOTAN_HAS_MD5) #endif #if defined(BOTAN_HAS_RIPEMD_128) #endif #if defined(BOTAN_HAS_RIPEMD_160) #endif #if defined(BOTAN_HAS_SHA1) #endif #if defined(BOTAN_HAS_SHA2_32) #endif #if defined(BOTAN_HAS_SHA2_64) #endif #if defined(BOTAN_HAS_SKEIN_512) #endif #if defined(BOTAN_HAS_TIGER) #endif #if defined(BOTAN_HAS_WHIRLPOOL) #endif #if defined(BOTAN_HAS_PARALLEL_HASH) #endif #if defined(BOTAN_HAS_COMB4P) #endif namespace Botan { /* * Look for an algorithm with this name */ HashFunction* Core_Engine::find_hash(const SCAN_Name& request, Algorithm_Factory& af) const { #if defined(BOTAN_HAS_ADLER32) if(request.algo_name() == "Adler32") return new Adler32; #endif #if defined(BOTAN_HAS_CRC24) if(request.algo_name() == "CRC24") return new CRC24; #endif #if defined(BOTAN_HAS_CRC32) if(request.algo_name() == "CRC32") 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_GOST_34_11) if(request.algo_name() == "GOST-34.11") return new GOST_34_11; #endif #if defined(BOTAN_HAS_HAS_160) if(request.algo_name() == "HAS-160") return new HAS_160; #endif #if defined(BOTAN_HAS_KECCAK) if(request.algo_name() == "Keccak-1600") return new Keccak_1600(request.arg_as_integer(0, 512)); #endif #if defined(BOTAN_HAS_MD2) if(request.algo_name() == "MD2") return new MD2; #endif #if defined(BOTAN_HAS_MD4) if(request.algo_name() == "MD4") return new MD4; #endif #if defined(BOTAN_HAS_MD5) if(request.algo_name() == "MD5") return new MD5; #endif #if defined(BOTAN_HAS_RIPEMD_128) if(request.algo_name() == "RIPEMD-128") return new RIPEMD_128; #endif #if defined(BOTAN_HAS_RIPEMD_160) if(request.algo_name() == "RIPEMD-160") return new RIPEMD_160; #endif #if defined(BOTAN_HAS_SHA1) if(request.algo_name() == "SHA-160") return new SHA_160; #endif #if defined(BOTAN_HAS_SHA2_32) if(request.algo_name() == "SHA-224") return new SHA_224; if(request.algo_name() == "SHA-256") return new SHA_256; #endif #if defined(BOTAN_HAS_SHA2_64) if(request.algo_name() == "SHA-384") return new SHA_384; if(request.algo_name() == "SHA-512") return new SHA_512; #endif #if defined(BOTAN_HAS_TIGER) if(request.algo_name() == "Tiger") return new Tiger(request.arg_as_integer(0, 24), // hash output request.arg_as_integer(1, 3)); // # passes #endif #if defined(BOTAN_HAS_SKEIN_512) if(request.algo_name() == "Skein-512") return new Skein_512(request.arg_as_integer(0, 512), request.arg(1, "")); #endif #if defined(BOTAN_HAS_WHIRLPOOL) if(request.algo_name() == "Whirlpool") return new Whirlpool; #endif #if defined(BOTAN_HAS_COMB4P) if(request.algo_name() == "Comb4P" && request.arg_count() == 2) { const HashFunction* h1 = af.prototype_hash_function(request.arg(0)); const HashFunction* h2 = af.prototype_hash_function(request.arg(1)); if(h1 && h2) return new Comb4P(h1->clone(), h2->clone()); } #endif #if defined(BOTAN_HAS_PARALLEL_HASH) if(request.algo_name() == "Parallel") { std::vector hash_prototypes; /* First pass, just get the prototypes (no memory allocation). Then if all were found, replace each prototype with a newly created clone */ for(size_t i = 0; i != request.arg_count(); ++i) { const HashFunction* hash = af.prototype_hash_function(request.arg(i)); if(!hash) return 0; hash_prototypes.push_back(hash); } std::vector hashes; for(size_t i = 0; i != hash_prototypes.size(); ++i) hashes.push_back(hash_prototypes[i]->clone()); return new Parallel(hashes); } #endif return 0; } } /* * MAC Lookup * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ #if defined(BOTAN_HAS_CBC_MAC) #endif #if defined(BOTAN_HAS_CMAC) #endif #if defined(BOTAN_HAS_HMAC) #endif #if defined(BOTAN_HAS_SSL3_MAC) #endif #if defined(BOTAN_HAS_ANSI_X919_MAC) #endif namespace Botan { /* * Look for an algorithm with this name */ MessageAuthenticationCode* Core_Engine::find_mac(const SCAN_Name& request, Algorithm_Factory& af) const { #if defined(BOTAN_HAS_CBC_MAC) if(request.algo_name() == "CBC-MAC" && request.arg_count() == 1) return new CBC_MAC(af.make_block_cipher(request.arg(0))); #endif #if defined(BOTAN_HAS_CMAC) if(request.algo_name() == "CMAC" && request.arg_count() == 1) return new CMAC(af.make_block_cipher(request.arg(0))); #endif #if defined(BOTAN_HAS_HMAC) if(request.algo_name() == "HMAC" && request.arg_count() == 1) return new HMAC(af.make_hash_function(request.arg(0))); #endif #if defined(BOTAN_HAS_SSL3_MAC) if(request.algo_name() == "SSL3-MAC" && request.arg_count() == 1) return new SSL3_MAC(af.make_hash_function(request.arg(0))); #endif #if defined(BOTAN_HAS_ANSI_X919_MAC) if(request.algo_name() == "X9.19-MAC" && request.arg_count() == 0) return new ANSI_X919_MAC(af.make_block_cipher("DES")); #endif return 0; } } /* * PBKDF Lookup * (C) 2010 Jack Lloyd * * Distributed under the terms of the Botan license */ #if defined(BOTAN_HAS_PBKDF1) #endif #if defined(BOTAN_HAS_PBKDF2) #endif #if defined(BOTAN_HAS_PGPS2K) #endif namespace Botan { PBKDF* Core_Engine::find_pbkdf(const SCAN_Name& algo_spec, Algorithm_Factory& af) const { #if defined(BOTAN_HAS_PBKDF1) if(algo_spec.algo_name() == "PBKDF1" && algo_spec.arg_count() == 1) return new PKCS5_PBKDF1(af.make_hash_function(algo_spec.arg(0))); #endif #if defined(BOTAN_HAS_PBKDF2) if(algo_spec.algo_name() == "PBKDF2" && algo_spec.arg_count() == 1) { if(const MessageAuthenticationCode* mac_proto = af.prototype_mac(algo_spec.arg(0))) return new PKCS5_PBKDF2(mac_proto->clone()); return new PKCS5_PBKDF2(af.make_mac("HMAC(" + algo_spec.arg(0) + ")")); } #endif #if defined(BOTAN_HAS_PGPS2K) if(algo_spec.algo_name() == "OpenPGP-S2K" && algo_spec.arg_count() == 1) return new OpenPGP_S2K(af.make_hash_function(algo_spec.arg(0))); #endif return 0; } } /* * Stream Cipher Lookup * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ #if defined(BOTAN_HAS_ARC4) #endif #if defined(BOTAN_HAS_SALSA20) #endif #if defined(BOTAN_HAS_TURING) #endif #if defined(BOTAN_HAS_WID_WAKE) #endif namespace Botan { /* * Look for an algorithm with this name */ StreamCipher* Core_Engine::find_stream_cipher(const SCAN_Name& request, Algorithm_Factory&) const { #if defined(BOTAN_HAS_ARC4) if(request.algo_name() == "ARC4") return new ARC4(request.arg_as_integer(0, 0)); if(request.algo_name() == "RC4_drop") return new ARC4(768); #endif #if defined(BOTAN_HAS_SALSA20) if(request.algo_name() == "Salsa20") return new Salsa20; #endif #if defined(BOTAN_HAS_TURING) if(request.algo_name() == "Turing") return new Turing; #endif #if defined(BOTAN_HAS_WID_WAKE) if(request.algo_name() == "WiderWake4+1-BE") return new WiderWake_41_BE; #endif return 0; } } /** * Dynamically Loaded Engine * (C) 2010 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { namespace { extern "C" { typedef Engine* (*creator_func)(void); typedef u32bit (*module_version_func)(void); } } Dynamically_Loaded_Engine::Dynamically_Loaded_Engine( const std::string& library_path) : engine(0) { lib = new Dynamically_Loaded_Library(library_path); try { module_version_func get_version = lib->resolve("module_version"); const u32bit mod_version = get_version(); if(mod_version != 20101003) throw std::runtime_error("Incompatible version in " + library_path + " of " + to_string(mod_version)); creator_func creator = lib->resolve("create_engine"); engine = creator(); if(!engine) throw std::runtime_error("Creator function in " + library_path + " failed"); } catch(...) { delete lib; lib = 0; throw; } } Dynamically_Loaded_Engine::~Dynamically_Loaded_Engine() { delete engine; delete lib; } } /* * Engine * (C) 2010 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { BlockCipher* Engine::find_block_cipher(const SCAN_Name&, Algorithm_Factory&) const { return 0; } StreamCipher* Engine::find_stream_cipher(const SCAN_Name&, Algorithm_Factory&) const { return 0; } HashFunction* Engine::find_hash(const SCAN_Name&, Algorithm_Factory&) const { return 0; } MessageAuthenticationCode* Engine::find_mac(const SCAN_Name&, Algorithm_Factory&) const { return 0; } PBKDF* Engine::find_pbkdf(const SCAN_Name&, Algorithm_Factory&) const { return 0; } Modular_Exponentiator* Engine::mod_exp(const BigInt&, Power_Mod::Usage_Hints) const { return 0; } Keyed_Filter* Engine::get_cipher(const std::string&, Cipher_Dir, Algorithm_Factory&) { return 0; } PK_Ops::Key_Agreement* Engine::get_key_agreement_op(const Private_Key&) const { return 0; } PK_Ops::Signature* Engine::get_signature_op(const Private_Key&) const { return 0; } PK_Ops::Verification* Engine::get_verify_op(const Public_Key&) const { return 0; } PK_Ops::Encryption* Engine::get_encryption_op(const Public_Key&) const { return 0; } PK_Ops::Decryption* Engine::get_decryption_op(const Private_Key&) const { return 0; } } /* * SIMD Engine * (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ #if defined(BOTAN_HAS_AES_SSSE3) #endif #if defined(BOTAN_HAS_SERPENT_SIMD) #endif #if defined(BOTAN_HAS_NOEKEON_SIMD) #endif #if defined(BOTAN_HAS_XTEA_SIMD) #endif #if defined(BOTAN_HAS_IDEA_SSE2) #endif #if defined(BOTAN_HAS_SHA1_SSE2) #endif namespace Botan { BlockCipher* SIMD_Engine::find_block_cipher(const SCAN_Name& request, Algorithm_Factory&) const { #if defined(BOTAN_HAS_AES_SSSE3) if(request.algo_name() == "AES-128" && CPUID::has_ssse3()) return new AES_128_SSSE3; if(request.algo_name() == "AES-192" && CPUID::has_ssse3()) return new AES_192_SSSE3; if(request.algo_name() == "AES-256" && CPUID::has_ssse3()) return new AES_256_SSSE3; #endif #if defined(BOTAN_HAS_IDEA_SSE2) if(request.algo_name() == "IDEA" && CPUID::has_sse2()) return new IDEA_SSE2; #endif #if defined(BOTAN_HAS_NOEKEON_SIMD) if(request.algo_name() == "Noekeon" && SIMD_32::enabled()) return new Noekeon_SIMD; #endif #if defined(BOTAN_HAS_SERPENT_SIMD) if(request.algo_name() == "Serpent" && SIMD_32::enabled()) return new Serpent_SIMD; #endif #if defined(BOTAN_HAS_XTEA_SIMD) if(request.algo_name() == "XTEA" && SIMD_32::enabled()) return new XTEA_SIMD; #endif return 0; } HashFunction* SIMD_Engine::find_hash(const SCAN_Name& request, Algorithm_Factory&) const { #if defined(BOTAN_HAS_SHA1_SSE2) if(request.algo_name() == "SHA-160" && CPUID::has_sse2()) return new SHA_160_SSE2; #else Q_UNUSED(request); #endif return 0; } } #ifdef Q_OS_WIN /* * Win32 CryptoAPI EntropySource * (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ #include #include namespace Botan { namespace { class CSP_Handle { public: CSP_Handle(u64bit capi_provider) { valid = false; DWORD prov_type = (DWORD)capi_provider; if(CryptAcquireContext(&handle, 0, 0, prov_type, CRYPT_VERIFYCONTEXT)) valid = true; } ~CSP_Handle() { if(is_valid()) CryptReleaseContext(handle, 0); } size_t gen_random(byte out[], size_t n) const { if(is_valid() && CryptGenRandom(handle, static_cast(n), out)) return n; return 0; } bool is_valid() const { return valid; } HCRYPTPROV get_handle() const { return handle; } private: HCRYPTPROV handle; bool valid; }; } /* * Gather Entropy from Win32 CAPI */ void Win32_CAPI_EntropySource::poll(Entropy_Accumulator& accum) { MemoryRegion& io_buffer = accum.get_io_buffer(32); for(size_t i = 0; i != prov_types.size(); ++i) { CSP_Handle csp(prov_types[i]); size_t got = csp.gen_random(&io_buffer[0], io_buffer.size()); if(got) { accum.add(&io_buffer[0], io_buffer.size(), 6); break; } } } /* * Win32_Capi_Entropysource Constructor */ Win32_CAPI_EntropySource::Win32_CAPI_EntropySource(const std::string& provs) { std::vector capi_provs = split_on(provs, ':'); for(size_t i = 0; i != capi_provs.size(); ++i) { if(capi_provs[i] == "RSA_FULL") prov_types.push_back(PROV_RSA_FULL); if(capi_provs[i] == "INTEL_SEC") prov_types.push_back(PROV_INTEL_SEC); if(capi_provs[i] == "FORTEZZA") prov_types.push_back(PROV_FORTEZZA); if(capi_provs[i] == "RNG") prov_types.push_back(PROV_RNG); } if(prov_types.size() == 0) prov_types.push_back(PROV_RSA_FULL); } } #endif #ifdef Q_OS_UNIX /* * /dev/random EntropySource * (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ #include #include #include #include #include #include namespace Botan { /** Close the device, if open */ void Device_EntropySource::Device_Reader::close() { if(fd > 0) { ::close(fd); fd = -1; } } /** Read bytes from a device file */ size_t Device_EntropySource::Device_Reader::get(byte out[], size_t length, size_t ms_wait_time) { if(fd < 0) return 0; if(fd >= FD_SETSIZE) return 0; fd_set read_set; FD_ZERO(&read_set); FD_SET(fd, &read_set); struct ::timeval timeout; timeout.tv_sec = (ms_wait_time / 1000); timeout.tv_usec = (ms_wait_time % 1000) * 1000; if(::select(fd + 1, &read_set, 0, 0, &timeout) < 0) return 0; if(!(FD_ISSET(fd, &read_set))) return 0; const ssize_t got = ::read(fd, out, length); if(got <= 0) return 0; return static_cast(got); } /** Attempt to open a device */ Device_EntropySource::Device_Reader::fd_type Device_EntropySource::Device_Reader::open(const std::string& pathname) { #ifndef O_NONBLOCK #define O_NONBLOCK 0 #endif #ifndef O_NOCTTY #define O_NOCTTY 0 #endif const int flags = O_RDONLY | O_NONBLOCK | O_NOCTTY; return ::open(pathname.c_str(), flags); } /** Device_EntropySource constructor Open a file descriptor to each (available) device in fsnames */ Device_EntropySource::Device_EntropySource( const std::vector& fsnames) { for(size_t i = 0; i != fsnames.size(); ++i) { Device_Reader::fd_type fd = Device_Reader::open(fsnames[i]); if(fd > 0) devices.push_back(Device_Reader(fd)); } } /** Device_EntropySource destructor: close all open devices */ Device_EntropySource::~Device_EntropySource() { for(size_t i = 0; i != devices.size(); ++i) devices[i].close(); } /** * Gather entropy from a RNG device */ void Device_EntropySource::poll(Entropy_Accumulator& accum) { const size_t ENTROPY_BITS_PER_BYTE = 7; const size_t go_get = std::min( accum.desired_remaining_bits() / ENTROPY_BITS_PER_BYTE, 32); const size_t read_wait_ms = std::max(go_get, 100); MemoryRegion& io_buffer = accum.get_io_buffer(go_get); for(size_t i = 0; i != devices.size(); ++i) { size_t got = devices[i].get(&io_buffer[0], io_buffer.size(), read_wait_ms); if(got) { accum.add(&io_buffer[0], got, ENTROPY_BITS_PER_BYTE); break; } } } } /* * EGD EntropySource * (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ #include #include #include #include #include #include #include #include #ifndef PF_LOCAL #define PF_LOCAL PF_UNIX #endif namespace Botan { EGD_EntropySource::EGD_Socket::EGD_Socket(const std::string& path) : socket_path(path), m_fd(-1) { } /** * Attempt a connection to an EGD/PRNGD socket */ int EGD_EntropySource::EGD_Socket::open_socket(const std::string& path) { int fd = ::socket(PF_LOCAL, SOCK_STREAM, 0); if(fd >= 0) { sockaddr_un addr; std::memset(&addr, 0, sizeof(addr)); addr.sun_family = PF_LOCAL; if(sizeof(addr.sun_path) < path.length() + 1) throw std::invalid_argument("EGD socket path is too long"); std::strncpy(addr.sun_path, path.c_str(), sizeof(addr.sun_path)); int len = sizeof(addr.sun_family) + std::strlen(addr.sun_path) + 1; if(::connect(fd, reinterpret_cast(&addr), len) < 0) { ::close(fd); fd = -1; } } return fd; } /** * Attempt to read entropy from EGD */ size_t EGD_EntropySource::EGD_Socket::read(byte outbuf[], size_t length) { if(length == 0) return 0; if(m_fd < 0) { m_fd = open_socket(socket_path); if(m_fd < 0) return 0; } try { // 1 == EGD command for non-blocking read byte egd_read_command[2] = { 1, static_cast(std::min(length, 255)) }; if(::write(m_fd, egd_read_command, 2) != 2) throw std::runtime_error("Writing entropy read command to EGD failed"); byte out_len = 0; if(::read(m_fd, &out_len, 1) != 1) throw std::runtime_error("Reading response length from EGD failed"); if(out_len > egd_read_command[1]) throw std::runtime_error("Bogus length field received from EGD"); ssize_t count = ::read(m_fd, outbuf, out_len); if(count != out_len) throw std::runtime_error("Reading entropy result from EGD failed"); return static_cast(count); } catch(std::exception) { this->close(); // Will attempt to reopen next poll } return 0; } void EGD_EntropySource::EGD_Socket::close() { if(m_fd > 0) { ::close(m_fd); m_fd = -1; } } /** * EGD_EntropySource constructor */ EGD_EntropySource::EGD_EntropySource(const std::vector& paths) { for(size_t i = 0; i != paths.size(); ++i) sockets.push_back(EGD_Socket(paths[i])); } EGD_EntropySource::~EGD_EntropySource() { for(size_t i = 0; i != sockets.size(); ++i) sockets[i].close(); sockets.clear(); } /** * Gather Entropy from EGD */ void EGD_EntropySource::poll(Entropy_Accumulator& accum) { size_t go_get = std::min(accum.desired_remaining_bits() / 8, 32); MemoryRegion& io_buffer = accum.get_io_buffer(go_get); for(size_t i = 0; i != sockets.size(); ++i) { size_t got = sockets[i].read(&io_buffer[0], io_buffer.size()); if(got) { accum.add(&io_buffer[0], got, 6); break; } } } } #endif /* * High Resolution Timestamp Entropy Source * (C) 1999-2009,2011 Jack Lloyd * * Distributed under the terms of the Botan license */ #if defined(BOTAN_TARGET_OS_IS_WINDOWS) #include #endif namespace Botan { /* * Get the timestamp */ void High_Resolution_Timestamp::poll(Entropy_Accumulator& accum) { // If Windows, grab the Performance Counter (usually TSC or PIT) #if defined(BOTAN_TARGET_OS_IS_WINDOWS) { LARGE_INTEGER tv; ::QueryPerformanceCounter(&tv); accum.add(tv.QuadPart, 0); } #endif #if defined(BOTAN_TARGET_OS_HAS_CLOCK_GETTIME) #define CLOCK_POLL(src) \ do { \ struct timespec ts; \ clock_gettime(src, &ts); \ accum.add(&ts, sizeof(ts), 0); \ } while(0) #if defined(CLOCK_REALTIME) CLOCK_POLL(CLOCK_REALTIME); #endif #if defined(CLOCK_MONOTONIC) CLOCK_POLL(CLOCK_MONOTONIC); #endif #if defined(CLOCK_MONOTONIC_RAW) CLOCK_POLL(CLOCK_MONOTONIC_RAW); #endif #if defined(CLOCK_PROCESS_CPUTIME_ID) CLOCK_POLL(CLOCK_PROCESS_CPUTIME_ID); #endif #if defined(CLOCK_THREAD_CPUTIME_ID) CLOCK_POLL(CLOCK_THREAD_CPUTIME_ID); #endif #undef CLOCK_POLL #endif #if BOTAN_USE_GCC_INLINE_ASM u64bit rtc = 0; #if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY) if(CPUID::has_rdtsc()) // not availble on all x86 CPUs { u32bit rtc_low = 0, rtc_high = 0; asm volatile("rdtsc" : "=d" (rtc_high), "=a" (rtc_low)); rtc = (static_cast(rtc_high) << 32) | rtc_low; } #elif defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY) u32bit rtc_low = 0, rtc_high = 0; asm volatile("mftbu %0; mftb %1" : "=r" (rtc_high), "=r" (rtc_low)); rtc = (static_cast(rtc_high) << 32) | rtc_low; #elif defined(BOTAN_TARGET_ARCH_IS_ALPHA) asm volatile("rpcc %0" : "=r" (rtc)); #elif defined(BOTAN_TARGET_ARCH_IS_SPARC64) && !defined(BOTAN_TARGET_OS_IS_OPENBSD) asm volatile("rd %%tick, %0" : "=r" (rtc)); #elif defined(BOTAN_TARGET_ARCH_IS_IA64) asm volatile("mov %0=ar.itc" : "=r" (rtc)); #elif defined(BOTAN_TARGET_ARCH_IS_S390X) asm volatile("stck 0(%0)" : : "a" (&rtc) : "memory", "cc"); #elif defined(BOTAN_TARGET_ARCH_IS_HPPA) asm volatile("mfctl 16,%0" : "=r" (rtc)); // 64-bit only? #endif // Don't count the timestamp as contributing entropy accum.add(rtc, 0); #endif } } #ifdef Q_OS_UNIX /* * FTW EntropySource * (C) 1999-2008,2012 Jack Lloyd * * Distributed under the terms of the Botan license */ #include #include #ifndef _POSIX_C_SOURCE #define _POSIX_C_SOURCE 199309 #endif #include #include #include #include #include namespace Botan { /** * Returns file descriptors. Until it doesn't */ class File_Descriptor_Source { public: /** * @return next file descriptor, or -1 if done */ virtual int next_fd() = 0; virtual ~File_Descriptor_Source() {} }; namespace { class Directory_Walker : public File_Descriptor_Source { public: Directory_Walker(const std::string& root) : m_cur_dir(std::make_pair(0, "")) { if(DIR* root_dir = ::opendir(root.c_str())) m_cur_dir = std::make_pair(root_dir, root); } ~Directory_Walker() { if(m_cur_dir.first) ::closedir(m_cur_dir.first); } int next_fd(); private: void add_directory(const std::string& dirname) { m_dirlist.push_back(dirname); } std::pair get_next_dirent(); std::pair m_cur_dir; std::deque m_dirlist; }; std::pair Directory_Walker::get_next_dirent() { while(m_cur_dir.first) { struct dirent* dir = ::readdir(m_cur_dir.first); if(dir) return std::make_pair(dir, m_cur_dir.second); ::closedir(m_cur_dir.first); m_cur_dir = std::make_pair(0, ""); while(!m_dirlist.empty() && m_cur_dir.first == 0) { const std::string next_dir_name = m_dirlist[0]; m_dirlist.pop_front(); if(DIR* next_dir = ::opendir(next_dir_name.c_str())) m_cur_dir = std::make_pair(next_dir, next_dir_name); } } return std::make_pair(0, ""); // nothing left } int Directory_Walker::next_fd() { while(true) { std::pair entry = get_next_dirent(); if(!entry.first) break; // no more dirs const std::string filename = entry.first->d_name; if(filename == "." || filename == "..") continue; const std::string full_path = entry.second + '/' + filename; struct stat stat_buf; if(::lstat(full_path.c_str(), &stat_buf) == -1) continue; if(S_ISDIR(stat_buf.st_mode)) { add_directory(full_path); } else if(S_ISREG(stat_buf.st_mode) && (stat_buf.st_mode & S_IROTH)) { int fd = ::open(full_path.c_str(), O_RDONLY | O_NOCTTY); if(fd > 0) return fd; } } return -1; } } /** * FTW_EntropySource Constructor */ FTW_EntropySource::FTW_EntropySource(const std::string& p) : path(p) { dir = 0; } /** * FTW_EntropySource Destructor */ FTW_EntropySource::~FTW_EntropySource() { delete dir; } void FTW_EntropySource::poll(Entropy_Accumulator& accum) { const size_t MAX_FILES_READ_PER_POLL = 2048; if(!dir) dir = new Directory_Walker(path); MemoryRegion& io_buffer = accum.get_io_buffer(4096); for(size_t i = 0; i != MAX_FILES_READ_PER_POLL; ++i) { int fd = dir->next_fd(); // If we've exhaused this walk of the directory, halt the poll if(fd == -1) { delete dir; dir = 0; break; } ssize_t got = ::read(fd, &io_buffer[0], io_buffer.size()); ::close(fd); if(got > 0) accum.add(&io_buffer[0], got, .001); if(accum.polling_goal_achieved()) break; } } } /* * Unix EntropySource * (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ #include #include #include #include #include namespace Botan { namespace { /** * Sort ordering by priority */ bool Unix_Program_Cmp(const Unix_Program& a, const Unix_Program& b) { if(a.priority == b.priority) return (a.name_and_args < b.name_and_args); return (a.priority < b.priority); } } /** * Unix_EntropySource Constructor */ Unix_EntropySource::Unix_EntropySource(const std::vector& path) : PATH(path) { std::vector default_sources = get_default_sources(); add_sources(&default_sources[0], default_sources.size()); } /** * Add sources to the list */ void Unix_EntropySource::add_sources(const Unix_Program srcs[], size_t count) { sources.insert(sources.end(), srcs, srcs + count); std::sort(sources.begin(), sources.end(), Unix_Program_Cmp); } /** * Poll for entropy on a generic Unix system, first by grabbing various * statistics (stat on common files, getrusage, etc), and then, if more * is required, by exec'ing various programs like uname and rpcinfo and * reading the output. */ void Unix_EntropySource::poll(Entropy_Accumulator& accum) { const char* stat_targets[] = { "/", "/tmp", "/var/tmp", "/usr", "/home", "/etc/passwd", ".", "..", 0 }; for(size_t i = 0; stat_targets[i]; i++) { struct stat statbuf; clear_mem(&statbuf, 1); ::stat(stat_targets[i], &statbuf); accum.add(&statbuf, sizeof(statbuf), .005); } accum.add(::getpid(), 0); accum.add(::getppid(), 0); accum.add(::getuid(), 0); accum.add(::getgid(), 0); accum.add(::getpgrp(), 0); struct ::rusage usage; ::getrusage(RUSAGE_SELF, &usage); accum.add(usage, .005); ::getrusage(RUSAGE_CHILDREN, &usage); accum.add(usage, .005); const size_t MINIMAL_WORKING = 16; MemoryRegion& io_buffer = accum.get_io_buffer(DEFAULT_BUFFERSIZE); for(size_t i = 0; i != sources.size(); i++) { DataSource_Command pipe(sources[i].name_and_args, PATH); size_t got_from_src = 0; while(!pipe.end_of_data()) { size_t got_this_loop = pipe.read(&io_buffer[0], io_buffer.size()); got_from_src += got_this_loop; accum.add(&io_buffer[0], got_this_loop, .005); } sources[i].working = (got_from_src >= MINIMAL_WORKING) ? true : false; if(accum.polling_goal_achieved()) break; } } } /* * Unix Command Execution * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ #include #include #include #include #include #include #include namespace Botan { namespace { /** * Attempt to execute the command */ void do_exec(const std::vector& arg_list, const std::vector& paths) { const size_t args = arg_list.size() - 1; const char* arg1 = (args >= 1) ? arg_list[1].c_str() : 0; const char* arg2 = (args >= 2) ? arg_list[2].c_str() : 0; const char* arg3 = (args >= 3) ? arg_list[3].c_str() : 0; const char* arg4 = (args >= 4) ? arg_list[4].c_str() : 0; for(size_t j = 0; j != paths.size(); j++) { const std::string full_path = paths[j] + "/" + arg_list[0]; const char* fsname = full_path.c_str(); ::execl(fsname, fsname, arg1, arg2, arg3, arg4, NULL); } } } /** * Local information about the pipe */ struct pipe_wrapper { int fd; pid_t pid; pipe_wrapper(int f, pid_t p) : fd(f), pid(p) {} ~pipe_wrapper() { ::close(fd); } }; /** * Read from the pipe */ size_t DataSource_Command::read(byte buf[], size_t length) { if(end_of_data()) return 0; fd_set set; FD_ZERO(&set); FD_SET(pipe->fd, &set); struct ::timeval tv; tv.tv_sec = 0; tv.tv_usec = MAX_BLOCK_USECS; ssize_t got = 0; if(::select(pipe->fd + 1, &set, 0, 0, &tv) == 1) { if(FD_ISSET(pipe->fd, &set)) got = ::read(pipe->fd, buf, length); } if(got <= 0) { shutdown_pipe(); return 0; } return static_cast(got); } /** * Peek at the pipe contents */ size_t DataSource_Command::peek(byte[], size_t, size_t) const { if(end_of_data()) throw Invalid_State("DataSource_Command: Cannot peek when out of data"); throw Stream_IO_Error("Cannot peek/seek on a command pipe"); } /** * Check if we reached EOF */ bool DataSource_Command::end_of_data() const { return (pipe) ? false : true; } /** * Return the Unix file descriptor of the pipe */ int DataSource_Command::fd() const { if(!pipe) return -1; return pipe->fd; } /** * Return a human-readable ID for this stream */ std::string DataSource_Command::id() const { return "Unix command: " + arg_list[0]; } /** * Create the pipe */ void DataSource_Command::create_pipe(const std::vector& paths) { bool found_something = false; for(size_t j = 0; j != paths.size(); j++) { const std::string full_path = paths[j] + "/" + arg_list[0]; if(::access(full_path.c_str(), X_OK) == 0) { found_something = true; break; } } if(!found_something) return; int pipe_fd[2]; if(::pipe(pipe_fd) != 0) return; pid_t pid = ::fork(); if(pid == -1) { ::close(pipe_fd[0]); ::close(pipe_fd[1]); } else if(pid > 0) { pipe = new pipe_wrapper(pipe_fd[0], pid); ::close(pipe_fd[1]); } else { if(dup2(pipe_fd[1], STDOUT_FILENO) == -1) ::exit(127); if(close(pipe_fd[0]) != 0 || close(pipe_fd[1]) != 0) ::exit(127); if(close(STDERR_FILENO) != 0) ::exit(127); do_exec(arg_list, paths); ::exit(127); } } /** * Shutdown the pipe */ void DataSource_Command::shutdown_pipe() { if(pipe) { pid_t reaped = waitpid(pipe->pid, 0, WNOHANG); if(reaped == 0) { kill(pipe->pid, SIGTERM); struct ::timeval tv; tv.tv_sec = 0; tv.tv_usec = KILL_WAIT; select(0, 0, 0, 0, &tv); reaped = ::waitpid(pipe->pid, 0, WNOHANG); if(reaped == 0) { ::kill(pipe->pid, SIGKILL); do reaped = ::waitpid(pipe->pid, 0, 0); while(reaped == -1); } } delete pipe; pipe = 0; } } /** * DataSource_Command Constructor */ DataSource_Command::DataSource_Command(const std::string& prog_and_args, const std::vector& paths) : MAX_BLOCK_USECS(100000), KILL_WAIT(10000) { arg_list = split_on(prog_and_args, ' '); if(arg_list.size() == 0) throw Invalid_Argument("DataSource_Command: No command given"); if(arg_list.size() > 5) throw Invalid_Argument("DataSource_Command: Too many args"); pipe = 0; create_pipe(paths); } /** * DataSource_Command Destructor */ DataSource_Command::~DataSource_Command() { if(!end_of_data()) shutdown_pipe(); } } /* * Program List for Unix_EntropySource * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { /** * Default Commands for Entropy Gathering */ std::vector Unix_EntropySource::get_default_sources() { std::vector srcs; srcs.push_back(Unix_Program("netstat -in", 1)); srcs.push_back(Unix_Program("pfstat", 1)); srcs.push_back(Unix_Program("vmstat -s", 1)); srcs.push_back(Unix_Program("vmstat", 1)); srcs.push_back(Unix_Program("arp -a -n", 2)); srcs.push_back(Unix_Program("ifconfig -a", 2)); srcs.push_back(Unix_Program("iostat", 2)); srcs.push_back(Unix_Program("ipcs -a", 2)); srcs.push_back(Unix_Program("mpstat", 2)); srcs.push_back(Unix_Program("netstat -an", 2)); srcs.push_back(Unix_Program("netstat -s", 2)); srcs.push_back(Unix_Program("nfsstat", 2)); srcs.push_back(Unix_Program("portstat", 2)); srcs.push_back(Unix_Program("procinfo -a", 2)); srcs.push_back(Unix_Program("pstat -T", 2)); srcs.push_back(Unix_Program("pstat -s", 2)); srcs.push_back(Unix_Program("uname -a", 2)); srcs.push_back(Unix_Program("uptime", 2)); srcs.push_back(Unix_Program("listarea", 3)); srcs.push_back(Unix_Program("listdev", 3)); srcs.push_back(Unix_Program("ps -A", 3)); srcs.push_back(Unix_Program("sysinfo", 3)); srcs.push_back(Unix_Program("finger", 4)); srcs.push_back(Unix_Program("mailstats", 4)); srcs.push_back(Unix_Program("rpcinfo -p localhost", 4)); srcs.push_back(Unix_Program("who", 4)); srcs.push_back(Unix_Program("df -l", 4)); srcs.push_back(Unix_Program("dmesg", 4)); srcs.push_back(Unix_Program("last -5", 4)); srcs.push_back(Unix_Program("ls -alni /proc", 4)); srcs.push_back(Unix_Program("ls -alni /tmp", 4)); srcs.push_back(Unix_Program("pstat -f", 4)); srcs.push_back(Unix_Program("ps -elf", 5)); srcs.push_back(Unix_Program("ps aux", 5)); srcs.push_back(Unix_Program("lsof -n", 6)); srcs.push_back(Unix_Program("sar -A", 6)); return srcs; } } #endif #ifdef Q_OS_WIN /* * Win32 EntropySource * (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ #include #include namespace Botan { /** * Win32 poll using stats functions including Tooltip32 */ void Win32_EntropySource::poll(Entropy_Accumulator& accum) { /* First query a bunch of basic statistical stuff, though don't count it for much in terms of contributed entropy. */ accum.add(GetTickCount(), 0); accum.add(GetMessagePos(), 0); accum.add(GetMessageTime(), 0); accum.add(GetInputState(), 0); accum.add(GetCurrentProcessId(), 0); accum.add(GetCurrentThreadId(), 0); SYSTEM_INFO sys_info; GetSystemInfo(&sys_info); accum.add(sys_info, 1); MEMORYSTATUS mem_info; GlobalMemoryStatus(&mem_info); accum.add(mem_info, 1); POINT point; GetCursorPos(&point); accum.add(point, 1); GetCaretPos(&point); accum.add(point, 1); LARGE_INTEGER perf_counter; QueryPerformanceCounter(&perf_counter); accum.add(perf_counter, 0); /* Now use the Tooltip library to iterate throug various objects on the system, including processes, threads, and heap objects. */ HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0); #define TOOLHELP32_ITER(DATA_TYPE, FUNC_FIRST, FUNC_NEXT) \ if(!accum.polling_goal_achieved()) \ { \ DATA_TYPE info; \ info.dwSize = sizeof(DATA_TYPE); \ if(FUNC_FIRST(snapshot, &info)) \ { \ do \ { \ accum.add(info, 1); \ } while(FUNC_NEXT(snapshot, &info)); \ } \ } TOOLHELP32_ITER(MODULEENTRY32, Module32First, Module32Next); TOOLHELP32_ITER(PROCESSENTRY32, Process32First, Process32Next); TOOLHELP32_ITER(THREADENTRY32, Thread32First, Thread32Next); #undef TOOLHELP32_ITER if(!accum.polling_goal_achieved()) { size_t heap_lists_found = 0; HEAPLIST32 heap_list; heap_list.dwSize = sizeof(HEAPLIST32); const size_t HEAP_LISTS_MAX = 32; const size_t HEAP_OBJS_PER_LIST = 128; if(Heap32ListFirst(snapshot, &heap_list)) { do { accum.add(heap_list, 1); if(++heap_lists_found > HEAP_LISTS_MAX) break; size_t heap_objs_found = 0; HEAPENTRY32 heap_entry; heap_entry.dwSize = sizeof(HEAPENTRY32); if(Heap32First(&heap_entry, heap_list.th32ProcessID, heap_list.th32HeapID)) { do { if(heap_objs_found++ > HEAP_OBJS_PER_LIST) break; accum.add(heap_entry, 1); } while(Heap32Next(&heap_entry)); } if(accum.polling_goal_achieved()) break; } while(Heap32ListNext(snapshot, &heap_list)); } } CloseHandle(snapshot); } } #endif /* * Filters * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ #include namespace Botan { /* * StreamCipher_Filter Constructor */ StreamCipher_Filter::StreamCipher_Filter(StreamCipher* stream_cipher) : buffer(DEFAULT_BUFFERSIZE) { cipher = stream_cipher; } /* * StreamCipher_Filter Constructor */ StreamCipher_Filter::StreamCipher_Filter(StreamCipher* stream_cipher, const SymmetricKey& key) : buffer(DEFAULT_BUFFERSIZE) { cipher = stream_cipher; cipher->set_key(key); } /* * StreamCipher_Filter Constructor */ StreamCipher_Filter::StreamCipher_Filter(const std::string& sc_name) : buffer(DEFAULT_BUFFERSIZE) { Algorithm_Factory& af = global_state().algorithm_factory(); cipher = af.make_stream_cipher(sc_name); } /* * StreamCipher_Filter Constructor */ StreamCipher_Filter::StreamCipher_Filter(const std::string& sc_name, const SymmetricKey& key) : buffer(DEFAULT_BUFFERSIZE) { Algorithm_Factory& af = global_state().algorithm_factory(); cipher = af.make_stream_cipher(sc_name); cipher->set_key(key); } /* * Set the IV of a stream cipher */ void StreamCipher_Filter::set_iv(const InitializationVector& iv) { cipher->set_iv(iv.begin(), iv.length()); } /* * Write data into a StreamCipher_Filter */ void StreamCipher_Filter::write(const byte input[], size_t length) { while(length) { size_t copied = std::min(length, buffer.size()); cipher->cipher(input, &buffer[0], copied); send(buffer, copied); input += copied; length -= copied; } } /* * Hash_Filter Constructor */ Hash_Filter::Hash_Filter(const std::string& algo_spec, size_t len) : OUTPUT_LENGTH(len) { Algorithm_Factory& af = global_state().algorithm_factory(); hash = af.make_hash_function(algo_spec); } /* * Complete a calculation by a Hash_Filter */ void Hash_Filter::end_msg() { SecureVector output = hash->final(); if(OUTPUT_LENGTH) send(output, std::min(OUTPUT_LENGTH, output.size())); else send(output); } /* * MAC_Filter Constructor */ MAC_Filter::MAC_Filter(const std::string& mac_name, size_t len) : OUTPUT_LENGTH(len) { Algorithm_Factory& af = global_state().algorithm_factory(); mac = af.make_mac(mac_name); } /* * MAC_Filter Constructor */ MAC_Filter::MAC_Filter(const std::string& mac_name, const SymmetricKey& key, size_t len) : OUTPUT_LENGTH(len) { Algorithm_Factory& af = global_state().algorithm_factory(); mac = af.make_mac(mac_name); mac->set_key(key); } /* * Complete a calculation by a MAC_Filter */ void MAC_Filter::end_msg() { SecureVector output = mac->final(); if(OUTPUT_LENGTH) send(output, std::min(OUTPUT_LENGTH, output.size())); else send(output); } } /* * Basic Filters * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { void Keyed_Filter::set_iv(const InitializationVector& iv) { if(iv.length() != 0) throw Invalid_IV_Length(name(), iv.length()); } /* * Chain Constructor */ Chain::Chain(Filter* f1, Filter* f2, Filter* f3, Filter* f4) { if(f1) { attach(f1); incr_owns(); } if(f2) { attach(f2); incr_owns(); } if(f3) { attach(f3); incr_owns(); } if(f4) { attach(f4); incr_owns(); } } /* * Chain Constructor */ Chain::Chain(Filter* filters[], size_t count) { for(size_t j = 0; j != count; ++j) if(filters[j]) { attach(filters[j]); incr_owns(); } } std::string Chain::name() const { return "Chain"; } /* * Fork Constructor */ Fork::Fork(Filter* f1, Filter* f2, Filter* f3, Filter* f4) { Filter* filters[4] = { f1, f2, f3, f4 }; set_next(filters, 4); } /* * Fork Constructor */ Fork::Fork(Filter* filters[], size_t count) { set_next(filters, count); } std::string Fork::name() const { return "Fork"; } } /* * Buffered Filter * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ #include namespace Botan { /* * Buffered_Filter Constructor */ Buffered_Filter::Buffered_Filter(size_t b, size_t f) : main_block_mod(b), final_minimum(f) { if(main_block_mod == 0) throw std::invalid_argument("main_block_mod == 0"); if(final_minimum > main_block_mod) throw std::invalid_argument("final_minimum > main_block_mod"); buffer.resize(2 * main_block_mod); buffer_pos = 0; } /* * Buffer input into blocks, trying to minimize copying */ void Buffered_Filter::write(const byte input[], size_t input_size) { if(!input_size) return; if(buffer_pos + input_size >= main_block_mod + final_minimum) { size_t to_copy = std::min(buffer.size() - buffer_pos, input_size); copy_mem(&buffer[buffer_pos], input, to_copy); buffer_pos += to_copy; input += to_copy; input_size -= to_copy; size_t total_to_consume = round_down(std::min(buffer_pos, buffer_pos + input_size - final_minimum), main_block_mod); buffered_block(&buffer[0], total_to_consume); buffer_pos -= total_to_consume; copy_mem(&buffer[0], &buffer[total_to_consume], buffer_pos); } if(input_size >= final_minimum) { size_t full_blocks = (input_size - final_minimum) / main_block_mod; size_t to_copy = full_blocks * main_block_mod; if(to_copy) { buffered_block(input, to_copy); input += to_copy; input_size -= to_copy; } } copy_mem(&buffer[buffer_pos], input, input_size); buffer_pos += input_size; } /* * Finish/flush operation */ void Buffered_Filter::end_msg() { if(buffer_pos < final_minimum) throw std::runtime_error("Buffered filter end_msg without enough input"); size_t spare_blocks = (buffer_pos - final_minimum) / main_block_mod; if(spare_blocks) { size_t spare_bytes = main_block_mod * spare_blocks; buffered_block(&buffer[0], spare_bytes); buffered_final(&buffer[spare_bytes], buffer_pos - spare_bytes); } else { buffered_final(&buffer[0], buffer_pos); } buffer_pos = 0; } } /* * Base64 Encoder/Decoder * (C) 1999-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ #include namespace Botan { /* * Base64_Encoder Constructor */ Base64_Encoder::Base64_Encoder(bool breaks, size_t length, bool t_n) : line_length(breaks ? length : 0), trailing_newline(t_n && breaks), in(48), out(64), position(0), out_position(0) { } /* * Encode and send a block */ void Base64_Encoder::encode_and_send(const byte input[], size_t length, bool final_inputs) { while(length) { const size_t proc = std::min(length, in.size()); size_t consumed = 0; size_t produced = base64_encode(reinterpret_cast(&out[0]), input, proc, consumed, final_inputs); do_output(&out[0], produced); // FIXME: s/proc/consumed/? input += proc; length -= proc; } } /* * Handle the output */ void Base64_Encoder::do_output(const byte input[], size_t length) { if(line_length == 0) send(input, length); else { size_t remaining = length, offset = 0; while(remaining) { size_t sent = std::min(line_length - out_position, remaining); send(input + offset, sent); out_position += sent; remaining -= sent; offset += sent; if(out_position == line_length) { send('\n'); out_position = 0; } } } } /* * Convert some data into Base64 */ void Base64_Encoder::write(const byte input[], size_t length) { in.copy(position, input, length); if(position + length >= in.size()) { encode_and_send(&in[0], in.size()); input += (in.size() - position); length -= (in.size() - position); while(length >= in.size()) { encode_and_send(input, in.size()); input += in.size(); length -= in.size(); } in.copy(input, length); position = 0; } position += length; } /* * Flush buffers */ void Base64_Encoder::end_msg() { encode_and_send(&in[0], position, true); if(trailing_newline || (out_position && line_length)) send('\n'); out_position = position = 0; } /* * Base64_Decoder Constructor */ Base64_Decoder::Base64_Decoder(Decoder_Checking c) : checking(c), in(64), out(48), position(0) { } /* * Convert some data from Base64 */ void Base64_Decoder::write(const byte input[], size_t length) { while(length) { size_t to_copy = std::min(length, in.size() - position); copy_mem(&in[position], input, to_copy); position += to_copy; size_t consumed = 0; size_t written = base64_decode(&out[0], reinterpret_cast(&in[0]), position, consumed, false, checking != FULL_CHECK); send(out, written); if(consumed != position) { copy_mem(&in[0], &in[consumed], position - consumed); position = position - consumed; } else position = 0; length -= to_copy; input += to_copy; } } /* * Flush buffers */ void Base64_Decoder::end_msg() { size_t consumed = 0; size_t written = base64_decode(&out[0], reinterpret_cast(&in[0]), position, consumed, true, checking != FULL_CHECK); send(out, written); const bool not_full_bytes = consumed != position; position = 0; if(not_full_bytes) throw std::invalid_argument("Base64_Decoder: Input not full bytes"); } } /* * Hex Encoder/Decoder * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ #include namespace Botan { /** * Size used for internal buffer in hex encoder/decoder */ const size_t HEX_CODEC_BUFFER_SIZE = 256; /* * Hex_Encoder Constructor */ Hex_Encoder::Hex_Encoder(bool breaks, size_t length, Case c) : casing(c), line_length(breaks ? length : 0) { in.resize(HEX_CODEC_BUFFER_SIZE); out.resize(2*in.size()); counter = position = 0; } /* * Hex_Encoder Constructor */ Hex_Encoder::Hex_Encoder(Case c) : casing(c), line_length(0) { in.resize(HEX_CODEC_BUFFER_SIZE); out.resize(2*in.size()); counter = position = 0; } /* * Encode and send a block */ void Hex_Encoder::encode_and_send(const byte block[], size_t length) { hex_encode(reinterpret_cast(&out[0]), block, length, casing == Uppercase); if(line_length == 0) send(out, 2*length); else { size_t remaining = 2*length, offset = 0; while(remaining) { size_t sent = std::min(line_length - counter, remaining); send(&out[offset], sent); counter += sent; remaining -= sent; offset += sent; if(counter == line_length) { send('\n'); counter = 0; } } } } /* * Convert some data into hex format */ void Hex_Encoder::write(const byte input[], size_t length) { in.copy(position, input, length); if(position + length >= in.size()) { encode_and_send(&in[0], in.size()); input += (in.size() - position); length -= (in.size() - position); while(length >= in.size()) { encode_and_send(input, in.size()); input += in.size(); length -= in.size(); } in.copy(input, length); position = 0; } position += length; } /* * Flush buffers */ void Hex_Encoder::end_msg() { encode_and_send(&in[0], position); if(counter && line_length) send('\n'); counter = position = 0; } /* * Hex_Decoder Constructor */ Hex_Decoder::Hex_Decoder(Decoder_Checking c) : checking(c) { in.resize(HEX_CODEC_BUFFER_SIZE); out.resize(in.size() / 2); position = 0; } /* * Convert some data from hex format */ void Hex_Decoder::write(const byte input[], size_t length) { while(length) { size_t to_copy = std::min(length, in.size() - position); copy_mem(&in[position], input, to_copy); position += to_copy; size_t consumed = 0; size_t written = hex_decode(&out[0], reinterpret_cast(&in[0]), position, consumed, checking != FULL_CHECK); send(out, written); if(consumed != position) { copy_mem(&in[0], &in[consumed], position - consumed); position = position - consumed; } else position = 0; length -= to_copy; input += to_copy; } } /* * Flush buffers */ void Hex_Decoder::end_msg() { size_t consumed = 0; size_t written = hex_decode(&out[0], reinterpret_cast(&in[0]), position, consumed, checking != FULL_CHECK); send(out, written); const bool not_full_bytes = consumed != position; position = 0; if(not_full_bytes) throw std::invalid_argument("Hex_Decoder: Input not full bytes"); } } /* * DataSink * (C) 1999-2007 Jack Lloyd * 2005 Matthew Gregan * * Distributed under the terms of the Botan license */ #include namespace Botan { /* * Write to a stream */ void DataSink_Stream::write(const byte out[], size_t length) { sink.write(reinterpret_cast(out), length); if(!sink.good()) throw Stream_IO_Error("DataSink_Stream: Failure writing to " + identifier); } /* * DataSink_Stream Constructor */ DataSink_Stream::DataSink_Stream(std::ostream& out, const std::string& name) : identifier(name), sink_p(0), sink(out) { } /* * DataSink_Stream Constructor */ DataSink_Stream::DataSink_Stream(const std::string& path, bool use_binary) : identifier(path), sink_p(new std::ofstream( path.c_str(), use_binary ? std::ios::binary : std::ios::out)), sink(*sink_p) { if(!sink.good()) { delete sink_p; throw Stream_IO_Error("DataSink_Stream: Failure opening " + path); } } /* * DataSink_Stream Destructor */ DataSink_Stream::~DataSink_Stream() { delete sink_p; } } /* * DataSource * (C) 1999-2007 Jack Lloyd * 2005 Matthew Gregan * * Distributed under the terms of the Botan license */ #include #include namespace Botan { /* * Read a single byte from the DataSource */ size_t DataSource::read_byte(byte& out) { return read(&out, 1); } /* * Peek a single byte from the DataSource */ size_t DataSource::peek_byte(byte& out) const { return peek(&out, 1, 0); } /* * Discard the next N bytes of the data */ size_t DataSource::discard_next(size_t n) { size_t discarded = 0; byte dummy; for(size_t j = 0; j != n; ++j) discarded += read_byte(dummy); return discarded; } /* * Read from a memory buffer */ size_t DataSource_Memory::read(byte out[], size_t length) { size_t got = std::min(source.size() - offset, length); copy_mem(out, &source[offset], got); offset += got; return got; } /* * Peek into a memory buffer */ size_t DataSource_Memory::peek(byte out[], size_t length, size_t peek_offset) const { const size_t bytes_left = source.size() - offset; if(peek_offset >= bytes_left) return 0; size_t got = std::min(bytes_left - peek_offset, length); copy_mem(out, &source[offset + peek_offset], got); return got; } /* * Check if the memory buffer is empty */ bool DataSource_Memory::end_of_data() const { return (offset == source.size()); } /* * DataSource_Memory Constructor */ DataSource_Memory::DataSource_Memory(const byte in[], size_t length) : source(in, length) { offset = 0; } /* * DataSource_Memory Constructor */ DataSource_Memory::DataSource_Memory(const MemoryRegion& in) : source(in) { offset = 0; } /* * DataSource_Memory Constructor */ DataSource_Memory::DataSource_Memory(const std::string& in) : source(reinterpret_cast(in.data()), in.length()) { offset = 0; } /* * Read from a stream */ size_t DataSource_Stream::read(byte out[], size_t length) { source.read(reinterpret_cast(out), length); if(source.bad()) throw Stream_IO_Error("DataSource_Stream::read: Source failure"); size_t got = source.gcount(); total_read += got; return got; } /* * Peek into a stream */ size_t DataSource_Stream::peek(byte out[], size_t length, size_t offset) const { if(end_of_data()) throw Invalid_State("DataSource_Stream: Cannot peek when out of data"); size_t got = 0; if(offset) { SecureVector buf(offset); source.read(reinterpret_cast(&buf[0]), buf.size()); if(source.bad()) throw Stream_IO_Error("DataSource_Stream::peek: Source failure"); got = source.gcount(); } if(got == offset) { source.read(reinterpret_cast(out), length); if(source.bad()) throw Stream_IO_Error("DataSource_Stream::peek: Source failure"); got = source.gcount(); } if(source.eof()) source.clear(); source.seekg(total_read, std::ios::beg); return got; } /* * Check if the stream is empty or in error */ bool DataSource_Stream::end_of_data() const { return (!source.good()); } /* * Return a human-readable ID for this stream */ std::string DataSource_Stream::id() const { return identifier; } /* * DataSource_Stream Constructor */ DataSource_Stream::DataSource_Stream(const std::string& path, bool use_binary) : identifier(path), source_p(new std::ifstream( path.c_str(), use_binary ? std::ios::binary : std::ios::in)), source(*source_p), total_read(0) { if(!source.good()) { delete source_p; throw Stream_IO_Error("DataSource: Failure opening file " + path); } } /* * DataSource_Stream Constructor */ DataSource_Stream::DataSource_Stream(std::istream& in, const std::string& name) : identifier(name), source_p(0), source(in), total_read(0) { } /* * DataSource_Stream Destructor */ DataSource_Stream::~DataSource_Stream() { delete source_p; } } #ifdef Q_OS_UNIX /* * Pipe I/O for Unix * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ #include namespace Botan { /* * Write data from a pipe into a Unix fd */ int operator<<(int fd, Pipe& pipe) { SecureVector buffer(DEFAULT_BUFFERSIZE); while(pipe.remaining()) { size_t got = pipe.read(&buffer[0], buffer.size()); size_t position = 0; while(got) { ssize_t ret = write(fd, &buffer[position], got); if(ret == -1) throw Stream_IO_Error("Pipe output operator (unixfd) has failed"); position += ret; got -= ret; } } return fd; } /* * Read data from a Unix fd into a pipe */ int operator>>(int fd, Pipe& pipe) { SecureVector buffer(DEFAULT_BUFFERSIZE); while(true) { ssize_t ret = read(fd, &buffer[0], buffer.size()); if(ret == 0) break; if(ret == -1) throw Stream_IO_Error("Pipe input operator (unixfd) has failed"); pipe.write(&buffer[0], ret); } return fd; } } #endif /* * Filter * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { /* * Filter Constructor */ Filter::Filter() { next.resize(1); port_num = 0; filter_owns = 0; owned = false; } /* * Send data to all ports */ void Filter::send(const byte input[], size_t length) { bool nothing_attached = true; for(size_t j = 0; j != total_ports(); ++j) if(next[j]) { if(write_queue.size()) next[j]->write(&write_queue[0], write_queue.size()); next[j]->write(input, length); nothing_attached = false; } if(nothing_attached) write_queue += std::make_pair(input, length); else write_queue.clear(); } /* * Start a new message */ void Filter::new_msg() { start_msg(); for(size_t j = 0; j != total_ports(); ++j) if(next[j]) next[j]->new_msg(); } /* * End the current message */ void Filter::finish_msg() { end_msg(); for(size_t j = 0; j != total_ports(); ++j) if(next[j]) next[j]->finish_msg(); } /* * Attach a filter to the current port */ void Filter::attach(Filter* new_filter) { if(new_filter) { Filter* last = this; while(last->get_next()) last = last->get_next(); last->next[last->current_port()] = new_filter; } } /* * Set the active port on a filter */ void Filter::set_port(size_t new_port) { if(new_port >= total_ports()) throw Invalid_Argument("Filter: Invalid port number"); port_num = new_port; } /* * Return the next Filter in the logical chain */ Filter* Filter::get_next() const { if(port_num < next.size()) return next[port_num]; return 0; } /* * Set the next Filters */ void Filter::set_next(Filter* filters[], size_t size) { while(size && filters && filters[size-1] == 0) --size; next.clear(); next.resize(size); port_num = 0; filter_owns = 0; for(size_t j = 0; j != size; ++j) next[j] = filters[j]; } /* * Return the total number of ports */ size_t Filter::total_ports() const { return next.size(); } } /* * CBC Mode * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ #include namespace Botan { /* * CBC Encryption Constructor */ CBC_Encryption::CBC_Encryption(BlockCipher* ciph, BlockCipherModePaddingMethod* pad) : Buffered_Filter(ciph->block_size(), 0), cipher(ciph), padder(pad) { if(!padder->valid_blocksize(cipher->block_size())) throw Invalid_Block_Size(name(), padder->name()); state.resize(cipher->block_size()); } /* * CBC Encryption Constructor */ CBC_Encryption::CBC_Encryption(BlockCipher* ciph, BlockCipherModePaddingMethod* pad, const SymmetricKey& key, const InitializationVector& iv) : Buffered_Filter(ciph->block_size(), 0), cipher(ciph), padder(pad) { if(!padder->valid_blocksize(cipher->block_size())) throw Invalid_Block_Size(name(), padder->name()); state.resize(cipher->block_size()); set_key(key); set_iv(iv); } /* * Set the IV */ void CBC_Encryption::set_iv(const InitializationVector& iv) { if(!valid_iv_length(iv.length())) throw Invalid_IV_Length(name(), iv.length()); state = iv.bits_of(); buffer_reset(); } /* * Encrypt in CBC mode */ void CBC_Encryption::buffered_block(const byte input[], size_t length) { size_t blocks = length / state.size(); for(size_t i = 0; i != blocks; ++i) { xor_buf(state, input + i * cipher->block_size(), state.size()); cipher->encrypt(state); send(state, state.size()); } } /* * Finish encrypting in CBC mode */ void CBC_Encryption::buffered_final(const byte input[], size_t length) { if(length % cipher->block_size() == 0) buffered_block(input, length); else if(length != 0) throw Encoding_Error(name() + ": Did not pad to full blocksize"); } void CBC_Encryption::write(const byte input[], size_t input_length) { Buffered_Filter::write(input, input_length); } void CBC_Encryption::end_msg() { size_t last_block = current_position() % cipher->block_size(); SecureVector padding(cipher->block_size()); padder->pad(padding, padding.size(), last_block); size_t pad_bytes = padder->pad_bytes(cipher->block_size(), last_block); if(pad_bytes) Buffered_Filter::write(padding, pad_bytes); Buffered_Filter::end_msg(); } /* * Return a CBC mode name */ std::string CBC_Encryption::name() const { return (cipher->name() + "/CBC/" + padder->name()); } /* * CBC Decryption Constructor */ CBC_Decryption::CBC_Decryption(BlockCipher* ciph, BlockCipherModePaddingMethod* pad) : Buffered_Filter(ciph->parallel_bytes(), ciph->block_size()), cipher(ciph), padder(pad) { if(!padder->valid_blocksize(cipher->block_size())) throw Invalid_Block_Size(name(), padder->name()); state.resize(cipher->block_size()); temp.resize(buffered_block_size()); } /* * CBC Decryption Constructor */ CBC_Decryption::CBC_Decryption(BlockCipher* ciph, BlockCipherModePaddingMethod* pad, const SymmetricKey& key, const InitializationVector& iv) : Buffered_Filter(ciph->parallel_bytes(), ciph->block_size()), cipher(ciph), padder(pad) { if(!padder->valid_blocksize(cipher->block_size())) throw Invalid_Block_Size(name(), padder->name()); state.resize(cipher->block_size()); temp.resize(buffered_block_size()); set_key(key); set_iv(iv); } /* * Set the IV */ void CBC_Decryption::set_iv(const InitializationVector& iv) { if(!valid_iv_length(iv.length())) throw Invalid_IV_Length(name(), iv.length()); state = iv.bits_of(); buffer_reset(); } /* * Decrypt in CBC mode */ void CBC_Decryption::buffered_block(const byte input[], size_t length) { const size_t blocks_in_temp = temp.size() / cipher->block_size(); size_t blocks = length / cipher->block_size(); while(blocks) { size_t to_proc = std::min(blocks, blocks_in_temp); cipher->decrypt_n(input, &temp[0], to_proc); xor_buf(temp, state, cipher->block_size()); for(size_t i = 1; i < to_proc; ++i) xor_buf(&temp[i * cipher->block_size()], input + (i-1) * cipher->block_size(), cipher->block_size()); copy_mem(&state[0], input + (to_proc - 1) * cipher->block_size(), cipher->block_size()); send(temp, to_proc * cipher->block_size()); input += to_proc * cipher->block_size(); blocks -= to_proc; } } /* * Finish encrypting in CBC mode */ void CBC_Decryption::buffered_final(const byte input[], size_t length) { if(length == 0 || length % cipher->block_size() != 0) throw Decoding_Error(name() + ": Ciphertext not multiple of block size"); size_t extra_blocks = (length - 1) / cipher->block_size(); buffered_block(input, extra_blocks * cipher->block_size()); input += extra_blocks * cipher->block_size(); cipher->decrypt(input, temp); xor_buf(temp, state, cipher->block_size()); send(temp, padder->unpad(temp, cipher->block_size())); copy_mem(&state[0], input, state.size()); // save for IV chaining } /* * Decrypt in CBC mode */ void CBC_Decryption::write(const byte input[], size_t length) { Buffered_Filter::write(input, length); } /* * Finish decrypting in CBC mode */ void CBC_Decryption::end_msg() { Buffered_Filter::end_msg(); } /* * Return a CBC mode name */ std::string CBC_Decryption::name() const { return (cipher->name() + "/CBC/" + padder->name()); } } /* * CFB Mode * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ #include namespace Botan { /* * CFB Encryption Constructor */ CFB_Encryption::CFB_Encryption(BlockCipher* ciph, size_t fback_bits) { cipher = ciph; feedback = fback_bits ? fback_bits / 8: cipher->block_size(); buffer.resize(cipher->block_size()); state.resize(cipher->block_size()); position = 0; if(feedback == 0 || fback_bits % 8 != 0 || feedback > cipher->block_size()) throw Invalid_Argument("CFB_Encryption: Invalid feedback size " + to_string(fback_bits)); } /* * CFB Encryption Constructor */ CFB_Encryption::CFB_Encryption(BlockCipher* ciph, const SymmetricKey& key, const InitializationVector& iv, size_t fback_bits) { cipher = ciph; feedback = fback_bits ? fback_bits / 8: cipher->block_size(); buffer.resize(cipher->block_size()); state.resize(cipher->block_size()); position = 0; if(feedback == 0 || fback_bits % 8 != 0 || feedback > cipher->block_size()) throw Invalid_Argument("CFB_Encryption: Invalid feedback size " + to_string(fback_bits)); set_key(key); set_iv(iv); } void CFB_Encryption::set_iv(const InitializationVector& iv) { if(!valid_iv_length(iv.length())) throw Invalid_IV_Length(name(), iv.length()); state = iv.bits_of(); zeroise(buffer); position = 0; cipher->encrypt(state, buffer); } /* * Encrypt data in CFB mode */ void CFB_Encryption::write(const byte input[], size_t length) { while(length) { size_t xored = std::min(feedback - position, length); xor_buf(&buffer[position], input, xored); send(&buffer[position], xored); input += xored; length -= xored; position += xored; if(position == feedback) { for(size_t j = 0; j != cipher->block_size() - feedback; ++j) state[j] = state[j + feedback]; state.copy(cipher->block_size() - feedback, buffer, feedback); cipher->encrypt(state, buffer); position = 0; } } } /* * CFB Decryption Constructor */ CFB_Decryption::CFB_Decryption(BlockCipher* ciph, size_t fback_bits) { cipher = ciph; feedback = fback_bits ? fback_bits / 8: cipher->block_size(); buffer.resize(cipher->block_size()); state.resize(cipher->block_size()); position = 0; if(feedback == 0 || fback_bits % 8 != 0 || feedback > cipher->block_size()) throw Invalid_Argument("CFB_Decryption: Invalid feedback size " + to_string(fback_bits)); } /* * CFB Decryption Constructor */ CFB_Decryption::CFB_Decryption(BlockCipher* ciph, const SymmetricKey& key, const InitializationVector& iv, size_t fback_bits) { cipher = ciph; feedback = fback_bits ? fback_bits / 8: cipher->block_size(); buffer.resize(cipher->block_size()); state.resize(cipher->block_size()); position = 0; if(feedback == 0 || fback_bits % 8 != 0 || feedback > cipher->block_size()) throw Invalid_Argument("CFB_Decryption: Invalid feedback size " + to_string(fback_bits)); set_key(key); set_iv(iv); } void CFB_Decryption::set_iv(const InitializationVector& iv) { if(!valid_iv_length(iv.length())) throw Invalid_IV_Length(name(), iv.length()); state = iv.bits_of(); zeroise(buffer); position = 0; cipher->encrypt(state, buffer); } /* * Decrypt data in CFB mode */ void CFB_Decryption::write(const byte input[], size_t length) { while(length) { size_t xored = std::min(feedback - position, length); xor_buf(&buffer[position], input, xored); send(&buffer[position], xored); buffer.copy(position, input, xored); input += xored; length -= xored; position += xored; if(position == feedback) { for(size_t j = 0; j != cipher->block_size() - feedback; ++j) state[j] = state[j + feedback]; state.copy(cipher->block_size() - feedback, buffer, feedback); cipher->encrypt(state, buffer); position = 0; } } } } /* * CTS Mode * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ #include namespace Botan { /* * CTS Encryption Constructor */ CTS_Encryption::CTS_Encryption(BlockCipher* ciph) : cipher(ciph) { buffer.resize(2 * cipher->block_size()); state.resize(cipher->block_size()); position = 0; } /* * CTS Encryption Constructor */ CTS_Encryption::CTS_Encryption(BlockCipher* ciph, const SymmetricKey& key, const InitializationVector& iv) : cipher(ciph) { buffer.resize(2 * cipher->block_size()); state.resize(cipher->block_size()); position = 0; set_key(key); set_iv(iv); } /* * Set the IV */ void CTS_Encryption::set_iv(const InitializationVector& iv) { if(!valid_iv_length(iv.length())) throw Invalid_IV_Length(name(), iv.length()); state = iv.bits_of(); zeroise(buffer); position = 0; } /* * Encrypt a block */ void CTS_Encryption::encrypt(const byte block[]) { xor_buf(state, block, cipher->block_size()); cipher->encrypt(state); send(state, cipher->block_size()); } /* * Encrypt in CTS mode */ void CTS_Encryption::write(const byte input[], size_t length) { size_t copied = std::min(buffer.size() - position, length); buffer.copy(position, input, copied); length -= copied; input += copied; position += copied; if(length == 0) return; encrypt(&buffer[0]); if(length > cipher->block_size()) { encrypt(&buffer[cipher->block_size()]); while(length > 2*cipher->block_size()) { encrypt(input); length -= cipher->block_size(); input += cipher->block_size(); } position = 0; } else { copy_mem(&buffer[0], &buffer[cipher->block_size()], cipher->block_size()); position = cipher->block_size(); } buffer.copy(position, input, length); position += length; } /* * Finish encrypting in CTS mode */ void CTS_Encryption::end_msg() { if(position < cipher->block_size() + 1) throw Encoding_Error(name() + ": insufficient data to encrypt"); xor_buf(state, buffer, cipher->block_size()); cipher->encrypt(state); SecureVector cn = state; clear_mem(&buffer[position], buffer.size() - position); encrypt(&buffer[cipher->block_size()]); send(cn, position - cipher->block_size()); } /* * CTS Decryption Constructor */ CTS_Decryption::CTS_Decryption(BlockCipher* ciph) : cipher(ciph) { buffer.resize(2 * cipher->block_size()); state.resize(cipher->block_size()); temp.resize(cipher->block_size()); position = 0; } /* * CTS Decryption Constructor */ CTS_Decryption::CTS_Decryption(BlockCipher* ciph, const SymmetricKey& key, const InitializationVector& iv) : cipher(ciph) { buffer.resize(2 * cipher->block_size()); state.resize(cipher->block_size()); temp.resize(cipher->block_size()); position = 0; set_key(key); set_iv(iv); } /* * Set the IV */ void CTS_Decryption::set_iv(const InitializationVector& iv) { if(!valid_iv_length(iv.length())) throw Invalid_IV_Length(name(), iv.length()); state = iv.bits_of(); zeroise(buffer); position = 0; } /* * Decrypt a block */ void CTS_Decryption::decrypt(const byte block[]) { cipher->decrypt(block, &temp[0]); xor_buf(temp, state, cipher->block_size()); send(temp, cipher->block_size()); state.copy(block, cipher->block_size()); } /* * Decrypt in CTS mode */ void CTS_Decryption::write(const byte input[], size_t length) { size_t copied = std::min(buffer.size() - position, length); buffer.copy(position, input, copied); length -= copied; input += copied; position += copied; if(length == 0) return; decrypt(buffer); if(length > cipher->block_size()) { decrypt(&buffer[cipher->block_size()]); while(length > 2*cipher->block_size()) { decrypt(input); length -= cipher->block_size(); input += cipher->block_size(); } position = 0; } else { copy_mem(&buffer[0], &buffer[cipher->block_size()], cipher->block_size()); position = cipher->block_size(); } buffer.copy(position, input, length); position += length; } /* * Finish decrypting in CTS mode */ void CTS_Decryption::end_msg() { cipher->decrypt(buffer, temp); xor_buf(temp, &buffer[cipher->block_size()], position - cipher->block_size()); SecureVector xn = temp; copy_mem(&buffer[position], &xn[position - cipher->block_size()], buffer.size() - position); cipher->decrypt(&buffer[cipher->block_size()], temp); xor_buf(temp, state, cipher->block_size()); send(temp, cipher->block_size()); send(xn, position - cipher->block_size()); } } /* * EAX Mode Encryption * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ #include namespace Botan { namespace { /* * EAX MAC-based PRF */ SecureVector eax_prf(byte tag, size_t BLOCK_SIZE, MessageAuthenticationCode* mac, const byte in[], size_t length) { for(size_t i = 0; i != BLOCK_SIZE - 1; ++i) mac->update(0); mac->update(tag); mac->update(in, length); return mac->final(); } } /* * EAX_Base Constructor */ EAX_Base::EAX_Base(BlockCipher* cipher, size_t tag_size) : BLOCK_SIZE(cipher->block_size()), TAG_SIZE(tag_size ? tag_size / 8 : BLOCK_SIZE), cipher_name(cipher->name()), ctr_buf(DEFAULT_BUFFERSIZE) { cmac = new CMAC(cipher->clone()); ctr = new CTR_BE(cipher); // takes ownership if(tag_size % 8 != 0 || TAG_SIZE == 0 || TAG_SIZE > cmac->output_length()) throw Invalid_Argument(name() + ": Bad tag size " + to_string(tag_size)); } /* * Check if a keylength is valid for EAX */ bool EAX_Base::valid_keylength(size_t n) const { if(!ctr->valid_keylength(n)) return false; return true; } /* * Set the EAX key */ void EAX_Base::set_key(const SymmetricKey& key) { /* * These could share the key schedule, which is one nice part of EAX, * but it's much easier to ignore that here... */ ctr->set_key(key); cmac->set_key(key); header_mac = eax_prf(1, BLOCK_SIZE, cmac, 0, 0); } /* * Do setup at the start of each message */ void EAX_Base::start_msg() { for(size_t i = 0; i != BLOCK_SIZE - 1; ++i) cmac->update(0); cmac->update(2); } /* * Set the EAX nonce */ void EAX_Base::set_iv(const InitializationVector& iv) { nonce_mac = eax_prf(0, BLOCK_SIZE, cmac, iv.begin(), iv.length()); ctr->set_iv(&nonce_mac[0], nonce_mac.size()); } /* * Set the EAX header */ void EAX_Base::set_header(const byte header[], size_t length) { header_mac = eax_prf(1, BLOCK_SIZE, cmac, header, length); } /* * Return the name of this cipher mode */ std::string EAX_Base::name() const { return (cipher_name + "/EAX"); } /* * Encrypt in EAX mode */ void EAX_Encryption::write(const byte input[], size_t length) { while(length) { size_t copied = std::min(length, ctr_buf.size()); ctr->cipher(input, &ctr_buf[0], copied); cmac->update(&ctr_buf[0], copied); send(ctr_buf, copied); input += copied; length -= copied; } } /* * Finish encrypting in EAX mode */ void EAX_Encryption::end_msg() { SecureVector data_mac = cmac->final(); xor_buf(data_mac, nonce_mac, data_mac.size()); xor_buf(data_mac, header_mac, data_mac.size()); send(data_mac, TAG_SIZE); } } /* * EAX Mode Encryption * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ #include namespace Botan { /* * EAX_Decryption Constructor */ EAX_Decryption::EAX_Decryption(BlockCipher* ciph, size_t tag_size) : EAX_Base(ciph, tag_size) { queue.resize(2*TAG_SIZE + DEFAULT_BUFFERSIZE); queue_start = queue_end = 0; } /* * EAX_Decryption Constructor */ EAX_Decryption::EAX_Decryption(BlockCipher* ciph, const SymmetricKey& key, const InitializationVector& iv, size_t tag_size) : EAX_Base(ciph, tag_size) { set_key(key); set_iv(iv); queue.resize(2*TAG_SIZE + DEFAULT_BUFFERSIZE); queue_start = queue_end = 0; } /* * Decrypt in EAX mode */ void EAX_Decryption::write(const byte input[], size_t length) { while(length) { const size_t copied = std::min(length, queue.size() - queue_end); queue.copy(queue_end, input, copied); input += copied; length -= copied; queue_end += copied; while((queue_end - queue_start) > TAG_SIZE) { size_t removed = (queue_end - queue_start) - TAG_SIZE; do_write(&queue[queue_start], removed); queue_start += removed; } if(queue_start + TAG_SIZE == queue_end && queue_start >= queue.size() / 2) { SecureVector queue_data(TAG_SIZE); queue_data.copy(&queue[queue_start], TAG_SIZE); queue.copy(&queue_data[0], TAG_SIZE); queue_start = 0; queue_end = TAG_SIZE; } } } /* * Decrypt in EAX mode */ void EAX_Decryption::do_write(const byte input[], size_t length) { while(length) { size_t copied = std::min(length, ctr_buf.size()); /* Process same block with cmac and ctr at the same time to help cache locality. */ cmac->update(input, copied); ctr->cipher(input, &ctr_buf[0], copied); send(ctr_buf, copied); input += copied; length -= copied; } } /* * Finish decrypting in EAX mode */ void EAX_Decryption::end_msg() { if((queue_end - queue_start) != TAG_SIZE) throw Decoding_Error(name() + ": Message authentication failure"); SecureVector data_mac = cmac->final(); for(size_t j = 0; j != TAG_SIZE; ++j) if(queue[queue_start+j] != (data_mac[j] ^ nonce_mac[j] ^ header_mac[j])) throw Decoding_Error(name() + ": Message authentication failure"); queue_start = queue_end = 0; } } /* * ECB Mode * (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { /* * ECB_Encryption Constructor */ ECB_Encryption::ECB_Encryption(BlockCipher* ciph, BlockCipherModePaddingMethod* pad) : Buffered_Filter(ciph->parallel_bytes(), 0) { cipher = ciph; padder = pad; temp.resize(buffered_block_size()); } /* * ECB_Encryption Constructor */ ECB_Encryption::ECB_Encryption(BlockCipher* ciph, BlockCipherModePaddingMethod* pad, const SymmetricKey& key) : Buffered_Filter(ciph->parallel_bytes(), 0) { cipher = ciph; padder = pad; temp.resize(buffered_block_size()); cipher->set_key(key); } /* * ECB_Encryption Destructor */ ECB_Encryption::~ECB_Encryption() { delete cipher; delete padder; } /* * Return an ECB mode name */ std::string ECB_Encryption::name() const { return (cipher->name() + "/ECB/" + padder->name()); } /* * Encrypt in ECB mode */ void ECB_Encryption::write(const byte input[], size_t length) { Buffered_Filter::write(input, length); } /* * Finish encrypting in ECB mode */ void ECB_Encryption::end_msg() { size_t last_block = current_position() % cipher->block_size(); SecureVector padding(cipher->block_size()); padder->pad(padding, padding.size(), last_block); size_t pad_bytes = padder->pad_bytes(cipher->block_size(), last_block); if(pad_bytes) Buffered_Filter::write(padding, pad_bytes); Buffered_Filter::end_msg(); } void ECB_Encryption::buffered_block(const byte input[], size_t input_length) { const size_t blocks_in_temp = temp.size() / cipher->block_size(); size_t blocks = input_length / cipher->block_size(); while(blocks) { size_t to_proc = std::min(blocks, blocks_in_temp); cipher->encrypt_n(input, &temp[0], to_proc); send(temp, to_proc * cipher->block_size()); input += to_proc * cipher->block_size(); blocks -= to_proc; } } void ECB_Encryption::buffered_final(const byte input[], size_t input_length) { if(input_length % cipher->block_size() == 0) buffered_block(input, input_length); else if(input_length != 0) throw Encoding_Error(name() + ": Did not pad to full blocksize"); } /* * ECB_Decryption Constructor */ ECB_Decryption::ECB_Decryption(BlockCipher* ciph, BlockCipherModePaddingMethod* pad) : Buffered_Filter(ciph->parallel_bytes(), 1) { cipher = ciph; padder = pad; temp.resize(buffered_block_size()); } /* * ECB_Decryption Constructor */ ECB_Decryption::ECB_Decryption(BlockCipher* ciph, BlockCipherModePaddingMethod* pad, const SymmetricKey& key) : Buffered_Filter(ciph->parallel_bytes(), 1) { cipher = ciph; padder = pad; temp.resize(buffered_block_size()); 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[], size_t length) { Buffered_Filter::write(input, length); } /* * Finish decrypting in ECB mode */ void ECB_Decryption::end_msg() { Buffered_Filter::end_msg(); } /* * Decrypt in ECB mode */ void ECB_Decryption::buffered_block(const byte input[], size_t length) { const size_t blocks_in_temp = temp.size() / cipher->block_size(); size_t blocks = length / cipher->block_size(); while(blocks) { size_t to_proc = std::min(blocks, blocks_in_temp); cipher->decrypt_n(input, &temp[0], to_proc); send(temp, to_proc * cipher->block_size()); input += to_proc * cipher->block_size(); blocks -= to_proc; } } /* * Finish encrypting in ECB mode */ void ECB_Decryption::buffered_final(const byte input[], size_t length) { if(length == 0 || length % cipher->block_size() != 0) throw Decoding_Error(name() + ": Ciphertext not multiple of block size"); size_t extra_blocks = (length - 1) / cipher->block_size(); buffered_block(input, extra_blocks * cipher->block_size()); input += extra_blocks * cipher->block_size(); cipher->decrypt(input, temp); send(temp, padder->unpad(temp, cipher->block_size())); } } /* * CBC Padding Methods * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { /* * Default amount of padding */ size_t BlockCipherModePaddingMethod::pad_bytes(size_t bs, size_t pos) const { return (bs - pos); } /* * Pad with PKCS #7 Method */ void PKCS7_Padding::pad(byte block[], size_t size, size_t position) const { const size_t bytes_remaining = size - position; const byte pad_value = static_cast(bytes_remaining); BOTAN_ASSERT_EQUAL(pad_value, bytes_remaining, "Overflow in PKCS7_Padding"); for(size_t j = 0; j != size; ++j) block[j] = pad_value; } /* * Unpad with PKCS #7 Method */ size_t PKCS7_Padding::unpad(const byte block[], size_t size) const { size_t position = block[size-1]; if(position > size) throw Decoding_Error(name()); for(size_t j = size-position; j != size-1; ++j) if(block[j] != position) throw Decoding_Error(name()); return (size-position); } /* * Query if the size is valid for this method */ bool PKCS7_Padding::valid_blocksize(size_t size) const { if(size > 0 && size < 256) return true; else return false; } /* * Pad with ANSI X9.23 Method */ void ANSI_X923_Padding::pad(byte block[], size_t size, size_t position) const { for(size_t j = 0; j != size-position; ++j) block[j] = 0; block[size-position-1] = static_cast(size-position); } /* * Unpad with ANSI X9.23 Method */ size_t ANSI_X923_Padding::unpad(const byte block[], size_t size) const { size_t position = block[size-1]; if(position > size) throw Decoding_Error(name()); for(size_t j = size-position; j != size-1; ++j) if(block[j] != 0) throw Decoding_Error(name()); return (size-position); } /* * Query if the size is valid for this method */ bool ANSI_X923_Padding::valid_blocksize(size_t size) const { if(size > 0 && size < 256) return true; else return false; } /* * Pad with One and Zeros Method */ void OneAndZeros_Padding::pad(byte block[], size_t size, size_t) const { block[0] = 0x80; for(size_t j = 1; j != size; ++j) block[j] = 0x00; } /* * Unpad with One and Zeros Method */ size_t OneAndZeros_Padding::unpad(const byte block[], size_t size) const { while(size) { if(block[size-1] == 0x80) break; if(block[size-1] != 0x00) throw Decoding_Error(name()); size--; } if(!size) throw Decoding_Error(name()); return (size-1); } /* * Query if the size is valid for this method */ bool OneAndZeros_Padding::valid_blocksize(size_t size) const { return (size > 0); } } /* * XTS Mode * (C) 2009 Jack Lloyd * * Distributed under the terms of the Botan license */ #include #include namespace Botan { namespace { void poly_double(byte tweak[], size_t size) { const byte polynomial = (size == 16) ? 0x87 : 0x1B; byte carry = 0; for(size_t i = 0; i != size; ++i) { byte carry2 = (tweak[i] >> 7); tweak[i] = (tweak[i] << 1) | carry; carry = carry2; } if(carry) tweak[0] ^= polynomial; } /* XTS needs to process at least 2 blocks in parallel because block_size+1 bytes are needed at the end */ size_t xts_parallelism(BlockCipher* cipher) { return std::max(cipher->parallel_bytes(), 2 * cipher->block_size()); } } /* * XTS_Encryption constructor */ XTS_Encryption::XTS_Encryption(BlockCipher* ciph) : Buffered_Filter(xts_parallelism(ciph), ciph->block_size() + 1), cipher(ciph) { if(cipher->block_size() != 8 && cipher->block_size() != 16) throw std::invalid_argument("Bad cipher for XTS: " + cipher->name()); cipher2 = cipher->clone(); tweak.resize(buffered_block_size()); } /* * XTS_Encryption constructor */ XTS_Encryption::XTS_Encryption(BlockCipher* ciph, const SymmetricKey& key, const InitializationVector& iv) : Buffered_Filter(xts_parallelism(ciph), ciph->block_size() + 1), cipher(ciph) { if(cipher->block_size() != 8 && cipher->block_size() != 16) throw std::invalid_argument("Bad cipher for XTS: " + cipher->name()); cipher2 = cipher->clone(); tweak.resize(buffered_block_size()); set_key(key); set_iv(iv); } /* * Return the name */ std::string XTS_Encryption::name() const { return (cipher->name() + "/XTS"); } /* * Set new tweak */ void XTS_Encryption::set_iv(const InitializationVector& iv) { if(!valid_iv_length(iv.length())) throw Invalid_IV_Length(name(), iv.length()); const size_t blocks_in_tweak = tweak.size() / cipher->block_size(); tweak.copy(iv.begin(), iv.length()); cipher2->encrypt(tweak); for(size_t i = 1; i < blocks_in_tweak; ++i) { tweak.copy(i*cipher->block_size(), &tweak[(i-1)*cipher->block_size()], cipher->block_size()); poly_double(&tweak[i*cipher->block_size()], cipher->block_size()); } } void XTS_Encryption::set_key(const SymmetricKey& key) { size_t key_half = key.length() / 2; if(key.length() % 2 == 1 || !cipher->valid_keylength(key_half)) throw Invalid_Key_Length(name(), key.length()); cipher->set_key(key.begin(), key_half); cipher2->set_key(key.begin() + key_half, key_half); } /* * Encrypt in XTS mode */ void XTS_Encryption::write(const byte input[], size_t length) { Buffered_Filter::write(input, length); } /* * Finish encrypting in XTS mode */ void XTS_Encryption::end_msg() { Buffered_Filter::end_msg(); } void XTS_Encryption::buffered_block(const byte input[], size_t length) { const size_t blocks_in_tweak = tweak.size() / cipher->block_size(); size_t blocks = length / cipher->block_size(); SecureVector temp(tweak.size()); while(blocks) { size_t to_proc = std::min(blocks, blocks_in_tweak); size_t to_proc_bytes = to_proc * cipher->block_size(); xor_buf(temp, input, tweak, to_proc_bytes); cipher->encrypt_n(&temp[0], &temp[0], to_proc); xor_buf(temp, tweak, to_proc_bytes); send(temp, to_proc_bytes); tweak.copy(&tweak[(to_proc-1)*cipher->block_size()], cipher->block_size()); poly_double(&tweak[0], cipher->block_size()); for(size_t i = 1; i < blocks_in_tweak; ++i) { tweak.copy(i*cipher->block_size(), &tweak[(i-1)*cipher->block_size()], cipher->block_size()); poly_double(&tweak[i*cipher->block_size()], cipher->block_size()); } input += to_proc * cipher->block_size(); blocks -= to_proc; } } /* * Finish encrypting in XTS mode */ void XTS_Encryption::buffered_final(const byte input[], size_t length) { if(length <= cipher->block_size()) throw Encoding_Error("XTS_Encryption: insufficient data to encrypt"); if(length % cipher->block_size() == 0) { buffered_block(input, length); } else { // steal ciphertext size_t leftover_blocks = ((length / cipher->block_size()) - 1) * cipher->block_size(); buffered_block(input, leftover_blocks); input += leftover_blocks; length -= leftover_blocks; SecureVector temp(input, length); xor_buf(temp, tweak, cipher->block_size()); cipher->encrypt(temp); xor_buf(temp, tweak, cipher->block_size()); poly_double(&tweak[0], cipher->block_size()); for(size_t i = 0; i != length - cipher->block_size(); ++i) std::swap(temp[i], temp[i + cipher->block_size()]); xor_buf(temp, tweak, cipher->block_size()); cipher->encrypt(temp); xor_buf(temp, tweak, cipher->block_size()); send(temp, temp.size()); } buffer_reset(); } /* * XTS_Decryption constructor */ XTS_Decryption::XTS_Decryption(BlockCipher* ciph) : Buffered_Filter(xts_parallelism(ciph), ciph->block_size() + 1), cipher(ciph) { if(cipher->block_size() != 8 && cipher->block_size() != 16) throw std::invalid_argument("Bad cipher for XTS: " + cipher->name()); cipher2 = ciph->clone(); tweak.resize(buffered_block_size()); } /* * XTS_Decryption constructor */ XTS_Decryption::XTS_Decryption(BlockCipher* ciph, const SymmetricKey& key, const InitializationVector& iv) : Buffered_Filter(xts_parallelism(ciph), ciph->block_size() + 1), cipher(ciph) { if(cipher->block_size() != 8 && cipher->block_size() != 16) throw std::invalid_argument("Bad cipher for XTS: " + cipher->name()); cipher2 = ciph->clone(); tweak.resize(buffered_block_size()); set_key(key); set_iv(iv); } /* * Return the name */ std::string XTS_Decryption::name() const { return (cipher->name() + "/XTS"); } /* * Set new tweak */ void XTS_Decryption::set_iv(const InitializationVector& iv) { if(!valid_iv_length(iv.length())) throw Invalid_IV_Length(name(), iv.length()); const size_t blocks_in_tweak = tweak.size() / cipher->block_size(); tweak.copy(iv.begin(), iv.length()); cipher2->encrypt(tweak); for(size_t i = 1; i < blocks_in_tweak; ++i) { tweak.copy(i*cipher->block_size(), &tweak[(i-1)*cipher->block_size()], cipher->block_size()); poly_double(&tweak[i*cipher->block_size()], cipher->block_size()); } } void XTS_Decryption::set_key(const SymmetricKey& key) { size_t key_half = key.length() / 2; if(key.length() % 2 == 1 || !cipher->valid_keylength(key_half)) throw Invalid_Key_Length(name(), key.length()); cipher->set_key(key.begin(), key_half); cipher2->set_key(key.begin() + key_half, key_half); } /* * Decrypt in XTS mode */ void XTS_Decryption::write(const byte input[], size_t length) { Buffered_Filter::write(input, length); } /* * Finish decrypting in XTS mode */ void XTS_Decryption::end_msg() { Buffered_Filter::end_msg(); } void XTS_Decryption::buffered_block(const byte input[], size_t input_length) { const size_t blocks_in_tweak = tweak.size() / cipher->block_size(); size_t blocks = input_length / cipher->block_size(); SecureVector temp(tweak.size()); while(blocks) { size_t to_proc = std::min(blocks, blocks_in_tweak); size_t to_proc_bytes = to_proc * cipher->block_size(); xor_buf(temp, input, tweak, to_proc_bytes); cipher->decrypt_n(&temp[0], &temp[0], to_proc); xor_buf(temp, tweak, to_proc_bytes); send(temp, to_proc_bytes); tweak.copy(&tweak[(to_proc-1)*cipher->block_size()], cipher->block_size()); poly_double(&tweak[0], cipher->block_size()); for(size_t i = 1; i < blocks_in_tweak; ++i) { tweak.copy(i*cipher->block_size(), &tweak[(i-1)*cipher->block_size()], cipher->block_size()); poly_double(&tweak[i*cipher->block_size()], cipher->block_size()); } input += to_proc * cipher->block_size(); blocks -= to_proc; } } void XTS_Decryption::buffered_final(const byte input[], size_t length) { if(length <= cipher->block_size()) throw Decoding_Error("XTS_Decryption: insufficient data to decrypt"); if(length % cipher->block_size() == 0) { buffered_block(input, length); } else { size_t leftover_blocks = ((length / cipher->block_size()) - 1) * cipher->block_size(); buffered_block(input, leftover_blocks); input += leftover_blocks; length -= leftover_blocks; SecureVector temp(input, length); SecureVector tweak_copy(&tweak[0], cipher->block_size()); poly_double(&tweak_copy[0], cipher->block_size()); xor_buf(temp, tweak_copy, cipher->block_size()); cipher->decrypt(temp); xor_buf(temp, tweak_copy, cipher->block_size()); for(size_t i = 0; i != length - cipher->block_size(); ++i) std::swap(temp[i], temp[i + cipher->block_size()]); xor_buf(temp, tweak, cipher->block_size()); cipher->decrypt(temp); xor_buf(temp, tweak, cipher->block_size()); send(temp, length); } buffer_reset(); } } /* * Pipe Output Buffer * (C) 1999-2007,2011 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { /* * Read data from a message */ size_t Output_Buffers::read(byte output[], size_t length, Pipe::message_id msg) { SecureQueue* q = get(msg); if(q) return q->read(output, length); return 0; } /* * Peek at data in a message */ size_t Output_Buffers::peek(byte output[], size_t length, size_t stream_offset, Pipe::message_id msg) const { SecureQueue* q = get(msg); if(q) return q->peek(output, length, stream_offset); return 0; } /* * Check available bytes in a message */ size_t Output_Buffers::remaining(Pipe::message_id msg) const { SecureQueue* q = get(msg); if(q) return q->size(); return 0; } /* * Add a new output queue */ void Output_Buffers::add(SecureQueue* queue) { BOTAN_ASSERT(queue, "argument was NULL"); BOTAN_ASSERT(buffers.size() < buffers.max_size(), "No more room in container"); buffers.push_back(queue); } /* * Retire old output queues */ void Output_Buffers::retire() { for(size_t i = 0; i != buffers.size(); ++i) if(buffers[i] && buffers[i]->size() == 0) { delete buffers[i]; buffers[i] = 0; } while(buffers.size() && !buffers[0]) { buffers.pop_front(); offset = offset + Pipe::message_id(1); } } /* * Get a particular output queue */ SecureQueue* Output_Buffers::get(Pipe::message_id msg) const { if(msg < offset) return 0; BOTAN_ASSERT(msg < message_count(), "Message number out of range"); return buffers[msg-offset]; } /* * Return the total number of messages */ Pipe::message_id Output_Buffers::message_count() const { return (offset + buffers.size()); } /* * Output_Buffers Constructor */ Output_Buffers::Output_Buffers() { offset = 0; } /* * Output_Buffers Destructor */ Output_Buffers::~Output_Buffers() { for(size_t j = 0; j != buffers.size(); ++j) delete buffers[j]; } } /* * Pipe * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { namespace { /* * A Filter that does nothing */ class Null_Filter : public Filter { public: void write(const byte input[], size_t length) { send(input, length); } std::string name() const { return "Null"; } }; } /* * Pipe Constructor */ Pipe::Pipe(Filter* f1, Filter* f2, Filter* f3, Filter* f4) { init(); append(f1); append(f2); append(f3); append(f4); } /* * Pipe Constructor */ Pipe::Pipe(Filter* filter_array[], size_t count) { init(); for(size_t j = 0; j != count; ++j) append(filter_array[j]); } /* * Pipe Destructor */ Pipe::~Pipe() { destruct(pipe); delete outputs; } /* * Initialize the Pipe */ void Pipe::init() { outputs = new Output_Buffers; pipe = 0; default_read = 0; inside_msg = false; } /* * Reset the Pipe */ void Pipe::reset() { destruct(pipe); pipe = 0; inside_msg = false; } /* * Destroy the Pipe */ void Pipe::destruct(Filter* to_kill) { if(!to_kill || dynamic_cast(to_kill)) return; for(size_t j = 0; j != to_kill->total_ports(); ++j) destruct(to_kill->next[j]); delete to_kill; } /* * Test if the Pipe has any data in it */ bool Pipe::end_of_data() const { return (remaining() == 0); } /* * Set the default read message */ void Pipe::set_default_msg(message_id msg) { if(msg >= message_count()) throw Invalid_Argument("Pipe::set_default_msg: msg number is too high"); default_read = msg; } /* * Process a full message at once */ void Pipe::process_msg(const byte input[], size_t length) { start_msg(); write(input, length); end_msg(); } /* * Process a full message at once */ void Pipe::process_msg(const MemoryRegion& input) { process_msg(&input[0], input.size()); } /* * Process a full message at once */ void Pipe::process_msg(const std::string& input) { process_msg(reinterpret_cast(input.data()), input.length()); } /* * Process a full message at once */ void Pipe::process_msg(DataSource& input) { start_msg(); write(input); end_msg(); } /* * Start a new message */ void Pipe::start_msg() { if(inside_msg) throw Invalid_State("Pipe::start_msg: Message was already started"); if(pipe == 0) pipe = new Null_Filter; find_endpoints(pipe); pipe->new_msg(); inside_msg = true; } /* * End the current message */ void Pipe::end_msg() { if(!inside_msg) throw Invalid_State("Pipe::end_msg: Message was already ended"); pipe->finish_msg(); clear_endpoints(pipe); if(dynamic_cast(pipe)) { delete pipe; pipe = 0; } inside_msg = false; outputs->retire(); } /* * Find the endpoints of the Pipe */ void Pipe::find_endpoints(Filter* f) { for(size_t j = 0; j != f->total_ports(); ++j) if(f->next[j] && !dynamic_cast(f->next[j])) find_endpoints(f->next[j]); else { SecureQueue* q = new SecureQueue; f->next[j] = q; outputs->add(q); } } /* * Remove the SecureQueues attached to the Filter */ void Pipe::clear_endpoints(Filter* f) { if(!f) return; for(size_t j = 0; j != f->total_ports(); ++j) { if(f->next[j] && dynamic_cast(f->next[j])) f->next[j] = 0; clear_endpoints(f->next[j]); } } /* * Append a Filter to the Pipe */ void Pipe::append(Filter* filter) { if(inside_msg) throw Invalid_State("Cannot append to a Pipe while it is processing"); if(!filter) return; if(dynamic_cast(filter)) throw Invalid_Argument("Pipe::append: SecureQueue cannot be used"); if(filter->owned) throw Invalid_Argument("Filters cannot be shared among multiple Pipes"); filter->owned = true; if(!pipe) pipe = filter; else pipe->attach(filter); } /* * Prepend a Filter to the Pipe */ void Pipe::prepend(Filter* filter) { if(inside_msg) throw Invalid_State("Cannot prepend to a Pipe while it is processing"); if(!filter) return; if(dynamic_cast(filter)) throw Invalid_Argument("Pipe::prepend: SecureQueue cannot be used"); if(filter->owned) throw Invalid_Argument("Filters cannot be shared among multiple Pipes"); filter->owned = true; if(pipe) filter->attach(pipe); pipe = filter; } /* * Pop a Filter off the Pipe */ void Pipe::pop() { if(inside_msg) throw Invalid_State("Cannot pop off a Pipe while it is processing"); if(!pipe) return; if(pipe->total_ports() > 1) throw Invalid_State("Cannot pop off a Filter with multiple ports"); Filter* f = pipe; size_t owns = f->owns(); pipe = pipe->next[0]; delete f; while(owns--) { f = pipe; pipe = pipe->next[0]; delete f; } } /* * Return the number of messages in this Pipe */ Pipe::message_id Pipe::message_count() const { return outputs->message_count(); } /* * Static Member Variables */ const Pipe::message_id Pipe::LAST_MESSAGE = static_cast(-2); const Pipe::message_id Pipe::DEFAULT_MESSAGE = static_cast(-1); } /* * Pipe I/O * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ #include namespace Botan { /* * Write data from a pipe into an ostream */ std::ostream& operator<<(std::ostream& stream, Pipe& pipe) { SecureVector buffer(DEFAULT_BUFFERSIZE); while(stream.good() && pipe.remaining()) { size_t got = pipe.read(&buffer[0], buffer.size()); stream.write(reinterpret_cast(&buffer[0]), got); } if(!stream.good()) throw Stream_IO_Error("Pipe output operator (iostream) has failed"); return stream; } /* * Read data from an istream into a pipe */ std::istream& operator>>(std::istream& stream, Pipe& pipe) { SecureVector buffer(DEFAULT_BUFFERSIZE); while(stream.good()) { stream.read(reinterpret_cast(&buffer[0]), buffer.size()); pipe.write(&buffer[0], stream.gcount()); } if(stream.bad() || (stream.fail() && !stream.eof())) throw Stream_IO_Error("Pipe input operator (iostream) has failed"); return stream; } } /* * Pipe Reading/Writing * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { /* * Look up the canonical ID for a queue */ Pipe::message_id Pipe::get_message_no(const std::string& func_name, message_id msg) const { if(msg == DEFAULT_MESSAGE) msg = default_msg(); else if(msg == LAST_MESSAGE) msg = message_count() - 1; if(msg >= message_count()) throw Invalid_Message_Number(func_name, msg); return msg; } /* * Write into a Pipe */ void Pipe::write(const byte input[], size_t length) { if(!inside_msg) throw Invalid_State("Cannot write to a Pipe while it is not processing"); pipe->write(input, length); } /* * Write into a Pipe */ void Pipe::write(const MemoryRegion& input) { write(&input[0], input.size()); } /* * Write a string into a Pipe */ void Pipe::write(const std::string& str) { write(reinterpret_cast(str.data()), str.size()); } /* * Write a single byte into a Pipe */ void Pipe::write(byte input) { write(&input, 1); } /* * Write the contents of a DataSource into a Pipe */ void Pipe::write(DataSource& source) { SecureVector buffer(DEFAULT_BUFFERSIZE); while(!source.end_of_data()) { size_t got = source.read(&buffer[0], buffer.size()); write(&buffer[0], got); } } /* * Read some data from the pipe */ size_t Pipe::read(byte output[], size_t length, message_id msg) { return outputs->read(output, length, get_message_no("read", msg)); } /* * Read some data from the pipe */ size_t Pipe::read(byte output[], size_t length) { return read(output, length, DEFAULT_MESSAGE); } /* * Read a single byte from the pipe */ size_t Pipe::read(byte& out, message_id msg) { return read(&out, 1, msg); } /* * Return all data in the pipe */ SecureVector Pipe::read_all(message_id msg) { msg = ((msg != DEFAULT_MESSAGE) ? msg : default_msg()); SecureVector buffer(remaining(msg)); size_t got = read(&buffer[0], buffer.size(), msg); buffer.resize(got); return buffer; } /* * Return all data in the pipe as a string */ std::string Pipe::read_all_as_string(message_id msg) { msg = ((msg != DEFAULT_MESSAGE) ? msg : default_msg()); SecureVector buffer(DEFAULT_BUFFERSIZE); std::string str; str.reserve(remaining(msg)); while(true) { size_t got = read(&buffer[0], buffer.size(), msg); if(got == 0) break; str.append(reinterpret_cast(&buffer[0]), got); } return str; } /* * Find out how many bytes are ready to read */ size_t Pipe::remaining(message_id msg) const { return outputs->remaining(get_message_no("remaining", msg)); } /* * Peek at some data in the pipe */ size_t Pipe::peek(byte output[], size_t length, size_t offset, message_id msg) const { return outputs->peek(output, length, offset, get_message_no("peek", msg)); } /* * Peek at some data in the pipe */ size_t Pipe::peek(byte output[], size_t length, size_t offset) const { return peek(output, length, offset, DEFAULT_MESSAGE); } /* * Peek at a byte in the pipe */ size_t Pipe::peek(byte& out, size_t offset, message_id msg) const { return peek(&out, 1, offset, msg); } } /* * PK Filters * (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { /* * Append to the buffer */ void PK_Encryptor_Filter::write(const byte input[], size_t length) { buffer += std::make_pair(input, length); } /* * Encrypt the message */ void PK_Encryptor_Filter::end_msg() { send(cipher->encrypt(buffer, rng)); buffer.clear(); } /* * Append to the buffer */ void PK_Decryptor_Filter::write(const byte input[], size_t length) { buffer += std::make_pair(input, length); } /* * Decrypt the message */ void PK_Decryptor_Filter::end_msg() { send(cipher->decrypt(buffer)); buffer.clear(); } /* * Add more data */ void PK_Signer_Filter::write(const byte input[], size_t length) { signer->update(input, length); } /* * Sign the message */ void PK_Signer_Filter::end_msg() { send(signer->signature(rng)); } /* * Add more data */ void PK_Verifier_Filter::write(const byte input[], size_t length) { verifier->update(input, length); } /* * Verify the message */ void PK_Verifier_Filter::end_msg() { if(signature.empty()) throw Invalid_State("PK_Verifier_Filter: No signature to check against"); bool is_valid = verifier->check_signature(signature); send((is_valid ? 1 : 0)); } /* * Set the signature to check */ void PK_Verifier_Filter::set_signature(const byte sig[], size_t length) { signature.resize(length); copy_mem(&signature[0], sig, length); } /* * Set the signature to check */ void PK_Verifier_Filter::set_signature(const MemoryRegion& sig) { signature = sig; } /* * PK_Verifier_Filter Constructor */ PK_Verifier_Filter::PK_Verifier_Filter(PK_Verifier* v, const byte sig[], size_t length) : verifier(v), signature(sig, length) { } /* * PK_Verifier_Filter Constructor */ PK_Verifier_Filter::PK_Verifier_Filter(PK_Verifier* v, const MemoryRegion& sig) : verifier(v), signature(sig) { } } /* * SecureQueue * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ #include namespace Botan { /** * A node in a SecureQueue */ class SecureQueueNode { public: SecureQueueNode() : buffer(DEFAULT_BUFFERSIZE) { next = 0; start = end = 0; } ~SecureQueueNode() { next = 0; start = end = 0; } size_t write(const byte input[], size_t length) { size_t copied = std::min(length, buffer.size() - end); copy_mem(&buffer[end], input, copied); end += copied; return copied; } size_t read(byte output[], size_t length) { size_t copied = std::min(length, end - start); copy_mem(output, &buffer[start], copied); start += copied; return copied; } size_t peek(byte output[], size_t length, size_t offset = 0) { const size_t left = end - start; if(offset >= left) return 0; size_t copied = std::min(length, left - offset); copy_mem(output, &buffer[start + offset], copied); return copied; } size_t size() const { return (end - start); } private: friend class SecureQueue; SecureQueueNode* next; SecureVector buffer; size_t start, end; }; /* * Create a SecureQueue */ SecureQueue::SecureQueue() { set_next(0, 0); head = tail = new SecureQueueNode; } /* * Copy a SecureQueue */ SecureQueue::SecureQueue(const SecureQueue& input) : Fanout_Filter(), DataSource() { set_next(0, 0); head = tail = new SecureQueueNode; SecureQueueNode* temp = input.head; while(temp) { write(&temp->buffer[temp->start], temp->end - temp->start); temp = temp->next; } } /* * Destroy this SecureQueue */ void SecureQueue::destroy() { SecureQueueNode* temp = head; while(temp) { SecureQueueNode* holder = temp->next; delete temp; temp = holder; } head = tail = 0; } /* * Copy a SecureQueue */ SecureQueue& SecureQueue::operator=(const SecureQueue& input) { destroy(); head = tail = new SecureQueueNode; SecureQueueNode* temp = input.head; while(temp) { write(&temp->buffer[temp->start], temp->end - temp->start); temp = temp->next; } return (*this); } /* * Add some bytes to the queue */ void SecureQueue::write(const byte input[], size_t length) { if(!head) head = tail = new SecureQueueNode; while(length) { const size_t n = tail->write(input, length); input += n; length -= n; if(length) { tail->next = new SecureQueueNode; tail = tail->next; } } } /* * Read some bytes from the queue */ size_t SecureQueue::read(byte output[], size_t length) { size_t got = 0; while(length && head) { const size_t n = head->read(output, length); output += n; got += n; length -= n; if(head->size() == 0) { SecureQueueNode* holder = head->next; delete head; head = holder; } } return got; } /* * Read data, but do not remove it from queue */ size_t SecureQueue::peek(byte output[], size_t length, size_t offset) const { SecureQueueNode* current = head; while(offset && current) { if(offset >= current->size()) { offset -= current->size(); current = current->next; } else break; } size_t got = 0; while(length && current) { const size_t n = current->peek(output, length, offset); offset = 0; output += n; got += n; length -= n; current = current->next; } return got; } /* * Return how many bytes the queue holds */ size_t SecureQueue::size() const { SecureQueueNode* current = head; size_t count = 0; while(current) { count += current->size(); current = current->next; } return count; } /* * Test if the queue has any data in it */ bool SecureQueue::end_of_data() const { return (size() == 0); } } /* * Blue Midnight Wish 512 (Round 2 tweaked) * (C) 2009 Jack Lloyd * * Distributed under the terms of the Botan license */ 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 size_t EXPAND_1_ROUNDS = 2; for(size_t 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(size_t 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) + (0x0555555555555555ULL * i)) ^ H[(i-16+7)%16]); } for(size_t 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)) + (0x0555555555555555ULL * 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[], size_t blocks) { for(size_t i = 0; i != blocks; ++i) { load_le(&M[0], input, M.size()); BMW_512_compress(&H[0], &M[0], &Q[0]); input += hash_block_size(); } } /* * Copy out the digest */ void BMW_512::copy_out(byte output[]) { u64bit final[16] = { 0xAAAAAAAAAAAAAAA0ULL, 0xAAAAAAAAAAAAAAA1ULL, 0xAAAAAAAAAAAAAAA2ULL, 0xAAAAAAAAAAAAAAA3ULL, 0xAAAAAAAAAAAAAAA4ULL, 0xAAAAAAAAAAAAAAA5ULL, 0xAAAAAAAAAAAAAAA6ULL, 0xAAAAAAAAAAAAAAA7ULL, 0xAAAAAAAAAAAAAAA8ULL, 0xAAAAAAAAAAAAAAA9ULL, 0xAAAAAAAAAAAAAAAAULL, 0xAAAAAAAAAAAAAAABULL, 0xAAAAAAAAAAAAAAACULL, 0xAAAAAAAAAAAAAAADULL, 0xAAAAAAAAAAAAAAAEULL, 0xAAAAAAAAAAAAAAAFULL }; BMW_512_compress(final, &H[0], &Q[0]); for(size_t i = 0; i != output_length(); i += 8) store_le(final[8 + i/8], output + i); } /* * Clear memory of sensitive data */ void BMW_512::clear() { MDx_HashFunction::clear(); zeroise(M); zeroise(Q); H[ 0] = 0x8081828384858687ULL; H[ 1] = 0x88898A8B8C8D8E8FULL; H[ 2] = 0x9091929394959697ULL; H[ 3] = 0x98999A9B9C9D9E9FULL; H[ 4] = 0xA0A1A2A3A4A5A6A7ULL; H[ 5] = 0xA8A9AAABACADAEAFULL; H[ 6] = 0xB0B1B2B3B4B5B6B7ULL; H[ 7] = 0xB8B9BABBBCBDBEBFULL; H[ 8] = 0xC0C1C2C3C4C5C6C7ULL; H[ 9] = 0xC8C9CACBCCCDCECFULL; H[10] = 0xD0D1D2D3D4D5D6D7ULL; H[11] = 0xD8D9DADBDCDDDEDFULL; H[12] = 0xE0E1E2E3E4E5E6E7ULL; H[13] = 0xE8E9EAEBECEDEEEFULL; H[14] = 0xF0F1F2F3F4F5F6F7ULL; H[15] = 0xF8F9FAFBFCFDFEFFULL; } } /* * Comb4P hash combiner * (C) 2010 Jack Lloyd * * Distributed under the terms of the Botan license */ #include namespace Botan { namespace { void comb4p_round(MemoryRegion& out, const MemoryRegion& in, byte round_no, HashFunction* h1, HashFunction* h2) { h1->update(round_no); h2->update(round_no); h1->update(&in[0], in.size()); h2->update(&in[0], in.size()); SecureVector h_buf = h1->final(); xor_buf(&out[0], &h_buf[0], std::min(out.size(), h_buf.size())); h_buf = h2->final(); xor_buf(&out[0], &h_buf[0], std::min(out.size(), h_buf.size())); } } Comb4P::Comb4P(HashFunction* h1, HashFunction* h2) : hash1(h1), hash2(h2) { if(hash1->name() == hash2->name()) throw std::invalid_argument("Comb4P: Must use two distinct hashes"); if(hash1->output_length() != hash2->output_length()) throw std::invalid_argument("Comb4P: Incompatible hashes " + hash1->name() + " and " + hash2->name()); clear(); } size_t Comb4P::hash_block_size() const { if(hash1->hash_block_size() == hash2->hash_block_size()) return hash1->hash_block_size(); /* * Return LCM of the block sizes? This would probably be OK for * HMAC, which is the main thing relying on knowing the block size. */ return 0; } void Comb4P::clear() { hash1->clear(); hash2->clear(); // Prep for processing next message, if any hash1->update(0); hash2->update(0); } void Comb4P::add_data(const byte input[], size_t length) { hash1->update(input, length); hash2->update(input, length); } void Comb4P::final_result(byte out[]) { SecureVector h1 = hash1->final(); SecureVector h2 = hash2->final(); // First round xor_buf(&h1[0], &h2[0], std::min(h1.size(), h2.size())); // Second round comb4p_round(h2, h1, 1, hash1, hash2); // Third round comb4p_round(h1, h2, 2, hash1, hash2); copy_mem(out , &h1[0], h1.size()); copy_mem(out + h1.size(), &h2[0], h2.size()); // Prep for processing next message, if any hash1->update(0); hash2->update(0); } } /* * GOST 34.11 * (C) 2009 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { /** * GOST 34.11 Constructor */ GOST_34_11::GOST_34_11() : cipher(GOST_28147_89_Params("R3411_CryptoPro")), buffer(32), sum(32), hash(32) { count = 0; position = 0; } void GOST_34_11::clear() { cipher.clear(); zeroise(sum); zeroise(hash); count = 0; position = 0; } /** * Hash additional inputs */ void GOST_34_11::add_data(const byte input[], size_t length) { count += length; if(position) { buffer.copy(position, input, length); if(position + length >= hash_block_size()) { compress_n(&buffer[0], 1); input += (hash_block_size() - position); length -= (hash_block_size() - position); position = 0; } } const size_t full_blocks = length / hash_block_size(); const size_t remaining = length % hash_block_size(); if(full_blocks) compress_n(input, full_blocks); buffer.copy(position, input + full_blocks * hash_block_size(), remaining); position += remaining; } /** * The GOST 34.11 compression function */ void GOST_34_11::compress_n(const byte input[], size_t blocks) { for(size_t i = 0; i != blocks; ++i) { for(u16bit j = 0, carry = 0; j != 32; ++j) { u16bit s = sum[j] + input[32*i+j] + carry; carry = get_byte(0, s); sum[j] = get_byte(1, s); } byte S[32] = { 0 }; u64bit U[4], V[4]; load_be(U, &hash[0], 4); load_be(V, input + 32*i, 4); for(size_t j = 0; j != 4; ++j) { byte key[32] = { 0 }; // P transformation for(size_t k = 0; k != 4; ++k) for(size_t l = 0; l != 8; ++l) key[4*l+k] = get_byte(l, U[k]) ^ get_byte(l, V[k]); cipher.set_key(key, 32); cipher.encrypt(&hash[8*j], S + 8*j); if(j == 3) break; // A(x) u64bit A_U = U[0]; U[0] = U[1]; U[1] = U[2]; U[2] = U[3]; U[3] = U[0] ^ A_U; if(j == 1) // C_3 { U[0] ^= 0x00FF00FF00FF00FFULL; U[1] ^= 0xFF00FF00FF00FF00ULL; U[2] ^= 0x00FFFF00FF0000FFULL; U[3] ^= 0xFF000000FFFF00FFULL; } // A(A(x)) u64bit AA_V_1 = V[0] ^ V[1]; u64bit AA_V_2 = V[1] ^ V[2]; V[0] = V[2]; V[1] = V[3]; V[2] = AA_V_1; V[3] = AA_V_2; } byte S2[32] = { 0 }; // 12 rounds of psi S2[ 0] = S[24]; S2[ 1] = S[25]; S2[ 2] = S[26]; S2[ 3] = S[27]; S2[ 4] = S[28]; S2[ 5] = S[29]; S2[ 6] = S[30]; S2[ 7] = S[31]; S2[ 8] = S[ 0] ^ S[ 2] ^ S[ 4] ^ S[ 6] ^ S[24] ^ S[30]; S2[ 9] = S[ 1] ^ S[ 3] ^ S[ 5] ^ S[ 7] ^ S[25] ^ S[31]; S2[10] = S[ 0] ^ S[ 8] ^ S[24] ^ S[26] ^ S[30]; S2[11] = S[ 1] ^ S[ 9] ^ S[25] ^ S[27] ^ S[31]; S2[12] = S[ 0] ^ S[ 4] ^ S[ 6] ^ S[10] ^ S[24] ^ S[26] ^ S[28] ^ S[30]; S2[13] = S[ 1] ^ S[ 5] ^ S[ 7] ^ S[11] ^ S[25] ^ S[27] ^ S[29] ^ S[31]; S2[14] = S[ 0] ^ S[ 4] ^ S[ 8] ^ S[12] ^ S[24] ^ S[26] ^ S[28]; S2[15] = S[ 1] ^ S[ 5] ^ S[ 9] ^ S[13] ^ S[25] ^ S[27] ^ S[29]; S2[16] = S[ 2] ^ S[ 6] ^ S[10] ^ S[14] ^ S[26] ^ S[28] ^ S[30]; S2[17] = S[ 3] ^ S[ 7] ^ S[11] ^ S[15] ^ S[27] ^ S[29] ^ S[31]; S2[18] = S[ 0] ^ S[ 2] ^ S[ 6] ^ S[ 8] ^ S[12] ^ S[16] ^ S[24] ^ S[28]; S2[19] = S[ 1] ^ S[ 3] ^ S[ 7] ^ S[ 9] ^ S[13] ^ S[17] ^ S[25] ^ S[29]; S2[20] = S[ 2] ^ S[ 4] ^ S[ 8] ^ S[10] ^ S[14] ^ S[18] ^ S[26] ^ S[30]; S2[21] = S[ 3] ^ S[ 5] ^ S[ 9] ^ S[11] ^ S[15] ^ S[19] ^ S[27] ^ S[31]; S2[22] = S[ 0] ^ S[ 2] ^ S[10] ^ S[12] ^ S[16] ^ S[20] ^ S[24] ^ S[28] ^ S[30]; S2[23] = S[ 1] ^ S[ 3] ^ S[11] ^ S[13] ^ S[17] ^ S[21] ^ S[25] ^ S[29] ^ S[31]; S2[24] = S[ 0] ^ S[ 6] ^ S[12] ^ S[14] ^ S[18] ^ S[22] ^ S[24] ^ S[26]; S2[25] = S[ 1] ^ S[ 7] ^ S[13] ^ S[15] ^ S[19] ^ S[23] ^ S[25] ^ S[27]; S2[26] = S[ 2] ^ S[ 8] ^ S[14] ^ S[16] ^ S[20] ^ S[24] ^ S[26] ^ S[28]; S2[27] = S[ 3] ^ S[ 9] ^ S[15] ^ S[17] ^ S[21] ^ S[25] ^ S[27] ^ S[29]; S2[28] = S[ 4] ^ S[10] ^ S[16] ^ S[18] ^ S[22] ^ S[26] ^ S[28] ^ S[30]; S2[29] = S[ 5] ^ S[11] ^ S[17] ^ S[19] ^ S[23] ^ S[27] ^ S[29] ^ S[31]; S2[30] = S[ 0] ^ S[ 2] ^ S[ 4] ^ S[12] ^ S[18] ^ S[20] ^ S[28]; S2[31] = S[ 1] ^ S[ 3] ^ S[ 5] ^ S[13] ^ S[19] ^ S[21] ^ S[29]; xor_buf(S, S2, input + 32*i, 32); S2[0] = S[0] ^ S[2] ^ S[4] ^ S[6] ^ S[24] ^ S[30]; S2[1] = S[1] ^ S[3] ^ S[5] ^ S[7] ^ S[25] ^ S[31]; copy_mem(S, S+2, 30); S[30] = S2[0]; S[31] = S2[1]; xor_buf(S, &hash[0], 32); // 61 rounds of psi S2[ 0] = S[ 2] ^ S[ 6] ^ S[14] ^ S[20] ^ S[22] ^ S[26] ^ S[28] ^ S[30]; S2[ 1] = S[ 3] ^ S[ 7] ^ S[15] ^ S[21] ^ S[23] ^ S[27] ^ S[29] ^ S[31]; S2[ 2] = S[ 0] ^ S[ 2] ^ S[ 6] ^ S[ 8] ^ S[16] ^ S[22] ^ S[28]; S2[ 3] = S[ 1] ^ S[ 3] ^ S[ 7] ^ S[ 9] ^ S[17] ^ S[23] ^ S[29]; S2[ 4] = S[ 2] ^ S[ 4] ^ S[ 8] ^ S[10] ^ S[18] ^ S[24] ^ S[30]; S2[ 5] = S[ 3] ^ S[ 5] ^ S[ 9] ^ S[11] ^ S[19] ^ S[25] ^ S[31]; S2[ 6] = S[ 0] ^ S[ 2] ^ S[10] ^ S[12] ^ S[20] ^ S[24] ^ S[26] ^ S[30]; S2[ 7] = S[ 1] ^ S[ 3] ^ S[11] ^ S[13] ^ S[21] ^ S[25] ^ S[27] ^ S[31]; S2[ 8] = S[ 0] ^ S[ 6] ^ S[12] ^ S[14] ^ S[22] ^ S[24] ^ S[26] ^ S[28] ^ S[30]; S2[ 9] = S[ 1] ^ S[ 7] ^ S[13] ^ S[15] ^ S[23] ^ S[25] ^ S[27] ^ S[29] ^ S[31]; S2[10] = S[ 0] ^ S[ 4] ^ S[ 6] ^ S[ 8] ^ S[14] ^ S[16] ^ S[26] ^ S[28]; S2[11] = S[ 1] ^ S[ 5] ^ S[ 7] ^ S[ 9] ^ S[15] ^ S[17] ^ S[27] ^ S[29]; S2[12] = S[ 2] ^ S[ 6] ^ S[ 8] ^ S[10] ^ S[16] ^ S[18] ^ S[28] ^ S[30]; S2[13] = S[ 3] ^ S[ 7] ^ S[ 9] ^ S[11] ^ S[17] ^ S[19] ^ S[29] ^ S[31]; S2[14] = S[ 0] ^ S[ 2] ^ S[ 6] ^ S[ 8] ^ S[10] ^ S[12] ^ S[18] ^ S[20] ^ S[24]; S2[15] = S[ 1] ^ S[ 3] ^ S[ 7] ^ S[ 9] ^ S[11] ^ S[13] ^ S[19] ^ S[21] ^ S[25]; S2[16] = S[ 2] ^ S[ 4] ^ S[ 8] ^ S[10] ^ S[12] ^ S[14] ^ S[20] ^ S[22] ^ S[26]; S2[17] = S[ 3] ^ S[ 5] ^ S[ 9] ^ S[11] ^ S[13] ^ S[15] ^ S[21] ^ S[23] ^ S[27]; S2[18] = S[ 4] ^ S[ 6] ^ S[10] ^ S[12] ^ S[14] ^ S[16] ^ S[22] ^ S[24] ^ S[28]; S2[19] = S[ 5] ^ S[ 7] ^ S[11] ^ S[13] ^ S[15] ^ S[17] ^ S[23] ^ S[25] ^ S[29]; S2[20] = S[ 6] ^ S[ 8] ^ S[12] ^ S[14] ^ S[16] ^ S[18] ^ S[24] ^ S[26] ^ S[30]; S2[21] = S[ 7] ^ S[ 9] ^ S[13] ^ S[15] ^ S[17] ^ S[19] ^ S[25] ^ S[27] ^ S[31]; S2[22] = S[ 0] ^ S[ 2] ^ S[ 4] ^ S[ 6] ^ S[ 8] ^ S[10] ^ S[14] ^ S[16] ^ S[18] ^ S[20] ^ S[24] ^ S[26] ^ S[28] ^ S[30]; S2[23] = S[ 1] ^ S[ 3] ^ S[ 5] ^ S[ 7] ^ S[ 9] ^ S[11] ^ S[15] ^ S[17] ^ S[19] ^ S[21] ^ S[25] ^ S[27] ^ S[29] ^ S[31]; S2[24] = S[ 0] ^ S[ 8] ^ S[10] ^ S[12] ^ S[16] ^ S[18] ^ S[20] ^ S[22] ^ S[24] ^ S[26] ^ S[28]; S2[25] = S[ 1] ^ S[ 9] ^ S[11] ^ S[13] ^ S[17] ^ S[19] ^ S[21] ^ S[23] ^ S[25] ^ S[27] ^ S[29]; S2[26] = S[ 2] ^ S[10] ^ S[12] ^ S[14] ^ S[18] ^ S[20] ^ S[22] ^ S[24] ^ S[26] ^ S[28] ^ S[30]; S2[27] = S[ 3] ^ S[11] ^ S[13] ^ S[15] ^ S[19] ^ S[21] ^ S[23] ^ S[25] ^ S[27] ^ S[29] ^ S[31]; S2[28] = S[ 0] ^ S[ 2] ^ S[ 6] ^ S[12] ^ S[14] ^ S[16] ^ S[20] ^ S[22] ^ S[26] ^ S[28]; S2[29] = S[ 1] ^ S[ 3] ^ S[ 7] ^ S[13] ^ S[15] ^ S[17] ^ S[21] ^ S[23] ^ S[27] ^ S[29]; S2[30] = S[ 2] ^ S[ 4] ^ S[ 8] ^ S[14] ^ S[16] ^ S[18] ^ S[22] ^ S[24] ^ S[28] ^ S[30]; S2[31] = S[ 3] ^ S[ 5] ^ S[ 9] ^ S[15] ^ S[17] ^ S[19] ^ S[23] ^ S[25] ^ S[29] ^ S[31]; hash.copy(S2, 32); } } /** * Produce the final GOST 34.11 output */ void GOST_34_11::final_result(byte out[]) { if(position) { clear_mem(&buffer[0] + position, buffer.size() - position); compress_n(&buffer[0], 1); } SecureVector length_buf(32); const u64bit bit_count = count * 8; store_le(bit_count, &length_buf[0]); SecureVector sum_buf = sum; compress_n(&length_buf[0], 1); compress_n(&sum_buf[0], 1); copy_mem(out, &hash[0], 32); clear(); } } /* * HAS-160 * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { namespace HAS_160_F { /* * HAS-160 F1 Function */ inline void F1(u32bit A, u32bit& B, u32bit C, u32bit D, u32bit& E, u32bit msg, u32bit rot) { E += rotate_left(A, rot) + (D ^ (B & (C ^ D))) + msg; B = rotate_left(B, 10); } /* * HAS-160 F2 Function */ inline void F2(u32bit A, u32bit& B, u32bit C, u32bit D, u32bit& E, u32bit msg, u32bit rot) { E += rotate_left(A, rot) + (B ^ C ^ D) + msg + 0x5A827999; B = rotate_left(B, 17); } /* * HAS-160 F3 Function */ inline void F3(u32bit A, u32bit& B, u32bit C, u32bit D, u32bit& E, u32bit msg, u32bit rot) { E += rotate_left(A, rot) + (C ^ (B | ~D)) + msg + 0x6ED9EBA1; B = rotate_left(B, 25); } /* * HAS-160 F4 Function */ inline void F4(u32bit A, u32bit& B, u32bit C, u32bit D, u32bit& E, u32bit msg, u32bit rot) { E += rotate_left(A, rot) + (B ^ C ^ D) + msg + 0x8F1BBCDC; B = rotate_left(B, 30); } } /* * HAS-160 Compression Function */ void HAS_160::compress_n(const byte input[], size_t blocks) { using namespace HAS_160_F; u32bit A = digest[0], B = digest[1], C = digest[2], D = digest[3], E = digest[4]; for(size_t i = 0; i != blocks; ++i) { load_le(&X[0], input, 16); X[16] = X[ 0] ^ X[ 1] ^ X[ 2] ^ X[ 3]; X[17] = X[ 4] ^ X[ 5] ^ X[ 6] ^ X[ 7]; X[18] = X[ 8] ^ X[ 9] ^ X[10] ^ X[11]; X[19] = X[12] ^ X[13] ^ X[14] ^ X[15]; F1(A,B,C,D,E,X[18], 5); F1(E,A,B,C,D,X[ 0],11); F1(D,E,A,B,C,X[ 1], 7); F1(C,D,E,A,B,X[ 2],15); F1(B,C,D,E,A,X[ 3], 6); F1(A,B,C,D,E,X[19],13); F1(E,A,B,C,D,X[ 4], 8); F1(D,E,A,B,C,X[ 5],14); F1(C,D,E,A,B,X[ 6], 7); F1(B,C,D,E,A,X[ 7],12); F1(A,B,C,D,E,X[16], 9); F1(E,A,B,C,D,X[ 8],11); F1(D,E,A,B,C,X[ 9], 8); F1(C,D,E,A,B,X[10],15); F1(B,C,D,E,A,X[11], 6); F1(A,B,C,D,E,X[17],12); F1(E,A,B,C,D,X[12], 9); F1(D,E,A,B,C,X[13],14); F1(C,D,E,A,B,X[14], 5); F1(B,C,D,E,A,X[15],13); X[16] = X[ 3] ^ X[ 6] ^ X[ 9] ^ X[12]; X[17] = X[ 2] ^ X[ 5] ^ X[ 8] ^ X[15]; X[18] = X[ 1] ^ X[ 4] ^ X[11] ^ X[14]; X[19] = X[ 0] ^ X[ 7] ^ X[10] ^ X[13]; F2(A,B,C,D,E,X[18], 5); F2(E,A,B,C,D,X[ 3],11); F2(D,E,A,B,C,X[ 6], 7); F2(C,D,E,A,B,X[ 9],15); F2(B,C,D,E,A,X[12], 6); F2(A,B,C,D,E,X[19],13); F2(E,A,B,C,D,X[15], 8); F2(D,E,A,B,C,X[ 2],14); F2(C,D,E,A,B,X[ 5], 7); F2(B,C,D,E,A,X[ 8],12); F2(A,B,C,D,E,X[16], 9); F2(E,A,B,C,D,X[11],11); F2(D,E,A,B,C,X[14], 8); F2(C,D,E,A,B,X[ 1],15); F2(B,C,D,E,A,X[ 4], 6); F2(A,B,C,D,E,X[17],12); F2(E,A,B,C,D,X[ 7], 9); F2(D,E,A,B,C,X[10],14); F2(C,D,E,A,B,X[13], 5); F2(B,C,D,E,A,X[ 0],13); X[16] = X[ 5] ^ X[ 7] ^ X[12] ^ X[14]; X[17] = X[ 0] ^ X[ 2] ^ X[ 9] ^ X[11]; X[18] = X[ 4] ^ X[ 6] ^ X[13] ^ X[15]; X[19] = X[ 1] ^ X[ 3] ^ X[ 8] ^ X[10]; F3(A,B,C,D,E,X[18], 5); F3(E,A,B,C,D,X[12],11); F3(D,E,A,B,C,X[ 5], 7); F3(C,D,E,A,B,X[14],15); F3(B,C,D,E,A,X[ 7], 6); F3(A,B,C,D,E,X[19],13); F3(E,A,B,C,D,X[ 0], 8); F3(D,E,A,B,C,X[ 9],14); F3(C,D,E,A,B,X[ 2], 7); F3(B,C,D,E,A,X[11],12); F3(A,B,C,D,E,X[16], 9); F3(E,A,B,C,D,X[ 4],11); F3(D,E,A,B,C,X[13], 8); F3(C,D,E,A,B,X[ 6],15); F3(B,C,D,E,A,X[15], 6); F3(A,B,C,D,E,X[17],12); F3(E,A,B,C,D,X[ 8], 9); F3(D,E,A,B,C,X[ 1],14); F3(C,D,E,A,B,X[10], 5); F3(B,C,D,E,A,X[ 3],13); X[16] = X[ 2] ^ X[ 7] ^ X[ 8] ^ X[13]; X[17] = X[ 3] ^ X[ 4] ^ X[ 9] ^ X[14]; X[18] = X[ 0] ^ X[ 5] ^ X[10] ^ X[15]; X[19] = X[ 1] ^ X[ 6] ^ X[11] ^ X[12]; F4(A,B,C,D,E,X[18], 5); F4(E,A,B,C,D,X[ 7],11); F4(D,E,A,B,C,X[ 2], 7); F4(C,D,E,A,B,X[13],15); F4(B,C,D,E,A,X[ 8], 6); F4(A,B,C,D,E,X[19],13); F4(E,A,B,C,D,X[ 3], 8); F4(D,E,A,B,C,X[14],14); F4(C,D,E,A,B,X[ 9], 7); F4(B,C,D,E,A,X[ 4],12); F4(A,B,C,D,E,X[16], 9); F4(E,A,B,C,D,X[15],11); F4(D,E,A,B,C,X[10], 8); F4(C,D,E,A,B,X[ 5],15); F4(B,C,D,E,A,X[ 0], 6); F4(A,B,C,D,E,X[17],12); F4(E,A,B,C,D,X[11], 9); F4(D,E,A,B,C,X[ 6],14); F4(C,D,E,A,B,X[ 1], 5); F4(B,C,D,E,A,X[12],13); A = (digest[0] += A); B = (digest[1] += B); C = (digest[2] += C); D = (digest[3] += D); E = (digest[4] += E); input += hash_block_size(); } } /* * Copy out the digest */ void HAS_160::copy_out(byte output[]) { for(size_t i = 0; i != output_length(); i += 4) store_le(digest[i/4], output + i); } /* * Clear memory of sensitive data */ void HAS_160::clear() { MDx_HashFunction::clear(); zeroise(X); digest[0] = 0x67452301; digest[1] = 0xEFCDAB89; digest[2] = 0x98BADCFE; digest[3] = 0x10325476; digest[4] = 0xC3D2E1F0; } } /* * Keccak * (C) 2010 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { namespace { void keccak_f_1600(u64bit A[25]) { static const u64bit RC[24] = { 0x0000000000000001ULL, 0x0000000000008082ULL, 0x800000000000808AULL, 0x8000000080008000ULL, 0x000000000000808BULL, 0x0000000080000001ULL, 0x8000000080008081ULL, 0x8000000000008009ULL, 0x000000000000008AULL, 0x0000000000000088ULL, 0x0000000080008009ULL, 0x000000008000000AULL, 0x000000008000808BULL, 0x800000000000008BULL, 0x8000000000008089ULL, 0x8000000000008003ULL, 0x8000000000008002ULL, 0x8000000000000080ULL, 0x000000000000800AULL, 0x800000008000000AULL, 0x8000000080008081ULL, 0x8000000000008080ULL, 0x0000000080000001ULL, 0x8000000080008008ULL }; for(size_t i = 0; i != 24; ++i) { const u64bit C0 = A[0] ^ A[5] ^ A[10] ^ A[15] ^ A[20]; const u64bit C1 = A[1] ^ A[6] ^ A[11] ^ A[16] ^ A[21]; const u64bit C2 = A[2] ^ A[7] ^ A[12] ^ A[17] ^ A[22]; const u64bit C3 = A[3] ^ A[8] ^ A[13] ^ A[18] ^ A[23]; const u64bit C4 = A[4] ^ A[9] ^ A[14] ^ A[19] ^ A[24]; const u64bit D0 = rotate_left(C0, 1) ^ C3; const u64bit D1 = rotate_left(C1, 1) ^ C4; const u64bit D2 = rotate_left(C2, 1) ^ C0; const u64bit D3 = rotate_left(C3, 1) ^ C1; const u64bit D4 = rotate_left(C4, 1) ^ C2; const u64bit B00 = A[ 0] ^ D1; const u64bit B01 = rotate_left(A[ 6] ^ D2, 44); const u64bit B02 = rotate_left(A[12] ^ D3, 43); const u64bit B03 = rotate_left(A[18] ^ D4, 21); const u64bit B04 = rotate_left(A[24] ^ D0, 14); const u64bit B05 = rotate_left(A[ 3] ^ D4, 28); const u64bit B06 = rotate_left(A[ 9] ^ D0, 20); const u64bit B07 = rotate_left(A[10] ^ D1, 3); const u64bit B08 = rotate_left(A[16] ^ D2, 45); const u64bit B09 = rotate_left(A[22] ^ D3, 61); const u64bit B10 = rotate_left(A[ 1] ^ D2, 1); const u64bit B11 = rotate_left(A[ 7] ^ D3, 6); const u64bit B12 = rotate_left(A[13] ^ D4, 25); const u64bit B13 = rotate_left(A[19] ^ D0, 8); const u64bit B14 = rotate_left(A[20] ^ D1, 18); const u64bit B15 = rotate_left(A[ 4] ^ D0, 27); const u64bit B16 = rotate_left(A[ 5] ^ D1, 36); const u64bit B17 = rotate_left(A[11] ^ D2, 10); const u64bit B18 = rotate_left(A[17] ^ D3, 15); const u64bit B19 = rotate_left(A[23] ^ D4, 56); const u64bit B20 = rotate_left(A[ 2] ^ D3, 62); const u64bit B21 = rotate_left(A[ 8] ^ D4, 55); const u64bit B22 = rotate_left(A[14] ^ D0, 39); const u64bit B23 = rotate_left(A[15] ^ D1, 41); const u64bit B24 = rotate_left(A[21] ^ D2, 2); A[ 0] = B00 ^ (~B01 & B02); A[ 1] = B01 ^ (~B02 & B03); A[ 2] = B02 ^ (~B03 & B04); A[ 3] = B03 ^ (~B04 & B00); A[ 4] = B04 ^ (~B00 & B01); A[ 5] = B05 ^ (~B06 & B07); A[ 6] = B06 ^ (~B07 & B08); A[ 7] = B07 ^ (~B08 & B09); A[ 8] = B08 ^ (~B09 & B05); A[ 9] = B09 ^ (~B05 & B06); A[10] = B10 ^ (~B11 & B12); A[11] = B11 ^ (~B12 & B13); A[12] = B12 ^ (~B13 & B14); A[13] = B13 ^ (~B14 & B10); A[14] = B14 ^ (~B10 & B11); A[15] = B15 ^ (~B16 & B17); A[16] = B16 ^ (~B17 & B18); A[17] = B17 ^ (~B18 & B19); A[18] = B18 ^ (~B19 & B15); A[19] = B19 ^ (~B15 & B16); A[20] = B20 ^ (~B21 & B22); A[21] = B21 ^ (~B22 & B23); A[22] = B22 ^ (~B23 & B24); A[23] = B23 ^ (~B24 & B20); A[24] = B24 ^ (~B20 & B21); A[0] ^= RC[i]; } } } Keccak_1600::Keccak_1600(size_t output_bits) : output_bits(output_bits), bitrate(1600 - 2*output_bits), S(25), S_pos(0) { // We only support the parameters for the SHA-3 proposal if(output_bits != 224 && output_bits != 256 && output_bits != 384 && output_bits != 512) throw Invalid_Argument("Keccak_1600: Invalid output length " + to_string(output_bits)); } std::string Keccak_1600::name() const { return "Keccak-1600(" + to_string(output_bits) + ")"; } HashFunction* Keccak_1600::clone() const { return new Keccak_1600(output_bits); } void Keccak_1600::clear() { zeroise(S); S_pos = 0; } void Keccak_1600::add_data(const byte input[], size_t length) { if(length == 0) return; while(length) { size_t to_take = std::min(length, bitrate / 8 - S_pos); length -= to_take; while(to_take && S_pos % 8) { S[S_pos / 8] ^= static_cast(input[0]) << (8 * (S_pos % 8)); ++S_pos; ++input; --to_take; } while(to_take && to_take % 8 == 0) { S[S_pos / 8] ^= load_le(input, 0); S_pos += 8; input += 8; to_take -= 8; } while(to_take) { S[S_pos / 8] ^= static_cast(input[0]) << (8 * (S_pos % 8)); ++S_pos; ++input; --to_take; } if(S_pos == bitrate / 8) { keccak_f_1600(&S[0]); S_pos = 0; } } } void Keccak_1600::final_result(byte output[]) { MemoryVector padding(bitrate / 8 - S_pos); padding[0] = 0x01; padding[padding.size()-1] |= 0x80; add_data(padding, padding.size()); /* * We never have to run the permutation again because we only support * limited output lengths */ for(size_t i = 0; i != output_bits/8; ++i) output[i] = get_byte(7 - (i % 8), S[i/8]); clear(); } } /* * MD2 * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { /** * MD2 Compression Function */ void MD2::hash(const byte input[]) { static const byte SBOX[256] = { 0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36, 0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13, 0x62, 0xA7, 0x05, 0xF3, 0xC0, 0xC7, 0x73, 0x8C, 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C, 0x82, 0xCA, 0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16, 0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12, 0xBE, 0x4E, 0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49, 0xA0, 0xFB, 0xF5, 0x8E, 0xBB, 0x2F, 0xEE, 0x7A, 0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2, 0x07, 0x3F, 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21, 0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27, 0x35, 0x3E, 0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03, 0xFF, 0x19, 0x30, 0xB3, 0x48, 0xA5, 0xB5, 0xD1, 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56, 0xAA, 0xC6, 0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6, 0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1, 0x45, 0x9D, 0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5B, 0xCF, 0x65, 0xE6, 0x2D, 0xA8, 0x02, 0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0, 0xB9, 0xF6, 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F, 0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A, 0xC3, 0x5C, 0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26, 0x2C, 0x53, 0x0D, 0x6E, 0x85, 0x28, 0x84, 0x09, 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81, 0x4D, 0x52, 0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA, 0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A, 0x78, 0x88, 0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D, 0xE9, 0xCB, 0xD5, 0xFE, 0x3B, 0x00, 0x1D, 0x39, 0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58, 0xD0, 0xE4, 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A, 0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, 0xDB, 0x99, 0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14 }; X.copy(16, input, hash_block_size()); xor_buf(&X[32], &X[0], &X[16], hash_block_size()); byte T = 0; for(size_t i = 0; i != 18; ++i) { for(size_t k = 0; k != 48; k += 8) { T = X[k ] ^= SBOX[T]; T = X[k+1] ^= SBOX[T]; T = X[k+2] ^= SBOX[T]; T = X[k+3] ^= SBOX[T]; T = X[k+4] ^= SBOX[T]; T = X[k+5] ^= SBOX[T]; T = X[k+6] ^= SBOX[T]; T = X[k+7] ^= SBOX[T]; } T += static_cast(i); } T = checksum[15]; for(size_t i = 0; i != hash_block_size(); ++i) T = checksum[i] ^= SBOX[input[i] ^ T]; } /** * Update the hash */ void MD2::add_data(const byte input[], size_t length) { buffer.copy(position, input, length); if(position + length >= hash_block_size()) { hash(&buffer[0]); input += (hash_block_size() - position); length -= (hash_block_size() - position); while(length >= hash_block_size()) { hash(input); input += hash_block_size(); length -= hash_block_size(); } buffer.copy(input, length); position = 0; } position += length; } /** * Finalize a MD2 Hash */ void MD2::final_result(byte output[]) { for(size_t i = position; i != hash_block_size(); ++i) buffer[i] = static_cast(hash_block_size() - position); hash(&buffer[0]); hash(&checksum[0]); copy_mem(output, &X[0], output_length()); clear(); } /** * Clear memory of sensitive data */ void MD2::clear() { zeroise(X); zeroise(checksum); zeroise(buffer); position = 0; } } /* * MD4 * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { namespace { /* * MD4 FF Function */ inline void FF(u32bit& A, u32bit B, u32bit C, u32bit D, u32bit M, byte S) { A += (D ^ (B & (C ^ D))) + M; A = rotate_left(A, S); } /* * MD4 GG Function */ inline void GG(u32bit& A, u32bit B, u32bit C, u32bit D, u32bit M, byte S) { A += ((B & C) | (D & (B | C))) + M + 0x5A827999; A = rotate_left(A, S); } /* * MD4 HH Function */ inline void HH(u32bit& A, u32bit B, u32bit C, u32bit D, u32bit M, byte S) { A += (B ^ C ^ D) + M + 0x6ED9EBA1; A = rotate_left(A, S); } } /* * MD4 Compression Function */ void MD4::compress_n(const byte input[], size_t blocks) { u32bit A = digest[0], B = digest[1], C = digest[2], D = digest[3]; for(size_t i = 0; i != blocks; ++i) { load_le(&M[0], input, M.size()); FF(A,B,C,D,M[ 0], 3); FF(D,A,B,C,M[ 1], 7); FF(C,D,A,B,M[ 2],11); FF(B,C,D,A,M[ 3],19); FF(A,B,C,D,M[ 4], 3); FF(D,A,B,C,M[ 5], 7); FF(C,D,A,B,M[ 6],11); FF(B,C,D,A,M[ 7],19); FF(A,B,C,D,M[ 8], 3); FF(D,A,B,C,M[ 9], 7); FF(C,D,A,B,M[10],11); FF(B,C,D,A,M[11],19); FF(A,B,C,D,M[12], 3); FF(D,A,B,C,M[13], 7); FF(C,D,A,B,M[14],11); FF(B,C,D,A,M[15],19); GG(A,B,C,D,M[ 0], 3); GG(D,A,B,C,M[ 4], 5); GG(C,D,A,B,M[ 8], 9); GG(B,C,D,A,M[12],13); GG(A,B,C,D,M[ 1], 3); GG(D,A,B,C,M[ 5], 5); GG(C,D,A,B,M[ 9], 9); GG(B,C,D,A,M[13],13); GG(A,B,C,D,M[ 2], 3); GG(D,A,B,C,M[ 6], 5); GG(C,D,A,B,M[10], 9); GG(B,C,D,A,M[14],13); GG(A,B,C,D,M[ 3], 3); GG(D,A,B,C,M[ 7], 5); GG(C,D,A,B,M[11], 9); GG(B,C,D,A,M[15],13); HH(A,B,C,D,M[ 0], 3); HH(D,A,B,C,M[ 8], 9); HH(C,D,A,B,M[ 4],11); HH(B,C,D,A,M[12],15); HH(A,B,C,D,M[ 2], 3); HH(D,A,B,C,M[10], 9); HH(C,D,A,B,M[ 6],11); HH(B,C,D,A,M[14],15); HH(A,B,C,D,M[ 1], 3); HH(D,A,B,C,M[ 9], 9); HH(C,D,A,B,M[ 5],11); HH(B,C,D,A,M[13],15); HH(A,B,C,D,M[ 3], 3); HH(D,A,B,C,M[11], 9); HH(C,D,A,B,M[ 7],11); HH(B,C,D,A,M[15],15); A = (digest[0] += A); B = (digest[1] += B); C = (digest[2] += C); D = (digest[3] += D); input += hash_block_size(); } } /* * Copy out the digest */ void MD4::copy_out(byte output[]) { for(size_t i = 0; i != output_length(); i += 4) store_le(digest[i/4], output + i); } /* * Clear memory of sensitive data */ void MD4::clear() { MDx_HashFunction::clear(); zeroise(M); digest[0] = 0x67452301; digest[1] = 0xEFCDAB89; digest[2] = 0x98BADCFE; digest[3] = 0x10325476; } } /* * MD5 * (C) 1999-2008 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { namespace { /* * MD5 FF Function */ inline void FF(u32bit& A, u32bit B, u32bit C, u32bit D, u32bit msg, byte S, u32bit magic) { A += (D ^ (B & (C ^ D))) + msg + magic; A = rotate_left(A, S) + B; } /* * MD5 GG Function */ inline void GG(u32bit& A, u32bit B, u32bit C, u32bit D, u32bit msg, byte S, u32bit magic) { A += (C ^ (D & (B ^ C))) + msg + magic; A = rotate_left(A, S) + B; } /* * MD5 HH Function */ inline void HH(u32bit& A, u32bit B, u32bit C, u32bit D, u32bit msg, byte S, u32bit magic) { A += (B ^ C ^ D) + msg + magic; A = rotate_left(A, S) + B; } /* * MD5 II Function */ inline void II(u32bit& A, u32bit B, u32bit C, u32bit D, u32bit msg, byte S, u32bit magic) { A += (C ^ (B | ~D)) + msg + magic; A = rotate_left(A, S) + B; } } /* * MD5 Compression Function */ void MD5::compress_n(const byte input[], size_t blocks) { u32bit A = digest[0], B = digest[1], C = digest[2], D = digest[3]; for(size_t i = 0; i != blocks; ++i) { load_le(&M[0], input, M.size()); FF(A,B,C,D,M[ 0], 7,0xD76AA478); FF(D,A,B,C,M[ 1],12,0xE8C7B756); FF(C,D,A,B,M[ 2],17,0x242070DB); FF(B,C,D,A,M[ 3],22,0xC1BDCEEE); FF(A,B,C,D,M[ 4], 7,0xF57C0FAF); FF(D,A,B,C,M[ 5],12,0x4787C62A); FF(C,D,A,B,M[ 6],17,0xA8304613); FF(B,C,D,A,M[ 7],22,0xFD469501); FF(A,B,C,D,M[ 8], 7,0x698098D8); FF(D,A,B,C,M[ 9],12,0x8B44F7AF); FF(C,D,A,B,M[10],17,0xFFFF5BB1); FF(B,C,D,A,M[11],22,0x895CD7BE); FF(A,B,C,D,M[12], 7,0x6B901122); FF(D,A,B,C,M[13],12,0xFD987193); FF(C,D,A,B,M[14],17,0xA679438E); FF(B,C,D,A,M[15],22,0x49B40821); GG(A,B,C,D,M[ 1], 5,0xF61E2562); GG(D,A,B,C,M[ 6], 9,0xC040B340); GG(C,D,A,B,M[11],14,0x265E5A51); GG(B,C,D,A,M[ 0],20,0xE9B6C7AA); GG(A,B,C,D,M[ 5], 5,0xD62F105D); GG(D,A,B,C,M[10], 9,0x02441453); GG(C,D,A,B,M[15],14,0xD8A1E681); GG(B,C,D,A,M[ 4],20,0xE7D3FBC8); GG(A,B,C,D,M[ 9], 5,0x21E1CDE6); GG(D,A,B,C,M[14], 9,0xC33707D6); GG(C,D,A,B,M[ 3],14,0xF4D50D87); GG(B,C,D,A,M[ 8],20,0x455A14ED); GG(A,B,C,D,M[13], 5,0xA9E3E905); GG(D,A,B,C,M[ 2], 9,0xFCEFA3F8); GG(C,D,A,B,M[ 7],14,0x676F02D9); GG(B,C,D,A,M[12],20,0x8D2A4C8A); HH(A,B,C,D,M[ 5], 4,0xFFFA3942); HH(D,A,B,C,M[ 8],11,0x8771F681); HH(C,D,A,B,M[11],16,0x6D9D6122); HH(B,C,D,A,M[14],23,0xFDE5380C); HH(A,B,C,D,M[ 1], 4,0xA4BEEA44); HH(D,A,B,C,M[ 4],11,0x4BDECFA9); HH(C,D,A,B,M[ 7],16,0xF6BB4B60); HH(B,C,D,A,M[10],23,0xBEBFBC70); HH(A,B,C,D,M[13], 4,0x289B7EC6); HH(D,A,B,C,M[ 0],11,0xEAA127FA); HH(C,D,A,B,M[ 3],16,0xD4EF3085); HH(B,C,D,A,M[ 6],23,0x04881D05); HH(A,B,C,D,M[ 9], 4,0xD9D4D039); HH(D,A,B,C,M[12],11,0xE6DB99E5); HH(C,D,A,B,M[15],16,0x1FA27CF8); HH(B,C,D,A,M[ 2],23,0xC4AC5665); II(A,B,C,D,M[ 0], 6,0xF4292244); II(D,A,B,C,M[ 7],10,0x432AFF97); II(C,D,A,B,M[14],15,0xAB9423A7); II(B,C,D,A,M[ 5],21,0xFC93A039); II(A,B,C,D,M[12], 6,0x655B59C3); II(D,A,B,C,M[ 3],10,0x8F0CCC92); II(C,D,A,B,M[10],15,0xFFEFF47D); II(B,C,D,A,M[ 1],21,0x85845DD1); II(A,B,C,D,M[ 8], 6,0x6FA87E4F); II(D,A,B,C,M[15],10,0xFE2CE6E0); II(C,D,A,B,M[ 6],15,0xA3014314); II(B,C,D,A,M[13],21,0x4E0811A1); II(A,B,C,D,M[ 4], 6,0xF7537E82); II(D,A,B,C,M[11],10,0xBD3AF235); II(C,D,A,B,M[ 2],15,0x2AD7D2BB); II(B,C,D,A,M[ 9],21,0xEB86D391); A = (digest[0] += A); B = (digest[1] += B); C = (digest[2] += C); D = (digest[3] += D); input += hash_block_size(); } } /* * Copy out the digest */ void MD5::copy_out(byte output[]) { for(size_t i = 0; i != output_length(); i += 4) store_le(digest[i/4], output + i); } /* * Clear memory of sensitive data */ void MD5::clear() { MDx_HashFunction::clear(); zeroise(M); digest[0] = 0x67452301; digest[1] = 0xEFCDAB89; digest[2] = 0x98BADCFE; digest[3] = 0x10325476; } } /* * Merkle-Damgard Hash Function * (C) 1999-2008 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { /* * MDx_HashFunction Constructor */ MDx_HashFunction::MDx_HashFunction(size_t block_len, bool byte_end, bool bit_end, size_t cnt_size) : buffer(block_len), BIG_BYTE_ENDIAN(byte_end), BIG_BIT_ENDIAN(bit_end), COUNT_SIZE(cnt_size) { count = position = 0; } /* * Clear memory of sensitive data */ void MDx_HashFunction::clear() { zeroise(buffer); count = position = 0; } /* * Update the hash */ void MDx_HashFunction::add_data(const byte input[], size_t length) { count += length; if(position) { buffer.copy(position, input, length); if(position + length >= buffer.size()) { compress_n(&buffer[0], 1); input += (buffer.size() - position); length -= (buffer.size() - position); position = 0; } } const size_t full_blocks = length / buffer.size(); const size_t remaining = length % buffer.size(); if(full_blocks) compress_n(input, full_blocks); buffer.copy(position, input + full_blocks * buffer.size(), remaining); position += remaining; } /* * Finalize a hash */ void MDx_HashFunction::final_result(byte output[]) { buffer[position] = (BIG_BIT_ENDIAN ? 0x80 : 0x01); for(size_t i = position+1; i != buffer.size(); ++i) buffer[i] = 0; if(position >= buffer.size() - COUNT_SIZE) { compress_n(&buffer[0], 1); zeroise(buffer); } write_count(&buffer[buffer.size() - COUNT_SIZE]); compress_n(&buffer[0], 1); copy_out(output); clear(); } /* * Write the count bits to the buffer */ void MDx_HashFunction::write_count(byte out[]) { if(COUNT_SIZE < 8) throw Invalid_State("MDx_HashFunction::write_count: COUNT_SIZE < 8"); if(COUNT_SIZE >= output_length() || COUNT_SIZE >= hash_block_size()) throw Invalid_Argument("MDx_HashFunction: COUNT_SIZE is too big"); const u64bit bit_count = count * 8; if(BIG_BYTE_ENDIAN) store_be(bit_count, out + COUNT_SIZE - 8); else store_le(bit_count, out + COUNT_SIZE - 8); } } /* * Parallel * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { /* * Update the hash */ void Parallel::add_data(const byte input[], size_t length) { for(size_t i = 0; i != hashes.size(); ++i) hashes[i]->update(input, length); } /* * Finalize the hash */ void Parallel::final_result(byte hash[]) { size_t offset = 0; for(size_t i = 0; i != hashes.size(); ++i) { hashes[i]->final(hash + offset); offset += hashes[i]->output_length(); } } /* * Return output size */ size_t Parallel::output_length() const { size_t sum = 0; for(size_t i = 0; i != hashes.size(); ++i) sum += hashes[i]->output_length(); return sum; } /* * Return the name of this type */ std::string Parallel::name() const { std::string hash_names; for(size_t i = 0; i != hashes.size(); ++i) { if(i) hash_names += ','; hash_names += hashes[i]->name(); } return "Parallel(" + hash_names + ")"; } /* * Return a clone of this object */ HashFunction* Parallel::clone() const { std::vector hash_copies; for(size_t i = 0; i != hashes.size(); ++i) hash_copies.push_back(hashes[i]->clone()); return new Parallel(hash_copies); } /* * Clear memory of sensitive data */ void Parallel::clear() { for(size_t i = 0; i != hashes.size(); ++i) hashes[i]->clear(); } /* * Parallel Constructor */ Parallel::Parallel(const std::vector& hash_in) : hashes(hash_in) { } /* * Parallel Destructor */ Parallel::~Parallel() { for(size_t i = 0; i != hashes.size(); ++i) delete hashes[i]; } } /* * RIPEMD-128 * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { namespace RIPEMD_128_F { /* * RIPEMD-128 F1 Function */ inline void F1(u32bit& A, u32bit B, u32bit C, u32bit D, u32bit msg, u32bit shift) { A += (B ^ C ^ D) + msg; A = rotate_left(A, shift); } /* * RIPEMD-128 F2 Function */ inline void F2(u32bit& A, u32bit B, u32bit C, u32bit D, u32bit msg, u32bit shift, u32bit magic) { A += (D ^ (B & (C ^ D))) + msg + magic; A = rotate_left(A, shift); } /* * RIPEMD-128 F3 Function */ inline void F3(u32bit& A, u32bit B, u32bit C, u32bit D, u32bit msg, u32bit shift, u32bit magic) { A += (D ^ (B | ~C)) + msg + magic; A = rotate_left(A, shift); } /* * RIPEMD-128 F4 Function */ inline void F4(u32bit& A, u32bit B, u32bit C, u32bit D, u32bit msg, u32bit shift, u32bit magic) { A += (C ^ (D & (B ^ C))) + msg + magic; A = rotate_left(A, shift); } } /* * RIPEMD-128 Compression Function */ void RIPEMD_128::compress_n(const byte input[], size_t blocks) { using namespace RIPEMD_128_F; const u32bit MAGIC2 = 0x5A827999, MAGIC3 = 0x6ED9EBA1, MAGIC4 = 0x8F1BBCDC, MAGIC5 = 0x50A28BE6, MAGIC6 = 0x5C4DD124, MAGIC7 = 0x6D703EF3; for(size_t i = 0; i != blocks; ++i) { load_le(&M[0], input, M.size()); u32bit A1 = digest[0], A2 = A1, B1 = digest[1], B2 = B1, C1 = digest[2], C2 = C1, D1 = digest[3], D2 = D1; F1(A1,B1,C1,D1,M[ 0],11 ); F4(A2,B2,C2,D2,M[ 5], 8,MAGIC5); F1(D1,A1,B1,C1,M[ 1],14 ); F4(D2,A2,B2,C2,M[14], 9,MAGIC5); F1(C1,D1,A1,B1,M[ 2],15 ); F4(C2,D2,A2,B2,M[ 7], 9,MAGIC5); F1(B1,C1,D1,A1,M[ 3],12 ); F4(B2,C2,D2,A2,M[ 0],11,MAGIC5); F1(A1,B1,C1,D1,M[ 4], 5 ); F4(A2,B2,C2,D2,M[ 9],13,MAGIC5); F1(D1,A1,B1,C1,M[ 5], 8 ); F4(D2,A2,B2,C2,M[ 2],15,MAGIC5); F1(C1,D1,A1,B1,M[ 6], 7 ); F4(C2,D2,A2,B2,M[11],15,MAGIC5); F1(B1,C1,D1,A1,M[ 7], 9 ); F4(B2,C2,D2,A2,M[ 4], 5,MAGIC5); F1(A1,B1,C1,D1,M[ 8],11 ); F4(A2,B2,C2,D2,M[13], 7,MAGIC5); F1(D1,A1,B1,C1,M[ 9],13 ); F4(D2,A2,B2,C2,M[ 6], 7,MAGIC5); F1(C1,D1,A1,B1,M[10],14 ); F4(C2,D2,A2,B2,M[15], 8,MAGIC5); F1(B1,C1,D1,A1,M[11],15 ); F4(B2,C2,D2,A2,M[ 8],11,MAGIC5); F1(A1,B1,C1,D1,M[12], 6 ); F4(A2,B2,C2,D2,M[ 1],14,MAGIC5); F1(D1,A1,B1,C1,M[13], 7 ); F4(D2,A2,B2,C2,M[10],14,MAGIC5); F1(C1,D1,A1,B1,M[14], 9 ); F4(C2,D2,A2,B2,M[ 3],12,MAGIC5); F1(B1,C1,D1,A1,M[15], 8 ); F4(B2,C2,D2,A2,M[12], 6,MAGIC5); F2(A1,B1,C1,D1,M[ 7], 7,MAGIC2); F3(A2,B2,C2,D2,M[ 6], 9,MAGIC6); F2(D1,A1,B1,C1,M[ 4], 6,MAGIC2); F3(D2,A2,B2,C2,M[11],13,MAGIC6); F2(C1,D1,A1,B1,M[13], 8,MAGIC2); F3(C2,D2,A2,B2,M[ 3],15,MAGIC6); F2(B1,C1,D1,A1,M[ 1],13,MAGIC2); F3(B2,C2,D2,A2,M[ 7], 7,MAGIC6); F2(A1,B1,C1,D1,M[10],11,MAGIC2); F3(A2,B2,C2,D2,M[ 0],12,MAGIC6); F2(D1,A1,B1,C1,M[ 6], 9,MAGIC2); F3(D2,A2,B2,C2,M[13], 8,MAGIC6); F2(C1,D1,A1,B1,M[15], 7,MAGIC2); F3(C2,D2,A2,B2,M[ 5], 9,MAGIC6); F2(B1,C1,D1,A1,M[ 3],15,MAGIC2); F3(B2,C2,D2,A2,M[10],11,MAGIC6); F2(A1,B1,C1,D1,M[12], 7,MAGIC2); F3(A2,B2,C2,D2,M[14], 7,MAGIC6); F2(D1,A1,B1,C1,M[ 0],12,MAGIC2); F3(D2,A2,B2,C2,M[15], 7,MAGIC6); F2(C1,D1,A1,B1,M[ 9],15,MAGIC2); F3(C2,D2,A2,B2,M[ 8],12,MAGIC6); F2(B1,C1,D1,A1,M[ 5], 9,MAGIC2); F3(B2,C2,D2,A2,M[12], 7,MAGIC6); F2(A1,B1,C1,D1,M[ 2],11,MAGIC2); F3(A2,B2,C2,D2,M[ 4], 6,MAGIC6); F2(D1,A1,B1,C1,M[14], 7,MAGIC2); F3(D2,A2,B2,C2,M[ 9],15,MAGIC6); F2(C1,D1,A1,B1,M[11],13,MAGIC2); F3(C2,D2,A2,B2,M[ 1],13,MAGIC6); F2(B1,C1,D1,A1,M[ 8],12,MAGIC2); F3(B2,C2,D2,A2,M[ 2],11,MAGIC6); F3(A1,B1,C1,D1,M[ 3],11,MAGIC3); F2(A2,B2,C2,D2,M[15], 9,MAGIC7); F3(D1,A1,B1,C1,M[10],13,MAGIC3); F2(D2,A2,B2,C2,M[ 5], 7,MAGIC7); F3(C1,D1,A1,B1,M[14], 6,MAGIC3); F2(C2,D2,A2,B2,M[ 1],15,MAGIC7); F3(B1,C1,D1,A1,M[ 4], 7,MAGIC3); F2(B2,C2,D2,A2,M[ 3],11,MAGIC7); F3(A1,B1,C1,D1,M[ 9],14,MAGIC3); F2(A2,B2,C2,D2,M[ 7], 8,MAGIC7); F3(D1,A1,B1,C1,M[15], 9,MAGIC3); F2(D2,A2,B2,C2,M[14], 6,MAGIC7); F3(C1,D1,A1,B1,M[ 8],13,MAGIC3); F2(C2,D2,A2,B2,M[ 6], 6,MAGIC7); F3(B1,C1,D1,A1,M[ 1],15,MAGIC3); F2(B2,C2,D2,A2,M[ 9],14,MAGIC7); F3(A1,B1,C1,D1,M[ 2],14,MAGIC3); F2(A2,B2,C2,D2,M[11],12,MAGIC7); F3(D1,A1,B1,C1,M[ 7], 8,MAGIC3); F2(D2,A2,B2,C2,M[ 8],13,MAGIC7); F3(C1,D1,A1,B1,M[ 0],13,MAGIC3); F2(C2,D2,A2,B2,M[12], 5,MAGIC7); F3(B1,C1,D1,A1,M[ 6], 6,MAGIC3); F2(B2,C2,D2,A2,M[ 2],14,MAGIC7); F3(A1,B1,C1,D1,M[13], 5,MAGIC3); F2(A2,B2,C2,D2,M[10],13,MAGIC7); F3(D1,A1,B1,C1,M[11],12,MAGIC3); F2(D2,A2,B2,C2,M[ 0],13,MAGIC7); F3(C1,D1,A1,B1,M[ 5], 7,MAGIC3); F2(C2,D2,A2,B2,M[ 4], 7,MAGIC7); F3(B1,C1,D1,A1,M[12], 5,MAGIC3); F2(B2,C2,D2,A2,M[13], 5,MAGIC7); F4(A1,B1,C1,D1,M[ 1],11,MAGIC4); F1(A2,B2,C2,D2,M[ 8],15 ); F4(D1,A1,B1,C1,M[ 9],12,MAGIC4); F1(D2,A2,B2,C2,M[ 6], 5 ); F4(C1,D1,A1,B1,M[11],14,MAGIC4); F1(C2,D2,A2,B2,M[ 4], 8 ); F4(B1,C1,D1,A1,M[10],15,MAGIC4); F1(B2,C2,D2,A2,M[ 1],11 ); F4(A1,B1,C1,D1,M[ 0],14,MAGIC4); F1(A2,B2,C2,D2,M[ 3],14 ); F4(D1,A1,B1,C1,M[ 8],15,MAGIC4); F1(D2,A2,B2,C2,M[11],14 ); F4(C1,D1,A1,B1,M[12], 9,MAGIC4); F1(C2,D2,A2,B2,M[15], 6 ); F4(B1,C1,D1,A1,M[ 4], 8,MAGIC4); F1(B2,C2,D2,A2,M[ 0],14 ); F4(A1,B1,C1,D1,M[13], 9,MAGIC4); F1(A2,B2,C2,D2,M[ 5], 6 ); F4(D1,A1,B1,C1,M[ 3],14,MAGIC4); F1(D2,A2,B2,C2,M[12], 9 ); F4(C1,D1,A1,B1,M[ 7], 5,MAGIC4); F1(C2,D2,A2,B2,M[ 2],12 ); F4(B1,C1,D1,A1,M[15], 6,MAGIC4); F1(B2,C2,D2,A2,M[13], 9 ); F4(A1,B1,C1,D1,M[14], 8,MAGIC4); F1(A2,B2,C2,D2,M[ 9],12 ); F4(D1,A1,B1,C1,M[ 5], 6,MAGIC4); F1(D2,A2,B2,C2,M[ 7], 5 ); F4(C1,D1,A1,B1,M[ 6], 5,MAGIC4); F1(C2,D2,A2,B2,M[10],15 ); F4(B1,C1,D1,A1,M[ 2],12,MAGIC4); F1(B2,C2,D2,A2,M[14], 8 ); D2 = digest[1] + C1 + D2; digest[1] = digest[2] + D1 + A2; digest[2] = digest[3] + A1 + B2; digest[3] = digest[0] + B1 + C2; digest[0] = D2; input += hash_block_size(); } } /* * Copy out the digest */ void RIPEMD_128::copy_out(byte output[]) { for(size_t i = 0; i != output_length(); i += 4) store_le(digest[i/4], output + i); } /* * Clear memory of sensitive data */ void RIPEMD_128::clear() { MDx_HashFunction::clear(); zeroise(M); digest[0] = 0x67452301; digest[1] = 0xEFCDAB89; digest[2] = 0x98BADCFE; digest[3] = 0x10325476; } } /* * RIPEMD-160 * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { namespace { /* * RIPEMD-160 F1 Function */ inline void F1(u32bit& A, u32bit B, u32bit& C, u32bit D, u32bit E, u32bit msg, u32bit shift) { A += (B ^ C ^ D) + msg; A = rotate_left(A, shift) + E; C = rotate_left(C, 10); } /* * RIPEMD-160 F2 Function */ inline void F2(u32bit& A, u32bit B, u32bit& C, u32bit D, u32bit E, u32bit msg, u32bit shift, u32bit magic) { A += (D ^ (B & (C ^ D))) + msg + magic; A = rotate_left(A, shift) + E; C = rotate_left(C, 10); } /* * RIPEMD-160 F3 Function */ inline void F3(u32bit& A, u32bit B, u32bit& C, u32bit D, u32bit E, u32bit msg, u32bit shift, u32bit magic) { A += (D ^ (B | ~C)) + msg + magic; A = rotate_left(A, shift) + E; C = rotate_left(C, 10); } /* * RIPEMD-160 F4 Function */ inline void F4(u32bit& A, u32bit B, u32bit& C, u32bit D, u32bit E, u32bit msg, u32bit shift, u32bit magic) { A += (C ^ (D & (B ^ C))) + msg + magic; A = rotate_left(A, shift) + E; C = rotate_left(C, 10); } /* * RIPEMD-160 F5 Function */ inline void F5(u32bit& A, u32bit B, u32bit& C, u32bit D, u32bit E, u32bit msg, u32bit shift, u32bit magic) { A += (B ^ (C | ~D)) + msg + magic; A = rotate_left(A, shift) + E; C = rotate_left(C, 10); } } /* * RIPEMD-160 Compression Function */ void RIPEMD_160::compress_n(const byte input[], size_t blocks) { const u32bit MAGIC2 = 0x5A827999, MAGIC3 = 0x6ED9EBA1, MAGIC4 = 0x8F1BBCDC, MAGIC5 = 0xA953FD4E, MAGIC6 = 0x50A28BE6, MAGIC7 = 0x5C4DD124, MAGIC8 = 0x6D703EF3, MAGIC9 = 0x7A6D76E9; for(size_t i = 0; i != blocks; ++i) { load_le(&M[0], input, M.size()); u32bit A1 = digest[0], A2 = A1, B1 = digest[1], B2 = B1, C1 = digest[2], C2 = C1, D1 = digest[3], D2 = D1, E1 = digest[4], E2 = E1; F1(A1,B1,C1,D1,E1,M[ 0],11 ); F5(A2,B2,C2,D2,E2,M[ 5], 8,MAGIC6); F1(E1,A1,B1,C1,D1,M[ 1],14 ); F5(E2,A2,B2,C2,D2,M[14], 9,MAGIC6); F1(D1,E1,A1,B1,C1,M[ 2],15 ); F5(D2,E2,A2,B2,C2,M[ 7], 9,MAGIC6); F1(C1,D1,E1,A1,B1,M[ 3],12 ); F5(C2,D2,E2,A2,B2,M[ 0],11,MAGIC6); F1(B1,C1,D1,E1,A1,M[ 4], 5 ); F5(B2,C2,D2,E2,A2,M[ 9],13,MAGIC6); F1(A1,B1,C1,D1,E1,M[ 5], 8 ); F5(A2,B2,C2,D2,E2,M[ 2],15,MAGIC6); F1(E1,A1,B1,C1,D1,M[ 6], 7 ); F5(E2,A2,B2,C2,D2,M[11],15,MAGIC6); F1(D1,E1,A1,B1,C1,M[ 7], 9 ); F5(D2,E2,A2,B2,C2,M[ 4], 5,MAGIC6); F1(C1,D1,E1,A1,B1,M[ 8],11 ); F5(C2,D2,E2,A2,B2,M[13], 7,MAGIC6); F1(B1,C1,D1,E1,A1,M[ 9],13 ); F5(B2,C2,D2,E2,A2,M[ 6], 7,MAGIC6); F1(A1,B1,C1,D1,E1,M[10],14 ); F5(A2,B2,C2,D2,E2,M[15], 8,MAGIC6); F1(E1,A1,B1,C1,D1,M[11],15 ); F5(E2,A2,B2,C2,D2,M[ 8],11,MAGIC6); F1(D1,E1,A1,B1,C1,M[12], 6 ); F5(D2,E2,A2,B2,C2,M[ 1],14,MAGIC6); F1(C1,D1,E1,A1,B1,M[13], 7 ); F5(C2,D2,E2,A2,B2,M[10],14,MAGIC6); F1(B1,C1,D1,E1,A1,M[14], 9 ); F5(B2,C2,D2,E2,A2,M[ 3],12,MAGIC6); F1(A1,B1,C1,D1,E1,M[15], 8 ); F5(A2,B2,C2,D2,E2,M[12], 6,MAGIC6); F2(E1,A1,B1,C1,D1,M[ 7], 7,MAGIC2); F4(E2,A2,B2,C2,D2,M[ 6], 9,MAGIC7); F2(D1,E1,A1,B1,C1,M[ 4], 6,MAGIC2); F4(D2,E2,A2,B2,C2,M[11],13,MAGIC7); F2(C1,D1,E1,A1,B1,M[13], 8,MAGIC2); F4(C2,D2,E2,A2,B2,M[ 3],15,MAGIC7); F2(B1,C1,D1,E1,A1,M[ 1],13,MAGIC2); F4(B2,C2,D2,E2,A2,M[ 7], 7,MAGIC7); F2(A1,B1,C1,D1,E1,M[10],11,MAGIC2); F4(A2,B2,C2,D2,E2,M[ 0],12,MAGIC7); F2(E1,A1,B1,C1,D1,M[ 6], 9,MAGIC2); F4(E2,A2,B2,C2,D2,M[13], 8,MAGIC7); F2(D1,E1,A1,B1,C1,M[15], 7,MAGIC2); F4(D2,E2,A2,B2,C2,M[ 5], 9,MAGIC7); F2(C1,D1,E1,A1,B1,M[ 3],15,MAGIC2); F4(C2,D2,E2,A2,B2,M[10],11,MAGIC7); F2(B1,C1,D1,E1,A1,M[12], 7,MAGIC2); F4(B2,C2,D2,E2,A2,M[14], 7,MAGIC7); F2(A1,B1,C1,D1,E1,M[ 0],12,MAGIC2); F4(A2,B2,C2,D2,E2,M[15], 7,MAGIC7); F2(E1,A1,B1,C1,D1,M[ 9],15,MAGIC2); F4(E2,A2,B2,C2,D2,M[ 8],12,MAGIC7); F2(D1,E1,A1,B1,C1,M[ 5], 9,MAGIC2); F4(D2,E2,A2,B2,C2,M[12], 7,MAGIC7); F2(C1,D1,E1,A1,B1,M[ 2],11,MAGIC2); F4(C2,D2,E2,A2,B2,M[ 4], 6,MAGIC7); F2(B1,C1,D1,E1,A1,M[14], 7,MAGIC2); F4(B2,C2,D2,E2,A2,M[ 9],15,MAGIC7); F2(A1,B1,C1,D1,E1,M[11],13,MAGIC2); F4(A2,B2,C2,D2,E2,M[ 1],13,MAGIC7); F2(E1,A1,B1,C1,D1,M[ 8],12,MAGIC2); F4(E2,A2,B2,C2,D2,M[ 2],11,MAGIC7); F3(D1,E1,A1,B1,C1,M[ 3],11,MAGIC3); F3(D2,E2,A2,B2,C2,M[15], 9,MAGIC8); F3(C1,D1,E1,A1,B1,M[10],13,MAGIC3); F3(C2,D2,E2,A2,B2,M[ 5], 7,MAGIC8); F3(B1,C1,D1,E1,A1,M[14], 6,MAGIC3); F3(B2,C2,D2,E2,A2,M[ 1],15,MAGIC8); F3(A1,B1,C1,D1,E1,M[ 4], 7,MAGIC3); F3(A2,B2,C2,D2,E2,M[ 3],11,MAGIC8); F3(E1,A1,B1,C1,D1,M[ 9],14,MAGIC3); F3(E2,A2,B2,C2,D2,M[ 7], 8,MAGIC8); F3(D1,E1,A1,B1,C1,M[15], 9,MAGIC3); F3(D2,E2,A2,B2,C2,M[14], 6,MAGIC8); F3(C1,D1,E1,A1,B1,M[ 8],13,MAGIC3); F3(C2,D2,E2,A2,B2,M[ 6], 6,MAGIC8); F3(B1,C1,D1,E1,A1,M[ 1],15,MAGIC3); F3(B2,C2,D2,E2,A2,M[ 9],14,MAGIC8); F3(A1,B1,C1,D1,E1,M[ 2],14,MAGIC3); F3(A2,B2,C2,D2,E2,M[11],12,MAGIC8); F3(E1,A1,B1,C1,D1,M[ 7], 8,MAGIC3); F3(E2,A2,B2,C2,D2,M[ 8],13,MAGIC8); F3(D1,E1,A1,B1,C1,M[ 0],13,MAGIC3); F3(D2,E2,A2,B2,C2,M[12], 5,MAGIC8); F3(C1,D1,E1,A1,B1,M[ 6], 6,MAGIC3); F3(C2,D2,E2,A2,B2,M[ 2],14,MAGIC8); F3(B1,C1,D1,E1,A1,M[13], 5,MAGIC3); F3(B2,C2,D2,E2,A2,M[10],13,MAGIC8); F3(A1,B1,C1,D1,E1,M[11],12,MAGIC3); F3(A2,B2,C2,D2,E2,M[ 0],13,MAGIC8); F3(E1,A1,B1,C1,D1,M[ 5], 7,MAGIC3); F3(E2,A2,B2,C2,D2,M[ 4], 7,MAGIC8); F3(D1,E1,A1,B1,C1,M[12], 5,MAGIC3); F3(D2,E2,A2,B2,C2,M[13], 5,MAGIC8); F4(C1,D1,E1,A1,B1,M[ 1],11,MAGIC4); F2(C2,D2,E2,A2,B2,M[ 8],15,MAGIC9); F4(B1,C1,D1,E1,A1,M[ 9],12,MAGIC4); F2(B2,C2,D2,E2,A2,M[ 6], 5,MAGIC9); F4(A1,B1,C1,D1,E1,M[11],14,MAGIC4); F2(A2,B2,C2,D2,E2,M[ 4], 8,MAGIC9); F4(E1,A1,B1,C1,D1,M[10],15,MAGIC4); F2(E2,A2,B2,C2,D2,M[ 1],11,MAGIC9); F4(D1,E1,A1,B1,C1,M[ 0],14,MAGIC4); F2(D2,E2,A2,B2,C2,M[ 3],14,MAGIC9); F4(C1,D1,E1,A1,B1,M[ 8],15,MAGIC4); F2(C2,D2,E2,A2,B2,M[11],14,MAGIC9); F4(B1,C1,D1,E1,A1,M[12], 9,MAGIC4); F2(B2,C2,D2,E2,A2,M[15], 6,MAGIC9); F4(A1,B1,C1,D1,E1,M[ 4], 8,MAGIC4); F2(A2,B2,C2,D2,E2,M[ 0],14,MAGIC9); F4(E1,A1,B1,C1,D1,M[13], 9,MAGIC4); F2(E2,A2,B2,C2,D2,M[ 5], 6,MAGIC9); F4(D1,E1,A1,B1,C1,M[ 3],14,MAGIC4); F2(D2,E2,A2,B2,C2,M[12], 9,MAGIC9); F4(C1,D1,E1,A1,B1,M[ 7], 5,MAGIC4); F2(C2,D2,E2,A2,B2,M[ 2],12,MAGIC9); F4(B1,C1,D1,E1,A1,M[15], 6,MAGIC4); F2(B2,C2,D2,E2,A2,M[13], 9,MAGIC9); F4(A1,B1,C1,D1,E1,M[14], 8,MAGIC4); F2(A2,B2,C2,D2,E2,M[ 9],12,MAGIC9); F4(E1,A1,B1,C1,D1,M[ 5], 6,MAGIC4); F2(E2,A2,B2,C2,D2,M[ 7], 5,MAGIC9); F4(D1,E1,A1,B1,C1,M[ 6], 5,MAGIC4); F2(D2,E2,A2,B2,C2,M[10],15,MAGIC9); F4(C1,D1,E1,A1,B1,M[ 2],12,MAGIC4); F2(C2,D2,E2,A2,B2,M[14], 8,MAGIC9); F5(B1,C1,D1,E1,A1,M[ 4], 9,MAGIC5); F1(B2,C2,D2,E2,A2,M[12], 8 ); F5(A1,B1,C1,D1,E1,M[ 0],15,MAGIC5); F1(A2,B2,C2,D2,E2,M[15], 5 ); F5(E1,A1,B1,C1,D1,M[ 5], 5,MAGIC5); F1(E2,A2,B2,C2,D2,M[10],12 ); F5(D1,E1,A1,B1,C1,M[ 9],11,MAGIC5); F1(D2,E2,A2,B2,C2,M[ 4], 9 ); F5(C1,D1,E1,A1,B1,M[ 7], 6,MAGIC5); F1(C2,D2,E2,A2,B2,M[ 1],12 ); F5(B1,C1,D1,E1,A1,M[12], 8,MAGIC5); F1(B2,C2,D2,E2,A2,M[ 5], 5 ); F5(A1,B1,C1,D1,E1,M[ 2],13,MAGIC5); F1(A2,B2,C2,D2,E2,M[ 8],14 ); F5(E1,A1,B1,C1,D1,M[10],12,MAGIC5); F1(E2,A2,B2,C2,D2,M[ 7], 6 ); F5(D1,E1,A1,B1,C1,M[14], 5,MAGIC5); F1(D2,E2,A2,B2,C2,M[ 6], 8 ); F5(C1,D1,E1,A1,B1,M[ 1],12,MAGIC5); F1(C2,D2,E2,A2,B2,M[ 2],13 ); F5(B1,C1,D1,E1,A1,M[ 3],13,MAGIC5); F1(B2,C2,D2,E2,A2,M[13], 6 ); F5(A1,B1,C1,D1,E1,M[ 8],14,MAGIC5); F1(A2,B2,C2,D2,E2,M[14], 5 ); F5(E1,A1,B1,C1,D1,M[11],11,MAGIC5); F1(E2,A2,B2,C2,D2,M[ 0],15 ); F5(D1,E1,A1,B1,C1,M[ 6], 8,MAGIC5); F1(D2,E2,A2,B2,C2,M[ 3],13 ); F5(C1,D1,E1,A1,B1,M[15], 5,MAGIC5); F1(C2,D2,E2,A2,B2,M[ 9],11 ); F5(B1,C1,D1,E1,A1,M[13], 6,MAGIC5); F1(B2,C2,D2,E2,A2,M[11],11 ); C1 = digest[1] + C1 + D2; digest[1] = digest[2] + D1 + E2; digest[2] = digest[3] + E1 + A2; digest[3] = digest[4] + A1 + B2; digest[4] = digest[0] + B1 + C2; digest[0] = C1; input += hash_block_size(); } } /* * Copy out the digest */ void RIPEMD_160::copy_out(byte output[]) { for(size_t i = 0; i != output_length(); i += 4) store_le(digest[i/4], output + i); } /* * Clear memory of sensitive data */ void RIPEMD_160::clear() { MDx_HashFunction::clear(); zeroise(M); digest[0] = 0x67452301; digest[1] = 0xEFCDAB89; digest[2] = 0x98BADCFE; digest[3] = 0x10325476; digest[4] = 0xC3D2E1F0; } } /* * SHA-160 * (C) 1999-2008,2011 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { namespace SHA1_F { namespace { /* * SHA-160 F1 Function */ inline void F1(u32bit A, u32bit& B, u32bit C, u32bit D, u32bit& E, u32bit msg) { E += (D ^ (B & (C ^ D))) + msg + 0x5A827999 + rotate_left(A, 5); B = rotate_left(B, 30); } /* * SHA-160 F2 Function */ inline void F2(u32bit A, u32bit& B, u32bit C, u32bit D, u32bit& E, u32bit msg) { E += (B ^ C ^ D) + msg + 0x6ED9EBA1 + rotate_left(A, 5); B = rotate_left(B, 30); } /* * SHA-160 F3 Function */ inline void F3(u32bit A, u32bit& B, u32bit C, u32bit D, u32bit& E, u32bit msg) { E += ((B & C) | ((B | C) & D)) + msg + 0x8F1BBCDC + rotate_left(A, 5); B = rotate_left(B, 30); } /* * SHA-160 F4 Function */ inline void F4(u32bit A, u32bit& B, u32bit C, u32bit D, u32bit& E, u32bit msg) { E += (B ^ C ^ D) + msg + 0xCA62C1D6 + rotate_left(A, 5); B = rotate_left(B, 30); } } } /* * SHA-160 Compression Function */ void SHA_160::compress_n(const byte input[], size_t blocks) { using namespace SHA1_F; u32bit A = digest[0], B = digest[1], C = digest[2], D = digest[3], E = digest[4]; for(size_t i = 0; i != blocks; ++i) { load_be(&W[0], input, 16); for(size_t j = 16; j != 80; j += 8) { W[j ] = rotate_left((W[j-3] ^ W[j-8] ^ W[j-14] ^ W[j-16]), 1); W[j+1] = rotate_left((W[j-2] ^ W[j-7] ^ W[j-13] ^ W[j-15]), 1); W[j+2] = rotate_left((W[j-1] ^ W[j-6] ^ W[j-12] ^ W[j-14]), 1); W[j+3] = rotate_left((W[j ] ^ W[j-5] ^ W[j-11] ^ W[j-13]), 1); W[j+4] = rotate_left((W[j+1] ^ W[j-4] ^ W[j-10] ^ W[j-12]), 1); W[j+5] = rotate_left((W[j+2] ^ W[j-3] ^ W[j- 9] ^ W[j-11]), 1); W[j+6] = rotate_left((W[j+3] ^ W[j-2] ^ W[j- 8] ^ W[j-10]), 1); W[j+7] = rotate_left((W[j+4] ^ W[j-1] ^ W[j- 7] ^ W[j- 9]), 1); } F1(A, B, C, D, E, W[ 0]); F1(E, A, B, C, D, W[ 1]); F1(D, E, A, B, C, W[ 2]); F1(C, D, E, A, B, W[ 3]); F1(B, C, D, E, A, W[ 4]); F1(A, B, C, D, E, W[ 5]); F1(E, A, B, C, D, W[ 6]); F1(D, E, A, B, C, W[ 7]); F1(C, D, E, A, B, W[ 8]); F1(B, C, D, E, A, W[ 9]); F1(A, B, C, D, E, W[10]); F1(E, A, B, C, D, W[11]); F1(D, E, A, B, C, W[12]); F1(C, D, E, A, B, W[13]); F1(B, C, D, E, A, W[14]); F1(A, B, C, D, E, W[15]); F1(E, A, B, C, D, W[16]); F1(D, E, A, B, C, W[17]); F1(C, D, E, A, B, W[18]); F1(B, C, D, E, A, W[19]); F2(A, B, C, D, E, W[20]); F2(E, A, B, C, D, W[21]); F2(D, E, A, B, C, W[22]); F2(C, D, E, A, B, W[23]); F2(B, C, D, E, A, W[24]); F2(A, B, C, D, E, W[25]); F2(E, A, B, C, D, W[26]); F2(D, E, A, B, C, W[27]); F2(C, D, E, A, B, W[28]); F2(B, C, D, E, A, W[29]); F2(A, B, C, D, E, W[30]); F2(E, A, B, C, D, W[31]); F2(D, E, A, B, C, W[32]); F2(C, D, E, A, B, W[33]); F2(B, C, D, E, A, W[34]); F2(A, B, C, D, E, W[35]); F2(E, A, B, C, D, W[36]); F2(D, E, A, B, C, W[37]); F2(C, D, E, A, B, W[38]); F2(B, C, D, E, A, W[39]); F3(A, B, C, D, E, W[40]); F3(E, A, B, C, D, W[41]); F3(D, E, A, B, C, W[42]); F3(C, D, E, A, B, W[43]); F3(B, C, D, E, A, W[44]); F3(A, B, C, D, E, W[45]); F3(E, A, B, C, D, W[46]); F3(D, E, A, B, C, W[47]); F3(C, D, E, A, B, W[48]); F3(B, C, D, E, A, W[49]); F3(A, B, C, D, E, W[50]); F3(E, A, B, C, D, W[51]); F3(D, E, A, B, C, W[52]); F3(C, D, E, A, B, W[53]); F3(B, C, D, E, A, W[54]); F3(A, B, C, D, E, W[55]); F3(E, A, B, C, D, W[56]); F3(D, E, A, B, C, W[57]); F3(C, D, E, A, B, W[58]); F3(B, C, D, E, A, W[59]); F4(A, B, C, D, E, W[60]); F4(E, A, B, C, D, W[61]); F4(D, E, A, B, C, W[62]); F4(C, D, E, A, B, W[63]); F4(B, C, D, E, A, W[64]); F4(A, B, C, D, E, W[65]); F4(E, A, B, C, D, W[66]); F4(D, E, A, B, C, W[67]); F4(C, D, E, A, B, W[68]); F4(B, C, D, E, A, W[69]); F4(A, B, C, D, E, W[70]); F4(E, A, B, C, D, W[71]); F4(D, E, A, B, C, W[72]); F4(C, D, E, A, B, W[73]); F4(B, C, D, E, A, W[74]); F4(A, B, C, D, E, W[75]); F4(E, A, B, C, D, W[76]); F4(D, E, A, B, C, W[77]); F4(C, D, E, A, B, W[78]); F4(B, C, D, E, A, W[79]); A = (digest[0] += A); B = (digest[1] += B); C = (digest[2] += C); D = (digest[3] += D); E = (digest[4] += E); input += hash_block_size(); } } /* * Copy out the digest */ void SHA_160::copy_out(byte output[]) { for(size_t i = 0; i != output_length(); i += 4) store_be(digest[i/4], output + i); } /* * Clear memory of sensitive data */ void SHA_160::clear() { MDx_HashFunction::clear(); zeroise(W); digest[0] = 0x67452301; digest[1] = 0xEFCDAB89; digest[2] = 0x98BADCFE; digest[3] = 0x10325476; digest[4] = 0xC3D2E1F0; } } /* * SHA-{224,256} * (C) 1999-2010 Jack Lloyd * 2007 FlexSecure GmbH * * Distributed under the terms of the Botan license */ namespace Botan { namespace { namespace SHA2_32 { /* * SHA-256 Rho Function */ inline u32bit rho(u32bit X, u32bit rot1, u32bit rot2, u32bit rot3) { return (rotate_right(X, rot1) ^ rotate_right(X, rot2) ^ rotate_right(X, rot3)); } /* * SHA-256 Sigma Function */ inline u32bit sigma(u32bit X, u32bit rot1, u32bit rot2, u32bit shift) { return (rotate_right(X, rot1) ^ rotate_right(X, rot2) ^ (X >> shift)); } /* * SHA-256 F1 Function * * Use a macro as many compilers won't inline a function this big, * even though it is much faster if inlined. */ #define SHA2_32_F(A, B, C, D, E, F, G, H, M1, M2, M3, M4, magic) \ do { \ H += magic + rho(E, 6, 11, 25) + ((E & F) ^ (~E & G)) + M1; \ D += H; \ H += rho(A, 2, 13, 22) + ((A & B) | ((A | B) & C)); \ M1 += sigma(M2, 17, 19, 10) + M3 + sigma(M4, 7, 18, 3); \ } while(0); /* * SHA-224 / SHA-256 compression function */ void compress(MemoryRegion& digest, const byte input[], size_t blocks) { u32bit A = digest[0], B = digest[1], C = digest[2], D = digest[3], E = digest[4], F = digest[5], G = digest[6], H = digest[7]; for(size_t i = 0; i != blocks; ++i) { u32bit W00 = load_be(input, 0); u32bit W01 = load_be(input, 1); u32bit W02 = load_be(input, 2); u32bit W03 = load_be(input, 3); u32bit W04 = load_be(input, 4); u32bit W05 = load_be(input, 5); u32bit W06 = load_be(input, 6); u32bit W07 = load_be(input, 7); u32bit W08 = load_be(input, 8); u32bit W09 = load_be(input, 9); u32bit W10 = load_be(input, 10); u32bit W11 = load_be(input, 11); u32bit W12 = load_be(input, 12); u32bit W13 = load_be(input, 13); u32bit W14 = load_be(input, 14); u32bit W15 = load_be(input, 15); SHA2_32_F(A, B, C, D, E, F, G, H, W00, W14, W09, W01, 0x428A2F98); SHA2_32_F(H, A, B, C, D, E, F, G, W01, W15, W10, W02, 0x71374491); SHA2_32_F(G, H, A, B, C, D, E, F, W02, W00, W11, W03, 0xB5C0FBCF); SHA2_32_F(F, G, H, A, B, C, D, E, W03, W01, W12, W04, 0xE9B5DBA5); SHA2_32_F(E, F, G, H, A, B, C, D, W04, W02, W13, W05, 0x3956C25B); SHA2_32_F(D, E, F, G, H, A, B, C, W05, W03, W14, W06, 0x59F111F1); SHA2_32_F(C, D, E, F, G, H, A, B, W06, W04, W15, W07, 0x923F82A4); SHA2_32_F(B, C, D, E, F, G, H, A, W07, W05, W00, W08, 0xAB1C5ED5); SHA2_32_F(A, B, C, D, E, F, G, H, W08, W06, W01, W09, 0xD807AA98); SHA2_32_F(H, A, B, C, D, E, F, G, W09, W07, W02, W10, 0x12835B01); SHA2_32_F(G, H, A, B, C, D, E, F, W10, W08, W03, W11, 0x243185BE); SHA2_32_F(F, G, H, A, B, C, D, E, W11, W09, W04, W12, 0x550C7DC3); SHA2_32_F(E, F, G, H, A, B, C, D, W12, W10, W05, W13, 0x72BE5D74); SHA2_32_F(D, E, F, G, H, A, B, C, W13, W11, W06, W14, 0x80DEB1FE); SHA2_32_F(C, D, E, F, G, H, A, B, W14, W12, W07, W15, 0x9BDC06A7); SHA2_32_F(B, C, D, E, F, G, H, A, W15, W13, W08, W00, 0xC19BF174); SHA2_32_F(A, B, C, D, E, F, G, H, W00, W14, W09, W01, 0xE49B69C1); SHA2_32_F(H, A, B, C, D, E, F, G, W01, W15, W10, W02, 0xEFBE4786); SHA2_32_F(G, H, A, B, C, D, E, F, W02, W00, W11, W03, 0x0FC19DC6); SHA2_32_F(F, G, H, A, B, C, D, E, W03, W01, W12, W04, 0x240CA1CC); SHA2_32_F(E, F, G, H, A, B, C, D, W04, W02, W13, W05, 0x2DE92C6F); SHA2_32_F(D, E, F, G, H, A, B, C, W05, W03, W14, W06, 0x4A7484AA); SHA2_32_F(C, D, E, F, G, H, A, B, W06, W04, W15, W07, 0x5CB0A9DC); SHA2_32_F(B, C, D, E, F, G, H, A, W07, W05, W00, W08, 0x76F988DA); SHA2_32_F(A, B, C, D, E, F, G, H, W08, W06, W01, W09, 0x983E5152); SHA2_32_F(H, A, B, C, D, E, F, G, W09, W07, W02, W10, 0xA831C66D); SHA2_32_F(G, H, A, B, C, D, E, F, W10, W08, W03, W11, 0xB00327C8); SHA2_32_F(F, G, H, A, B, C, D, E, W11, W09, W04, W12, 0xBF597FC7); SHA2_32_F(E, F, G, H, A, B, C, D, W12, W10, W05, W13, 0xC6E00BF3); SHA2_32_F(D, E, F, G, H, A, B, C, W13, W11, W06, W14, 0xD5A79147); SHA2_32_F(C, D, E, F, G, H, A, B, W14, W12, W07, W15, 0x06CA6351); SHA2_32_F(B, C, D, E, F, G, H, A, W15, W13, W08, W00, 0x14292967); SHA2_32_F(A, B, C, D, E, F, G, H, W00, W14, W09, W01, 0x27B70A85); SHA2_32_F(H, A, B, C, D, E, F, G, W01, W15, W10, W02, 0x2E1B2138); SHA2_32_F(G, H, A, B, C, D, E, F, W02, W00, W11, W03, 0x4D2C6DFC); SHA2_32_F(F, G, H, A, B, C, D, E, W03, W01, W12, W04, 0x53380D13); SHA2_32_F(E, F, G, H, A, B, C, D, W04, W02, W13, W05, 0x650A7354); SHA2_32_F(D, E, F, G, H, A, B, C, W05, W03, W14, W06, 0x766A0ABB); SHA2_32_F(C, D, E, F, G, H, A, B, W06, W04, W15, W07, 0x81C2C92E); SHA2_32_F(B, C, D, E, F, G, H, A, W07, W05, W00, W08, 0x92722C85); SHA2_32_F(A, B, C, D, E, F, G, H, W08, W06, W01, W09, 0xA2BFE8A1); SHA2_32_F(H, A, B, C, D, E, F, G, W09, W07, W02, W10, 0xA81A664B); SHA2_32_F(G, H, A, B, C, D, E, F, W10, W08, W03, W11, 0xC24B8B70); SHA2_32_F(F, G, H, A, B, C, D, E, W11, W09, W04, W12, 0xC76C51A3); SHA2_32_F(E, F, G, H, A, B, C, D, W12, W10, W05, W13, 0xD192E819); SHA2_32_F(D, E, F, G, H, A, B, C, W13, W11, W06, W14, 0xD6990624); SHA2_32_F(C, D, E, F, G, H, A, B, W14, W12, W07, W15, 0xF40E3585); SHA2_32_F(B, C, D, E, F, G, H, A, W15, W13, W08, W00, 0x106AA070); SHA2_32_F(A, B, C, D, E, F, G, H, W00, W14, W09, W01, 0x19A4C116); SHA2_32_F(H, A, B, C, D, E, F, G, W01, W15, W10, W02, 0x1E376C08); SHA2_32_F(G, H, A, B, C, D, E, F, W02, W00, W11, W03, 0x2748774C); SHA2_32_F(F, G, H, A, B, C, D, E, W03, W01, W12, W04, 0x34B0BCB5); SHA2_32_F(E, F, G, H, A, B, C, D, W04, W02, W13, W05, 0x391C0CB3); SHA2_32_F(D, E, F, G, H, A, B, C, W05, W03, W14, W06, 0x4ED8AA4A); SHA2_32_F(C, D, E, F, G, H, A, B, W06, W04, W15, W07, 0x5B9CCA4F); SHA2_32_F(B, C, D, E, F, G, H, A, W07, W05, W00, W08, 0x682E6FF3); SHA2_32_F(A, B, C, D, E, F, G, H, W08, W06, W01, W09, 0x748F82EE); SHA2_32_F(H, A, B, C, D, E, F, G, W09, W07, W02, W10, 0x78A5636F); SHA2_32_F(G, H, A, B, C, D, E, F, W10, W08, W03, W11, 0x84C87814); SHA2_32_F(F, G, H, A, B, C, D, E, W11, W09, W04, W12, 0x8CC70208); SHA2_32_F(E, F, G, H, A, B, C, D, W12, W10, W05, W13, 0x90BEFFFA); SHA2_32_F(D, E, F, G, H, A, B, C, W13, W11, W06, W14, 0xA4506CEB); SHA2_32_F(C, D, E, F, G, H, A, B, W14, W12, W07, W15, 0xBEF9A3F7); SHA2_32_F(B, C, D, E, F, G, H, A, W15, W13, W08, W00, 0xC67178F2); A = (digest[0] += A); B = (digest[1] += B); C = (digest[2] += C); D = (digest[3] += D); E = (digest[4] += E); F = (digest[5] += F); G = (digest[6] += G); H = (digest[7] += H); input += 64; } } } } /* * SHA-224 compression function */ void SHA_224::compress_n(const byte input[], size_t blocks) { SHA2_32::compress(digest, input, blocks); } /* * Copy out the digest */ void SHA_224::copy_out(byte output[]) { for(size_t i = 0; i != output_length(); i += 4) store_be(digest[i/4], output + i); } /* * Clear memory of sensitive data */ void SHA_224::clear() { MDx_HashFunction::clear(); digest[0] = 0xC1059ED8; digest[1] = 0x367CD507; digest[2] = 0x3070DD17; digest[3] = 0xF70E5939; digest[4] = 0xFFC00B31; digest[5] = 0x68581511; digest[6] = 0x64F98FA7; digest[7] = 0xBEFA4FA4; } /* * SHA-256 compression function */ void SHA_256::compress_n(const byte input[], size_t blocks) { SHA2_32::compress(digest, input, blocks); } /* * Copy out the digest */ void SHA_256::copy_out(byte output[]) { for(size_t i = 0; i != output_length(); i += 4) store_be(digest[i/4], output + i); } /* * Clear memory of sensitive data */ void SHA_256::clear() { MDx_HashFunction::clear(); digest[0] = 0x6A09E667; digest[1] = 0xBB67AE85; digest[2] = 0x3C6EF372; digest[3] = 0xA54FF53A; digest[4] = 0x510E527F; digest[5] = 0x9B05688C; digest[6] = 0x1F83D9AB; digest[7] = 0x5BE0CD19; } } /* * SHA-{384,512} * (C) 1999-2011 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { namespace { namespace SHA2_64 { /* * SHA-{384,512} Rho Function */ inline u64bit rho(u64bit X, u32bit rot1, u32bit rot2, u32bit rot3) { return (rotate_right(X, rot1) ^ rotate_right(X, rot2) ^ rotate_right(X, rot3)); } /* * SHA-{384,512} Sigma Function */ inline u64bit sigma(u64bit X, u32bit rot1, u32bit rot2, u32bit shift) { return (rotate_right(X, rot1) ^ rotate_right(X, rot2) ^ (X >> shift)); } /* * SHA-512 F1 Function * * Use a macro as many compilers won't inline a function this big, * even though it is much faster if inlined. */ #define SHA2_64_F(A, B, C, D, E, F, G, H, M1, M2, M3, M4, magic) \ do { \ H += magic + rho(E, 14, 18, 41) + ((E & F) ^ (~E & G)) + M1; \ D += H; \ H += rho(A, 28, 34, 39) + ((A & B) | ((A | B) & C)); \ M1 += sigma(M2, 19, 61, 6) + M3 + sigma(M4, 1, 8, 7); \ } while(0); /* * SHA-{384,512} Compression Function */ void compress(MemoryRegion& digest, const byte input[], size_t blocks) { u64bit A = digest[0], B = digest[1], C = digest[2], D = digest[3], E = digest[4], F = digest[5], G = digest[6], H = digest[7]; for(size_t i = 0; i != blocks; ++i) { u64bit W00 = load_be(input, 0); u64bit W01 = load_be(input, 1); u64bit W02 = load_be(input, 2); u64bit W03 = load_be(input, 3); u64bit W04 = load_be(input, 4); u64bit W05 = load_be(input, 5); u64bit W06 = load_be(input, 6); u64bit W07 = load_be(input, 7); u64bit W08 = load_be(input, 8); u64bit W09 = load_be(input, 9); u64bit W10 = load_be(input, 10); u64bit W11 = load_be(input, 11); u64bit W12 = load_be(input, 12); u64bit W13 = load_be(input, 13); u64bit W14 = load_be(input, 14); u64bit W15 = load_be(input, 15); SHA2_64_F(A, B, C, D, E, F, G, H, W00, W14, W09, W01, 0x428A2F98D728AE22ULL); SHA2_64_F(H, A, B, C, D, E, F, G, W01, W15, W10, W02, 0x7137449123EF65CDULL); SHA2_64_F(G, H, A, B, C, D, E, F, W02, W00, W11, W03, 0xB5C0FBCFEC4D3B2FULL); SHA2_64_F(F, G, H, A, B, C, D, E, W03, W01, W12, W04, 0xE9B5DBA58189DBBCULL); SHA2_64_F(E, F, G, H, A, B, C, D, W04, W02, W13, W05, 0x3956C25BF348B538ULL); SHA2_64_F(D, E, F, G, H, A, B, C, W05, W03, W14, W06, 0x59F111F1B605D019ULL); SHA2_64_F(C, D, E, F, G, H, A, B, W06, W04, W15, W07, 0x923F82A4AF194F9BULL); SHA2_64_F(B, C, D, E, F, G, H, A, W07, W05, W00, W08, 0xAB1C5ED5DA6D8118ULL); SHA2_64_F(A, B, C, D, E, F, G, H, W08, W06, W01, W09, 0xD807AA98A3030242ULL); SHA2_64_F(H, A, B, C, D, E, F, G, W09, W07, W02, W10, 0x12835B0145706FBEULL); SHA2_64_F(G, H, A, B, C, D, E, F, W10, W08, W03, W11, 0x243185BE4EE4B28CULL); SHA2_64_F(F, G, H, A, B, C, D, E, W11, W09, W04, W12, 0x550C7DC3D5FFB4E2ULL); SHA2_64_F(E, F, G, H, A, B, C, D, W12, W10, W05, W13, 0x72BE5D74F27B896FULL); SHA2_64_F(D, E, F, G, H, A, B, C, W13, W11, W06, W14, 0x80DEB1FE3B1696B1ULL); SHA2_64_F(C, D, E, F, G, H, A, B, W14, W12, W07, W15, 0x9BDC06A725C71235ULL); SHA2_64_F(B, C, D, E, F, G, H, A, W15, W13, W08, W00, 0xC19BF174CF692694ULL); SHA2_64_F(A, B, C, D, E, F, G, H, W00, W14, W09, W01, 0xE49B69C19EF14AD2ULL); SHA2_64_F(H, A, B, C, D, E, F, G, W01, W15, W10, W02, 0xEFBE4786384F25E3ULL); SHA2_64_F(G, H, A, B, C, D, E, F, W02, W00, W11, W03, 0x0FC19DC68B8CD5B5ULL); SHA2_64_F(F, G, H, A, B, C, D, E, W03, W01, W12, W04, 0x240CA1CC77AC9C65ULL); SHA2_64_F(E, F, G, H, A, B, C, D, W04, W02, W13, W05, 0x2DE92C6F592B0275ULL); SHA2_64_F(D, E, F, G, H, A, B, C, W05, W03, W14, W06, 0x4A7484AA6EA6E483ULL); SHA2_64_F(C, D, E, F, G, H, A, B, W06, W04, W15, W07, 0x5CB0A9DCBD41FBD4ULL); SHA2_64_F(B, C, D, E, F, G, H, A, W07, W05, W00, W08, 0x76F988DA831153B5ULL); SHA2_64_F(A, B, C, D, E, F, G, H, W08, W06, W01, W09, 0x983E5152EE66DFABULL); SHA2_64_F(H, A, B, C, D, E, F, G, W09, W07, W02, W10, 0xA831C66D2DB43210ULL); SHA2_64_F(G, H, A, B, C, D, E, F, W10, W08, W03, W11, 0xB00327C898FB213FULL); SHA2_64_F(F, G, H, A, B, C, D, E, W11, W09, W04, W12, 0xBF597FC7BEEF0EE4ULL); SHA2_64_F(E, F, G, H, A, B, C, D, W12, W10, W05, W13, 0xC6E00BF33DA88FC2ULL); SHA2_64_F(D, E, F, G, H, A, B, C, W13, W11, W06, W14, 0xD5A79147930AA725ULL); SHA2_64_F(C, D, E, F, G, H, A, B, W14, W12, W07, W15, 0x06CA6351E003826FULL); SHA2_64_F(B, C, D, E, F, G, H, A, W15, W13, W08, W00, 0x142929670A0E6E70ULL); SHA2_64_F(A, B, C, D, E, F, G, H, W00, W14, W09, W01, 0x27B70A8546D22FFCULL); SHA2_64_F(H, A, B, C, D, E, F, G, W01, W15, W10, W02, 0x2E1B21385C26C926ULL); SHA2_64_F(G, H, A, B, C, D, E, F, W02, W00, W11, W03, 0x4D2C6DFC5AC42AEDULL); SHA2_64_F(F, G, H, A, B, C, D, E, W03, W01, W12, W04, 0x53380D139D95B3DFULL); SHA2_64_F(E, F, G, H, A, B, C, D, W04, W02, W13, W05, 0x650A73548BAF63DEULL); SHA2_64_F(D, E, F, G, H, A, B, C, W05, W03, W14, W06, 0x766A0ABB3C77B2A8ULL); SHA2_64_F(C, D, E, F, G, H, A, B, W06, W04, W15, W07, 0x81C2C92E47EDAEE6ULL); SHA2_64_F(B, C, D, E, F, G, H, A, W07, W05, W00, W08, 0x92722C851482353BULL); SHA2_64_F(A, B, C, D, E, F, G, H, W08, W06, W01, W09, 0xA2BFE8A14CF10364ULL); SHA2_64_F(H, A, B, C, D, E, F, G, W09, W07, W02, W10, 0xA81A664BBC423001ULL); SHA2_64_F(G, H, A, B, C, D, E, F, W10, W08, W03, W11, 0xC24B8B70D0F89791ULL); SHA2_64_F(F, G, H, A, B, C, D, E, W11, W09, W04, W12, 0xC76C51A30654BE30ULL); SHA2_64_F(E, F, G, H, A, B, C, D, W12, W10, W05, W13, 0xD192E819D6EF5218ULL); SHA2_64_F(D, E, F, G, H, A, B, C, W13, W11, W06, W14, 0xD69906245565A910ULL); SHA2_64_F(C, D, E, F, G, H, A, B, W14, W12, W07, W15, 0xF40E35855771202AULL); SHA2_64_F(B, C, D, E, F, G, H, A, W15, W13, W08, W00, 0x106AA07032BBD1B8ULL); SHA2_64_F(A, B, C, D, E, F, G, H, W00, W14, W09, W01, 0x19A4C116B8D2D0C8ULL); SHA2_64_F(H, A, B, C, D, E, F, G, W01, W15, W10, W02, 0x1E376C085141AB53ULL); SHA2_64_F(G, H, A, B, C, D, E, F, W02, W00, W11, W03, 0x2748774CDF8EEB99ULL); SHA2_64_F(F, G, H, A, B, C, D, E, W03, W01, W12, W04, 0x34B0BCB5E19B48A8ULL); SHA2_64_F(E, F, G, H, A, B, C, D, W04, W02, W13, W05, 0x391C0CB3C5C95A63ULL); SHA2_64_F(D, E, F, G, H, A, B, C, W05, W03, W14, W06, 0x4ED8AA4AE3418ACBULL); SHA2_64_F(C, D, E, F, G, H, A, B, W06, W04, W15, W07, 0x5B9CCA4F7763E373ULL); SHA2_64_F(B, C, D, E, F, G, H, A, W07, W05, W00, W08, 0x682E6FF3D6B2B8A3ULL); SHA2_64_F(A, B, C, D, E, F, G, H, W08, W06, W01, W09, 0x748F82EE5DEFB2FCULL); SHA2_64_F(H, A, B, C, D, E, F, G, W09, W07, W02, W10, 0x78A5636F43172F60ULL); SHA2_64_F(G, H, A, B, C, D, E, F, W10, W08, W03, W11, 0x84C87814A1F0AB72ULL); SHA2_64_F(F, G, H, A, B, C, D, E, W11, W09, W04, W12, 0x8CC702081A6439ECULL); SHA2_64_F(E, F, G, H, A, B, C, D, W12, W10, W05, W13, 0x90BEFFFA23631E28ULL); SHA2_64_F(D, E, F, G, H, A, B, C, W13, W11, W06, W14, 0xA4506CEBDE82BDE9ULL); SHA2_64_F(C, D, E, F, G, H, A, B, W14, W12, W07, W15, 0xBEF9A3F7B2C67915ULL); SHA2_64_F(B, C, D, E, F, G, H, A, W15, W13, W08, W00, 0xC67178F2E372532BULL); SHA2_64_F(A, B, C, D, E, F, G, H, W00, W14, W09, W01, 0xCA273ECEEA26619CULL); SHA2_64_F(H, A, B, C, D, E, F, G, W01, W15, W10, W02, 0xD186B8C721C0C207ULL); SHA2_64_F(G, H, A, B, C, D, E, F, W02, W00, W11, W03, 0xEADA7DD6CDE0EB1EULL); SHA2_64_F(F, G, H, A, B, C, D, E, W03, W01, W12, W04, 0xF57D4F7FEE6ED178ULL); SHA2_64_F(E, F, G, H, A, B, C, D, W04, W02, W13, W05, 0x06F067AA72176FBAULL); SHA2_64_F(D, E, F, G, H, A, B, C, W05, W03, W14, W06, 0x0A637DC5A2C898A6ULL); SHA2_64_F(C, D, E, F, G, H, A, B, W06, W04, W15, W07, 0x113F9804BEF90DAEULL); SHA2_64_F(B, C, D, E, F, G, H, A, W07, W05, W00, W08, 0x1B710B35131C471BULL); SHA2_64_F(A, B, C, D, E, F, G, H, W08, W06, W01, W09, 0x28DB77F523047D84ULL); SHA2_64_F(H, A, B, C, D, E, F, G, W09, W07, W02, W10, 0x32CAAB7B40C72493ULL); SHA2_64_F(G, H, A, B, C, D, E, F, W10, W08, W03, W11, 0x3C9EBE0A15C9BEBCULL); SHA2_64_F(F, G, H, A, B, C, D, E, W11, W09, W04, W12, 0x431D67C49C100D4CULL); SHA2_64_F(E, F, G, H, A, B, C, D, W12, W10, W05, W13, 0x4CC5D4BECB3E42B6ULL); SHA2_64_F(D, E, F, G, H, A, B, C, W13, W11, W06, W14, 0x597F299CFC657E2AULL); SHA2_64_F(C, D, E, F, G, H, A, B, W14, W12, W07, W15, 0x5FCB6FAB3AD6FAECULL); SHA2_64_F(B, C, D, E, F, G, H, A, W15, W13, W08, W00, 0x6C44198C4A475817ULL); A = (digest[0] += A); B = (digest[1] += B); C = (digest[2] += C); D = (digest[3] += D); E = (digest[4] += E); F = (digest[5] += F); G = (digest[6] += G); H = (digest[7] += H); input += 128; } } } } /* * SHA-384 compression function */ void SHA_384::compress_n(const byte input[], size_t blocks) { SHA2_64::compress(digest, input, blocks); } /* * Copy out the digest */ void SHA_384::copy_out(byte output[]) { for(size_t i = 0; i != output_length(); i += 8) store_be(digest[i/8], output + i); } /* * Clear memory of sensitive data */ void SHA_384::clear() { MDx_HashFunction::clear(); digest[0] = 0xCBBB9D5DC1059ED8ULL; digest[1] = 0x629A292A367CD507ULL; digest[2] = 0x9159015A3070DD17ULL; digest[3] = 0x152FECD8F70E5939ULL; digest[4] = 0x67332667FFC00B31ULL; digest[5] = 0x8EB44A8768581511ULL; digest[6] = 0xDB0C2E0D64F98FA7ULL; digest[7] = 0x47B5481DBEFA4FA4ULL; } /* * SHA-512 compression function */ void SHA_512::compress_n(const byte input[], size_t blocks) { SHA2_64::compress(digest, input, blocks); } /* * Copy out the digest */ void SHA_512::copy_out(byte output[]) { for(size_t i = 0; i != output_length(); i += 8) store_be(digest[i/8], output + i); } /* * Clear memory of sensitive data */ void SHA_512::clear() { MDx_HashFunction::clear(); digest[0] = 0x6A09E667F3BCC908ULL; digest[1] = 0xBB67AE8584CAA73BULL; digest[2] = 0x3C6EF372FE94F82BULL; digest[3] = 0xA54FF53A5F1D36F1ULL; digest[4] = 0x510E527FADE682D1ULL; digest[5] = 0x9B05688C2B3E6C1FULL; digest[6] = 0x1F83D9ABFB41BD6BULL; digest[7] = 0x5BE0CD19137E2179ULL; } } /* * The Skein-512 hash function * (C) 2009-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ #include namespace Botan { namespace { enum type_code { SKEIN_KEY = 0, SKEIN_CONFIG = 4, SKEIN_PERSONALIZATION = 8, SKEIN_PUBLIC_KEY = 12, SKEIN_KEY_IDENTIFIER = 16, SKEIN_NONCE = 20, SKEIN_MSG = 48, SKEIN_OUTPUT = 63 }; void ubi_512(MemoryRegion& H, MemoryRegion& T, const byte msg[], size_t msg_len) { do { const size_t to_proc = std::min(msg_len, 64); T[0] += to_proc; u64bit M[8] = { 0 }; load_le(M, msg, to_proc / 8); if(to_proc % 8) { for(size_t j = 0; j != to_proc % 8; ++j) M[to_proc/8] |= static_cast(msg[8*(to_proc/8)+j]) << (8*j); } H[8] = H[0] ^ H[1] ^ H[2] ^ H[3] ^ H[4] ^ H[5] ^ H[6] ^ H[7] ^ 0x1BD11BDAA9FC1A22ULL; T[2] = T[0] ^ T[1]; u64bit X0 = M[0] + H[0]; u64bit X1 = M[1] + H[1]; u64bit X2 = M[2] + H[2]; u64bit X3 = M[3] + H[3]; u64bit X4 = M[4] + H[4]; u64bit X5 = M[5] + H[5] + T[0]; u64bit X6 = M[6] + H[6] + T[1]; u64bit X7 = M[7] + H[7]; #define THREEFISH_ROUND(I1,I2,I3,I4,I5,I6,I7,I8,ROT1,ROT2,ROT3,ROT4) \ do { \ X##I1 += X##I2; X##I2 = rotate_left(X##I2, ROT1) ^ X##I1; \ X##I3 += X##I4; X##I4 = rotate_left(X##I4, ROT2) ^ X##I3; \ X##I5 += X##I6; X##I6 = rotate_left(X##I6, ROT3) ^ X##I5; \ X##I7 += X##I8; X##I8 = rotate_left(X##I8, ROT4) ^ X##I7; \ } while(0); #define THREEFISH_INJECT_KEY(r) \ do { \ X0 += H[(r ) % 9]; \ X1 += H[(r+1) % 9]; \ X2 += H[(r+2) % 9]; \ X3 += H[(r+3) % 9]; \ X4 += H[(r+4) % 9]; \ X5 += H[(r+5) % 9] + T[(r ) % 3]; \ X6 += H[(r+6) % 9] + T[(r+1) % 3]; \ X7 += H[(r+7) % 9] + (r); \ } while(0); #define THREEFISH_8_ROUNDS(R1,R2) \ do { \ THREEFISH_ROUND(0,1,2,3,4,5,6,7, 46,36,19,37); \ THREEFISH_ROUND(2,1,4,7,6,5,0,3, 33,27,14,42); \ THREEFISH_ROUND(4,1,6,3,0,5,2,7, 17,49,36,39); \ THREEFISH_ROUND(6,1,0,7,2,5,4,3, 44, 9,54,56); \ \ THREEFISH_INJECT_KEY(R1); \ \ THREEFISH_ROUND(0,1,2,3,4,5,6,7, 39,30,34,24); \ THREEFISH_ROUND(2,1,4,7,6,5,0,3, 13,50,10,17); \ THREEFISH_ROUND(4,1,6,3,0,5,2,7, 25,29,39,43); \ THREEFISH_ROUND(6,1,0,7,2,5,4,3, 8,35,56,22); \ \ THREEFISH_INJECT_KEY(R2); \ } while(0); THREEFISH_8_ROUNDS(1,2); THREEFISH_8_ROUNDS(3,4); THREEFISH_8_ROUNDS(5,6); THREEFISH_8_ROUNDS(7,8); THREEFISH_8_ROUNDS(9,10); THREEFISH_8_ROUNDS(11,12); THREEFISH_8_ROUNDS(13,14); THREEFISH_8_ROUNDS(15,16); THREEFISH_8_ROUNDS(17,18); // message feed forward H[0] = X0 ^ M[0]; H[1] = X1 ^ M[1]; H[2] = X2 ^ M[2]; H[3] = X3 ^ M[3]; H[4] = X4 ^ M[4]; H[5] = X5 ^ M[5]; H[6] = X6 ^ M[6]; H[7] = X7 ^ M[7]; // clear first flag if set T[1] &= ~(static_cast(1) << 62); msg_len -= to_proc; msg += to_proc; } while(msg_len); } void reset_tweak(MemoryRegion& T, type_code type, bool final) { T[0] = 0; T[1] = (static_cast(type) << 56) | (static_cast(1) << 62) | (static_cast(final) << 63); } void initial_block(MemoryRegion& H, MemoryRegion& T, size_t output_bits, const std::string& personalization) { zeroise(H); // ASCII("SHA3") followed by version (0x0001) code byte config_str[32] = { 0x53, 0x48, 0x41, 0x33, 0x01, 0x00, 0 }; store_le(u32bit(output_bits), config_str + 8); reset_tweak(T, SKEIN_CONFIG, true); ubi_512(H, T, config_str, sizeof(config_str)); if(personalization != "") { /* This is a limitation of this implementation, and not of the algorithm specification. Could be fixed relatively easily, but doesn't seem worth the trouble. */ if(personalization.length() > 64) throw Invalid_Argument("Skein personalization must be <= 64 bytes"); const byte* bits = reinterpret_cast(personalization.data()); reset_tweak(T, SKEIN_PERSONALIZATION, true); ubi_512(H, T, bits, personalization.length()); } reset_tweak(T, SKEIN_MSG, false); } } Skein_512::Skein_512(size_t arg_output_bits, const std::string& arg_personalization) : personalization(arg_personalization), output_bits(arg_output_bits), H(9), T(3), buffer(64), buf_pos(0) { if(output_bits == 0 || output_bits % 8 != 0 || output_bits > 64*1024) throw Invalid_Argument("Bad output bits size for Skein-512"); initial_block(H, T, output_bits, personalization); } std::string Skein_512::name() const { if(personalization != "") return "Skein-512(" + to_string(output_bits) + "," + personalization + ")"; return "Skein-512(" + to_string(output_bits) + ")"; } HashFunction* Skein_512::clone() const { return new Skein_512(output_bits, personalization); } void Skein_512::clear() { zeroise(H); zeroise(T); zeroise(buffer); buf_pos = 0; } void Skein_512::add_data(const byte input[], size_t length) { if(length == 0) return; if(buf_pos) { buffer.copy(buf_pos, input, length); if(buf_pos + length > 64) { ubi_512(H, T, &buffer[0], buffer.size()); input += (64 - buf_pos); length -= (64 - buf_pos); buf_pos = 0; } } const size_t full_blocks = (length - 1) / 64; if(full_blocks) ubi_512(H, T, input, 64*full_blocks); length -= full_blocks * 64; buffer.copy(buf_pos, input + full_blocks * 64, length); buf_pos += length; } void Skein_512::final_result(byte out[]) { T[1] |= (static_cast(1) << 63); // final block flag for(size_t i = buf_pos; i != buffer.size(); ++i) buffer[i] = 0; ubi_512(H, T, &buffer[0], buf_pos); byte counter[8] = { 0 }; size_t out_bytes = output_bits / 8; SecureVector H_out(9); while(out_bytes) { const size_t to_proc = std::min(out_bytes, 64); H_out.copy(&H[0], 8); reset_tweak(T, SKEIN_OUTPUT, true); ubi_512(H_out, T, counter, sizeof(counter)); for(size_t i = 0; i != to_proc; ++i) out[i] = get_byte(7-i%8, H_out[i/8]); out_bytes -= to_proc; out += to_proc; for(size_t i = 0; i != sizeof(counter); ++i) if(++counter[i]) break; } buf_pos = 0; initial_block(H, T, output_bits, personalization); } } /* * S-Box Tables for Tiger * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { const u64bit Tiger::SBOX1[256] = { 0x02AAB17CF7E90C5EULL, 0xAC424B03E243A8ECULL, 0x72CD5BE30DD5FCD3ULL, 0x6D019B93F6F97F3AULL, 0xCD9978FFD21F9193ULL, 0x7573A1C9708029E2ULL, 0xB164326B922A83C3ULL, 0x46883EEE04915870ULL, 0xEAACE3057103ECE6ULL, 0xC54169B808A3535CULL, 0x4CE754918DDEC47CULL, 0x0AA2F4DFDC0DF40CULL, 0x10B76F18A74DBEFAULL, 0xC6CCB6235AD1AB6AULL, 0x13726121572FE2FFULL, 0x1A488C6F199D921EULL, 0x4BC9F9F4DA0007CAULL, 0x26F5E6F6E85241C7ULL, 0x859079DBEA5947B6ULL, 0x4F1885C5C99E8C92ULL, 0xD78E761EA96F864BULL, 0x8E36428C52B5C17DULL, 0x69CF6827373063C1ULL, 0xB607C93D9BB4C56EULL, 0x7D820E760E76B5EAULL, 0x645C9CC6F07FDC42ULL, 0xBF38A078243342E0ULL, 0x5F6B343C9D2E7D04ULL, 0xF2C28AEB600B0EC6ULL, 0x6C0ED85F7254BCACULL, 0x71592281A4DB4FE5ULL, 0x1967FA69CE0FED9FULL, 0xFD5293F8B96545DBULL, 0xC879E9D7F2A7600BULL, 0x860248920193194EULL, 0xA4F9533B2D9CC0B3ULL, 0x9053836C15957613ULL, 0xDB6DCF8AFC357BF1ULL, 0x18BEEA7A7A370F57ULL, 0x037117CA50B99066ULL, 0x6AB30A9774424A35ULL, 0xF4E92F02E325249BULL, 0x7739DB07061CCAE1ULL, 0xD8F3B49CECA42A05ULL, 0xBD56BE3F51382F73ULL, 0x45FAED5843B0BB28ULL, 0x1C813D5C11BF1F83ULL, 0x8AF0E4B6D75FA169ULL, 0x33EE18A487AD9999ULL, 0x3C26E8EAB1C94410ULL, 0xB510102BC0A822F9ULL, 0x141EEF310CE6123BULL, 0xFC65B90059DDB154ULL, 0xE0158640C5E0E607ULL, 0x884E079826C3A3CFULL, 0x930D0D9523C535FDULL, 0x35638D754E9A2B00ULL, 0x4085FCCF40469DD5ULL, 0xC4B17AD28BE23A4CULL, 0xCAB2F0FC6A3E6A2EULL, 0x2860971A6B943FCDULL, 0x3DDE6EE212E30446ULL, 0x6222F32AE01765AEULL, 0x5D550BB5478308FEULL, 0xA9EFA98DA0EDA22AULL, 0xC351A71686C40DA7ULL, 0x1105586D9C867C84ULL, 0xDCFFEE85FDA22853ULL, 0xCCFBD0262C5EEF76ULL, 0xBAF294CB8990D201ULL, 0xE69464F52AFAD975ULL, 0x94B013AFDF133E14ULL, 0x06A7D1A32823C958ULL, 0x6F95FE5130F61119ULL, 0xD92AB34E462C06C0ULL, 0xED7BDE33887C71D2ULL, 0x79746D6E6518393EULL, 0x5BA419385D713329ULL, 0x7C1BA6B948A97564ULL, 0x31987C197BFDAC67ULL, 0xDE6C23C44B053D02ULL, 0x581C49FED002D64DULL, 0xDD474D6338261571ULL, 0xAA4546C3E473D062ULL, 0x928FCE349455F860ULL, 0x48161BBACAAB94D9ULL, 0x63912430770E6F68ULL, 0x6EC8A5E602C6641CULL, 0x87282515337DDD2BULL, 0x2CDA6B42034B701BULL, 0xB03D37C181CB096DULL, 0xE108438266C71C6FULL, 0x2B3180C7EB51B255ULL, 0xDF92B82F96C08BBCULL, 0x5C68C8C0A632F3BAULL, 0x5504CC861C3D0556ULL, 0xABBFA4E55FB26B8FULL, 0x41848B0AB3BACEB4ULL, 0xB334A273AA445D32ULL, 0xBCA696F0A85AD881ULL, 0x24F6EC65B528D56CULL, 0x0CE1512E90F4524AULL, 0x4E9DD79D5506D35AULL, 0x258905FAC6CE9779ULL, 0x2019295B3E109B33ULL, 0xF8A9478B73A054CCULL, 0x2924F2F934417EB0ULL, 0x3993357D536D1BC4ULL, 0x38A81AC21DB6FF8BULL, 0x47C4FBF17D6016BFULL, 0x1E0FAADD7667E3F5ULL, 0x7ABCFF62938BEB96ULL, 0xA78DAD948FC179C9ULL, 0x8F1F98B72911E50DULL, 0x61E48EAE27121A91ULL, 0x4D62F7AD31859808ULL, 0xECEBA345EF5CEAEBULL, 0xF5CEB25EBC9684CEULL, 0xF633E20CB7F76221ULL, 0xA32CDF06AB8293E4ULL, 0x985A202CA5EE2CA4ULL, 0xCF0B8447CC8A8FB1ULL, 0x9F765244979859A3ULL, 0xA8D516B1A1240017ULL, 0x0BD7BA3EBB5DC726ULL, 0xE54BCA55B86ADB39ULL, 0x1D7A3AFD6C478063ULL, 0x519EC608E7669EDDULL, 0x0E5715A2D149AA23ULL, 0x177D4571848FF194ULL, 0xEEB55F3241014C22ULL, 0x0F5E5CA13A6E2EC2ULL, 0x8029927B75F5C361ULL, 0xAD139FABC3D6E436ULL, 0x0D5DF1A94CCF402FULL, 0x3E8BD948BEA5DFC8ULL, 0xA5A0D357BD3FF77EULL, 0xA2D12E251F74F645ULL, 0x66FD9E525E81A082ULL, 0x2E0C90CE7F687A49ULL, 0xC2E8BCBEBA973BC5ULL, 0x000001BCE509745FULL, 0x423777BBE6DAB3D6ULL, 0xD1661C7EAEF06EB5ULL, 0xA1781F354DAACFD8ULL, 0x2D11284A2B16AFFCULL, 0xF1FC4F67FA891D1FULL, 0x73ECC25DCB920ADAULL, 0xAE610C22C2A12651ULL, 0x96E0A810D356B78AULL, 0x5A9A381F2FE7870FULL, 0xD5AD62EDE94E5530ULL, 0xD225E5E8368D1427ULL, 0x65977B70C7AF4631ULL, 0x99F889B2DE39D74FULL, 0x233F30BF54E1D143ULL, 0x9A9675D3D9A63C97ULL, 0x5470554FF334F9A8ULL, 0x166ACB744A4F5688ULL, 0x70C74CAAB2E4AEADULL, 0xF0D091646F294D12ULL, 0x57B82A89684031D1ULL, 0xEFD95A5A61BE0B6BULL, 0x2FBD12E969F2F29AULL, 0x9BD37013FEFF9FE8ULL, 0x3F9B0404D6085A06ULL, 0x4940C1F3166CFE15ULL, 0x09542C4DCDF3DEFBULL, 0xB4C5218385CD5CE3ULL, 0xC935B7DC4462A641ULL, 0x3417F8A68ED3B63FULL, 0xB80959295B215B40ULL, 0xF99CDAEF3B8C8572ULL, 0x018C0614F8FCB95DULL, 0x1B14ACCD1A3ACDF3ULL, 0x84D471F200BB732DULL, 0xC1A3110E95E8DA16ULL, 0x430A7220BF1A82B8ULL, 0xB77E090D39DF210EULL, 0x5EF4BD9F3CD05E9DULL, 0x9D4FF6DA7E57A444ULL, 0xDA1D60E183D4A5F8ULL, 0xB287C38417998E47ULL, 0xFE3EDC121BB31886ULL, 0xC7FE3CCC980CCBEFULL, 0xE46FB590189BFD03ULL, 0x3732FD469A4C57DCULL, 0x7EF700A07CF1AD65ULL, 0x59C64468A31D8859ULL, 0x762FB0B4D45B61F6ULL, 0x155BAED099047718ULL, 0x68755E4C3D50BAA6ULL, 0xE9214E7F22D8B4DFULL, 0x2ADDBF532EAC95F4ULL, 0x32AE3909B4BD0109ULL, 0x834DF537B08E3450ULL, 0xFA209DA84220728DULL, 0x9E691D9B9EFE23F7ULL, 0x0446D288C4AE8D7FULL, 0x7B4CC524E169785BULL, 0x21D87F0135CA1385ULL, 0xCEBB400F137B8AA5ULL, 0x272E2B66580796BEULL, 0x3612264125C2B0DEULL, 0x057702BDAD1EFBB2ULL, 0xD4BABB8EACF84BE9ULL, 0x91583139641BC67BULL, 0x8BDC2DE08036E024ULL, 0x603C8156F49F68EDULL, 0xF7D236F7DBEF5111ULL, 0x9727C4598AD21E80ULL, 0xA08A0896670A5FD7ULL, 0xCB4A8F4309EBA9CBULL, 0x81AF564B0F7036A1ULL, 0xC0B99AA778199ABDULL, 0x959F1EC83FC8E952ULL, 0x8C505077794A81B9ULL, 0x3ACAAF8F056338F0ULL, 0x07B43F50627A6778ULL, 0x4A44AB49F5ECCC77ULL, 0x3BC3D6E4B679EE98ULL, 0x9CC0D4D1CF14108CULL, 0x4406C00B206BC8A0ULL, 0x82A18854C8D72D89ULL, 0x67E366B35C3C432CULL, 0xB923DD61102B37F2ULL, 0x56AB2779D884271DULL, 0xBE83E1B0FF1525AFULL, 0xFB7C65D4217E49A9ULL, 0x6BDBE0E76D48E7D4ULL, 0x08DF828745D9179EULL, 0x22EA6A9ADD53BD34ULL, 0xE36E141C5622200AULL, 0x7F805D1B8CB750EEULL, 0xAFE5C7A59F58E837ULL, 0xE27F996A4FB1C23CULL, 0xD3867DFB0775F0D0ULL, 0xD0E673DE6E88891AULL, 0x123AEB9EAFB86C25ULL, 0x30F1D5D5C145B895ULL, 0xBB434A2DEE7269E7ULL, 0x78CB67ECF931FA38ULL, 0xF33B0372323BBF9CULL, 0x52D66336FB279C74ULL, 0x505F33AC0AFB4EAAULL, 0xE8A5CD99A2CCE187ULL, 0x534974801E2D30BBULL, 0x8D2D5711D5876D90ULL, 0x1F1A412891BC038EULL, 0xD6E2E71D82E56648ULL, 0x74036C3A497732B7ULL, 0x89B67ED96361F5ABULL, 0xFFED95D8F1EA02A2ULL, 0xE72B3BD61464D43DULL, 0xA6300F170BDC4820ULL, 0xEBC18760ED78A77AULL }; const u64bit Tiger::SBOX2[256] = { 0xE6A6BE5A05A12138ULL, 0xB5A122A5B4F87C98ULL, 0x563C6089140B6990ULL, 0x4C46CB2E391F5DD5ULL, 0xD932ADDBC9B79434ULL, 0x08EA70E42015AFF5ULL, 0xD765A6673E478CF1ULL, 0xC4FB757EAB278D99ULL, 0xDF11C6862D6E0692ULL, 0xDDEB84F10D7F3B16ULL, 0x6F2EF604A665EA04ULL, 0x4A8E0F0FF0E0DFB3ULL, 0xA5EDEEF83DBCBA51ULL, 0xFC4F0A2A0EA4371EULL, 0xE83E1DA85CB38429ULL, 0xDC8FF882BA1B1CE2ULL, 0xCD45505E8353E80DULL, 0x18D19A00D4DB0717ULL, 0x34A0CFEDA5F38101ULL, 0x0BE77E518887CAF2ULL, 0x1E341438B3C45136ULL, 0xE05797F49089CCF9ULL, 0xFFD23F9DF2591D14ULL, 0x543DDA228595C5CDULL, 0x661F81FD99052A33ULL, 0x8736E641DB0F7B76ULL, 0x15227725418E5307ULL, 0xE25F7F46162EB2FAULL, 0x48A8B2126C13D9FEULL, 0xAFDC541792E76EEAULL, 0x03D912BFC6D1898FULL, 0x31B1AAFA1B83F51BULL, 0xF1AC2796E42AB7D9ULL, 0x40A3A7D7FCD2EBACULL, 0x1056136D0AFBBCC5ULL, 0x7889E1DD9A6D0C85ULL, 0xD33525782A7974AAULL, 0xA7E25D09078AC09BULL, 0xBD4138B3EAC6EDD0ULL, 0x920ABFBE71EB9E70ULL, 0xA2A5D0F54FC2625CULL, 0xC054E36B0B1290A3ULL, 0xF6DD59FF62FE932BULL, 0x3537354511A8AC7DULL, 0xCA845E9172FADCD4ULL, 0x84F82B60329D20DCULL, 0x79C62CE1CD672F18ULL, 0x8B09A2ADD124642CULL, 0xD0C1E96A19D9E726ULL, 0x5A786A9B4BA9500CULL, 0x0E020336634C43F3ULL, 0xC17B474AEB66D822ULL, 0x6A731AE3EC9BAAC2ULL, 0x8226667AE0840258ULL, 0x67D4567691CAECA5ULL, 0x1D94155C4875ADB5ULL, 0x6D00FD985B813FDFULL, 0x51286EFCB774CD06ULL, 0x5E8834471FA744AFULL, 0xF72CA0AEE761AE2EULL, 0xBE40E4CDAEE8E09AULL, 0xE9970BBB5118F665ULL, 0x726E4BEB33DF1964ULL, 0x703B000729199762ULL, 0x4631D816F5EF30A7ULL, 0xB880B5B51504A6BEULL, 0x641793C37ED84B6CULL, 0x7B21ED77F6E97D96ULL, 0x776306312EF96B73ULL, 0xAE528948E86FF3F4ULL, 0x53DBD7F286A3F8F8ULL, 0x16CADCE74CFC1063ULL, 0x005C19BDFA52C6DDULL, 0x68868F5D64D46AD3ULL, 0x3A9D512CCF1E186AULL, 0x367E62C2385660AEULL, 0xE359E7EA77DCB1D7ULL, 0x526C0773749ABE6EULL, 0x735AE5F9D09F734BULL, 0x493FC7CC8A558BA8ULL, 0xB0B9C1533041AB45ULL, 0x321958BA470A59BDULL, 0x852DB00B5F46C393ULL, 0x91209B2BD336B0E5ULL, 0x6E604F7D659EF19FULL, 0xB99A8AE2782CCB24ULL, 0xCCF52AB6C814C4C7ULL, 0x4727D9AFBE11727BULL, 0x7E950D0C0121B34DULL, 0x756F435670AD471FULL, 0xF5ADD442615A6849ULL, 0x4E87E09980B9957AULL, 0x2ACFA1DF50AEE355ULL, 0xD898263AFD2FD556ULL, 0xC8F4924DD80C8FD6ULL, 0xCF99CA3D754A173AULL, 0xFE477BACAF91BF3CULL, 0xED5371F6D690C12DULL, 0x831A5C285E687094ULL, 0xC5D3C90A3708A0A4ULL, 0x0F7F903717D06580ULL, 0x19F9BB13B8FDF27FULL, 0xB1BD6F1B4D502843ULL, 0x1C761BA38FFF4012ULL, 0x0D1530C4E2E21F3BULL, 0x8943CE69A7372C8AULL, 0xE5184E11FEB5CE66ULL, 0x618BDB80BD736621ULL, 0x7D29BAD68B574D0BULL, 0x81BB613E25E6FE5BULL, 0x071C9C10BC07913FULL, 0xC7BEEB7909AC2D97ULL, 0xC3E58D353BC5D757ULL, 0xEB017892F38F61E8ULL, 0xD4EFFB9C9B1CC21AULL, 0x99727D26F494F7ABULL, 0xA3E063A2956B3E03ULL, 0x9D4A8B9A4AA09C30ULL, 0x3F6AB7D500090FB4ULL, 0x9CC0F2A057268AC0ULL, 0x3DEE9D2DEDBF42D1ULL, 0x330F49C87960A972ULL, 0xC6B2720287421B41ULL, 0x0AC59EC07C00369CULL, 0xEF4EAC49CB353425ULL, 0xF450244EEF0129D8ULL, 0x8ACC46E5CAF4DEB6ULL, 0x2FFEAB63989263F7ULL, 0x8F7CB9FE5D7A4578ULL, 0x5BD8F7644E634635ULL, 0x427A7315BF2DC900ULL, 0x17D0C4AA2125261CULL, 0x3992486C93518E50ULL, 0xB4CBFEE0A2D7D4C3ULL, 0x7C75D6202C5DDD8DULL, 0xDBC295D8E35B6C61ULL, 0x60B369D302032B19ULL, 0xCE42685FDCE44132ULL, 0x06F3DDB9DDF65610ULL, 0x8EA4D21DB5E148F0ULL, 0x20B0FCE62FCD496FULL, 0x2C1B912358B0EE31ULL, 0xB28317B818F5A308ULL, 0xA89C1E189CA6D2CFULL, 0x0C6B18576AAADBC8ULL, 0xB65DEAA91299FAE3ULL, 0xFB2B794B7F1027E7ULL, 0x04E4317F443B5BEBULL, 0x4B852D325939D0A6ULL, 0xD5AE6BEEFB207FFCULL, 0x309682B281C7D374ULL, 0xBAE309A194C3B475ULL, 0x8CC3F97B13B49F05ULL, 0x98A9422FF8293967ULL, 0x244B16B01076FF7CULL, 0xF8BF571C663D67EEULL, 0x1F0D6758EEE30DA1ULL, 0xC9B611D97ADEB9B7ULL, 0xB7AFD5887B6C57A2ULL, 0x6290AE846B984FE1ULL, 0x94DF4CDEACC1A5FDULL, 0x058A5BD1C5483AFFULL, 0x63166CC142BA3C37ULL, 0x8DB8526EB2F76F40ULL, 0xE10880036F0D6D4EULL, 0x9E0523C9971D311DULL, 0x45EC2824CC7CD691ULL, 0x575B8359E62382C9ULL, 0xFA9E400DC4889995ULL, 0xD1823ECB45721568ULL, 0xDAFD983B8206082FULL, 0xAA7D29082386A8CBULL, 0x269FCD4403B87588ULL, 0x1B91F5F728BDD1E0ULL, 0xE4669F39040201F6ULL, 0x7A1D7C218CF04ADEULL, 0x65623C29D79CE5CEULL, 0x2368449096C00BB1ULL, 0xAB9BF1879DA503BAULL, 0xBC23ECB1A458058EULL, 0x9A58DF01BB401ECCULL, 0xA070E868A85F143DULL, 0x4FF188307DF2239EULL, 0x14D565B41A641183ULL, 0xEE13337452701602ULL, 0x950E3DCF3F285E09ULL, 0x59930254B9C80953ULL, 0x3BF299408930DA6DULL, 0xA955943F53691387ULL, 0xA15EDECAA9CB8784ULL, 0x29142127352BE9A0ULL, 0x76F0371FFF4E7AFBULL, 0x0239F450274F2228ULL, 0xBB073AF01D5E868BULL, 0xBFC80571C10E96C1ULL, 0xD267088568222E23ULL, 0x9671A3D48E80B5B0ULL, 0x55B5D38AE193BB81ULL, 0x693AE2D0A18B04B8ULL, 0x5C48B4ECADD5335FULL, 0xFD743B194916A1CAULL, 0x2577018134BE98C4ULL, 0xE77987E83C54A4ADULL, 0x28E11014DA33E1B9ULL, 0x270CC59E226AA213ULL, 0x71495F756D1A5F60ULL, 0x9BE853FB60AFEF77ULL, 0xADC786A7F7443DBFULL, 0x0904456173B29A82ULL, 0x58BC7A66C232BD5EULL, 0xF306558C673AC8B2ULL, 0x41F639C6B6C9772AULL, 0x216DEFE99FDA35DAULL, 0x11640CC71C7BE615ULL, 0x93C43694565C5527ULL, 0xEA038E6246777839ULL, 0xF9ABF3CE5A3E2469ULL, 0x741E768D0FD312D2ULL, 0x0144B883CED652C6ULL, 0xC20B5A5BA33F8552ULL, 0x1AE69633C3435A9DULL, 0x97A28CA4088CFDECULL, 0x8824A43C1E96F420ULL, 0x37612FA66EEEA746ULL, 0x6B4CB165F9CF0E5AULL, 0x43AA1C06A0ABFB4AULL, 0x7F4DC26FF162796BULL, 0x6CBACC8E54ED9B0FULL, 0xA6B7FFEFD2BB253EULL, 0x2E25BC95B0A29D4FULL, 0x86D6A58BDEF1388CULL, 0xDED74AC576B6F054ULL, 0x8030BDBC2B45805DULL, 0x3C81AF70E94D9289ULL, 0x3EFF6DDA9E3100DBULL, 0xB38DC39FDFCC8847ULL, 0x123885528D17B87EULL, 0xF2DA0ED240B1B642ULL, 0x44CEFADCD54BF9A9ULL, 0x1312200E433C7EE6ULL, 0x9FFCC84F3A78C748ULL, 0xF0CD1F72248576BBULL, 0xEC6974053638CFE4ULL, 0x2BA7B67C0CEC4E4CULL, 0xAC2F4DF3E5CE32EDULL, 0xCB33D14326EA4C11ULL, 0xA4E9044CC77E58BCULL, 0x5F513293D934FCEFULL, 0x5DC9645506E55444ULL, 0x50DE418F317DE40AULL, 0x388CB31A69DDE259ULL, 0x2DB4A83455820A86ULL, 0x9010A91E84711AE9ULL, 0x4DF7F0B7B1498371ULL, 0xD62A2EABC0977179ULL, 0x22FAC097AA8D5C0EULL }; const u64bit Tiger::SBOX3[256] = { 0xF49FCC2FF1DAF39BULL, 0x487FD5C66FF29281ULL, 0xE8A30667FCDCA83FULL, 0x2C9B4BE3D2FCCE63ULL, 0xDA3FF74B93FBBBC2ULL, 0x2FA165D2FE70BA66ULL, 0xA103E279970E93D4ULL, 0xBECDEC77B0E45E71ULL, 0xCFB41E723985E497ULL, 0xB70AAA025EF75017ULL, 0xD42309F03840B8E0ULL, 0x8EFC1AD035898579ULL, 0x96C6920BE2B2ABC5ULL, 0x66AF4163375A9172ULL, 0x2174ABDCCA7127FBULL, 0xB33CCEA64A72FF41ULL, 0xF04A4933083066A5ULL, 0x8D970ACDD7289AF5ULL, 0x8F96E8E031C8C25EULL, 0xF3FEC02276875D47ULL, 0xEC7BF310056190DDULL, 0xF5ADB0AEBB0F1491ULL, 0x9B50F8850FD58892ULL, 0x4975488358B74DE8ULL, 0xA3354FF691531C61ULL, 0x0702BBE481D2C6EEULL, 0x89FB24057DEDED98ULL, 0xAC3075138596E902ULL, 0x1D2D3580172772EDULL, 0xEB738FC28E6BC30DULL, 0x5854EF8F63044326ULL, 0x9E5C52325ADD3BBEULL, 0x90AA53CF325C4623ULL, 0xC1D24D51349DD067ULL, 0x2051CFEEA69EA624ULL, 0x13220F0A862E7E4FULL, 0xCE39399404E04864ULL, 0xD9C42CA47086FCB7ULL, 0x685AD2238A03E7CCULL, 0x066484B2AB2FF1DBULL, 0xFE9D5D70EFBF79ECULL, 0x5B13B9DD9C481854ULL, 0x15F0D475ED1509ADULL, 0x0BEBCD060EC79851ULL, 0xD58C6791183AB7F8ULL, 0xD1187C5052F3EEE4ULL, 0xC95D1192E54E82FFULL, 0x86EEA14CB9AC6CA2ULL, 0x3485BEB153677D5DULL, 0xDD191D781F8C492AULL, 0xF60866BAA784EBF9ULL, 0x518F643BA2D08C74ULL, 0x8852E956E1087C22ULL, 0xA768CB8DC410AE8DULL, 0x38047726BFEC8E1AULL, 0xA67738B4CD3B45AAULL, 0xAD16691CEC0DDE19ULL, 0xC6D4319380462E07ULL, 0xC5A5876D0BA61938ULL, 0x16B9FA1FA58FD840ULL, 0x188AB1173CA74F18ULL, 0xABDA2F98C99C021FULL, 0x3E0580AB134AE816ULL, 0x5F3B05B773645ABBULL, 0x2501A2BE5575F2F6ULL, 0x1B2F74004E7E8BA9ULL, 0x1CD7580371E8D953ULL, 0x7F6ED89562764E30ULL, 0xB15926FF596F003DULL, 0x9F65293DA8C5D6B9ULL, 0x6ECEF04DD690F84CULL, 0x4782275FFF33AF88ULL, 0xE41433083F820801ULL, 0xFD0DFE409A1AF9B5ULL, 0x4325A3342CDB396BULL, 0x8AE77E62B301B252ULL, 0xC36F9E9F6655615AULL, 0x85455A2D92D32C09ULL, 0xF2C7DEA949477485ULL, 0x63CFB4C133A39EBAULL, 0x83B040CC6EBC5462ULL, 0x3B9454C8FDB326B0ULL, 0x56F56A9E87FFD78CULL, 0x2DC2940D99F42BC6ULL, 0x98F7DF096B096E2DULL, 0x19A6E01E3AD852BFULL, 0x42A99CCBDBD4B40BULL, 0xA59998AF45E9C559ULL, 0x366295E807D93186ULL, 0x6B48181BFAA1F773ULL, 0x1FEC57E2157A0A1DULL, 0x4667446AF6201AD5ULL, 0xE615EBCACFB0F075ULL, 0xB8F31F4F68290778ULL, 0x22713ED6CE22D11EULL, 0x3057C1A72EC3C93BULL, 0xCB46ACC37C3F1F2FULL, 0xDBB893FD02AAF50EULL, 0x331FD92E600B9FCFULL, 0xA498F96148EA3AD6ULL, 0xA8D8426E8B6A83EAULL, 0xA089B274B7735CDCULL, 0x87F6B3731E524A11ULL, 0x118808E5CBC96749ULL, 0x9906E4C7B19BD394ULL, 0xAFED7F7E9B24A20CULL, 0x6509EADEEB3644A7ULL, 0x6C1EF1D3E8EF0EDEULL, 0xB9C97D43E9798FB4ULL, 0xA2F2D784740C28A3ULL, 0x7B8496476197566FULL, 0x7A5BE3E6B65F069DULL, 0xF96330ED78BE6F10ULL, 0xEEE60DE77A076A15ULL, 0x2B4BEE4AA08B9BD0ULL, 0x6A56A63EC7B8894EULL, 0x02121359BA34FEF4ULL, 0x4CBF99F8283703FCULL, 0x398071350CAF30C8ULL, 0xD0A77A89F017687AULL, 0xF1C1A9EB9E423569ULL, 0x8C7976282DEE8199ULL, 0x5D1737A5DD1F7ABDULL, 0x4F53433C09A9FA80ULL, 0xFA8B0C53DF7CA1D9ULL, 0x3FD9DCBC886CCB77ULL, 0xC040917CA91B4720ULL, 0x7DD00142F9D1DCDFULL, 0x8476FC1D4F387B58ULL, 0x23F8E7C5F3316503ULL, 0x032A2244E7E37339ULL, 0x5C87A5D750F5A74BULL, 0x082B4CC43698992EULL, 0xDF917BECB858F63CULL, 0x3270B8FC5BF86DDAULL, 0x10AE72BB29B5DD76ULL, 0x576AC94E7700362BULL, 0x1AD112DAC61EFB8FULL, 0x691BC30EC5FAA427ULL, 0xFF246311CC327143ULL, 0x3142368E30E53206ULL, 0x71380E31E02CA396ULL, 0x958D5C960AAD76F1ULL, 0xF8D6F430C16DA536ULL, 0xC8FFD13F1BE7E1D2ULL, 0x7578AE66004DDBE1ULL, 0x05833F01067BE646ULL, 0xBB34B5AD3BFE586DULL, 0x095F34C9A12B97F0ULL, 0x247AB64525D60CA8ULL, 0xDCDBC6F3017477D1ULL, 0x4A2E14D4DECAD24DULL, 0xBDB5E6D9BE0A1EEBULL, 0x2A7E70F7794301ABULL, 0xDEF42D8A270540FDULL, 0x01078EC0A34C22C1ULL, 0xE5DE511AF4C16387ULL, 0x7EBB3A52BD9A330AULL, 0x77697857AA7D6435ULL, 0x004E831603AE4C32ULL, 0xE7A21020AD78E312ULL, 0x9D41A70C6AB420F2ULL, 0x28E06C18EA1141E6ULL, 0xD2B28CBD984F6B28ULL, 0x26B75F6C446E9D83ULL, 0xBA47568C4D418D7FULL, 0xD80BADBFE6183D8EULL, 0x0E206D7F5F166044ULL, 0xE258A43911CBCA3EULL, 0x723A1746B21DC0BCULL, 0xC7CAA854F5D7CDD3ULL, 0x7CAC32883D261D9CULL, 0x7690C26423BA942CULL, 0x17E55524478042B8ULL, 0xE0BE477656A2389FULL, 0x4D289B5E67AB2DA0ULL, 0x44862B9C8FBBFD31ULL, 0xB47CC8049D141365ULL, 0x822C1B362B91C793ULL, 0x4EB14655FB13DFD8ULL, 0x1ECBBA0714E2A97BULL, 0x6143459D5CDE5F14ULL, 0x53A8FBF1D5F0AC89ULL, 0x97EA04D81C5E5B00ULL, 0x622181A8D4FDB3F3ULL, 0xE9BCD341572A1208ULL, 0x1411258643CCE58AULL, 0x9144C5FEA4C6E0A4ULL, 0x0D33D06565CF620FULL, 0x54A48D489F219CA1ULL, 0xC43E5EAC6D63C821ULL, 0xA9728B3A72770DAFULL, 0xD7934E7B20DF87EFULL, 0xE35503B61A3E86E5ULL, 0xCAE321FBC819D504ULL, 0x129A50B3AC60BFA6ULL, 0xCD5E68EA7E9FB6C3ULL, 0xB01C90199483B1C7ULL, 0x3DE93CD5C295376CULL, 0xAED52EDF2AB9AD13ULL, 0x2E60F512C0A07884ULL, 0xBC3D86A3E36210C9ULL, 0x35269D9B163951CEULL, 0x0C7D6E2AD0CDB5FAULL, 0x59E86297D87F5733ULL, 0x298EF221898DB0E7ULL, 0x55000029D1A5AA7EULL, 0x8BC08AE1B5061B45ULL, 0xC2C31C2B6C92703AULL, 0x94CC596BAF25EF42ULL, 0x0A1D73DB22540456ULL, 0x04B6A0F9D9C4179AULL, 0xEFFDAFA2AE3D3C60ULL, 0xF7C8075BB49496C4ULL, 0x9CC5C7141D1CD4E3ULL, 0x78BD1638218E5534ULL, 0xB2F11568F850246AULL, 0xEDFABCFA9502BC29ULL, 0x796CE5F2DA23051BULL, 0xAAE128B0DC93537CULL, 0x3A493DA0EE4B29AEULL, 0xB5DF6B2C416895D7ULL, 0xFCABBD25122D7F37ULL, 0x70810B58105DC4B1ULL, 0xE10FDD37F7882A90ULL, 0x524DCAB5518A3F5CULL, 0x3C9E85878451255BULL, 0x4029828119BD34E2ULL, 0x74A05B6F5D3CECCBULL, 0xB610021542E13ECAULL, 0x0FF979D12F59E2ACULL, 0x6037DA27E4F9CC50ULL, 0x5E92975A0DF1847DULL, 0xD66DE190D3E623FEULL, 0x5032D6B87B568048ULL, 0x9A36B7CE8235216EULL, 0x80272A7A24F64B4AULL, 0x93EFED8B8C6916F7ULL, 0x37DDBFF44CCE1555ULL, 0x4B95DB5D4B99BD25ULL, 0x92D3FDA169812FC0ULL, 0xFB1A4A9A90660BB6ULL, 0x730C196946A4B9B2ULL, 0x81E289AA7F49DA68ULL, 0x64669A0F83B1A05FULL, 0x27B3FF7D9644F48BULL, 0xCC6B615C8DB675B3ULL, 0x674F20B9BCEBBE95ULL, 0x6F31238275655982ULL, 0x5AE488713E45CF05ULL, 0xBF619F9954C21157ULL, 0xEABAC46040A8EAE9ULL, 0x454C6FE9F2C0C1CDULL, 0x419CF6496412691CULL, 0xD3DC3BEF265B0F70ULL, 0x6D0E60F5C3578A9EULL }; const u64bit Tiger::SBOX4[256] = { 0x5B0E608526323C55ULL, 0x1A46C1A9FA1B59F5ULL, 0xA9E245A17C4C8FFAULL, 0x65CA5159DB2955D7ULL, 0x05DB0A76CE35AFC2ULL, 0x81EAC77EA9113D45ULL, 0x528EF88AB6AC0A0DULL, 0xA09EA253597BE3FFULL, 0x430DDFB3AC48CD56ULL, 0xC4B3A67AF45CE46FULL, 0x4ECECFD8FBE2D05EULL, 0x3EF56F10B39935F0ULL, 0x0B22D6829CD619C6ULL, 0x17FD460A74DF2069ULL, 0x6CF8CC8E8510ED40ULL, 0xD6C824BF3A6ECAA7ULL, 0x61243D581A817049ULL, 0x048BACB6BBC163A2ULL, 0xD9A38AC27D44CC32ULL, 0x7FDDFF5BAAF410ABULL, 0xAD6D495AA804824BULL, 0xE1A6A74F2D8C9F94ULL, 0xD4F7851235DEE8E3ULL, 0xFD4B7F886540D893ULL, 0x247C20042AA4BFDAULL, 0x096EA1C517D1327CULL, 0xD56966B4361A6685ULL, 0x277DA5C31221057DULL, 0x94D59893A43ACFF7ULL, 0x64F0C51CCDC02281ULL, 0x3D33BCC4FF6189DBULL, 0xE005CB184CE66AF1ULL, 0xFF5CCD1D1DB99BEAULL, 0xB0B854A7FE42980FULL, 0x7BD46A6A718D4B9FULL, 0xD10FA8CC22A5FD8CULL, 0xD31484952BE4BD31ULL, 0xC7FA975FCB243847ULL, 0x4886ED1E5846C407ULL, 0x28CDDB791EB70B04ULL, 0xC2B00BE2F573417FULL, 0x5C9590452180F877ULL, 0x7A6BDDFFF370EB00ULL, 0xCE509E38D6D9D6A4ULL, 0xEBEB0F00647FA702ULL, 0x1DCC06CF76606F06ULL, 0xE4D9F28BA286FF0AULL, 0xD85A305DC918C262ULL, 0x475B1D8732225F54ULL, 0x2D4FB51668CCB5FEULL, 0xA679B9D9D72BBA20ULL, 0x53841C0D912D43A5ULL, 0x3B7EAA48BF12A4E8ULL, 0x781E0E47F22F1DDFULL, 0xEFF20CE60AB50973ULL, 0x20D261D19DFFB742ULL, 0x16A12B03062A2E39ULL, 0x1960EB2239650495ULL, 0x251C16FED50EB8B8ULL, 0x9AC0C330F826016EULL, 0xED152665953E7671ULL, 0x02D63194A6369570ULL, 0x5074F08394B1C987ULL, 0x70BA598C90B25CE1ULL, 0x794A15810B9742F6ULL, 0x0D5925E9FCAF8C6CULL, 0x3067716CD868744EULL, 0x910AB077E8D7731BULL, 0x6A61BBDB5AC42F61ULL, 0x93513EFBF0851567ULL, 0xF494724B9E83E9D5ULL, 0xE887E1985C09648DULL, 0x34B1D3C675370CFDULL, 0xDC35E433BC0D255DULL, 0xD0AAB84234131BE0ULL, 0x08042A50B48B7EAFULL, 0x9997C4EE44A3AB35ULL, 0x829A7B49201799D0ULL, 0x263B8307B7C54441ULL, 0x752F95F4FD6A6CA6ULL, 0x927217402C08C6E5ULL, 0x2A8AB754A795D9EEULL, 0xA442F7552F72943DULL, 0x2C31334E19781208ULL, 0x4FA98D7CEAEE6291ULL, 0x55C3862F665DB309ULL, 0xBD0610175D53B1F3ULL, 0x46FE6CB840413F27ULL, 0x3FE03792DF0CFA59ULL, 0xCFE700372EB85E8FULL, 0xA7BE29E7ADBCE118ULL, 0xE544EE5CDE8431DDULL, 0x8A781B1B41F1873EULL, 0xA5C94C78A0D2F0E7ULL, 0x39412E2877B60728ULL, 0xA1265EF3AFC9A62CULL, 0xBCC2770C6A2506C5ULL, 0x3AB66DD5DCE1CE12ULL, 0xE65499D04A675B37ULL, 0x7D8F523481BFD216ULL, 0x0F6F64FCEC15F389ULL, 0x74EFBE618B5B13C8ULL, 0xACDC82B714273E1DULL, 0xDD40BFE003199D17ULL, 0x37E99257E7E061F8ULL, 0xFA52626904775AAAULL, 0x8BBBF63A463D56F9ULL, 0xF0013F1543A26E64ULL, 0xA8307E9F879EC898ULL, 0xCC4C27A4150177CCULL, 0x1B432F2CCA1D3348ULL, 0xDE1D1F8F9F6FA013ULL, 0x606602A047A7DDD6ULL, 0xD237AB64CC1CB2C7ULL, 0x9B938E7225FCD1D3ULL, 0xEC4E03708E0FF476ULL, 0xFEB2FBDA3D03C12DULL, 0xAE0BCED2EE43889AULL, 0x22CB8923EBFB4F43ULL, 0x69360D013CF7396DULL, 0x855E3602D2D4E022ULL, 0x073805BAD01F784CULL, 0x33E17A133852F546ULL, 0xDF4874058AC7B638ULL, 0xBA92B29C678AA14AULL, 0x0CE89FC76CFAADCDULL, 0x5F9D4E0908339E34ULL, 0xF1AFE9291F5923B9ULL, 0x6E3480F60F4A265FULL, 0xEEBF3A2AB29B841CULL, 0xE21938A88F91B4ADULL, 0x57DFEFF845C6D3C3ULL, 0x2F006B0BF62CAAF2ULL, 0x62F479EF6F75EE78ULL, 0x11A55AD41C8916A9ULL, 0xF229D29084FED453ULL, 0x42F1C27B16B000E6ULL, 0x2B1F76749823C074ULL, 0x4B76ECA3C2745360ULL, 0x8C98F463B91691BDULL, 0x14BCC93CF1ADE66AULL, 0x8885213E6D458397ULL, 0x8E177DF0274D4711ULL, 0xB49B73B5503F2951ULL, 0x10168168C3F96B6BULL, 0x0E3D963B63CAB0AEULL, 0x8DFC4B5655A1DB14ULL, 0xF789F1356E14DE5CULL, 0x683E68AF4E51DAC1ULL, 0xC9A84F9D8D4B0FD9ULL, 0x3691E03F52A0F9D1ULL, 0x5ED86E46E1878E80ULL, 0x3C711A0E99D07150ULL, 0x5A0865B20C4E9310ULL, 0x56FBFC1FE4F0682EULL, 0xEA8D5DE3105EDF9BULL, 0x71ABFDB12379187AULL, 0x2EB99DE1BEE77B9CULL, 0x21ECC0EA33CF4523ULL, 0x59A4D7521805C7A1ULL, 0x3896F5EB56AE7C72ULL, 0xAA638F3DB18F75DCULL, 0x9F39358DABE9808EULL, 0xB7DEFA91C00B72ACULL, 0x6B5541FD62492D92ULL, 0x6DC6DEE8F92E4D5BULL, 0x353F57ABC4BEEA7EULL, 0x735769D6DA5690CEULL, 0x0A234AA642391484ULL, 0xF6F9508028F80D9DULL, 0xB8E319A27AB3F215ULL, 0x31AD9C1151341A4DULL, 0x773C22A57BEF5805ULL, 0x45C7561A07968633ULL, 0xF913DA9E249DBE36ULL, 0xDA652D9B78A64C68ULL, 0x4C27A97F3BC334EFULL, 0x76621220E66B17F4ULL, 0x967743899ACD7D0BULL, 0xF3EE5BCAE0ED6782ULL, 0x409F753600C879FCULL, 0x06D09A39B5926DB6ULL, 0x6F83AEB0317AC588ULL, 0x01E6CA4A86381F21ULL, 0x66FF3462D19F3025ULL, 0x72207C24DDFD3BFBULL, 0x4AF6B6D3E2ECE2EBULL, 0x9C994DBEC7EA08DEULL, 0x49ACE597B09A8BC4ULL, 0xB38C4766CF0797BAULL, 0x131B9373C57C2A75ULL, 0xB1822CCE61931E58ULL, 0x9D7555B909BA1C0CULL, 0x127FAFDD937D11D2ULL, 0x29DA3BADC66D92E4ULL, 0xA2C1D57154C2ECBCULL, 0x58C5134D82F6FE24ULL, 0x1C3AE3515B62274FULL, 0xE907C82E01CB8126ULL, 0xF8ED091913E37FCBULL, 0x3249D8F9C80046C9ULL, 0x80CF9BEDE388FB63ULL, 0x1881539A116CF19EULL, 0x5103F3F76BD52457ULL, 0x15B7E6F5AE47F7A8ULL, 0xDBD7C6DED47E9CCFULL, 0x44E55C410228BB1AULL, 0xB647D4255EDB4E99ULL, 0x5D11882BB8AAFC30ULL, 0xF5098BBB29D3212AULL, 0x8FB5EA14E90296B3ULL, 0x677B942157DD025AULL, 0xFB58E7C0A390ACB5ULL, 0x89D3674C83BD4A01ULL, 0x9E2DA4DF4BF3B93BULL, 0xFCC41E328CAB4829ULL, 0x03F38C96BA582C52ULL, 0xCAD1BDBD7FD85DB2ULL, 0xBBB442C16082AE83ULL, 0xB95FE86BA5DA9AB0ULL, 0xB22E04673771A93FULL, 0x845358C9493152D8ULL, 0xBE2A488697B4541EULL, 0x95A2DC2DD38E6966ULL, 0xC02C11AC923C852BULL, 0x2388B1990DF2A87BULL, 0x7C8008FA1B4F37BEULL, 0x1F70D0C84D54E503ULL, 0x5490ADEC7ECE57D4ULL, 0x002B3C27D9063A3AULL, 0x7EAEA3848030A2BFULL, 0xC602326DED2003C0ULL, 0x83A7287D69A94086ULL, 0xC57A5FCB30F57A8AULL, 0xB56844E479EBE779ULL, 0xA373B40F05DCBCE9ULL, 0xD71A786E88570EE2ULL, 0x879CBACDBDE8F6A0ULL, 0x976AD1BCC164A32FULL, 0xAB21E25E9666D78BULL, 0x901063AAE5E5C33CULL, 0x9818B34448698D90ULL, 0xE36487AE3E1E8ABBULL, 0xAFBDF931893BDCB4ULL, 0x6345A0DC5FBBD519ULL, 0x8628FE269B9465CAULL, 0x1E5D01603F9C51ECULL, 0x4DE44006A15049B7ULL, 0xBF6C70E5F776CBB1ULL, 0x411218F2EF552BEDULL, 0xCB0C0708705A36A3ULL, 0xE74D14754F986044ULL, 0xCD56D9430EA8280EULL, 0xC12591D7535F5065ULL, 0xC83223F1720AEF96ULL, 0xC3A0396F7363A51FULL }; } /* * Tiger * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { namespace { /* * Tiger Mixing Function */ inline void mix(MemoryRegion& X) { X[0] -= X[7] ^ 0xA5A5A5A5A5A5A5A5ULL; X[1] ^= X[0]; X[2] += X[1]; X[3] -= X[2] ^ ((~X[1]) << 19); X[4] ^= X[3]; X[5] += X[4]; X[6] -= X[5] ^ ((~X[4]) >> 23); X[7] ^= X[6]; X[0] += X[7]; X[1] -= X[0] ^ ((~X[7]) << 19); X[2] ^= X[1]; X[3] += X[2]; X[4] -= X[3] ^ ((~X[2]) >> 23); X[5] ^= X[4]; X[6] += X[5]; X[7] -= X[6] ^ 0x0123456789ABCDEFULL; } } /* * Tiger Compression Function */ void Tiger::compress_n(const byte input[], size_t blocks) { u64bit A = digest[0], B = digest[1], C = digest[2]; for(size_t i = 0; i != blocks; ++i) { load_le(&X[0], input, X.size()); pass(A, B, C, X, 5); mix(X); pass(C, A, B, X, 7); mix(X); pass(B, C, A, X, 9); for(size_t j = 3; j != passes; ++j) { mix(X); pass(A, B, C, X, 9); u64bit T = A; A = C; C = B; B = T; } A = (digest[0] ^= A); B = digest[1] = B - digest[1]; C = (digest[2] += C); input += hash_block_size(); } } /* * Copy out the digest */ void Tiger::copy_out(byte output[]) { for(size_t i = 0; i != output_length(); ++i) output[i] = get_byte(7 - (i % 8), digest[i/8]); } /* * Tiger Pass */ void Tiger::pass(u64bit& A, u64bit& B, u64bit& C, const MemoryRegion& X, byte mul) { C ^= X[0]; A -= SBOX1[get_byte(7, C)] ^ SBOX2[get_byte(5, C)] ^ SBOX3[get_byte(3, C)] ^ SBOX4[get_byte(1, C)]; B += SBOX1[get_byte(0, C)] ^ SBOX2[get_byte(2, C)] ^ SBOX3[get_byte(4, C)] ^ SBOX4[get_byte(6, C)]; B *= mul; A ^= X[1]; B -= SBOX1[get_byte(7, A)] ^ SBOX2[get_byte(5, A)] ^ SBOX3[get_byte(3, A)] ^ SBOX4[get_byte(1, A)]; C += SBOX1[get_byte(0, A)] ^ SBOX2[get_byte(2, A)] ^ SBOX3[get_byte(4, A)] ^ SBOX4[get_byte(6, A)]; C *= mul; B ^= X[2]; C -= SBOX1[get_byte(7, B)] ^ SBOX2[get_byte(5, B)] ^ SBOX3[get_byte(3, B)] ^ SBOX4[get_byte(1, B)]; A += SBOX1[get_byte(0, B)] ^ SBOX2[get_byte(2, B)] ^ SBOX3[get_byte(4, B)] ^ SBOX4[get_byte(6, B)]; A *= mul; C ^= X[3]; A -= SBOX1[get_byte(7, C)] ^ SBOX2[get_byte(5, C)] ^ SBOX3[get_byte(3, C)] ^ SBOX4[get_byte(1, C)]; B += SBOX1[get_byte(0, C)] ^ SBOX2[get_byte(2, C)] ^ SBOX3[get_byte(4, C)] ^ SBOX4[get_byte(6, C)]; B *= mul; A ^= X[4]; B -= SBOX1[get_byte(7, A)] ^ SBOX2[get_byte(5, A)] ^ SBOX3[get_byte(3, A)] ^ SBOX4[get_byte(1, A)]; C += SBOX1[get_byte(0, A)] ^ SBOX2[get_byte(2, A)] ^ SBOX3[get_byte(4, A)] ^ SBOX4[get_byte(6, A)]; C *= mul; B ^= X[5]; C -= SBOX1[get_byte(7, B)] ^ SBOX2[get_byte(5, B)] ^ SBOX3[get_byte(3, B)] ^ SBOX4[get_byte(1, B)]; A += SBOX1[get_byte(0, B)] ^ SBOX2[get_byte(2, B)] ^ SBOX3[get_byte(4, B)] ^ SBOX4[get_byte(6, B)]; A *= mul; C ^= X[6]; A -= SBOX1[get_byte(7, C)] ^ SBOX2[get_byte(5, C)] ^ SBOX3[get_byte(3, C)] ^ SBOX4[get_byte(1, C)]; B += SBOX1[get_byte(0, C)] ^ SBOX2[get_byte(2, C)] ^ SBOX3[get_byte(4, C)] ^ SBOX4[get_byte(6, C)]; B *= mul; A ^= X[7]; B -= SBOX1[get_byte(7, A)] ^ SBOX2[get_byte(5, A)] ^ SBOX3[get_byte(3, A)] ^ SBOX4[get_byte(1, A)]; C += SBOX1[get_byte(0, A)] ^ SBOX2[get_byte(2, A)] ^ SBOX3[get_byte(4, A)] ^ SBOX4[get_byte(6, A)]; C *= mul; } /* * Clear memory of sensitive data */ void Tiger::clear() { MDx_HashFunction::clear(); zeroise(X); digest[0] = 0x0123456789ABCDEFULL; digest[1] = 0xFEDCBA9876543210ULL; digest[2] = 0xF096A5B4C3B2E187ULL; } /* * Return the name of this type */ std::string Tiger::name() const { return "Tiger(" + to_string(output_length()) + "," + to_string(passes) + ")"; } /* * Tiger Constructor */ Tiger::Tiger(size_t hash_len, size_t passes) : MDx_HashFunction(64, false, false), X(8), digest(3), hash_len(hash_len), passes(passes) { if(output_length() != 16 && output_length() != 20 && output_length() != 24) throw Invalid_Argument("Tiger: Illegal hash output size: " + to_string(output_length())); if(passes < 3) throw Invalid_Argument("Tiger: Invalid number of passes: " + to_string(passes)); clear(); } } /* * Diffusion Tables for Whirlpool * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { const u64bit Whirlpool::C0[256] = { 0x18186018C07830D8ULL, 0x23238C2305AF4626ULL, 0xC6C63FC67EF991B8ULL, 0xE8E887E8136FCDFBULL, 0x878726874CA113CBULL, 0xB8B8DAB8A9626D11ULL, 0x0101040108050209ULL, 0x4F4F214F426E9E0DULL, 0x3636D836ADEE6C9BULL, 0xA6A6A2A6590451FFULL, 0xD2D26FD2DEBDB90CULL, 0xF5F5F3F5FB06F70EULL, 0x7979F979EF80F296ULL, 0x6F6FA16F5FCEDE30ULL, 0x91917E91FCEF3F6DULL, 0x52525552AA07A4F8ULL, 0x60609D6027FDC047ULL, 0xBCBCCABC89766535ULL, 0x9B9B569BACCD2B37ULL, 0x8E8E028E048C018AULL, 0xA3A3B6A371155BD2ULL, 0x0C0C300C603C186CULL, 0x7B7BF17BFF8AF684ULL, 0x3535D435B5E16A80ULL, 0x1D1D741DE8693AF5ULL, 0xE0E0A7E05347DDB3ULL, 0xD7D77BD7F6ACB321ULL, 0xC2C22FC25EED999CULL, 0x2E2EB82E6D965C43ULL, 0x4B4B314B627A9629ULL, 0xFEFEDFFEA321E15DULL, 0x575741578216AED5ULL, 0x15155415A8412ABDULL, 0x7777C1779FB6EEE8ULL, 0x3737DC37A5EB6E92ULL, 0xE5E5B3E57B56D79EULL, 0x9F9F469F8CD92313ULL, 0xF0F0E7F0D317FD23ULL, 0x4A4A354A6A7F9420ULL, 0xDADA4FDA9E95A944ULL, 0x58587D58FA25B0A2ULL, 0xC9C903C906CA8FCFULL, 0x2929A429558D527CULL, 0x0A0A280A5022145AULL, 0xB1B1FEB1E14F7F50ULL, 0xA0A0BAA0691A5DC9ULL, 0x6B6BB16B7FDAD614ULL, 0x85852E855CAB17D9ULL, 0xBDBDCEBD8173673CULL, 0x5D5D695DD234BA8FULL, 0x1010401080502090ULL, 0xF4F4F7F4F303F507ULL, 0xCBCB0BCB16C08BDDULL, 0x3E3EF83EEDC67CD3ULL, 0x0505140528110A2DULL, 0x676781671FE6CE78ULL, 0xE4E4B7E47353D597ULL, 0x27279C2725BB4E02ULL, 0x4141194132588273ULL, 0x8B8B168B2C9D0BA7ULL, 0xA7A7A6A7510153F6ULL, 0x7D7DE97DCF94FAB2ULL, 0x95956E95DCFB3749ULL, 0xD8D847D88E9FAD56ULL, 0xFBFBCBFB8B30EB70ULL, 0xEEEE9FEE2371C1CDULL, 0x7C7CED7CC791F8BBULL, 0x6666856617E3CC71ULL, 0xDDDD53DDA68EA77BULL, 0x17175C17B84B2EAFULL, 0x4747014702468E45ULL, 0x9E9E429E84DC211AULL, 0xCACA0FCA1EC589D4ULL, 0x2D2DB42D75995A58ULL, 0xBFBFC6BF9179632EULL, 0x07071C07381B0E3FULL, 0xADAD8EAD012347ACULL, 0x5A5A755AEA2FB4B0ULL, 0x838336836CB51BEFULL, 0x3333CC3385FF66B6ULL, 0x636391633FF2C65CULL, 0x02020802100A0412ULL, 0xAAAA92AA39384993ULL, 0x7171D971AFA8E2DEULL, 0xC8C807C80ECF8DC6ULL, 0x19196419C87D32D1ULL, 0x494939497270923BULL, 0xD9D943D9869AAF5FULL, 0xF2F2EFF2C31DF931ULL, 0xE3E3ABE34B48DBA8ULL, 0x5B5B715BE22AB6B9ULL, 0x88881A8834920DBCULL, 0x9A9A529AA4C8293EULL, 0x262698262DBE4C0BULL, 0x3232C8328DFA64BFULL, 0xB0B0FAB0E94A7D59ULL, 0xE9E983E91B6ACFF2ULL, 0x0F0F3C0F78331E77ULL, 0xD5D573D5E6A6B733ULL, 0x80803A8074BA1DF4ULL, 0xBEBEC2BE997C6127ULL, 0xCDCD13CD26DE87EBULL, 0x3434D034BDE46889ULL, 0x48483D487A759032ULL, 0xFFFFDBFFAB24E354ULL, 0x7A7AF57AF78FF48DULL, 0x90907A90F4EA3D64ULL, 0x5F5F615FC23EBE9DULL, 0x202080201DA0403DULL, 0x6868BD6867D5D00FULL, 0x1A1A681AD07234CAULL, 0xAEAE82AE192C41B7ULL, 0xB4B4EAB4C95E757DULL, 0x54544D549A19A8CEULL, 0x93937693ECE53B7FULL, 0x222288220DAA442FULL, 0x64648D6407E9C863ULL, 0xF1F1E3F1DB12FF2AULL, 0x7373D173BFA2E6CCULL, 0x12124812905A2482ULL, 0x40401D403A5D807AULL, 0x0808200840281048ULL, 0xC3C32BC356E89B95ULL, 0xECEC97EC337BC5DFULL, 0xDBDB4BDB9690AB4DULL, 0xA1A1BEA1611F5FC0ULL, 0x8D8D0E8D1C830791ULL, 0x3D3DF43DF5C97AC8ULL, 0x97976697CCF1335BULL, 0x0000000000000000ULL, 0xCFCF1BCF36D483F9ULL, 0x2B2BAC2B4587566EULL, 0x7676C57697B3ECE1ULL, 0x8282328264B019E6ULL, 0xD6D67FD6FEA9B128ULL, 0x1B1B6C1BD87736C3ULL, 0xB5B5EEB5C15B7774ULL, 0xAFAF86AF112943BEULL, 0x6A6AB56A77DFD41DULL, 0x50505D50BA0DA0EAULL, 0x45450945124C8A57ULL, 0xF3F3EBF3CB18FB38ULL, 0x3030C0309DF060ADULL, 0xEFEF9BEF2B74C3C4ULL, 0x3F3FFC3FE5C37EDAULL, 0x55554955921CAAC7ULL, 0xA2A2B2A2791059DBULL, 0xEAEA8FEA0365C9E9ULL, 0x656589650FECCA6AULL, 0xBABAD2BAB9686903ULL, 0x2F2FBC2F65935E4AULL, 0xC0C027C04EE79D8EULL, 0xDEDE5FDEBE81A160ULL, 0x1C1C701CE06C38FCULL, 0xFDFDD3FDBB2EE746ULL, 0x4D4D294D52649A1FULL, 0x92927292E4E03976ULL, 0x7575C9758FBCEAFAULL, 0x06061806301E0C36ULL, 0x8A8A128A249809AEULL, 0xB2B2F2B2F940794BULL, 0xE6E6BFE66359D185ULL, 0x0E0E380E70361C7EULL, 0x1F1F7C1FF8633EE7ULL, 0x6262956237F7C455ULL, 0xD4D477D4EEA3B53AULL, 0xA8A89AA829324D81ULL, 0x96966296C4F43152ULL, 0xF9F9C3F99B3AEF62ULL, 0xC5C533C566F697A3ULL, 0x2525942535B14A10ULL, 0x59597959F220B2ABULL, 0x84842A8454AE15D0ULL, 0x7272D572B7A7E4C5ULL, 0x3939E439D5DD72ECULL, 0x4C4C2D4C5A619816ULL, 0x5E5E655ECA3BBC94ULL, 0x7878FD78E785F09FULL, 0x3838E038DDD870E5ULL, 0x8C8C0A8C14860598ULL, 0xD1D163D1C6B2BF17ULL, 0xA5A5AEA5410B57E4ULL, 0xE2E2AFE2434DD9A1ULL, 0x616199612FF8C24EULL, 0xB3B3F6B3F1457B42ULL, 0x2121842115A54234ULL, 0x9C9C4A9C94D62508ULL, 0x1E1E781EF0663CEEULL, 0x4343114322528661ULL, 0xC7C73BC776FC93B1ULL, 0xFCFCD7FCB32BE54FULL, 0x0404100420140824ULL, 0x51515951B208A2E3ULL, 0x99995E99BCC72F25ULL, 0x6D6DA96D4FC4DA22ULL, 0x0D0D340D68391A65ULL, 0xFAFACFFA8335E979ULL, 0xDFDF5BDFB684A369ULL, 0x7E7EE57ED79BFCA9ULL, 0x242490243DB44819ULL, 0x3B3BEC3BC5D776FEULL, 0xABAB96AB313D4B9AULL, 0xCECE1FCE3ED181F0ULL, 0x1111441188552299ULL, 0x8F8F068F0C890383ULL, 0x4E4E254E4A6B9C04ULL, 0xB7B7E6B7D1517366ULL, 0xEBEB8BEB0B60CBE0ULL, 0x3C3CF03CFDCC78C1ULL, 0x81813E817CBF1FFDULL, 0x94946A94D4FE3540ULL, 0xF7F7FBF7EB0CF31CULL, 0xB9B9DEB9A1676F18ULL, 0x13134C13985F268BULL, 0x2C2CB02C7D9C5851ULL, 0xD3D36BD3D6B8BB05ULL, 0xE7E7BBE76B5CD38CULL, 0x6E6EA56E57CBDC39ULL, 0xC4C437C46EF395AAULL, 0x03030C03180F061BULL, 0x565645568A13ACDCULL, 0x44440D441A49885EULL, 0x7F7FE17FDF9EFEA0ULL, 0xA9A99EA921374F88ULL, 0x2A2AA82A4D825467ULL, 0xBBBBD6BBB16D6B0AULL, 0xC1C123C146E29F87ULL, 0x53535153A202A6F1ULL, 0xDCDC57DCAE8BA572ULL, 0x0B0B2C0B58271653ULL, 0x9D9D4E9D9CD32701ULL, 0x6C6CAD6C47C1D82BULL, 0x3131C43195F562A4ULL, 0x7474CD7487B9E8F3ULL, 0xF6F6FFF6E309F115ULL, 0x464605460A438C4CULL, 0xACAC8AAC092645A5ULL, 0x89891E893C970FB5ULL, 0x14145014A04428B4ULL, 0xE1E1A3E15B42DFBAULL, 0x16165816B04E2CA6ULL, 0x3A3AE83ACDD274F7ULL, 0x6969B9696FD0D206ULL, 0x09092409482D1241ULL, 0x7070DD70A7ADE0D7ULL, 0xB6B6E2B6D954716FULL, 0xD0D067D0CEB7BD1EULL, 0xEDED93ED3B7EC7D6ULL, 0xCCCC17CC2EDB85E2ULL, 0x424215422A578468ULL, 0x98985A98B4C22D2CULL, 0xA4A4AAA4490E55EDULL, 0x2828A0285D885075ULL, 0x5C5C6D5CDA31B886ULL, 0xF8F8C7F8933FED6BULL, 0x8686228644A411C2ULL }; const u64bit Whirlpool::C1[256] = { 0xD818186018C07830ULL, 0x2623238C2305AF46ULL, 0xB8C6C63FC67EF991ULL, 0xFBE8E887E8136FCDULL, 0xCB878726874CA113ULL, 0x11B8B8DAB8A9626DULL, 0x0901010401080502ULL, 0x0D4F4F214F426E9EULL, 0x9B3636D836ADEE6CULL, 0xFFA6A6A2A6590451ULL, 0x0CD2D26FD2DEBDB9ULL, 0x0EF5F5F3F5FB06F7ULL, 0x967979F979EF80F2ULL, 0x306F6FA16F5FCEDEULL, 0x6D91917E91FCEF3FULL, 0xF852525552AA07A4ULL, 0x4760609D6027FDC0ULL, 0x35BCBCCABC897665ULL, 0x379B9B569BACCD2BULL, 0x8A8E8E028E048C01ULL, 0xD2A3A3B6A371155BULL, 0x6C0C0C300C603C18ULL, 0x847B7BF17BFF8AF6ULL, 0x803535D435B5E16AULL, 0xF51D1D741DE8693AULL, 0xB3E0E0A7E05347DDULL, 0x21D7D77BD7F6ACB3ULL, 0x9CC2C22FC25EED99ULL, 0x432E2EB82E6D965CULL, 0x294B4B314B627A96ULL, 0x5DFEFEDFFEA321E1ULL, 0xD5575741578216AEULL, 0xBD15155415A8412AULL, 0xE87777C1779FB6EEULL, 0x923737DC37A5EB6EULL, 0x9EE5E5B3E57B56D7ULL, 0x139F9F469F8CD923ULL, 0x23F0F0E7F0D317FDULL, 0x204A4A354A6A7F94ULL, 0x44DADA4FDA9E95A9ULL, 0xA258587D58FA25B0ULL, 0xCFC9C903C906CA8FULL, 0x7C2929A429558D52ULL, 0x5A0A0A280A502214ULL, 0x50B1B1FEB1E14F7FULL, 0xC9A0A0BAA0691A5DULL, 0x146B6BB16B7FDAD6ULL, 0xD985852E855CAB17ULL, 0x3CBDBDCEBD817367ULL, 0x8F5D5D695DD234BAULL, 0x9010104010805020ULL, 0x07F4F4F7F4F303F5ULL, 0xDDCBCB0BCB16C08BULL, 0xD33E3EF83EEDC67CULL, 0x2D0505140528110AULL, 0x78676781671FE6CEULL, 0x97E4E4B7E47353D5ULL, 0x0227279C2725BB4EULL, 0x7341411941325882ULL, 0xA78B8B168B2C9D0BULL, 0xF6A7A7A6A7510153ULL, 0xB27D7DE97DCF94FAULL, 0x4995956E95DCFB37ULL, 0x56D8D847D88E9FADULL, 0x70FBFBCBFB8B30EBULL, 0xCDEEEE9FEE2371C1ULL, 0xBB7C7CED7CC791F8ULL, 0x716666856617E3CCULL, 0x7BDDDD53DDA68EA7ULL, 0xAF17175C17B84B2EULL, 0x454747014702468EULL, 0x1A9E9E429E84DC21ULL, 0xD4CACA0FCA1EC589ULL, 0x582D2DB42D75995AULL, 0x2EBFBFC6BF917963ULL, 0x3F07071C07381B0EULL, 0xACADAD8EAD012347ULL, 0xB05A5A755AEA2FB4ULL, 0xEF838336836CB51BULL, 0xB63333CC3385FF66ULL, 0x5C636391633FF2C6ULL, 0x1202020802100A04ULL, 0x93AAAA92AA393849ULL, 0xDE7171D971AFA8E2ULL, 0xC6C8C807C80ECF8DULL, 0xD119196419C87D32ULL, 0x3B49493949727092ULL, 0x5FD9D943D9869AAFULL, 0x31F2F2EFF2C31DF9ULL, 0xA8E3E3ABE34B48DBULL, 0xB95B5B715BE22AB6ULL, 0xBC88881A8834920DULL, 0x3E9A9A529AA4C829ULL, 0x0B262698262DBE4CULL, 0xBF3232C8328DFA64ULL, 0x59B0B0FAB0E94A7DULL, 0xF2E9E983E91B6ACFULL, 0x770F0F3C0F78331EULL, 0x33D5D573D5E6A6B7ULL, 0xF480803A8074BA1DULL, 0x27BEBEC2BE997C61ULL, 0xEBCDCD13CD26DE87ULL, 0x893434D034BDE468ULL, 0x3248483D487A7590ULL, 0x54FFFFDBFFAB24E3ULL, 0x8D7A7AF57AF78FF4ULL, 0x6490907A90F4EA3DULL, 0x9D5F5F615FC23EBEULL, 0x3D202080201DA040ULL, 0x0F6868BD6867D5D0ULL, 0xCA1A1A681AD07234ULL, 0xB7AEAE82AE192C41ULL, 0x7DB4B4EAB4C95E75ULL, 0xCE54544D549A19A8ULL, 0x7F93937693ECE53BULL, 0x2F222288220DAA44ULL, 0x6364648D6407E9C8ULL, 0x2AF1F1E3F1DB12FFULL, 0xCC7373D173BFA2E6ULL, 0x8212124812905A24ULL, 0x7A40401D403A5D80ULL, 0x4808082008402810ULL, 0x95C3C32BC356E89BULL, 0xDFECEC97EC337BC5ULL, 0x4DDBDB4BDB9690ABULL, 0xC0A1A1BEA1611F5FULL, 0x918D8D0E8D1C8307ULL, 0xC83D3DF43DF5C97AULL, 0x5B97976697CCF133ULL, 0x0000000000000000ULL, 0xF9CFCF1BCF36D483ULL, 0x6E2B2BAC2B458756ULL, 0xE17676C57697B3ECULL, 0xE68282328264B019ULL, 0x28D6D67FD6FEA9B1ULL, 0xC31B1B6C1BD87736ULL, 0x74B5B5EEB5C15B77ULL, 0xBEAFAF86AF112943ULL, 0x1D6A6AB56A77DFD4ULL, 0xEA50505D50BA0DA0ULL, 0x5745450945124C8AULL, 0x38F3F3EBF3CB18FBULL, 0xAD3030C0309DF060ULL, 0xC4EFEF9BEF2B74C3ULL, 0xDA3F3FFC3FE5C37EULL, 0xC755554955921CAAULL, 0xDBA2A2B2A2791059ULL, 0xE9EAEA8FEA0365C9ULL, 0x6A656589650FECCAULL, 0x03BABAD2BAB96869ULL, 0x4A2F2FBC2F65935EULL, 0x8EC0C027C04EE79DULL, 0x60DEDE5FDEBE81A1ULL, 0xFC1C1C701CE06C38ULL, 0x46FDFDD3FDBB2EE7ULL, 0x1F4D4D294D52649AULL, 0x7692927292E4E039ULL, 0xFA7575C9758FBCEAULL, 0x3606061806301E0CULL, 0xAE8A8A128A249809ULL, 0x4BB2B2F2B2F94079ULL, 0x85E6E6BFE66359D1ULL, 0x7E0E0E380E70361CULL, 0xE71F1F7C1FF8633EULL, 0x556262956237F7C4ULL, 0x3AD4D477D4EEA3B5ULL, 0x81A8A89AA829324DULL, 0x5296966296C4F431ULL, 0x62F9F9C3F99B3AEFULL, 0xA3C5C533C566F697ULL, 0x102525942535B14AULL, 0xAB59597959F220B2ULL, 0xD084842A8454AE15ULL, 0xC57272D572B7A7E4ULL, 0xEC3939E439D5DD72ULL, 0x164C4C2D4C5A6198ULL, 0x945E5E655ECA3BBCULL, 0x9F7878FD78E785F0ULL, 0xE53838E038DDD870ULL, 0x988C8C0A8C148605ULL, 0x17D1D163D1C6B2BFULL, 0xE4A5A5AEA5410B57ULL, 0xA1E2E2AFE2434DD9ULL, 0x4E616199612FF8C2ULL, 0x42B3B3F6B3F1457BULL, 0x342121842115A542ULL, 0x089C9C4A9C94D625ULL, 0xEE1E1E781EF0663CULL, 0x6143431143225286ULL, 0xB1C7C73BC776FC93ULL, 0x4FFCFCD7FCB32BE5ULL, 0x2404041004201408ULL, 0xE351515951B208A2ULL, 0x2599995E99BCC72FULL, 0x226D6DA96D4FC4DAULL, 0x650D0D340D68391AULL, 0x79FAFACFFA8335E9ULL, 0x69DFDF5BDFB684A3ULL, 0xA97E7EE57ED79BFCULL, 0x19242490243DB448ULL, 0xFE3B3BEC3BC5D776ULL, 0x9AABAB96AB313D4BULL, 0xF0CECE1FCE3ED181ULL, 0x9911114411885522ULL, 0x838F8F068F0C8903ULL, 0x044E4E254E4A6B9CULL, 0x66B7B7E6B7D15173ULL, 0xE0EBEB8BEB0B60CBULL, 0xC13C3CF03CFDCC78ULL, 0xFD81813E817CBF1FULL, 0x4094946A94D4FE35ULL, 0x1CF7F7FBF7EB0CF3ULL, 0x18B9B9DEB9A1676FULL, 0x8B13134C13985F26ULL, 0x512C2CB02C7D9C58ULL, 0x05D3D36BD3D6B8BBULL, 0x8CE7E7BBE76B5CD3ULL, 0x396E6EA56E57CBDCULL, 0xAAC4C437C46EF395ULL, 0x1B03030C03180F06ULL, 0xDC565645568A13ACULL, 0x5E44440D441A4988ULL, 0xA07F7FE17FDF9EFEULL, 0x88A9A99EA921374FULL, 0x672A2AA82A4D8254ULL, 0x0ABBBBD6BBB16D6BULL, 0x87C1C123C146E29FULL, 0xF153535153A202A6ULL, 0x72DCDC57DCAE8BA5ULL, 0x530B0B2C0B582716ULL, 0x019D9D4E9D9CD327ULL, 0x2B6C6CAD6C47C1D8ULL, 0xA43131C43195F562ULL, 0xF37474CD7487B9E8ULL, 0x15F6F6FFF6E309F1ULL, 0x4C464605460A438CULL, 0xA5ACAC8AAC092645ULL, 0xB589891E893C970FULL, 0xB414145014A04428ULL, 0xBAE1E1A3E15B42DFULL, 0xA616165816B04E2CULL, 0xF73A3AE83ACDD274ULL, 0x066969B9696FD0D2ULL, 0x4109092409482D12ULL, 0xD77070DD70A7ADE0ULL, 0x6FB6B6E2B6D95471ULL, 0x1ED0D067D0CEB7BDULL, 0xD6EDED93ED3B7EC7ULL, 0xE2CCCC17CC2EDB85ULL, 0x68424215422A5784ULL, 0x2C98985A98B4C22DULL, 0xEDA4A4AAA4490E55ULL, 0x752828A0285D8850ULL, 0x865C5C6D5CDA31B8ULL, 0x6BF8F8C7F8933FEDULL, 0xC28686228644A411ULL }; const u64bit Whirlpool::C2[256] = { 0x30D818186018C078ULL, 0x462623238C2305AFULL, 0x91B8C6C63FC67EF9ULL, 0xCDFBE8E887E8136FULL, 0x13CB878726874CA1ULL, 0x6D11B8B8DAB8A962ULL, 0x0209010104010805ULL, 0x9E0D4F4F214F426EULL, 0x6C9B3636D836ADEEULL, 0x51FFA6A6A2A65904ULL, 0xB90CD2D26FD2DEBDULL, 0xF70EF5F5F3F5FB06ULL, 0xF2967979F979EF80ULL, 0xDE306F6FA16F5FCEULL, 0x3F6D91917E91FCEFULL, 0xA4F852525552AA07ULL, 0xC04760609D6027FDULL, 0x6535BCBCCABC8976ULL, 0x2B379B9B569BACCDULL, 0x018A8E8E028E048CULL, 0x5BD2A3A3B6A37115ULL, 0x186C0C0C300C603CULL, 0xF6847B7BF17BFF8AULL, 0x6A803535D435B5E1ULL, 0x3AF51D1D741DE869ULL, 0xDDB3E0E0A7E05347ULL, 0xB321D7D77BD7F6ACULL, 0x999CC2C22FC25EEDULL, 0x5C432E2EB82E6D96ULL, 0x96294B4B314B627AULL, 0xE15DFEFEDFFEA321ULL, 0xAED5575741578216ULL, 0x2ABD15155415A841ULL, 0xEEE87777C1779FB6ULL, 0x6E923737DC37A5EBULL, 0xD79EE5E5B3E57B56ULL, 0x23139F9F469F8CD9ULL, 0xFD23F0F0E7F0D317ULL, 0x94204A4A354A6A7FULL, 0xA944DADA4FDA9E95ULL, 0xB0A258587D58FA25ULL, 0x8FCFC9C903C906CAULL, 0x527C2929A429558DULL, 0x145A0A0A280A5022ULL, 0x7F50B1B1FEB1E14FULL, 0x5DC9A0A0BAA0691AULL, 0xD6146B6BB16B7FDAULL, 0x17D985852E855CABULL, 0x673CBDBDCEBD8173ULL, 0xBA8F5D5D695DD234ULL, 0x2090101040108050ULL, 0xF507F4F4F7F4F303ULL, 0x8BDDCBCB0BCB16C0ULL, 0x7CD33E3EF83EEDC6ULL, 0x0A2D050514052811ULL, 0xCE78676781671FE6ULL, 0xD597E4E4B7E47353ULL, 0x4E0227279C2725BBULL, 0x8273414119413258ULL, 0x0BA78B8B168B2C9DULL, 0x53F6A7A7A6A75101ULL, 0xFAB27D7DE97DCF94ULL, 0x374995956E95DCFBULL, 0xAD56D8D847D88E9FULL, 0xEB70FBFBCBFB8B30ULL, 0xC1CDEEEE9FEE2371ULL, 0xF8BB7C7CED7CC791ULL, 0xCC716666856617E3ULL, 0xA77BDDDD53DDA68EULL, 0x2EAF17175C17B84BULL, 0x8E45474701470246ULL, 0x211A9E9E429E84DCULL, 0x89D4CACA0FCA1EC5ULL, 0x5A582D2DB42D7599ULL, 0x632EBFBFC6BF9179ULL, 0x0E3F07071C07381BULL, 0x47ACADAD8EAD0123ULL, 0xB4B05A5A755AEA2FULL, 0x1BEF838336836CB5ULL, 0x66B63333CC3385FFULL, 0xC65C636391633FF2ULL, 0x041202020802100AULL, 0x4993AAAA92AA3938ULL, 0xE2DE7171D971AFA8ULL, 0x8DC6C8C807C80ECFULL, 0x32D119196419C87DULL, 0x923B494939497270ULL, 0xAF5FD9D943D9869AULL, 0xF931F2F2EFF2C31DULL, 0xDBA8E3E3ABE34B48ULL, 0xB6B95B5B715BE22AULL, 0x0DBC88881A883492ULL, 0x293E9A9A529AA4C8ULL, 0x4C0B262698262DBEULL, 0x64BF3232C8328DFAULL, 0x7D59B0B0FAB0E94AULL, 0xCFF2E9E983E91B6AULL, 0x1E770F0F3C0F7833ULL, 0xB733D5D573D5E6A6ULL, 0x1DF480803A8074BAULL, 0x6127BEBEC2BE997CULL, 0x87EBCDCD13CD26DEULL, 0x68893434D034BDE4ULL, 0x903248483D487A75ULL, 0xE354FFFFDBFFAB24ULL, 0xF48D7A7AF57AF78FULL, 0x3D6490907A90F4EAULL, 0xBE9D5F5F615FC23EULL, 0x403D202080201DA0ULL, 0xD00F6868BD6867D5ULL, 0x34CA1A1A681AD072ULL, 0x41B7AEAE82AE192CULL, 0x757DB4B4EAB4C95EULL, 0xA8CE54544D549A19ULL, 0x3B7F93937693ECE5ULL, 0x442F222288220DAAULL, 0xC86364648D6407E9ULL, 0xFF2AF1F1E3F1DB12ULL, 0xE6CC7373D173BFA2ULL, 0x248212124812905AULL, 0x807A40401D403A5DULL, 0x1048080820084028ULL, 0x9B95C3C32BC356E8ULL, 0xC5DFECEC97EC337BULL, 0xAB4DDBDB4BDB9690ULL, 0x5FC0A1A1BEA1611FULL, 0x07918D8D0E8D1C83ULL, 0x7AC83D3DF43DF5C9ULL, 0x335B97976697CCF1ULL, 0x0000000000000000ULL, 0x83F9CFCF1BCF36D4ULL, 0x566E2B2BAC2B4587ULL, 0xECE17676C57697B3ULL, 0x19E68282328264B0ULL, 0xB128D6D67FD6FEA9ULL, 0x36C31B1B6C1BD877ULL, 0x7774B5B5EEB5C15BULL, 0x43BEAFAF86AF1129ULL, 0xD41D6A6AB56A77DFULL, 0xA0EA50505D50BA0DULL, 0x8A5745450945124CULL, 0xFB38F3F3EBF3CB18ULL, 0x60AD3030C0309DF0ULL, 0xC3C4EFEF9BEF2B74ULL, 0x7EDA3F3FFC3FE5C3ULL, 0xAAC755554955921CULL, 0x59DBA2A2B2A27910ULL, 0xC9E9EAEA8FEA0365ULL, 0xCA6A656589650FECULL, 0x6903BABAD2BAB968ULL, 0x5E4A2F2FBC2F6593ULL, 0x9D8EC0C027C04EE7ULL, 0xA160DEDE5FDEBE81ULL, 0x38FC1C1C701CE06CULL, 0xE746FDFDD3FDBB2EULL, 0x9A1F4D4D294D5264ULL, 0x397692927292E4E0ULL, 0xEAFA7575C9758FBCULL, 0x0C3606061806301EULL, 0x09AE8A8A128A2498ULL, 0x794BB2B2F2B2F940ULL, 0xD185E6E6BFE66359ULL, 0x1C7E0E0E380E7036ULL, 0x3EE71F1F7C1FF863ULL, 0xC4556262956237F7ULL, 0xB53AD4D477D4EEA3ULL, 0x4D81A8A89AA82932ULL, 0x315296966296C4F4ULL, 0xEF62F9F9C3F99B3AULL, 0x97A3C5C533C566F6ULL, 0x4A102525942535B1ULL, 0xB2AB59597959F220ULL, 0x15D084842A8454AEULL, 0xE4C57272D572B7A7ULL, 0x72EC3939E439D5DDULL, 0x98164C4C2D4C5A61ULL, 0xBC945E5E655ECA3BULL, 0xF09F7878FD78E785ULL, 0x70E53838E038DDD8ULL, 0x05988C8C0A8C1486ULL, 0xBF17D1D163D1C6B2ULL, 0x57E4A5A5AEA5410BULL, 0xD9A1E2E2AFE2434DULL, 0xC24E616199612FF8ULL, 0x7B42B3B3F6B3F145ULL, 0x42342121842115A5ULL, 0x25089C9C4A9C94D6ULL, 0x3CEE1E1E781EF066ULL, 0x8661434311432252ULL, 0x93B1C7C73BC776FCULL, 0xE54FFCFCD7FCB32BULL, 0x0824040410042014ULL, 0xA2E351515951B208ULL, 0x2F2599995E99BCC7ULL, 0xDA226D6DA96D4FC4ULL, 0x1A650D0D340D6839ULL, 0xE979FAFACFFA8335ULL, 0xA369DFDF5BDFB684ULL, 0xFCA97E7EE57ED79BULL, 0x4819242490243DB4ULL, 0x76FE3B3BEC3BC5D7ULL, 0x4B9AABAB96AB313DULL, 0x81F0CECE1FCE3ED1ULL, 0x2299111144118855ULL, 0x03838F8F068F0C89ULL, 0x9C044E4E254E4A6BULL, 0x7366B7B7E6B7D151ULL, 0xCBE0EBEB8BEB0B60ULL, 0x78C13C3CF03CFDCCULL, 0x1FFD81813E817CBFULL, 0x354094946A94D4FEULL, 0xF31CF7F7FBF7EB0CULL, 0x6F18B9B9DEB9A167ULL, 0x268B13134C13985FULL, 0x58512C2CB02C7D9CULL, 0xBB05D3D36BD3D6B8ULL, 0xD38CE7E7BBE76B5CULL, 0xDC396E6EA56E57CBULL, 0x95AAC4C437C46EF3ULL, 0x061B03030C03180FULL, 0xACDC565645568A13ULL, 0x885E44440D441A49ULL, 0xFEA07F7FE17FDF9EULL, 0x4F88A9A99EA92137ULL, 0x54672A2AA82A4D82ULL, 0x6B0ABBBBD6BBB16DULL, 0x9F87C1C123C146E2ULL, 0xA6F153535153A202ULL, 0xA572DCDC57DCAE8BULL, 0x16530B0B2C0B5827ULL, 0x27019D9D4E9D9CD3ULL, 0xD82B6C6CAD6C47C1ULL, 0x62A43131C43195F5ULL, 0xE8F37474CD7487B9ULL, 0xF115F6F6FFF6E309ULL, 0x8C4C464605460A43ULL, 0x45A5ACAC8AAC0926ULL, 0x0FB589891E893C97ULL, 0x28B414145014A044ULL, 0xDFBAE1E1A3E15B42ULL, 0x2CA616165816B04EULL, 0x74F73A3AE83ACDD2ULL, 0xD2066969B9696FD0ULL, 0x124109092409482DULL, 0xE0D77070DD70A7ADULL, 0x716FB6B6E2B6D954ULL, 0xBD1ED0D067D0CEB7ULL, 0xC7D6EDED93ED3B7EULL, 0x85E2CCCC17CC2EDBULL, 0x8468424215422A57ULL, 0x2D2C98985A98B4C2ULL, 0x55EDA4A4AAA4490EULL, 0x50752828A0285D88ULL, 0xB8865C5C6D5CDA31ULL, 0xED6BF8F8C7F8933FULL, 0x11C28686228644A4ULL }; const u64bit Whirlpool::C3[256] = { 0x7830D818186018C0ULL, 0xAF462623238C2305ULL, 0xF991B8C6C63FC67EULL, 0x6FCDFBE8E887E813ULL, 0xA113CB878726874CULL, 0x626D11B8B8DAB8A9ULL, 0x0502090101040108ULL, 0x6E9E0D4F4F214F42ULL, 0xEE6C9B3636D836ADULL, 0x0451FFA6A6A2A659ULL, 0xBDB90CD2D26FD2DEULL, 0x06F70EF5F5F3F5FBULL, 0x80F2967979F979EFULL, 0xCEDE306F6FA16F5FULL, 0xEF3F6D91917E91FCULL, 0x07A4F852525552AAULL, 0xFDC04760609D6027ULL, 0x766535BCBCCABC89ULL, 0xCD2B379B9B569BACULL, 0x8C018A8E8E028E04ULL, 0x155BD2A3A3B6A371ULL, 0x3C186C0C0C300C60ULL, 0x8AF6847B7BF17BFFULL, 0xE16A803535D435B5ULL, 0x693AF51D1D741DE8ULL, 0x47DDB3E0E0A7E053ULL, 0xACB321D7D77BD7F6ULL, 0xED999CC2C22FC25EULL, 0x965C432E2EB82E6DULL, 0x7A96294B4B314B62ULL, 0x21E15DFEFEDFFEA3ULL, 0x16AED55757415782ULL, 0x412ABD15155415A8ULL, 0xB6EEE87777C1779FULL, 0xEB6E923737DC37A5ULL, 0x56D79EE5E5B3E57BULL, 0xD923139F9F469F8CULL, 0x17FD23F0F0E7F0D3ULL, 0x7F94204A4A354A6AULL, 0x95A944DADA4FDA9EULL, 0x25B0A258587D58FAULL, 0xCA8FCFC9C903C906ULL, 0x8D527C2929A42955ULL, 0x22145A0A0A280A50ULL, 0x4F7F50B1B1FEB1E1ULL, 0x1A5DC9A0A0BAA069ULL, 0xDAD6146B6BB16B7FULL, 0xAB17D985852E855CULL, 0x73673CBDBDCEBD81ULL, 0x34BA8F5D5D695DD2ULL, 0x5020901010401080ULL, 0x03F507F4F4F7F4F3ULL, 0xC08BDDCBCB0BCB16ULL, 0xC67CD33E3EF83EEDULL, 0x110A2D0505140528ULL, 0xE6CE78676781671FULL, 0x53D597E4E4B7E473ULL, 0xBB4E0227279C2725ULL, 0x5882734141194132ULL, 0x9D0BA78B8B168B2CULL, 0x0153F6A7A7A6A751ULL, 0x94FAB27D7DE97DCFULL, 0xFB374995956E95DCULL, 0x9FAD56D8D847D88EULL, 0x30EB70FBFBCBFB8BULL, 0x71C1CDEEEE9FEE23ULL, 0x91F8BB7C7CED7CC7ULL, 0xE3CC716666856617ULL, 0x8EA77BDDDD53DDA6ULL, 0x4B2EAF17175C17B8ULL, 0x468E454747014702ULL, 0xDC211A9E9E429E84ULL, 0xC589D4CACA0FCA1EULL, 0x995A582D2DB42D75ULL, 0x79632EBFBFC6BF91ULL, 0x1B0E3F07071C0738ULL, 0x2347ACADAD8EAD01ULL, 0x2FB4B05A5A755AEAULL, 0xB51BEF838336836CULL, 0xFF66B63333CC3385ULL, 0xF2C65C636391633FULL, 0x0A04120202080210ULL, 0x384993AAAA92AA39ULL, 0xA8E2DE7171D971AFULL, 0xCF8DC6C8C807C80EULL, 0x7D32D119196419C8ULL, 0x70923B4949394972ULL, 0x9AAF5FD9D943D986ULL, 0x1DF931F2F2EFF2C3ULL, 0x48DBA8E3E3ABE34BULL, 0x2AB6B95B5B715BE2ULL, 0x920DBC88881A8834ULL, 0xC8293E9A9A529AA4ULL, 0xBE4C0B262698262DULL, 0xFA64BF3232C8328DULL, 0x4A7D59B0B0FAB0E9ULL, 0x6ACFF2E9E983E91BULL, 0x331E770F0F3C0F78ULL, 0xA6B733D5D573D5E6ULL, 0xBA1DF480803A8074ULL, 0x7C6127BEBEC2BE99ULL, 0xDE87EBCDCD13CD26ULL, 0xE468893434D034BDULL, 0x75903248483D487AULL, 0x24E354FFFFDBFFABULL, 0x8FF48D7A7AF57AF7ULL, 0xEA3D6490907A90F4ULL, 0x3EBE9D5F5F615FC2ULL, 0xA0403D202080201DULL, 0xD5D00F6868BD6867ULL, 0x7234CA1A1A681AD0ULL, 0x2C41B7AEAE82AE19ULL, 0x5E757DB4B4EAB4C9ULL, 0x19A8CE54544D549AULL, 0xE53B7F93937693ECULL, 0xAA442F222288220DULL, 0xE9C86364648D6407ULL, 0x12FF2AF1F1E3F1DBULL, 0xA2E6CC7373D173BFULL, 0x5A24821212481290ULL, 0x5D807A40401D403AULL, 0x2810480808200840ULL, 0xE89B95C3C32BC356ULL, 0x7BC5DFECEC97EC33ULL, 0x90AB4DDBDB4BDB96ULL, 0x1F5FC0A1A1BEA161ULL, 0x8307918D8D0E8D1CULL, 0xC97AC83D3DF43DF5ULL, 0xF1335B97976697CCULL, 0x0000000000000000ULL, 0xD483F9CFCF1BCF36ULL, 0x87566E2B2BAC2B45ULL, 0xB3ECE17676C57697ULL, 0xB019E68282328264ULL, 0xA9B128D6D67FD6FEULL, 0x7736C31B1B6C1BD8ULL, 0x5B7774B5B5EEB5C1ULL, 0x2943BEAFAF86AF11ULL, 0xDFD41D6A6AB56A77ULL, 0x0DA0EA50505D50BAULL, 0x4C8A574545094512ULL, 0x18FB38F3F3EBF3CBULL, 0xF060AD3030C0309DULL, 0x74C3C4EFEF9BEF2BULL, 0xC37EDA3F3FFC3FE5ULL, 0x1CAAC75555495592ULL, 0x1059DBA2A2B2A279ULL, 0x65C9E9EAEA8FEA03ULL, 0xECCA6A656589650FULL, 0x686903BABAD2BAB9ULL, 0x935E4A2F2FBC2F65ULL, 0xE79D8EC0C027C04EULL, 0x81A160DEDE5FDEBEULL, 0x6C38FC1C1C701CE0ULL, 0x2EE746FDFDD3FDBBULL, 0x649A1F4D4D294D52ULL, 0xE0397692927292E4ULL, 0xBCEAFA7575C9758FULL, 0x1E0C360606180630ULL, 0x9809AE8A8A128A24ULL, 0x40794BB2B2F2B2F9ULL, 0x59D185E6E6BFE663ULL, 0x361C7E0E0E380E70ULL, 0x633EE71F1F7C1FF8ULL, 0xF7C4556262956237ULL, 0xA3B53AD4D477D4EEULL, 0x324D81A8A89AA829ULL, 0xF4315296966296C4ULL, 0x3AEF62F9F9C3F99BULL, 0xF697A3C5C533C566ULL, 0xB14A102525942535ULL, 0x20B2AB59597959F2ULL, 0xAE15D084842A8454ULL, 0xA7E4C57272D572B7ULL, 0xDD72EC3939E439D5ULL, 0x6198164C4C2D4C5AULL, 0x3BBC945E5E655ECAULL, 0x85F09F7878FD78E7ULL, 0xD870E53838E038DDULL, 0x8605988C8C0A8C14ULL, 0xB2BF17D1D163D1C6ULL, 0x0B57E4A5A5AEA541ULL, 0x4DD9A1E2E2AFE243ULL, 0xF8C24E616199612FULL, 0x457B42B3B3F6B3F1ULL, 0xA542342121842115ULL, 0xD625089C9C4A9C94ULL, 0x663CEE1E1E781EF0ULL, 0x5286614343114322ULL, 0xFC93B1C7C73BC776ULL, 0x2BE54FFCFCD7FCB3ULL, 0x1408240404100420ULL, 0x08A2E351515951B2ULL, 0xC72F2599995E99BCULL, 0xC4DA226D6DA96D4FULL, 0x391A650D0D340D68ULL, 0x35E979FAFACFFA83ULL, 0x84A369DFDF5BDFB6ULL, 0x9BFCA97E7EE57ED7ULL, 0xB44819242490243DULL, 0xD776FE3B3BEC3BC5ULL, 0x3D4B9AABAB96AB31ULL, 0xD181F0CECE1FCE3EULL, 0x5522991111441188ULL, 0x8903838F8F068F0CULL, 0x6B9C044E4E254E4AULL, 0x517366B7B7E6B7D1ULL, 0x60CBE0EBEB8BEB0BULL, 0xCC78C13C3CF03CFDULL, 0xBF1FFD81813E817CULL, 0xFE354094946A94D4ULL, 0x0CF31CF7F7FBF7EBULL, 0x676F18B9B9DEB9A1ULL, 0x5F268B13134C1398ULL, 0x9C58512C2CB02C7DULL, 0xB8BB05D3D36BD3D6ULL, 0x5CD38CE7E7BBE76BULL, 0xCBDC396E6EA56E57ULL, 0xF395AAC4C437C46EULL, 0x0F061B03030C0318ULL, 0x13ACDC565645568AULL, 0x49885E44440D441AULL, 0x9EFEA07F7FE17FDFULL, 0x374F88A9A99EA921ULL, 0x8254672A2AA82A4DULL, 0x6D6B0ABBBBD6BBB1ULL, 0xE29F87C1C123C146ULL, 0x02A6F153535153A2ULL, 0x8BA572DCDC57DCAEULL, 0x2716530B0B2C0B58ULL, 0xD327019D9D4E9D9CULL, 0xC1D82B6C6CAD6C47ULL, 0xF562A43131C43195ULL, 0xB9E8F37474CD7487ULL, 0x09F115F6F6FFF6E3ULL, 0x438C4C464605460AULL, 0x2645A5ACAC8AAC09ULL, 0x970FB589891E893CULL, 0x4428B414145014A0ULL, 0x42DFBAE1E1A3E15BULL, 0x4E2CA616165816B0ULL, 0xD274F73A3AE83ACDULL, 0xD0D2066969B9696FULL, 0x2D12410909240948ULL, 0xADE0D77070DD70A7ULL, 0x54716FB6B6E2B6D9ULL, 0xB7BD1ED0D067D0CEULL, 0x7EC7D6EDED93ED3BULL, 0xDB85E2CCCC17CC2EULL, 0x578468424215422AULL, 0xC22D2C98985A98B4ULL, 0x0E55EDA4A4AAA449ULL, 0x8850752828A0285DULL, 0x31B8865C5C6D5CDAULL, 0x3FED6BF8F8C7F893ULL, 0xA411C28686228644ULL }; const u64bit Whirlpool::C4[256] = { 0xC07830D818186018ULL, 0x05AF462623238C23ULL, 0x7EF991B8C6C63FC6ULL, 0x136FCDFBE8E887E8ULL, 0x4CA113CB87872687ULL, 0xA9626D11B8B8DAB8ULL, 0x0805020901010401ULL, 0x426E9E0D4F4F214FULL, 0xADEE6C9B3636D836ULL, 0x590451FFA6A6A2A6ULL, 0xDEBDB90CD2D26FD2ULL, 0xFB06F70EF5F5F3F5ULL, 0xEF80F2967979F979ULL, 0x5FCEDE306F6FA16FULL, 0xFCEF3F6D91917E91ULL, 0xAA07A4F852525552ULL, 0x27FDC04760609D60ULL, 0x89766535BCBCCABCULL, 0xACCD2B379B9B569BULL, 0x048C018A8E8E028EULL, 0x71155BD2A3A3B6A3ULL, 0x603C186C0C0C300CULL, 0xFF8AF6847B7BF17BULL, 0xB5E16A803535D435ULL, 0xE8693AF51D1D741DULL, 0x5347DDB3E0E0A7E0ULL, 0xF6ACB321D7D77BD7ULL, 0x5EED999CC2C22FC2ULL, 0x6D965C432E2EB82EULL, 0x627A96294B4B314BULL, 0xA321E15DFEFEDFFEULL, 0x8216AED557574157ULL, 0xA8412ABD15155415ULL, 0x9FB6EEE87777C177ULL, 0xA5EB6E923737DC37ULL, 0x7B56D79EE5E5B3E5ULL, 0x8CD923139F9F469FULL, 0xD317FD23F0F0E7F0ULL, 0x6A7F94204A4A354AULL, 0x9E95A944DADA4FDAULL, 0xFA25B0A258587D58ULL, 0x06CA8FCFC9C903C9ULL, 0x558D527C2929A429ULL, 0x5022145A0A0A280AULL, 0xE14F7F50B1B1FEB1ULL, 0x691A5DC9A0A0BAA0ULL, 0x7FDAD6146B6BB16BULL, 0x5CAB17D985852E85ULL, 0x8173673CBDBDCEBDULL, 0xD234BA8F5D5D695DULL, 0x8050209010104010ULL, 0xF303F507F4F4F7F4ULL, 0x16C08BDDCBCB0BCBULL, 0xEDC67CD33E3EF83EULL, 0x28110A2D05051405ULL, 0x1FE6CE7867678167ULL, 0x7353D597E4E4B7E4ULL, 0x25BB4E0227279C27ULL, 0x3258827341411941ULL, 0x2C9D0BA78B8B168BULL, 0x510153F6A7A7A6A7ULL, 0xCF94FAB27D7DE97DULL, 0xDCFB374995956E95ULL, 0x8E9FAD56D8D847D8ULL, 0x8B30EB70FBFBCBFBULL, 0x2371C1CDEEEE9FEEULL, 0xC791F8BB7C7CED7CULL, 0x17E3CC7166668566ULL, 0xA68EA77BDDDD53DDULL, 0xB84B2EAF17175C17ULL, 0x02468E4547470147ULL, 0x84DC211A9E9E429EULL, 0x1EC589D4CACA0FCAULL, 0x75995A582D2DB42DULL, 0x9179632EBFBFC6BFULL, 0x381B0E3F07071C07ULL, 0x012347ACADAD8EADULL, 0xEA2FB4B05A5A755AULL, 0x6CB51BEF83833683ULL, 0x85FF66B63333CC33ULL, 0x3FF2C65C63639163ULL, 0x100A041202020802ULL, 0x39384993AAAA92AAULL, 0xAFA8E2DE7171D971ULL, 0x0ECF8DC6C8C807C8ULL, 0xC87D32D119196419ULL, 0x7270923B49493949ULL, 0x869AAF5FD9D943D9ULL, 0xC31DF931F2F2EFF2ULL, 0x4B48DBA8E3E3ABE3ULL, 0xE22AB6B95B5B715BULL, 0x34920DBC88881A88ULL, 0xA4C8293E9A9A529AULL, 0x2DBE4C0B26269826ULL, 0x8DFA64BF3232C832ULL, 0xE94A7D59B0B0FAB0ULL, 0x1B6ACFF2E9E983E9ULL, 0x78331E770F0F3C0FULL, 0xE6A6B733D5D573D5ULL, 0x74BA1DF480803A80ULL, 0x997C6127BEBEC2BEULL, 0x26DE87EBCDCD13CDULL, 0xBDE468893434D034ULL, 0x7A75903248483D48ULL, 0xAB24E354FFFFDBFFULL, 0xF78FF48D7A7AF57AULL, 0xF4EA3D6490907A90ULL, 0xC23EBE9D5F5F615FULL, 0x1DA0403D20208020ULL, 0x67D5D00F6868BD68ULL, 0xD07234CA1A1A681AULL, 0x192C41B7AEAE82AEULL, 0xC95E757DB4B4EAB4ULL, 0x9A19A8CE54544D54ULL, 0xECE53B7F93937693ULL, 0x0DAA442F22228822ULL, 0x07E9C86364648D64ULL, 0xDB12FF2AF1F1E3F1ULL, 0xBFA2E6CC7373D173ULL, 0x905A248212124812ULL, 0x3A5D807A40401D40ULL, 0x4028104808082008ULL, 0x56E89B95C3C32BC3ULL, 0x337BC5DFECEC97ECULL, 0x9690AB4DDBDB4BDBULL, 0x611F5FC0A1A1BEA1ULL, 0x1C8307918D8D0E8DULL, 0xF5C97AC83D3DF43DULL, 0xCCF1335B97976697ULL, 0x0000000000000000ULL, 0x36D483F9CFCF1BCFULL, 0x4587566E2B2BAC2BULL, 0x97B3ECE17676C576ULL, 0x64B019E682823282ULL, 0xFEA9B128D6D67FD6ULL, 0xD87736C31B1B6C1BULL, 0xC15B7774B5B5EEB5ULL, 0x112943BEAFAF86AFULL, 0x77DFD41D6A6AB56AULL, 0xBA0DA0EA50505D50ULL, 0x124C8A5745450945ULL, 0xCB18FB38F3F3EBF3ULL, 0x9DF060AD3030C030ULL, 0x2B74C3C4EFEF9BEFULL, 0xE5C37EDA3F3FFC3FULL, 0x921CAAC755554955ULL, 0x791059DBA2A2B2A2ULL, 0x0365C9E9EAEA8FEAULL, 0x0FECCA6A65658965ULL, 0xB9686903BABAD2BAULL, 0x65935E4A2F2FBC2FULL, 0x4EE79D8EC0C027C0ULL, 0xBE81A160DEDE5FDEULL, 0xE06C38FC1C1C701CULL, 0xBB2EE746FDFDD3FDULL, 0x52649A1F4D4D294DULL, 0xE4E0397692927292ULL, 0x8FBCEAFA7575C975ULL, 0x301E0C3606061806ULL, 0x249809AE8A8A128AULL, 0xF940794BB2B2F2B2ULL, 0x6359D185E6E6BFE6ULL, 0x70361C7E0E0E380EULL, 0xF8633EE71F1F7C1FULL, 0x37F7C45562629562ULL, 0xEEA3B53AD4D477D4ULL, 0x29324D81A8A89AA8ULL, 0xC4F4315296966296ULL, 0x9B3AEF62F9F9C3F9ULL, 0x66F697A3C5C533C5ULL, 0x35B14A1025259425ULL, 0xF220B2AB59597959ULL, 0x54AE15D084842A84ULL, 0xB7A7E4C57272D572ULL, 0xD5DD72EC3939E439ULL, 0x5A6198164C4C2D4CULL, 0xCA3BBC945E5E655EULL, 0xE785F09F7878FD78ULL, 0xDDD870E53838E038ULL, 0x148605988C8C0A8CULL, 0xC6B2BF17D1D163D1ULL, 0x410B57E4A5A5AEA5ULL, 0x434DD9A1E2E2AFE2ULL, 0x2FF8C24E61619961ULL, 0xF1457B42B3B3F6B3ULL, 0x15A5423421218421ULL, 0x94D625089C9C4A9CULL, 0xF0663CEE1E1E781EULL, 0x2252866143431143ULL, 0x76FC93B1C7C73BC7ULL, 0xB32BE54FFCFCD7FCULL, 0x2014082404041004ULL, 0xB208A2E351515951ULL, 0xBCC72F2599995E99ULL, 0x4FC4DA226D6DA96DULL, 0x68391A650D0D340DULL, 0x8335E979FAFACFFAULL, 0xB684A369DFDF5BDFULL, 0xD79BFCA97E7EE57EULL, 0x3DB4481924249024ULL, 0xC5D776FE3B3BEC3BULL, 0x313D4B9AABAB96ABULL, 0x3ED181F0CECE1FCEULL, 0x8855229911114411ULL, 0x0C8903838F8F068FULL, 0x4A6B9C044E4E254EULL, 0xD1517366B7B7E6B7ULL, 0x0B60CBE0EBEB8BEBULL, 0xFDCC78C13C3CF03CULL, 0x7CBF1FFD81813E81ULL, 0xD4FE354094946A94ULL, 0xEB0CF31CF7F7FBF7ULL, 0xA1676F18B9B9DEB9ULL, 0x985F268B13134C13ULL, 0x7D9C58512C2CB02CULL, 0xD6B8BB05D3D36BD3ULL, 0x6B5CD38CE7E7BBE7ULL, 0x57CBDC396E6EA56EULL, 0x6EF395AAC4C437C4ULL, 0x180F061B03030C03ULL, 0x8A13ACDC56564556ULL, 0x1A49885E44440D44ULL, 0xDF9EFEA07F7FE17FULL, 0x21374F88A9A99EA9ULL, 0x4D8254672A2AA82AULL, 0xB16D6B0ABBBBD6BBULL, 0x46E29F87C1C123C1ULL, 0xA202A6F153535153ULL, 0xAE8BA572DCDC57DCULL, 0x582716530B0B2C0BULL, 0x9CD327019D9D4E9DULL, 0x47C1D82B6C6CAD6CULL, 0x95F562A43131C431ULL, 0x87B9E8F37474CD74ULL, 0xE309F115F6F6FFF6ULL, 0x0A438C4C46460546ULL, 0x092645A5ACAC8AACULL, 0x3C970FB589891E89ULL, 0xA04428B414145014ULL, 0x5B42DFBAE1E1A3E1ULL, 0xB04E2CA616165816ULL, 0xCDD274F73A3AE83AULL, 0x6FD0D2066969B969ULL, 0x482D124109092409ULL, 0xA7ADE0D77070DD70ULL, 0xD954716FB6B6E2B6ULL, 0xCEB7BD1ED0D067D0ULL, 0x3B7EC7D6EDED93EDULL, 0x2EDB85E2CCCC17CCULL, 0x2A57846842421542ULL, 0xB4C22D2C98985A98ULL, 0x490E55EDA4A4AAA4ULL, 0x5D8850752828A028ULL, 0xDA31B8865C5C6D5CULL, 0x933FED6BF8F8C7F8ULL, 0x44A411C286862286ULL }; const u64bit Whirlpool::C5[256] = { 0x18C07830D8181860ULL, 0x2305AF462623238CULL, 0xC67EF991B8C6C63FULL, 0xE8136FCDFBE8E887ULL, 0x874CA113CB878726ULL, 0xB8A9626D11B8B8DAULL, 0x0108050209010104ULL, 0x4F426E9E0D4F4F21ULL, 0x36ADEE6C9B3636D8ULL, 0xA6590451FFA6A6A2ULL, 0xD2DEBDB90CD2D26FULL, 0xF5FB06F70EF5F5F3ULL, 0x79EF80F2967979F9ULL, 0x6F5FCEDE306F6FA1ULL, 0x91FCEF3F6D91917EULL, 0x52AA07A4F8525255ULL, 0x6027FDC04760609DULL, 0xBC89766535BCBCCAULL, 0x9BACCD2B379B9B56ULL, 0x8E048C018A8E8E02ULL, 0xA371155BD2A3A3B6ULL, 0x0C603C186C0C0C30ULL, 0x7BFF8AF6847B7BF1ULL, 0x35B5E16A803535D4ULL, 0x1DE8693AF51D1D74ULL, 0xE05347DDB3E0E0A7ULL, 0xD7F6ACB321D7D77BULL, 0xC25EED999CC2C22FULL, 0x2E6D965C432E2EB8ULL, 0x4B627A96294B4B31ULL, 0xFEA321E15DFEFEDFULL, 0x578216AED5575741ULL, 0x15A8412ABD151554ULL, 0x779FB6EEE87777C1ULL, 0x37A5EB6E923737DCULL, 0xE57B56D79EE5E5B3ULL, 0x9F8CD923139F9F46ULL, 0xF0D317FD23F0F0E7ULL, 0x4A6A7F94204A4A35ULL, 0xDA9E95A944DADA4FULL, 0x58FA25B0A258587DULL, 0xC906CA8FCFC9C903ULL, 0x29558D527C2929A4ULL, 0x0A5022145A0A0A28ULL, 0xB1E14F7F50B1B1FEULL, 0xA0691A5DC9A0A0BAULL, 0x6B7FDAD6146B6BB1ULL, 0x855CAB17D985852EULL, 0xBD8173673CBDBDCEULL, 0x5DD234BA8F5D5D69ULL, 0x1080502090101040ULL, 0xF4F303F507F4F4F7ULL, 0xCB16C08BDDCBCB0BULL, 0x3EEDC67CD33E3EF8ULL, 0x0528110A2D050514ULL, 0x671FE6CE78676781ULL, 0xE47353D597E4E4B7ULL, 0x2725BB4E0227279CULL, 0x4132588273414119ULL, 0x8B2C9D0BA78B8B16ULL, 0xA7510153F6A7A7A6ULL, 0x7DCF94FAB27D7DE9ULL, 0x95DCFB374995956EULL, 0xD88E9FAD56D8D847ULL, 0xFB8B30EB70FBFBCBULL, 0xEE2371C1CDEEEE9FULL, 0x7CC791F8BB7C7CEDULL, 0x6617E3CC71666685ULL, 0xDDA68EA77BDDDD53ULL, 0x17B84B2EAF17175CULL, 0x4702468E45474701ULL, 0x9E84DC211A9E9E42ULL, 0xCA1EC589D4CACA0FULL, 0x2D75995A582D2DB4ULL, 0xBF9179632EBFBFC6ULL, 0x07381B0E3F07071CULL, 0xAD012347ACADAD8EULL, 0x5AEA2FB4B05A5A75ULL, 0x836CB51BEF838336ULL, 0x3385FF66B63333CCULL, 0x633FF2C65C636391ULL, 0x02100A0412020208ULL, 0xAA39384993AAAA92ULL, 0x71AFA8E2DE7171D9ULL, 0xC80ECF8DC6C8C807ULL, 0x19C87D32D1191964ULL, 0x497270923B494939ULL, 0xD9869AAF5FD9D943ULL, 0xF2C31DF931F2F2EFULL, 0xE34B48DBA8E3E3ABULL, 0x5BE22AB6B95B5B71ULL, 0x8834920DBC88881AULL, 0x9AA4C8293E9A9A52ULL, 0x262DBE4C0B262698ULL, 0x328DFA64BF3232C8ULL, 0xB0E94A7D59B0B0FAULL, 0xE91B6ACFF2E9E983ULL, 0x0F78331E770F0F3CULL, 0xD5E6A6B733D5D573ULL, 0x8074BA1DF480803AULL, 0xBE997C6127BEBEC2ULL, 0xCD26DE87EBCDCD13ULL, 0x34BDE468893434D0ULL, 0x487A75903248483DULL, 0xFFAB24E354FFFFDBULL, 0x7AF78FF48D7A7AF5ULL, 0x90F4EA3D6490907AULL, 0x5FC23EBE9D5F5F61ULL, 0x201DA0403D202080ULL, 0x6867D5D00F6868BDULL, 0x1AD07234CA1A1A68ULL, 0xAE192C41B7AEAE82ULL, 0xB4C95E757DB4B4EAULL, 0x549A19A8CE54544DULL, 0x93ECE53B7F939376ULL, 0x220DAA442F222288ULL, 0x6407E9C86364648DULL, 0xF1DB12FF2AF1F1E3ULL, 0x73BFA2E6CC7373D1ULL, 0x12905A2482121248ULL, 0x403A5D807A40401DULL, 0x0840281048080820ULL, 0xC356E89B95C3C32BULL, 0xEC337BC5DFECEC97ULL, 0xDB9690AB4DDBDB4BULL, 0xA1611F5FC0A1A1BEULL, 0x8D1C8307918D8D0EULL, 0x3DF5C97AC83D3DF4ULL, 0x97CCF1335B979766ULL, 0x0000000000000000ULL, 0xCF36D483F9CFCF1BULL, 0x2B4587566E2B2BACULL, 0x7697B3ECE17676C5ULL, 0x8264B019E6828232ULL, 0xD6FEA9B128D6D67FULL, 0x1BD87736C31B1B6CULL, 0xB5C15B7774B5B5EEULL, 0xAF112943BEAFAF86ULL, 0x6A77DFD41D6A6AB5ULL, 0x50BA0DA0EA50505DULL, 0x45124C8A57454509ULL, 0xF3CB18FB38F3F3EBULL, 0x309DF060AD3030C0ULL, 0xEF2B74C3C4EFEF9BULL, 0x3FE5C37EDA3F3FFCULL, 0x55921CAAC7555549ULL, 0xA2791059DBA2A2B2ULL, 0xEA0365C9E9EAEA8FULL, 0x650FECCA6A656589ULL, 0xBAB9686903BABAD2ULL, 0x2F65935E4A2F2FBCULL, 0xC04EE79D8EC0C027ULL, 0xDEBE81A160DEDE5FULL, 0x1CE06C38FC1C1C70ULL, 0xFDBB2EE746FDFDD3ULL, 0x4D52649A1F4D4D29ULL, 0x92E4E03976929272ULL, 0x758FBCEAFA7575C9ULL, 0x06301E0C36060618ULL, 0x8A249809AE8A8A12ULL, 0xB2F940794BB2B2F2ULL, 0xE66359D185E6E6BFULL, 0x0E70361C7E0E0E38ULL, 0x1FF8633EE71F1F7CULL, 0x6237F7C455626295ULL, 0xD4EEA3B53AD4D477ULL, 0xA829324D81A8A89AULL, 0x96C4F43152969662ULL, 0xF99B3AEF62F9F9C3ULL, 0xC566F697A3C5C533ULL, 0x2535B14A10252594ULL, 0x59F220B2AB595979ULL, 0x8454AE15D084842AULL, 0x72B7A7E4C57272D5ULL, 0x39D5DD72EC3939E4ULL, 0x4C5A6198164C4C2DULL, 0x5ECA3BBC945E5E65ULL, 0x78E785F09F7878FDULL, 0x38DDD870E53838E0ULL, 0x8C148605988C8C0AULL, 0xD1C6B2BF17D1D163ULL, 0xA5410B57E4A5A5AEULL, 0xE2434DD9A1E2E2AFULL, 0x612FF8C24E616199ULL, 0xB3F1457B42B3B3F6ULL, 0x2115A54234212184ULL, 0x9C94D625089C9C4AULL, 0x1EF0663CEE1E1E78ULL, 0x4322528661434311ULL, 0xC776FC93B1C7C73BULL, 0xFCB32BE54FFCFCD7ULL, 0x0420140824040410ULL, 0x51B208A2E3515159ULL, 0x99BCC72F2599995EULL, 0x6D4FC4DA226D6DA9ULL, 0x0D68391A650D0D34ULL, 0xFA8335E979FAFACFULL, 0xDFB684A369DFDF5BULL, 0x7ED79BFCA97E7EE5ULL, 0x243DB44819242490ULL, 0x3BC5D776FE3B3BECULL, 0xAB313D4B9AABAB96ULL, 0xCE3ED181F0CECE1FULL, 0x1188552299111144ULL, 0x8F0C8903838F8F06ULL, 0x4E4A6B9C044E4E25ULL, 0xB7D1517366B7B7E6ULL, 0xEB0B60CBE0EBEB8BULL, 0x3CFDCC78C13C3CF0ULL, 0x817CBF1FFD81813EULL, 0x94D4FE354094946AULL, 0xF7EB0CF31CF7F7FBULL, 0xB9A1676F18B9B9DEULL, 0x13985F268B13134CULL, 0x2C7D9C58512C2CB0ULL, 0xD3D6B8BB05D3D36BULL, 0xE76B5CD38CE7E7BBULL, 0x6E57CBDC396E6EA5ULL, 0xC46EF395AAC4C437ULL, 0x03180F061B03030CULL, 0x568A13ACDC565645ULL, 0x441A49885E44440DULL, 0x7FDF9EFEA07F7FE1ULL, 0xA921374F88A9A99EULL, 0x2A4D8254672A2AA8ULL, 0xBBB16D6B0ABBBBD6ULL, 0xC146E29F87C1C123ULL, 0x53A202A6F1535351ULL, 0xDCAE8BA572DCDC57ULL, 0x0B582716530B0B2CULL, 0x9D9CD327019D9D4EULL, 0x6C47C1D82B6C6CADULL, 0x3195F562A43131C4ULL, 0x7487B9E8F37474CDULL, 0xF6E309F115F6F6FFULL, 0x460A438C4C464605ULL, 0xAC092645A5ACAC8AULL, 0x893C970FB589891EULL, 0x14A04428B4141450ULL, 0xE15B42DFBAE1E1A3ULL, 0x16B04E2CA6161658ULL, 0x3ACDD274F73A3AE8ULL, 0x696FD0D2066969B9ULL, 0x09482D1241090924ULL, 0x70A7ADE0D77070DDULL, 0xB6D954716FB6B6E2ULL, 0xD0CEB7BD1ED0D067ULL, 0xED3B7EC7D6EDED93ULL, 0xCC2EDB85E2CCCC17ULL, 0x422A578468424215ULL, 0x98B4C22D2C98985AULL, 0xA4490E55EDA4A4AAULL, 0x285D8850752828A0ULL, 0x5CDA31B8865C5C6DULL, 0xF8933FED6BF8F8C7ULL, 0x8644A411C2868622ULL }; const u64bit Whirlpool::C6[256] = { 0x6018C07830D81818ULL, 0x8C2305AF46262323ULL, 0x3FC67EF991B8C6C6ULL, 0x87E8136FCDFBE8E8ULL, 0x26874CA113CB8787ULL, 0xDAB8A9626D11B8B8ULL, 0x0401080502090101ULL, 0x214F426E9E0D4F4FULL, 0xD836ADEE6C9B3636ULL, 0xA2A6590451FFA6A6ULL, 0x6FD2DEBDB90CD2D2ULL, 0xF3F5FB06F70EF5F5ULL, 0xF979EF80F2967979ULL, 0xA16F5FCEDE306F6FULL, 0x7E91FCEF3F6D9191ULL, 0x5552AA07A4F85252ULL, 0x9D6027FDC0476060ULL, 0xCABC89766535BCBCULL, 0x569BACCD2B379B9BULL, 0x028E048C018A8E8EULL, 0xB6A371155BD2A3A3ULL, 0x300C603C186C0C0CULL, 0xF17BFF8AF6847B7BULL, 0xD435B5E16A803535ULL, 0x741DE8693AF51D1DULL, 0xA7E05347DDB3E0E0ULL, 0x7BD7F6ACB321D7D7ULL, 0x2FC25EED999CC2C2ULL, 0xB82E6D965C432E2EULL, 0x314B627A96294B4BULL, 0xDFFEA321E15DFEFEULL, 0x41578216AED55757ULL, 0x5415A8412ABD1515ULL, 0xC1779FB6EEE87777ULL, 0xDC37A5EB6E923737ULL, 0xB3E57B56D79EE5E5ULL, 0x469F8CD923139F9FULL, 0xE7F0D317FD23F0F0ULL, 0x354A6A7F94204A4AULL, 0x4FDA9E95A944DADAULL, 0x7D58FA25B0A25858ULL, 0x03C906CA8FCFC9C9ULL, 0xA429558D527C2929ULL, 0x280A5022145A0A0AULL, 0xFEB1E14F7F50B1B1ULL, 0xBAA0691A5DC9A0A0ULL, 0xB16B7FDAD6146B6BULL, 0x2E855CAB17D98585ULL, 0xCEBD8173673CBDBDULL, 0x695DD234BA8F5D5DULL, 0x4010805020901010ULL, 0xF7F4F303F507F4F4ULL, 0x0BCB16C08BDDCBCBULL, 0xF83EEDC67CD33E3EULL, 0x140528110A2D0505ULL, 0x81671FE6CE786767ULL, 0xB7E47353D597E4E4ULL, 0x9C2725BB4E022727ULL, 0x1941325882734141ULL, 0x168B2C9D0BA78B8BULL, 0xA6A7510153F6A7A7ULL, 0xE97DCF94FAB27D7DULL, 0x6E95DCFB37499595ULL, 0x47D88E9FAD56D8D8ULL, 0xCBFB8B30EB70FBFBULL, 0x9FEE2371C1CDEEEEULL, 0xED7CC791F8BB7C7CULL, 0x856617E3CC716666ULL, 0x53DDA68EA77BDDDDULL, 0x5C17B84B2EAF1717ULL, 0x014702468E454747ULL, 0x429E84DC211A9E9EULL, 0x0FCA1EC589D4CACAULL, 0xB42D75995A582D2DULL, 0xC6BF9179632EBFBFULL, 0x1C07381B0E3F0707ULL, 0x8EAD012347ACADADULL, 0x755AEA2FB4B05A5AULL, 0x36836CB51BEF8383ULL, 0xCC3385FF66B63333ULL, 0x91633FF2C65C6363ULL, 0x0802100A04120202ULL, 0x92AA39384993AAAAULL, 0xD971AFA8E2DE7171ULL, 0x07C80ECF8DC6C8C8ULL, 0x6419C87D32D11919ULL, 0x39497270923B4949ULL, 0x43D9869AAF5FD9D9ULL, 0xEFF2C31DF931F2F2ULL, 0xABE34B48DBA8E3E3ULL, 0x715BE22AB6B95B5BULL, 0x1A8834920DBC8888ULL, 0x529AA4C8293E9A9AULL, 0x98262DBE4C0B2626ULL, 0xC8328DFA64BF3232ULL, 0xFAB0E94A7D59B0B0ULL, 0x83E91B6ACFF2E9E9ULL, 0x3C0F78331E770F0FULL, 0x73D5E6A6B733D5D5ULL, 0x3A8074BA1DF48080ULL, 0xC2BE997C6127BEBEULL, 0x13CD26DE87EBCDCDULL, 0xD034BDE468893434ULL, 0x3D487A7590324848ULL, 0xDBFFAB24E354FFFFULL, 0xF57AF78FF48D7A7AULL, 0x7A90F4EA3D649090ULL, 0x615FC23EBE9D5F5FULL, 0x80201DA0403D2020ULL, 0xBD6867D5D00F6868ULL, 0x681AD07234CA1A1AULL, 0x82AE192C41B7AEAEULL, 0xEAB4C95E757DB4B4ULL, 0x4D549A19A8CE5454ULL, 0x7693ECE53B7F9393ULL, 0x88220DAA442F2222ULL, 0x8D6407E9C8636464ULL, 0xE3F1DB12FF2AF1F1ULL, 0xD173BFA2E6CC7373ULL, 0x4812905A24821212ULL, 0x1D403A5D807A4040ULL, 0x2008402810480808ULL, 0x2BC356E89B95C3C3ULL, 0x97EC337BC5DFECECULL, 0x4BDB9690AB4DDBDBULL, 0xBEA1611F5FC0A1A1ULL, 0x0E8D1C8307918D8DULL, 0xF43DF5C97AC83D3DULL, 0x6697CCF1335B9797ULL, 0x0000000000000000ULL, 0x1BCF36D483F9CFCFULL, 0xAC2B4587566E2B2BULL, 0xC57697B3ECE17676ULL, 0x328264B019E68282ULL, 0x7FD6FEA9B128D6D6ULL, 0x6C1BD87736C31B1BULL, 0xEEB5C15B7774B5B5ULL, 0x86AF112943BEAFAFULL, 0xB56A77DFD41D6A6AULL, 0x5D50BA0DA0EA5050ULL, 0x0945124C8A574545ULL, 0xEBF3CB18FB38F3F3ULL, 0xC0309DF060AD3030ULL, 0x9BEF2B74C3C4EFEFULL, 0xFC3FE5C37EDA3F3FULL, 0x4955921CAAC75555ULL, 0xB2A2791059DBA2A2ULL, 0x8FEA0365C9E9EAEAULL, 0x89650FECCA6A6565ULL, 0xD2BAB9686903BABAULL, 0xBC2F65935E4A2F2FULL, 0x27C04EE79D8EC0C0ULL, 0x5FDEBE81A160DEDEULL, 0x701CE06C38FC1C1CULL, 0xD3FDBB2EE746FDFDULL, 0x294D52649A1F4D4DULL, 0x7292E4E039769292ULL, 0xC9758FBCEAFA7575ULL, 0x1806301E0C360606ULL, 0x128A249809AE8A8AULL, 0xF2B2F940794BB2B2ULL, 0xBFE66359D185E6E6ULL, 0x380E70361C7E0E0EULL, 0x7C1FF8633EE71F1FULL, 0x956237F7C4556262ULL, 0x77D4EEA3B53AD4D4ULL, 0x9AA829324D81A8A8ULL, 0x6296C4F431529696ULL, 0xC3F99B3AEF62F9F9ULL, 0x33C566F697A3C5C5ULL, 0x942535B14A102525ULL, 0x7959F220B2AB5959ULL, 0x2A8454AE15D08484ULL, 0xD572B7A7E4C57272ULL, 0xE439D5DD72EC3939ULL, 0x2D4C5A6198164C4CULL, 0x655ECA3BBC945E5EULL, 0xFD78E785F09F7878ULL, 0xE038DDD870E53838ULL, 0x0A8C148605988C8CULL, 0x63D1C6B2BF17D1D1ULL, 0xAEA5410B57E4A5A5ULL, 0xAFE2434DD9A1E2E2ULL, 0x99612FF8C24E6161ULL, 0xF6B3F1457B42B3B3ULL, 0x842115A542342121ULL, 0x4A9C94D625089C9CULL, 0x781EF0663CEE1E1EULL, 0x1143225286614343ULL, 0x3BC776FC93B1C7C7ULL, 0xD7FCB32BE54FFCFCULL, 0x1004201408240404ULL, 0x5951B208A2E35151ULL, 0x5E99BCC72F259999ULL, 0xA96D4FC4DA226D6DULL, 0x340D68391A650D0DULL, 0xCFFA8335E979FAFAULL, 0x5BDFB684A369DFDFULL, 0xE57ED79BFCA97E7EULL, 0x90243DB448192424ULL, 0xEC3BC5D776FE3B3BULL, 0x96AB313D4B9AABABULL, 0x1FCE3ED181F0CECEULL, 0x4411885522991111ULL, 0x068F0C8903838F8FULL, 0x254E4A6B9C044E4EULL, 0xE6B7D1517366B7B7ULL, 0x8BEB0B60CBE0EBEBULL, 0xF03CFDCC78C13C3CULL, 0x3E817CBF1FFD8181ULL, 0x6A94D4FE35409494ULL, 0xFBF7EB0CF31CF7F7ULL, 0xDEB9A1676F18B9B9ULL, 0x4C13985F268B1313ULL, 0xB02C7D9C58512C2CULL, 0x6BD3D6B8BB05D3D3ULL, 0xBBE76B5CD38CE7E7ULL, 0xA56E57CBDC396E6EULL, 0x37C46EF395AAC4C4ULL, 0x0C03180F061B0303ULL, 0x45568A13ACDC5656ULL, 0x0D441A49885E4444ULL, 0xE17FDF9EFEA07F7FULL, 0x9EA921374F88A9A9ULL, 0xA82A4D8254672A2AULL, 0xD6BBB16D6B0ABBBBULL, 0x23C146E29F87C1C1ULL, 0x5153A202A6F15353ULL, 0x57DCAE8BA572DCDCULL, 0x2C0B582716530B0BULL, 0x4E9D9CD327019D9DULL, 0xAD6C47C1D82B6C6CULL, 0xC43195F562A43131ULL, 0xCD7487B9E8F37474ULL, 0xFFF6E309F115F6F6ULL, 0x05460A438C4C4646ULL, 0x8AAC092645A5ACACULL, 0x1E893C970FB58989ULL, 0x5014A04428B41414ULL, 0xA3E15B42DFBAE1E1ULL, 0x5816B04E2CA61616ULL, 0xE83ACDD274F73A3AULL, 0xB9696FD0D2066969ULL, 0x2409482D12410909ULL, 0xDD70A7ADE0D77070ULL, 0xE2B6D954716FB6B6ULL, 0x67D0CEB7BD1ED0D0ULL, 0x93ED3B7EC7D6EDEDULL, 0x17CC2EDB85E2CCCCULL, 0x15422A5784684242ULL, 0x5A98B4C22D2C9898ULL, 0xAAA4490E55EDA4A4ULL, 0xA0285D8850752828ULL, 0x6D5CDA31B8865C5CULL, 0xC7F8933FED6BF8F8ULL, 0x228644A411C28686ULL }; const u64bit Whirlpool::C7[256] = { 0x186018C07830D818ULL, 0x238C2305AF462623ULL, 0xC63FC67EF991B8C6ULL, 0xE887E8136FCDFBE8ULL, 0x8726874CA113CB87ULL, 0xB8DAB8A9626D11B8ULL, 0x0104010805020901ULL, 0x4F214F426E9E0D4FULL, 0x36D836ADEE6C9B36ULL, 0xA6A2A6590451FFA6ULL, 0xD26FD2DEBDB90CD2ULL, 0xF5F3F5FB06F70EF5ULL, 0x79F979EF80F29679ULL, 0x6FA16F5FCEDE306FULL, 0x917E91FCEF3F6D91ULL, 0x525552AA07A4F852ULL, 0x609D6027FDC04760ULL, 0xBCCABC89766535BCULL, 0x9B569BACCD2B379BULL, 0x8E028E048C018A8EULL, 0xA3B6A371155BD2A3ULL, 0x0C300C603C186C0CULL, 0x7BF17BFF8AF6847BULL, 0x35D435B5E16A8035ULL, 0x1D741DE8693AF51DULL, 0xE0A7E05347DDB3E0ULL, 0xD77BD7F6ACB321D7ULL, 0xC22FC25EED999CC2ULL, 0x2EB82E6D965C432EULL, 0x4B314B627A96294BULL, 0xFEDFFEA321E15DFEULL, 0x5741578216AED557ULL, 0x155415A8412ABD15ULL, 0x77C1779FB6EEE877ULL, 0x37DC37A5EB6E9237ULL, 0xE5B3E57B56D79EE5ULL, 0x9F469F8CD923139FULL, 0xF0E7F0D317FD23F0ULL, 0x4A354A6A7F94204AULL, 0xDA4FDA9E95A944DAULL, 0x587D58FA25B0A258ULL, 0xC903C906CA8FCFC9ULL, 0x29A429558D527C29ULL, 0x0A280A5022145A0AULL, 0xB1FEB1E14F7F50B1ULL, 0xA0BAA0691A5DC9A0ULL, 0x6BB16B7FDAD6146BULL, 0x852E855CAB17D985ULL, 0xBDCEBD8173673CBDULL, 0x5D695DD234BA8F5DULL, 0x1040108050209010ULL, 0xF4F7F4F303F507F4ULL, 0xCB0BCB16C08BDDCBULL, 0x3EF83EEDC67CD33EULL, 0x05140528110A2D05ULL, 0x6781671FE6CE7867ULL, 0xE4B7E47353D597E4ULL, 0x279C2725BB4E0227ULL, 0x4119413258827341ULL, 0x8B168B2C9D0BA78BULL, 0xA7A6A7510153F6A7ULL, 0x7DE97DCF94FAB27DULL, 0x956E95DCFB374995ULL, 0xD847D88E9FAD56D8ULL, 0xFBCBFB8B30EB70FBULL, 0xEE9FEE2371C1CDEEULL, 0x7CED7CC791F8BB7CULL, 0x66856617E3CC7166ULL, 0xDD53DDA68EA77BDDULL, 0x175C17B84B2EAF17ULL, 0x47014702468E4547ULL, 0x9E429E84DC211A9EULL, 0xCA0FCA1EC589D4CAULL, 0x2DB42D75995A582DULL, 0xBFC6BF9179632EBFULL, 0x071C07381B0E3F07ULL, 0xAD8EAD012347ACADULL, 0x5A755AEA2FB4B05AULL, 0x8336836CB51BEF83ULL, 0x33CC3385FF66B633ULL, 0x6391633FF2C65C63ULL, 0x020802100A041202ULL, 0xAA92AA39384993AAULL, 0x71D971AFA8E2DE71ULL, 0xC807C80ECF8DC6C8ULL, 0x196419C87D32D119ULL, 0x4939497270923B49ULL, 0xD943D9869AAF5FD9ULL, 0xF2EFF2C31DF931F2ULL, 0xE3ABE34B48DBA8E3ULL, 0x5B715BE22AB6B95BULL, 0x881A8834920DBC88ULL, 0x9A529AA4C8293E9AULL, 0x2698262DBE4C0B26ULL, 0x32C8328DFA64BF32ULL, 0xB0FAB0E94A7D59B0ULL, 0xE983E91B6ACFF2E9ULL, 0x0F3C0F78331E770FULL, 0xD573D5E6A6B733D5ULL, 0x803A8074BA1DF480ULL, 0xBEC2BE997C6127BEULL, 0xCD13CD26DE87EBCDULL, 0x34D034BDE4688934ULL, 0x483D487A75903248ULL, 0xFFDBFFAB24E354FFULL, 0x7AF57AF78FF48D7AULL, 0x907A90F4EA3D6490ULL, 0x5F615FC23EBE9D5FULL, 0x2080201DA0403D20ULL, 0x68BD6867D5D00F68ULL, 0x1A681AD07234CA1AULL, 0xAE82AE192C41B7AEULL, 0xB4EAB4C95E757DB4ULL, 0x544D549A19A8CE54ULL, 0x937693ECE53B7F93ULL, 0x2288220DAA442F22ULL, 0x648D6407E9C86364ULL, 0xF1E3F1DB12FF2AF1ULL, 0x73D173BFA2E6CC73ULL, 0x124812905A248212ULL, 0x401D403A5D807A40ULL, 0x0820084028104808ULL, 0xC32BC356E89B95C3ULL, 0xEC97EC337BC5DFECULL, 0xDB4BDB9690AB4DDBULL, 0xA1BEA1611F5FC0A1ULL, 0x8D0E8D1C8307918DULL, 0x3DF43DF5C97AC83DULL, 0x976697CCF1335B97ULL, 0x0000000000000000ULL, 0xCF1BCF36D483F9CFULL, 0x2BAC2B4587566E2BULL, 0x76C57697B3ECE176ULL, 0x82328264B019E682ULL, 0xD67FD6FEA9B128D6ULL, 0x1B6C1BD87736C31BULL, 0xB5EEB5C15B7774B5ULL, 0xAF86AF112943BEAFULL, 0x6AB56A77DFD41D6AULL, 0x505D50BA0DA0EA50ULL, 0x450945124C8A5745ULL, 0xF3EBF3CB18FB38F3ULL, 0x30C0309DF060AD30ULL, 0xEF9BEF2B74C3C4EFULL, 0x3FFC3FE5C37EDA3FULL, 0x554955921CAAC755ULL, 0xA2B2A2791059DBA2ULL, 0xEA8FEA0365C9E9EAULL, 0x6589650FECCA6A65ULL, 0xBAD2BAB9686903BAULL, 0x2FBC2F65935E4A2FULL, 0xC027C04EE79D8EC0ULL, 0xDE5FDEBE81A160DEULL, 0x1C701CE06C38FC1CULL, 0xFDD3FDBB2EE746FDULL, 0x4D294D52649A1F4DULL, 0x927292E4E0397692ULL, 0x75C9758FBCEAFA75ULL, 0x061806301E0C3606ULL, 0x8A128A249809AE8AULL, 0xB2F2B2F940794BB2ULL, 0xE6BFE66359D185E6ULL, 0x0E380E70361C7E0EULL, 0x1F7C1FF8633EE71FULL, 0x62956237F7C45562ULL, 0xD477D4EEA3B53AD4ULL, 0xA89AA829324D81A8ULL, 0x966296C4F4315296ULL, 0xF9C3F99B3AEF62F9ULL, 0xC533C566F697A3C5ULL, 0x25942535B14A1025ULL, 0x597959F220B2AB59ULL, 0x842A8454AE15D084ULL, 0x72D572B7A7E4C572ULL, 0x39E439D5DD72EC39ULL, 0x4C2D4C5A6198164CULL, 0x5E655ECA3BBC945EULL, 0x78FD78E785F09F78ULL, 0x38E038DDD870E538ULL, 0x8C0A8C148605988CULL, 0xD163D1C6B2BF17D1ULL, 0xA5AEA5410B57E4A5ULL, 0xE2AFE2434DD9A1E2ULL, 0x6199612FF8C24E61ULL, 0xB3F6B3F1457B42B3ULL, 0x21842115A5423421ULL, 0x9C4A9C94D625089CULL, 0x1E781EF0663CEE1EULL, 0x4311432252866143ULL, 0xC73BC776FC93B1C7ULL, 0xFCD7FCB32BE54FFCULL, 0x0410042014082404ULL, 0x515951B208A2E351ULL, 0x995E99BCC72F2599ULL, 0x6DA96D4FC4DA226DULL, 0x0D340D68391A650DULL, 0xFACFFA8335E979FAULL, 0xDF5BDFB684A369DFULL, 0x7EE57ED79BFCA97EULL, 0x2490243DB4481924ULL, 0x3BEC3BC5D776FE3BULL, 0xAB96AB313D4B9AABULL, 0xCE1FCE3ED181F0CEULL, 0x1144118855229911ULL, 0x8F068F0C8903838FULL, 0x4E254E4A6B9C044EULL, 0xB7E6B7D1517366B7ULL, 0xEB8BEB0B60CBE0EBULL, 0x3CF03CFDCC78C13CULL, 0x813E817CBF1FFD81ULL, 0x946A94D4FE354094ULL, 0xF7FBF7EB0CF31CF7ULL, 0xB9DEB9A1676F18B9ULL, 0x134C13985F268B13ULL, 0x2CB02C7D9C58512CULL, 0xD36BD3D6B8BB05D3ULL, 0xE7BBE76B5CD38CE7ULL, 0x6EA56E57CBDC396EULL, 0xC437C46EF395AAC4ULL, 0x030C03180F061B03ULL, 0x5645568A13ACDC56ULL, 0x440D441A49885E44ULL, 0x7FE17FDF9EFEA07FULL, 0xA99EA921374F88A9ULL, 0x2AA82A4D8254672AULL, 0xBBD6BBB16D6B0ABBULL, 0xC123C146E29F87C1ULL, 0x535153A202A6F153ULL, 0xDC57DCAE8BA572DCULL, 0x0B2C0B582716530BULL, 0x9D4E9D9CD327019DULL, 0x6CAD6C47C1D82B6CULL, 0x31C43195F562A431ULL, 0x74CD7487B9E8F374ULL, 0xF6FFF6E309F115F6ULL, 0x4605460A438C4C46ULL, 0xAC8AAC092645A5ACULL, 0x891E893C970FB589ULL, 0x145014A04428B414ULL, 0xE1A3E15B42DFBAE1ULL, 0x165816B04E2CA616ULL, 0x3AE83ACDD274F73AULL, 0x69B9696FD0D20669ULL, 0x092409482D124109ULL, 0x70DD70A7ADE0D770ULL, 0xB6E2B6D954716FB6ULL, 0xD067D0CEB7BD1ED0ULL, 0xED93ED3B7EC7D6EDULL, 0xCC17CC2EDB85E2CCULL, 0x4215422A57846842ULL, 0x985A98B4C22D2C98ULL, 0xA4AAA4490E55EDA4ULL, 0x28A0285D88507528ULL, 0x5C6D5CDA31B8865CULL, 0xF8C7F8933FED6BF8ULL, 0x86228644A411C286ULL }; } /* * Whirlpool * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { /* * Whirlpool Compression Function */ void Whirlpool::compress_n(const byte in[], size_t blocks) { static const u64bit RC[10] = { 0x1823C6E887B8014FULL, 0x36A6D2F5796F9152ULL, 0x60BC9B8EA30C7B35ULL, 0x1DE0D7C22E4BFE57ULL, 0x157737E59FF04ADAULL, 0x58C9290AB1A06B85ULL, 0xBD5D10F4CB3E0567ULL, 0xE427418BA77D95D8ULL, 0xFBEE7C66DD17479EULL, 0xCA2DBF07AD5A8333ULL }; for(size_t i = 0; i != blocks; ++i) { load_be(&M[0], in, M.size()); u64bit K0, K1, K2, K3, K4, K5, K6, K7; K0 = digest[0]; K1 = digest[1]; K2 = digest[2]; K3 = digest[3]; K4 = digest[4]; K5 = digest[5]; K6 = digest[6]; K7 = digest[7]; u64bit B0, B1, B2, B3, B4, B5, B6, B7; B0 = K0 ^ M[0]; B1 = K1 ^ M[1]; B2 = K2 ^ M[2]; B3 = K3 ^ M[3]; B4 = K4 ^ M[4]; B5 = K5 ^ M[5]; B6 = K6 ^ M[6]; B7 = K7 ^ M[7]; for(size_t j = 0; j != 10; ++j) { u64bit T0, T1, T2, T3, T4, T5, T6, T7; T0 = C0[get_byte(0, K0)] ^ C1[get_byte(1, K7)] ^ C2[get_byte(2, K6)] ^ C3[get_byte(3, K5)] ^ C4[get_byte(4, K4)] ^ C5[get_byte(5, K3)] ^ C6[get_byte(6, K2)] ^ C7[get_byte(7, K1)] ^ RC[j]; T1 = C0[get_byte(0, K1)] ^ C1[get_byte(1, K0)] ^ C2[get_byte(2, K7)] ^ C3[get_byte(3, K6)] ^ C4[get_byte(4, K5)] ^ C5[get_byte(5, K4)] ^ C6[get_byte(6, K3)] ^ C7[get_byte(7, K2)]; T2 = C0[get_byte(0, K2)] ^ C1[get_byte(1, K1)] ^ C2[get_byte(2, K0)] ^ C3[get_byte(3, K7)] ^ C4[get_byte(4, K6)] ^ C5[get_byte(5, K5)] ^ C6[get_byte(6, K4)] ^ C7[get_byte(7, K3)]; T3 = C0[get_byte(0, K3)] ^ C1[get_byte(1, K2)] ^ C2[get_byte(2, K1)] ^ C3[get_byte(3, K0)] ^ C4[get_byte(4, K7)] ^ C5[get_byte(5, K6)] ^ C6[get_byte(6, K5)] ^ C7[get_byte(7, K4)]; T4 = C0[get_byte(0, K4)] ^ C1[get_byte(1, K3)] ^ C2[get_byte(2, K2)] ^ C3[get_byte(3, K1)] ^ C4[get_byte(4, K0)] ^ C5[get_byte(5, K7)] ^ C6[get_byte(6, K6)] ^ C7[get_byte(7, K5)]; T5 = C0[get_byte(0, K5)] ^ C1[get_byte(1, K4)] ^ C2[get_byte(2, K3)] ^ C3[get_byte(3, K2)] ^ C4[get_byte(4, K1)] ^ C5[get_byte(5, K0)] ^ C6[get_byte(6, K7)] ^ C7[get_byte(7, K6)]; T6 = C0[get_byte(0, K6)] ^ C1[get_byte(1, K5)] ^ C2[get_byte(2, K4)] ^ C3[get_byte(3, K3)] ^ C4[get_byte(4, K2)] ^ C5[get_byte(5, K1)] ^ C6[get_byte(6, K0)] ^ C7[get_byte(7, K7)]; T7 = C0[get_byte(0, K7)] ^ C1[get_byte(1, K6)] ^ C2[get_byte(2, K5)] ^ C3[get_byte(3, K4)] ^ C4[get_byte(4, K3)] ^ C5[get_byte(5, K2)] ^ C6[get_byte(6, K1)] ^ C7[get_byte(7, K0)]; K0 = T0; K1 = T1; K2 = T2; K3 = T3; K4 = T4; K5 = T5; K6 = T6; K7 = T7; T0 = C0[get_byte(0, B0)] ^ C1[get_byte(1, B7)] ^ C2[get_byte(2, B6)] ^ C3[get_byte(3, B5)] ^ C4[get_byte(4, B4)] ^ C5[get_byte(5, B3)] ^ C6[get_byte(6, B2)] ^ C7[get_byte(7, B1)] ^ K0; T1 = C0[get_byte(0, B1)] ^ C1[get_byte(1, B0)] ^ C2[get_byte(2, B7)] ^ C3[get_byte(3, B6)] ^ C4[get_byte(4, B5)] ^ C5[get_byte(5, B4)] ^ C6[get_byte(6, B3)] ^ C7[get_byte(7, B2)] ^ K1; T2 = C0[get_byte(0, B2)] ^ C1[get_byte(1, B1)] ^ C2[get_byte(2, B0)] ^ C3[get_byte(3, B7)] ^ C4[get_byte(4, B6)] ^ C5[get_byte(5, B5)] ^ C6[get_byte(6, B4)] ^ C7[get_byte(7, B3)] ^ K2; T3 = C0[get_byte(0, B3)] ^ C1[get_byte(1, B2)] ^ C2[get_byte(2, B1)] ^ C3[get_byte(3, B0)] ^ C4[get_byte(4, B7)] ^ C5[get_byte(5, B6)] ^ C6[get_byte(6, B5)] ^ C7[get_byte(7, B4)] ^ K3; T4 = C0[get_byte(0, B4)] ^ C1[get_byte(1, B3)] ^ C2[get_byte(2, B2)] ^ C3[get_byte(3, B1)] ^ C4[get_byte(4, B0)] ^ C5[get_byte(5, B7)] ^ C6[get_byte(6, B6)] ^ C7[get_byte(7, B5)] ^ K4; T5 = C0[get_byte(0, B5)] ^ C1[get_byte(1, B4)] ^ C2[get_byte(2, B3)] ^ C3[get_byte(3, B2)] ^ C4[get_byte(4, B1)] ^ C5[get_byte(5, B0)] ^ C6[get_byte(6, B7)] ^ C7[get_byte(7, B6)] ^ K5; T6 = C0[get_byte(0, B6)] ^ C1[get_byte(1, B5)] ^ C2[get_byte(2, B4)] ^ C3[get_byte(3, B3)] ^ C4[get_byte(4, B2)] ^ C5[get_byte(5, B1)] ^ C6[get_byte(6, B0)] ^ C7[get_byte(7, B7)] ^ K6; T7 = C0[get_byte(0, B7)] ^ C1[get_byte(1, B6)] ^ C2[get_byte(2, B5)] ^ C3[get_byte(3, B4)] ^ C4[get_byte(4, B3)] ^ C5[get_byte(5, B2)] ^ C6[get_byte(6, B1)] ^ C7[get_byte(7, B0)] ^ K7; B0 = T0; B1 = T1; B2 = T2; B3 = T3; B4 = T4; B5 = T5; B6 = T6; B7 = T7; } digest[0] ^= B0 ^ M[0]; digest[1] ^= B1 ^ M[1]; digest[2] ^= B2 ^ M[2]; digest[3] ^= B3 ^ M[3]; digest[4] ^= B4 ^ M[4]; digest[5] ^= B5 ^ M[5]; digest[6] ^= B6 ^ M[6]; digest[7] ^= B7 ^ M[7]; in += hash_block_size(); } } /* * Copy out the digest */ void Whirlpool::copy_out(byte output[]) { for(size_t i = 0; i != output_length(); i += 8) store_be(digest[i/8], output + i); } /* * Clear memory of sensitive data */ void Whirlpool::clear() { MDx_HashFunction::clear(); zeroise(M); zeroise(digest); } } /* * KDF Base Class * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { /* * Derive a key */ SecureVector KDF::derive_key(size_t key_len, const MemoryRegion& secret, const std::string& salt) const { return derive_key(key_len, &secret[0], secret.size(), reinterpret_cast(salt.data()), salt.length()); } /* * Derive a key */ SecureVector KDF::derive_key(size_t key_len, const MemoryRegion& secret, const byte salt[], size_t salt_len) const { return derive_key(key_len, &secret[0], secret.size(), salt, salt_len); } /* * Derive a key */ SecureVector KDF::derive_key(size_t key_len, const MemoryRegion& secret, const MemoryRegion& salt) const { return derive_key(key_len, &secret[0], secret.size(), &salt[0], salt.size()); } /* * Derive a key */ SecureVector KDF::derive_key(size_t key_len, const byte secret[], size_t secret_len, const std::string& salt) const { return derive_key(key_len, secret, secret_len, reinterpret_cast(salt.data()), salt.length()); } /* * Derive a key */ SecureVector KDF::derive_key(size_t key_len, const byte secret[], size_t secret_len, const byte salt[], size_t salt_len) const { return derive(key_len, secret, secret_len, salt, salt_len); } } /* * KDF1 * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { /* * KDF1 Key Derivation Mechanism */ SecureVector KDF1::derive(size_t, const byte secret[], size_t secret_len, const byte P[], size_t P_len) const { hash->update(secret, secret_len); hash->update(P, P_len); return hash->final(); } } /* * KDF2 * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { /* * KDF2 Key Derivation Mechanism */ SecureVector KDF2::derive(size_t out_len, const byte secret[], size_t secret_len, const byte P[], size_t P_len) const { SecureVector output; u32bit counter = 1; while(out_len && counter) { hash->update(secret, secret_len); hash->update_be(counter); hash->update(P, P_len); SecureVector hash_result = hash->final(); size_t added = std::min(hash_result.size(), out_len); output += std::make_pair(&hash_result[0], added); out_len -= added; ++counter; } return output; } } /* * MGF1 * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ #include #include namespace Botan { /* * MGF1 Mask Generation Function */ void MGF1::mask(const byte in[], size_t in_len, byte out[], size_t out_len) const { u32bit counter = 0; while(out_len) { hash->update(in, in_len); hash->update_be(counter); SecureVector buffer = hash->final(); size_t xored = std::min(buffer.size(), out_len); xor_buf(out, &buffer[0], xored); out += xored; out_len -= xored; ++counter; } } /* * MGF1 Constructor */ MGF1::MGF1(HashFunction* h) : hash(h) { if(!hash) throw Invalid_Argument("MGF1 given null hash object"); } /* * MGF1 Destructor */ MGF1::~MGF1() { delete hash; } } /* * SSLv3 PRF * (C) 2004-2006 Jack Lloyd * * Distributed under the terms of the Botan license */ #include namespace Botan { namespace { /* * Return the next inner hash */ OctetString next_hash(size_t where, size_t want, HashFunction& md5, HashFunction& sha1, const byte secret[], size_t secret_len, const byte seed[], size_t seed_len) { BOTAN_ASSERT(want <= md5.output_length(), "Desired output too large"); const byte ASCII_A_CHAR = 0x41; for(size_t j = 0; j != where + 1; j++) sha1.update(static_cast(ASCII_A_CHAR + where)); sha1.update(secret, secret_len); sha1.update(seed, seed_len); SecureVector sha1_hash = sha1.final(); md5.update(secret, secret_len); md5.update(sha1_hash); SecureVector md5_hash = md5.final(); return OctetString(&md5_hash[0], want); } } /* * SSL3 PRF */ SecureVector SSL3_PRF::derive(size_t key_len, const byte secret[], size_t secret_len, const byte seed[], size_t seed_len) const { if(key_len > 416) throw Invalid_Argument("SSL3_PRF: Requested key length is too large"); MD5 md5; SHA_160 sha1; OctetString output; int counter = 0; while(key_len) { const size_t produce = std::min(key_len, md5.output_length()); output = output + next_hash(counter++, produce, md5, sha1, secret, secret_len, seed, seed_len); key_len -= produce; } return output.bits_of(); } } /* * TLS v1.0 and v1.2 PRFs * (C) 2004-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { namespace { /* * TLS PRF P_hash function */ void P_hash(MemoryRegion& output, MessageAuthenticationCode* mac, const byte secret[], size_t secret_len, const byte seed[], size_t seed_len) { mac->set_key(secret, secret_len); SecureVector A(seed, seed_len); size_t offset = 0; while(offset != output.size()) { const size_t this_block_len = std::min(mac->output_length(), output.size() - offset); A = mac->process(A); mac->update(A); mac->update(seed, seed_len); SecureVector block = mac->final(); xor_buf(&output[offset], &block[0], this_block_len); offset += this_block_len; } } } /* * TLS PRF Constructor and Destructor */ TLS_PRF::TLS_PRF() { hmac_md5 = new HMAC(new MD5); hmac_sha1 = new HMAC(new SHA_160); } TLS_PRF::~TLS_PRF() { delete hmac_md5; delete hmac_sha1; } /* * TLS PRF */ SecureVector TLS_PRF::derive(size_t key_len, const byte secret[], size_t secret_len, const byte seed[], size_t seed_len) const { SecureVector output(key_len); size_t S1_len = (secret_len + 1) / 2, S2_len = (secret_len + 1) / 2; const byte* S1 = secret; const byte* S2 = secret + (secret_len - S2_len); P_hash(output, hmac_md5, S1, S1_len, seed, seed_len); P_hash(output, hmac_sha1, S2, S2_len, seed, seed_len); return output; } /* * TLS v1.2 PRF Constructor and Destructor */ TLS_12_PRF::TLS_12_PRF(MessageAuthenticationCode* mac) : hmac(mac) { } TLS_12_PRF::~TLS_12_PRF() { delete hmac; } SecureVector TLS_12_PRF::derive(size_t key_len, const byte secret[], size_t secret_len, const byte seed[], size_t seed_len) const { SecureVector output(key_len); P_hash(output, hmac, secret, secret_len, seed, seed_len); return output; } } /* * X9.42 PRF * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ #include #include namespace Botan { namespace { /* * Encode an integer as an OCTET STRING */ MemoryVector encode_x942_int(u32bit n) { byte n_buf[4] = { 0 }; store_be(n, n_buf); return DER_Encoder().encode(n_buf, 4, OCTET_STRING).get_contents(); } } /* * X9.42 PRF */ SecureVector X942_PRF::derive(size_t key_len, const byte secret[], size_t secret_len, const byte salt[], size_t salt_len) const { SHA_160 hash; const OID kek_algo(key_wrap_oid); SecureVector key; u32bit counter = 1; while(key.size() != key_len && counter) { hash.update(secret, secret_len); hash.update( DER_Encoder().start_cons(SEQUENCE) .start_cons(SEQUENCE) .encode(kek_algo) .raw_bytes(encode_x942_int(counter)) .end_cons() .encode_if(salt_len != 0, DER_Encoder() .start_explicit(0) .encode(salt, salt_len, OCTET_STRING) .end_explicit() ) .start_explicit(2) .raw_bytes(encode_x942_int(static_cast(8 * key_len))) .end_explicit() .end_cons().get_contents() ); SecureVector digest = hash.final(); const size_t needed = std::min(digest.size(), key_len - key.size()); key += std::make_pair(&digest[0], needed); ++counter; } return key; } /* * X9.42 Constructor */ X942_PRF::X942_PRF(const std::string& oid) { if(OIDS::have_oid(oid)) key_wrap_oid = OIDS::lookup(oid).as_string(); else key_wrap_oid = oid; } } /* * PBKDF/EMSA/EME/KDF/MGF Retrieval * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ #if defined(BOTAN_HAS_MGF1) #endif #if defined(BOTAN_HAS_EMSA1) #endif #if defined(BOTAN_HAS_EMSA1_BSI) #endif #if defined(BOTAN_HAS_EMSA2) #endif #if defined(BOTAN_HAS_EMSA3) #endif #if defined(BOTAN_HAS_EMSA4) #endif #if defined(BOTAN_HAS_EMSA_RAW) #endif #if defined(BOTAN_HAS_EME1) #endif #if defined(BOTAN_HAS_EME_PKCS1v15) #endif #if defined(BOTAN_HAS_KDF1) #endif #if defined(BOTAN_HAS_KDF2) #endif #if defined(BOTAN_HAS_X942_PRF) #endif #if defined(BOTAN_HAS_SSL_V3_PRF) #endif #if defined(BOTAN_HAS_TLS_V10_PRF) #endif namespace Botan { /* * Get a PBKDF algorithm by name */ PBKDF* get_pbkdf(const std::string& algo_spec) { Algorithm_Factory& af = global_state().algorithm_factory(); if(PBKDF* pbkdf = af.make_pbkdf(algo_spec)) return pbkdf; throw Algorithm_Not_Found(algo_spec); } /* * Get an EMSA by name */ EMSA* get_emsa(const std::string& algo_spec) { SCAN_Name request(algo_spec); Algorithm_Factory& af = global_state().algorithm_factory(); #if defined(BOTAN_HAS_EMSA_RAW) if(request.algo_name() == "Raw" && request.arg_count() == 0) return new EMSA_Raw; #endif #if defined(BOTAN_HAS_EMSA1) if(request.algo_name() == "EMSA1" && request.arg_count() == 1) return new EMSA1(af.make_hash_function(request.arg(0))); #endif #if defined(BOTAN_HAS_EMSA1_BSI) if(request.algo_name() == "EMSA1_BSI" && request.arg_count() == 1) return new EMSA1_BSI(af.make_hash_function(request.arg(0))); #endif #if defined(BOTAN_HAS_EMSA2) if(request.algo_name() == "EMSA2" && request.arg_count() == 1) return new EMSA2(af.make_hash_function(request.arg(0))); #endif #if defined(BOTAN_HAS_EMSA3) if(request.algo_name() == "EMSA3" && request.arg_count() == 1) { if(request.arg(0) == "Raw") return new EMSA3_Raw; return new EMSA3(af.make_hash_function(request.arg(0))); } #endif #if defined(BOTAN_HAS_EMSA4) if(request.algo_name() == "EMSA4" && request.arg_count_between(1, 3)) { // 3 args: Hash, MGF, salt size (MGF is hardcoded MGF1 in Botan) if(request.arg_count() == 1) return new EMSA4(af.make_hash_function(request.arg(0))); if(request.arg_count() == 2 && request.arg(1) != "MGF1") return new EMSA4(af.make_hash_function(request.arg(0))); if(request.arg_count() == 3) return new EMSA4(af.make_hash_function(request.arg(0)), request.arg_as_integer(2, 0)); } #endif throw Algorithm_Not_Found(algo_spec); } /* * Get an EME by name */ EME* get_eme(const std::string& algo_spec) { SCAN_Name request(algo_spec); Algorithm_Factory& af = global_state().algorithm_factory(); if(request.algo_name() == "Raw") return 0; // No padding #if defined(BOTAN_HAS_EME_PKCS1v15) if(request.algo_name() == "PKCS1v15" && request.arg_count() == 0) return new EME_PKCS1v15; #endif #if defined(BOTAN_HAS_EME1) if(request.algo_name() == "EME1" && request.arg_count_between(1, 2)) { if(request.arg_count() == 1 || (request.arg_count() == 2 && request.arg(1) == "MGF1")) { return new EME1(af.make_hash_function(request.arg(0))); } } #endif throw Algorithm_Not_Found(algo_spec); } /* * Get an KDF by name */ KDF* get_kdf(const std::string& algo_spec) { SCAN_Name request(algo_spec); Algorithm_Factory& af = global_state().algorithm_factory(); if(request.algo_name() == "Raw") return 0; // No KDF #if defined(BOTAN_HAS_KDF1) if(request.algo_name() == "KDF1" && request.arg_count() == 1) return new KDF1(af.make_hash_function(request.arg(0))); #endif #if defined(BOTAN_HAS_KDF2) if(request.algo_name() == "KDF2" && request.arg_count() == 1) return new KDF2(af.make_hash_function(request.arg(0))); #endif #if defined(BOTAN_HAS_X942_PRF) if(request.algo_name() == "X9.42-PRF" && request.arg_count() == 1) return new X942_PRF(request.arg(0)); // OID #endif #if defined(BOTAN_HAS_TLS_V10_PRF) if(request.algo_name() == "TLS-PRF" && request.arg_count() == 0) return new TLS_PRF; #endif #if defined(BOTAN_HAS_SSL_V3_PRF) if(request.algo_name() == "SSL3-PRF" && request.arg_count() == 0) return new SSL3_PRF; #endif throw Algorithm_Not_Found(algo_spec); } } /* * Global PRNG * (C) 2008-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ #if defined(BOTAN_HAS_RANDPOOL) #endif #if defined(BOTAN_HAS_HMAC_RNG) #endif #if defined(BOTAN_HAS_X931_RNG) #endif #if defined(BOTAN_HAS_ENTROPY_SRC_HIGH_RESOLUTION_TIMER) #endif #if defined(BOTAN_HAS_ENTROPY_SRC_RDRAND) #endif #if defined(BOTAN_HAS_ENTROPY_SRC_DEV_RANDOM) #endif #if defined(BOTAN_HAS_ENTROPY_SRC_EGD) #endif #if defined(BOTAN_HAS_ENTROPY_SRC_UNIX) #endif #if defined(BOTAN_HAS_ENTROPY_SRC_BEOS) #endif #if defined(BOTAN_HAS_ENTROPY_SRC_CAPI) #endif #if defined(BOTAN_HAS_ENTROPY_SRC_WIN32) #endif #if defined(BOTAN_HAS_ENTROPY_SRC_FTW) #endif namespace Botan { namespace { /** * Add any known entropy sources to this RNG */ void add_entropy_sources(RandomNumberGenerator* rng) { #if defined(BOTAN_HAS_ENTROPY_SRC_HIGH_RESOLUTION_TIMER) rng->add_entropy_source(new High_Resolution_Timestamp); #endif #if defined(BOTAN_HAS_ENTROPY_SRC_RDRAND) rng->add_entropy_source(new Intel_Rdrand); #endif #if defined(BOTAN_HAS_ENTROPY_SRC_DEV_RANDOM) rng->add_entropy_source( new Device_EntropySource( split_on("/dev/random:/dev/srandom:/dev/urandom", ':') ) ); #endif #if defined(BOTAN_HAS_ENTROPY_SRC_EGD) rng->add_entropy_source( new EGD_EntropySource(split_on("/var/run/egd-pool:/dev/egd-pool", ':')) ); #endif #if defined(BOTAN_HAS_ENTROPY_SRC_CAPI) rng->add_entropy_source(new Win32_CAPI_EntropySource); #endif #if defined(BOTAN_HAS_ENTROPY_SRC_FTW) rng->add_entropy_source(new FTW_EntropySource("/proc")); #endif #if defined(BOTAN_HAS_ENTROPY_SRC_WIN32) rng->add_entropy_source(new Win32_EntropySource); #endif #if defined(BOTAN_HAS_ENTROPY_SRC_BEOS) rng->add_entropy_source(new BeOS_EntropySource); #endif #if defined(BOTAN_HAS_ENTROPY_SRC_UNIX) rng->add_entropy_source( new Unix_EntropySource(split_on("/bin:/sbin:/usr/bin:/usr/sbin", ':')) ); #endif } class Serialized_PRNG : public RandomNumberGenerator { public: void randomize(byte out[], size_t len) { Mutex_Holder lock(mutex); rng->randomize(out, len); } bool is_seeded() const { Mutex_Holder lock(mutex); return rng->is_seeded(); } void clear() { Mutex_Holder lock(mutex); rng->clear(); } std::string name() const { Mutex_Holder lock(mutex); return rng->name(); } void reseed(size_t poll_bits) { Mutex_Holder lock(mutex); rng->reseed(poll_bits); } void add_entropy_source(EntropySource* es) { Mutex_Holder lock(mutex); rng->add_entropy_source(es); } void add_entropy(const byte in[], size_t len) { Mutex_Holder lock(mutex); rng->add_entropy(in, len); } // We do not own the mutex; Library_State does Serialized_PRNG(RandomNumberGenerator* r, Mutex* m) : mutex(m), rng(r) {} ~Serialized_PRNG() { delete rng; } private: Mutex* mutex; RandomNumberGenerator* rng; }; } RandomNumberGenerator* Library_State::make_global_rng(Algorithm_Factory& af, Mutex* mutex) { RandomNumberGenerator* rng = 0; #if defined(BOTAN_HAS_HMAC_RNG) rng = new HMAC_RNG(af.make_mac("HMAC(SHA-512)"), af.make_mac("HMAC(SHA-256)")); #elif defined(BOTAN_HAS_RANDPOOL) rng = new Randpool(af.make_block_cipher("AES-256"), af.make_mac("HMAC(SHA-256)")); #endif if(!rng) 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) rng = new ANSI_X931_RNG(af.make_block_cipher("AES-256"), rng); #endif add_entropy_sources(rng); rng->reseed(256); return new Serialized_PRNG(rng, mutex); } } /* * Global State Management * (C) 2010 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { /* * @todo There should probably be a lock to avoid racy manipulation * of the state among different threads */ namespace Global_State_Management { /* * Botan's global state */ namespace { Library_State* global_lib_state = 0; } /* * Access the global state object */ Library_State& global_state() { /* Lazy initialization. Botan still needs to be deinitialized later on or memory might leak. */ if(!global_lib_state) { global_lib_state = new Library_State; global_lib_state->initialize(true); } return (*global_lib_state); } /* * Set a new global state object */ void set_global_state(Library_State* new_state) { delete swap_global_state(new_state); } /* * Set a new global state object unless one already existed */ bool set_global_state_unless_set(Library_State* new_state) { if(global_lib_state) { delete new_state; return false; } else { delete swap_global_state(new_state); return true; } } /* * Swap two global state objects */ Library_State* swap_global_state(Library_State* new_state) { Library_State* old_state = global_lib_state; global_lib_state = new_state; return old_state; } /* * Query if library is initialized */ bool global_state_exists() { return (global_lib_state != 0); } } } /* * Default Initialization Function * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { /* * Library Initialization */ void LibraryInitializer::initialize(const std::string& arg_string) { bool thread_safe = false; const std::vector arg_list = split_on(arg_string, ' '); for(size_t i = 0; i != arg_list.size(); ++i) { if(arg_list[i].size() == 0) continue; std::string name, value; if(arg_list[i].find('=') == std::string::npos) { name = arg_list[i]; value = "true"; } else { std::vector name_and_value = split_on(arg_list[i], '='); name = name_and_value[0]; value = name_and_value[1]; } bool is_on = (value == "1" || value == "true" || value == "yes" || value == "on"); if(name == "thread_safe") thread_safe = is_on; } try { /* This two stage initialization process is because Library_State's constructor will implicitly refer to global state through the allocators and so forth, so global_state() has to be a valid reference before initialize() can be called. Yeah, gross. */ Global_State_Management::set_global_state(new Library_State); global_state().initialize(thread_safe); } catch(...) { deinitialize(); throw; } } /* * Library Shutdown */ void LibraryInitializer::deinitialize() { Global_State_Management::set_global_state(0); } } /* * Library Internal/Global State * (C) 1999-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ #include #if defined(BOTAN_HAS_SELFTESTS) #endif #if defined(BOTAN_HAS_MUTEX_PTHREAD) #elif defined(BOTAN_HAS_MUTEX_WIN32) #endif #if defined(BOTAN_HAS_ALLOC_MMAP) #endif #if defined(BOTAN_HAS_ENGINE_ASSEMBLER) #endif #if defined(BOTAN_HAS_ENGINE_AES_ISA) #endif #if defined(BOTAN_HAS_ENGINE_SIMD) #endif #if defined(BOTAN_HAS_ENGINE_GNU_MP) #endif #if defined(BOTAN_HAS_ENGINE_OPENSSL) #endif namespace Botan { /* * Get a new mutex object */ Mutex* Library_State::get_mutex() const { return mutex_factory->make(); } /* * Get an allocator by its name */ Allocator* Library_State::get_allocator(const std::string& type) const { Mutex_Holder lock(allocator_lock); if(type != "") return search_map(alloc_factory, type, 0); if(!cached_default_allocator) { cached_default_allocator = search_map(alloc_factory, default_allocator_name, 0); } return cached_default_allocator; } /* * Create a new name to object mapping */ void Library_State::add_allocator(Allocator* allocator) { Mutex_Holder lock(allocator_lock); allocator->init(); allocators.push_back(allocator); alloc_factory[allocator->type()] = allocator; } /* * Set the default allocator type */ void Library_State::set_default_allocator(const std::string& type) { Mutex_Holder lock(allocator_lock); if(type == "") return; default_allocator_name = type; cached_default_allocator = 0; } /* * Get a configuration value */ std::string Library_State::get(const std::string& section, const std::string& key) const { Mutex_Holder lock(config_lock); return search_map(config, section + "/" + key, ""); } /* * See if a particular option has been set */ bool Library_State::is_set(const std::string& section, const std::string& key) const { Mutex_Holder lock(config_lock); return config.count(section + "/" + key) != 0; } /* * Set a configuration value */ void Library_State::set(const std::string& section, const std::string& key, const std::string& value, bool overwrite) { Mutex_Holder lock(config_lock); std::string full_key = section + "/" + key; std::map::const_iterator i = config.find(full_key); if(overwrite || i == config.end() || i->second == "") config[full_key] = value; } /* * Add an alias */ void Library_State::add_alias(const std::string& key, const std::string& value) { set("alias", key, value); } /* * Dereference an alias to a fixed name */ std::string Library_State::deref_alias(const std::string& key) const { std::string result = key; while(is_set("alias", result)) result = get("alias", result); return result; } /* * Return a reference to the Algorithm_Factory */ Algorithm_Factory& Library_State::algorithm_factory() const { if(!m_algorithm_factory) throw Invalid_State("Uninitialized in Library_State::algorithm_factory"); return *m_algorithm_factory; } /* * Return a reference to the global PRNG */ RandomNumberGenerator& Library_State::global_rng() { Mutex_Holder lock(global_rng_lock); if(!global_rng_ptr) global_rng_ptr = make_global_rng(algorithm_factory(), global_rng_lock); return *global_rng_ptr; } /* * Load a set of modules */ void Library_State::initialize(bool thread_safe) { CPUID::initialize(); if(mutex_factory) throw Invalid_State("Library_State has already been initialized"); if(!thread_safe) { mutex_factory = new Noop_Mutex_Factory; } else { #if defined(BOTAN_HAS_MUTEX_PTHREAD) mutex_factory = new Pthread_Mutex_Factory; #elif defined(BOTAN_HAS_MUTEX_WIN32) mutex_factory = new Win32_Mutex_Factory; #else throw Invalid_State("Could not find a thread-safe mutex object to use"); #endif } allocator_lock = get_mutex(); config_lock = get_mutex(); global_rng_lock = get_mutex(); default_allocator_name = has_mlock() ? "locking" : "malloc"; add_allocator(new Malloc_Allocator); add_allocator(new Locking_Allocator(get_mutex())); #if defined(BOTAN_HAS_ALLOC_MMAP) add_allocator(new MemoryMapping_Allocator(get_mutex())); #endif load_default_config(); m_algorithm_factory = new Algorithm_Factory(*mutex_factory); #if defined(BOTAN_HAS_ENGINE_GNU_MP) algorithm_factory().add_engine(new GMP_Engine); #endif #if defined(BOTAN_HAS_ENGINE_OPENSSL) algorithm_factory().add_engine(new OpenSSL_Engine); #endif #if defined(BOTAN_HAS_ENGINE_AES_ISA) algorithm_factory().add_engine(new AES_ISA_Engine); #endif #if defined(BOTAN_HAS_ENGINE_SIMD) algorithm_factory().add_engine(new SIMD_Engine); #endif #if defined(BOTAN_HAS_ENGINE_ASSEMBLER) algorithm_factory().add_engine(new Assembler_Engine); #endif algorithm_factory().add_engine(new Core_Engine); #if defined(BOTAN_HAS_SELFTESTS) confirm_startup_self_tests(algorithm_factory()); #endif } /* * Library_State Constructor */ Library_State::Library_State() { mutex_factory = 0; allocator_lock = config_lock = 0; cached_default_allocator = 0; m_algorithm_factory = 0; global_rng_lock = 0; global_rng_ptr = 0; } /* * Library_State Destructor */ Library_State::~Library_State() { delete m_algorithm_factory; delete global_rng_ptr; cached_default_allocator = 0; for(size_t i = 0; i != allocators.size(); ++i) { allocators[i]->destroy(); delete allocators[i]; } delete global_rng_lock; delete allocator_lock; delete mutex_factory; delete config_lock; } } /* * Algorithm Retrieval * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { /* * Query if an algorithm exists */ bool have_algorithm(const std::string& name) { Algorithm_Factory& af = global_state().algorithm_factory(); if(af.prototype_block_cipher(name)) return true; if(af.prototype_stream_cipher(name)) return true; if(af.prototype_hash_function(name)) return true; if(af.prototype_mac(name)) return true; return false; } /* * Query the block size of a cipher or hash */ size_t block_size_of(const std::string& name) { Algorithm_Factory& af = global_state().algorithm_factory(); if(const BlockCipher* cipher = af.prototype_block_cipher(name)) return cipher->block_size(); if(const HashFunction* hash = af.prototype_hash_function(name)) return hash->hash_block_size(); throw Algorithm_Not_Found(name); } /* * Query the output_length() of a hash or MAC */ size_t output_length_of(const std::string& name) { Algorithm_Factory& af = global_state().algorithm_factory(); if(const HashFunction* hash = af.prototype_hash_function(name)) return hash->output_length(); if(const MessageAuthenticationCode* mac = af.prototype_mac(name)) return mac->output_length(); throw Algorithm_Not_Found(name); } /* * Query the minimum allowed key length of an algorithm implementation */ size_t min_keylength_of(const std::string& name) { Algorithm_Factory& af = global_state().algorithm_factory(); if(const BlockCipher* bc = af.prototype_block_cipher(name)) return bc->key_spec().minimum_keylength(); if(const StreamCipher* sc = af.prototype_stream_cipher(name)) return sc->key_spec().minimum_keylength(); if(const MessageAuthenticationCode* mac = af.prototype_mac(name)) return mac->key_spec().minimum_keylength(); throw Algorithm_Not_Found(name); } /* * Query the maximum allowed keylength of an algorithm implementation */ size_t max_keylength_of(const std::string& name) { Algorithm_Factory& af = global_state().algorithm_factory(); if(const BlockCipher* bc = af.prototype_block_cipher(name)) return bc->key_spec().maximum_keylength(); if(const StreamCipher* sc = af.prototype_stream_cipher(name)) return sc->key_spec().maximum_keylength(); if(const MessageAuthenticationCode* mac = af.prototype_mac(name)) return mac->key_spec().maximum_keylength(); throw Algorithm_Not_Found(name); } /* * Query the number of byte a valid key must be a multiple of */ size_t keylength_multiple_of(const std::string& name) { Algorithm_Factory& af = global_state().algorithm_factory(); if(const BlockCipher* bc = af.prototype_block_cipher(name)) return bc->key_spec().keylength_multiple(); if(const StreamCipher* sc = af.prototype_stream_cipher(name)) return sc->key_spec().keylength_multiple(); if(const MessageAuthenticationCode* mac = af.prototype_mac(name)) return mac->key_spec().keylength_multiple(); throw Algorithm_Not_Found(name); } /* * Get a cipher object */ Keyed_Filter* get_cipher(const std::string& algo_spec, Cipher_Dir direction) { Algorithm_Factory& af = global_state().algorithm_factory(); Algorithm_Factory::Engine_Iterator i(af); while(Engine* engine = i.next()) { if(Keyed_Filter* algo = engine->get_cipher(algo_spec, direction, af)) return algo; } throw Algorithm_Not_Found(algo_spec); } /* * Get a cipher object */ Keyed_Filter* get_cipher(const std::string& algo_spec, const SymmetricKey& key, const InitializationVector& iv, Cipher_Dir direction) { Keyed_Filter* cipher = get_cipher(algo_spec, direction); cipher->set_key(key); if(iv.length()) cipher->set_iv(iv); return cipher; } /* * Get a cipher object */ Keyed_Filter* get_cipher(const std::string& algo_spec, const SymmetricKey& key, Cipher_Dir direction) { return get_cipher(algo_spec, key, InitializationVector(), direction); } } /* * OID Registry * (C) 1999-2008 Jack Lloyd * * Distributed under the terms of the Botan license */ namespace Botan { namespace OIDS { /* * Regis