forked from qt-creator/qt-creator
Testable on Linux/macOS by changing c++14 to c++1z in qtcreator.pri. Testable with latest MSVC2017 by setting _CL_=/std:c++17. unary_function, binary_function, and a few other things that were deprecated are removed in C++17. std::string got a non-const overload for its "data" member function, so we cannot create a function pointer on it without specifying its type. Use std::declval instead (though it requires a default constructor for the type). MSVC seems to have an issue with Utils::transform for std::vector (used in Nim plugin), but that looks like a compiler issue. Change-Id: I94f9a93d591d55b610f86fabfc618158927d6221 Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
47195 lines
1.4 MiB
47195 lines
1.4 MiB
/*
|
|
* Botan 1.10.2 Amalgamation
|
|
* (C) 1999-2011 Jack Lloyd and others
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
#include "botan.h"
|
|
#include <deque>
|
|
|
|
#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<typename T>
|
|
T resolve(const std::string& symbol)
|
|
{
|
|
#if defined(__GNUC__) && __GNUC__ < 4
|
|
return (T)(resolve_symbol(symbol));
|
|
#else
|
|
return reinterpret_cast<T>(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<const byte*>(in);
|
|
return SIMD_Scalar(Botan::load_le<u32bit>(in_b, 0),
|
|
Botan::load_le<u32bit>(in_b, 1),
|
|
Botan::load_le<u32bit>(in_b, 2),
|
|
Botan::load_le<u32bit>(in_b, 3));
|
|
}
|
|
|
|
static SIMD_Scalar load_be(const void* in)
|
|
{
|
|
const byte* in_b = static_cast<const byte*>(in);
|
|
return SIMD_Scalar(Botan::load_be<u32bit>(in_b, 0),
|
|
Botan::load_be<u32bit>(in_b, 1),
|
|
Botan::load_be<u32bit>(in_b, 2),
|
|
Botan::load_be<u32bit>(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<u64bit*>(out) ^= *reinterpret_cast<const u64bit*>(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<u64bit*>(out) =
|
|
*reinterpret_cast<const u64bit*>(in) ^
|
|
*reinterpret_cast<const u64bit*>(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() Q_DECL_NOEXCEPT_EXPR(false) {}
|
|
};
|
|
|
|
/**
|
|
* 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<typename InputIterator, typename OutputIterator, typename Predicate>
|
|
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<typename K, typename V>
|
|
inline V search_map(const std::map<K, V>& mapping,
|
|
const K& key,
|
|
const V& null_result = V())
|
|
{
|
|
typename std::map<K, V>::const_iterator i = mapping.find(key);
|
|
if(i == mapping.end())
|
|
return null_result;
|
|
return i->second;
|
|
}
|
|
|
|
/**
|
|
* Function adaptor for delete operation
|
|
*/
|
|
template<class T>
|
|
class del_fun
|
|
{
|
|
public:
|
|
void operator()(T* ptr) { delete ptr; }
|
|
};
|
|
|
|
/**
|
|
* Delete the second half of a pair of objects
|
|
*/
|
|
template<typename Pair>
|
|
void delete2nd(Pair& pair)
|
|
{
|
|
delete pair.second;
|
|
}
|
|
|
|
/**
|
|
* Insert a key/value pair into a multimap
|
|
*/
|
|
template<typename K, typename V>
|
|
void multimap_insert(std::multimap<K, V>& 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<const K, V>(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<typename T>
|
|
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<std::string> 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<std::string, std::map<std::string, T*> >::iterator
|
|
algorithms_iterator;
|
|
|
|
typedef typename std::map<std::string, T*>::iterator provider_iterator;
|
|
|
|
algorithms_iterator find_algorithm(const std::string& algo_spec);
|
|
|
|
Mutex* mutex;
|
|
std::map<std::string, std::string> aliases;
|
|
std::map<std::string, std::string> pref_providers;
|
|
std::map<std::string, std::map<std::string, T*> > algorithms;
|
|
};
|
|
|
|
/*
|
|
* Look for an algorithm implementation in the cache, also checking aliases
|
|
* Assumes object lock is held
|
|
*/
|
|
template<typename T>
|
|
typename Algorithm_Cache<T>::algorithms_iterator
|
|
Algorithm_Cache<T>::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<std::string, std::string>::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<typename T>
|
|
const T* Algorithm_Cache<T>::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<typename T>
|
|
void Algorithm_Cache<T>::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<typename T> std::vector<std::string>
|
|
Algorithm_Cache<T>::providers_of(const std::string& algo_name)
|
|
{
|
|
Mutex_Holder lock(mutex);
|
|
|
|
std::vector<std::string> 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<typename T>
|
|
void Algorithm_Cache<T>::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<typename T>
|
|
void Algorithm_Cache<T>::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<typename T>
|
|
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<typename T>
|
|
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<typename T>
|
|
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<typename T>
|
|
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<typename T>
|
|
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<typename T>
|
|
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<typename T>
|
|
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<typename T>
|
|
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<Memory_Block> blocks;
|
|
std::vector<Memory_Block>::iterator last_used;
|
|
std::vector<std::pair<void*, size_t> > 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<BigInt> 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<BigInt> 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<std::string>& paths);
|
|
~DataSource_Command();
|
|
private:
|
|
void create_pipe(const std::vector<std::string>&);
|
|
void shutdown_pipe();
|
|
|
|
const size_t MAX_BLOCK_USECS, KILL_WAIT;
|
|
|
|
std::vector<std::string> 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<std::string>& 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<Device_Reader> 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<<bits) + n0) / d
|
|
*/
|
|
word bigint_divop(word n1, word n0, word d);
|
|
|
|
/**
|
|
* Compute ((n1<<bits) + n0) % d
|
|
*/
|
|
word bigint_modop(word n1, word n0, word d);
|
|
|
|
/*
|
|
* Comba Multiplication / Squaring
|
|
*/
|
|
void bigint_comba_mul4(word z[8], const word x[4], const word y[4]);
|
|
void bigint_comba_mul6(word z[12], const word x[6], const word y[6]);
|
|
void bigint_comba_mul8(word z[16], const word x[8], const word y[8]);
|
|
void bigint_comba_mul16(word z[32], const word x[16], const word y[16]);
|
|
|
|
void bigint_comba_sqr4(word out[8], const word in[4]);
|
|
void bigint_comba_sqr6(word out[12], const word in[6]);
|
|
void bigint_comba_sqr8(word out[16], const word in[8]);
|
|
void bigint_comba_sqr16(word out[32], const word in[16]);
|
|
|
|
}
|
|
|
|
/*
|
|
* High Level Multiplication/Squaring Interfaces
|
|
*/
|
|
void bigint_mul(word z[], size_t z_size, word workspace[],
|
|
const word x[], size_t x_size, size_t x_sw,
|
|
const word y[], size_t y_size, size_t y_sw);
|
|
|
|
void bigint_sqr(word z[], size_t z_size, word workspace[],
|
|
const word x[], size_t x_size, size_t x_sw);
|
|
|
|
}
|
|
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Pthread Mutex Factory
|
|
*/
|
|
class Pthread_Mutex_Factory : public Mutex_Factory
|
|
{
|
|
public:
|
|
Mutex* make();
|
|
};
|
|
|
|
}
|
|
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Core Engine
|
|
*/
|
|
class Core_Engine : public Engine
|
|
{
|
|
public:
|
|
std::string provider_name() const { return "core"; }
|
|
|
|
PK_Ops::Key_Agreement*
|
|
get_key_agreement_op(const Private_Key& key) const;
|
|
|
|
PK_Ops::Signature*
|
|
get_signature_op(const Private_Key& key) const;
|
|
|
|
PK_Ops::Verification* get_verify_op(const Public_Key& key) const;
|
|
|
|
PK_Ops::Encryption* get_encryption_op(const Public_Key& key) const;
|
|
|
|
PK_Ops::Decryption* get_decryption_op(const Private_Key& key) const;
|
|
|
|
Modular_Exponentiator* mod_exp(const BigInt& n,
|
|
Power_Mod::Usage_Hints) const;
|
|
|
|
Keyed_Filter* get_cipher(const std::string&, Cipher_Dir,
|
|
Algorithm_Factory&);
|
|
|
|
BlockCipher* find_block_cipher(const SCAN_Name&,
|
|
Algorithm_Factory&) const;
|
|
|
|
StreamCipher* find_stream_cipher(const SCAN_Name&,
|
|
Algorithm_Factory&) const;
|
|
|
|
HashFunction* find_hash(const SCAN_Name& request,
|
|
Algorithm_Factory&) const;
|
|
|
|
MessageAuthenticationCode* find_mac(const SCAN_Name& request,
|
|
Algorithm_Factory&) const;
|
|
|
|
PBKDF* find_pbkdf(const SCAN_Name& algo_spec,
|
|
Algorithm_Factory& af) const;
|
|
};
|
|
|
|
/**
|
|
* Create a cipher mode filter object
|
|
* @param block_cipher a block cipher object
|
|
* @param direction are we encrypting or decrypting?
|
|
* @param mode the name of the cipher mode to use
|
|
* @param padding the mode padding to use (only used for ECB, CBC)
|
|
*/
|
|
Keyed_Filter* get_cipher_mode(const BlockCipher* block_cipher,
|
|
Cipher_Dir direction,
|
|
const std::string& mode,
|
|
const std::string& padding);
|
|
|
|
}
|
|
|
|
|
|
#ifdef Q_OS_UNIX
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Unix Entropy Source
|
|
*/
|
|
class Unix_EntropySource : public EntropySource
|
|
{
|
|
public:
|
|
std::string name() const { return "Unix Entropy Source"; }
|
|
|
|
void poll(Entropy_Accumulator& accum);
|
|
|
|
void add_sources(const Unix_Program[], size_t);
|
|
Unix_EntropySource(const std::vector<std::string>& path);
|
|
private:
|
|
static std::vector<Unix_Program> get_default_sources();
|
|
void fast_poll(Entropy_Accumulator& accum);
|
|
|
|
const std::vector<std::string> PATH;
|
|
std::vector<Unix_Program> 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<std::string>&);
|
|
~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<EGD_Socket> sockets;
|
|
};
|
|
|
|
}
|
|
#endif
|
|
|
|
namespace Botan {
|
|
|
|
Public_Key* make_public_key(const AlgorithmIdentifier& alg_id,
|
|
const MemoryRegion<byte>& key_bits);
|
|
|
|
Private_Key* make_private_key(const AlgorithmIdentifier& alg_id,
|
|
const MemoryRegion<byte>& 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<SecureQueue*> 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<u64bit> prov_types;
|
|
};
|
|
|
|
}
|
|
#endif
|
|
|
|
|
|
namespace Botan {
|
|
|
|
template<typename T>
|
|
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<typename T>
|
|
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 <algorithm>
|
|
|
|
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<byte> 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<byte> 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 <algorithm>
|
|
|
|
namespace Botan {
|
|
|
|
namespace {
|
|
|
|
/*
|
|
* Template functions for the factory prototype/search algorithm
|
|
*/
|
|
template<typename T>
|
|
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<typename T>
|
|
const T* factory_prototype(const std::string& algo_spec,
|
|
const std::string& provider,
|
|
const std::vector<Engine*>& engines,
|
|
Algorithm_Factory& af,
|
|
Algorithm_Cache<T>* 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<T>(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<BlockCipher>(mf.make());
|
|
stream_cipher_cache = new Algorithm_Cache<StreamCipher>(mf.make());
|
|
hash_cache = new Algorithm_Cache<HashFunction>(mf.make());
|
|
mac_cache = new Algorithm_Cache<MessageAuthenticationCode>(mf.make());
|
|
pbkdf_cache = new Algorithm_Cache<PBKDF>(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<Engine>());
|
|
}
|
|
|
|
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<std::string>
|
|
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<std::string>();
|
|
}
|
|
|
|
/*
|
|
* 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<BlockCipher>(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<StreamCipher>(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<HashFunction>(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<MessageAuthenticationCode>(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<PBKDF>(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 <vector>
|
|
#include <cstring>
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/mman.h>
|
|
#include <sys/stat.h>
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <fcntl.h>
|
|
#include <errno.h>
|
|
|
|
#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<char> 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() Q_DECL_NOEXCEPT_EXPR(false)
|
|
{
|
|
/*
|
|
* 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<byte> 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<void*>(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<char*>(ptr), n, MS_SYNC))
|
|
throw MemoryMapping_Failed("Sync operation failed");
|
|
}
|
|
|
|
if(::munmap(static_cast<char*>(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 <algorithm>
|
|
#include <exception>
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* Memory_Block Constructor
|
|
*/
|
|
Pooling_Allocator::Memory_Block::Memory_Block(void* buf)
|
|
{
|
|
buffer = static_cast<byte*>(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<byte*>(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<bitmap_type>(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<byte*>(ptr), blocks * BLOCK_SIZE);
|
|
|
|
const size_t offset = (static_cast<byte*>(ptr) - buffer) / BLOCK_SIZE;
|
|
|
|
if(offset == 0 && blocks == BITMAP_SIZE)
|
|
bitmap = ~bitmap;
|
|
else
|
|
{
|
|
for(size_t j = 0; j != blocks; ++j)
|
|
bitmap &= ~(static_cast<bitmap_type>(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<Memory_Block>::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<Memory_Block>::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<size_t>(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<byte*>(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 <cstdlib>
|
|
#include <cstring>
|
|
|
|
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<byte>& param)
|
|
{
|
|
oid = alg_id;
|
|
parameters = param;
|
|
}
|
|
|
|
/*
|
|
* Create an AlgorithmIdentifier
|
|
*/
|
|
AlgorithmIdentifier::AlgorithmIdentifier(const std::string& alg_id,
|
|
const MemoryRegion<byte>& 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<const byte*, size_t>(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<const byte*, size_t>(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<std::string, std::string>::iterator iter;
|
|
std::pair<iter, iter> 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<std::string, std::string> AlternativeName::get_attributes() const
|
|
{
|
|
return alt_info;
|
|
}
|
|
|
|
/*
|
|
* Get the otherNames
|
|
*/
|
|
std::multimap<OID, ASN1_String> AlternativeName::get_othernames() const
|
|
{
|
|
return othernames;
|
|
}
|
|
|
|
/*
|
|
* Return all of the alternative names
|
|
*/
|
|
std::multimap<std::string, std::string> AlternativeName::contents() const
|
|
{
|
|
std::multimap<std::string, std::string> names;
|
|
|
|
typedef std::multimap<std::string, std::string>::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<OID, ASN1_String>::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<std::string, std::string>& attr,
|
|
const std::string& type, ASN1_Tag tagging)
|
|
{
|
|
typedef std::multimap<std::string, std::string>::const_iterator iter;
|
|
|
|
std::pair<iter, iter> 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<OID, ASN1_String>::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<u32bit>(&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<byte>& attr_value)
|
|
{
|
|
oid = attr_oid;
|
|
parameters = attr_value;
|
|
}
|
|
|
|
/*
|
|
* Create an Attribute
|
|
*/
|
|
Attribute::Attribute(const std::string& attr_oid,
|
|
const MemoryRegion<byte>& 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<byte> put_in_sequence(const MemoryRegion<byte>& 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<const char*>(&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<u32bit> oid1 = a.get_id();
|
|
std::vector<u32bit> 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<byte> 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<byte>(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<std::string> 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<std::string> 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<byte> 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<byte>& 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<byte>& 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<byte> 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<byte>& 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<byte>& 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<byte>& out,
|
|
ASN1_Tag real_type,
|
|
u16bit type_no)
|
|
{
|
|
BER_Object obj = get_next_object();
|
|
|
|
ASN1_Tag type_tag = static_cast<ASN1_Tag>(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 <algorithm>
|
|
|
|
namespace Botan {
|
|
|
|
namespace {
|
|
|
|
/*
|
|
* DER encode an ASN.1 type tag
|
|
*/
|
|
SecureVector<byte> 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<byte> encoded_tag;
|
|
if(type_tag <= 30)
|
|
encoded_tag.push_back(static_cast<byte>(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<byte> encode_length(size_t length)
|
|
{
|
|
SecureVector<byte> encoded_length;
|
|
if(length <= 127)
|
|
encoded_length.push_back(static_cast<byte>(length));
|
|
else
|
|
{
|
|
const size_t top_byte = significant_bytes(length);
|
|
|
|
encoded_length.push_back(static_cast<byte>(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<byte> 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<byte> 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<byte>(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<byte> DER_Encoder::get_contents()
|
|
{
|
|
if(subsequences.size() != 0)
|
|
throw Invalid_State("DER_Encoder: Sequence hasn't been marked done");
|
|
|
|
SecureVector<byte> 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<byte> 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<ASN1_Tag>(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<byte>& 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<byte>& 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<byte> 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<byte>& 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<byte> 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<byte> 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<byte>& 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<const byte*>(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<OID, std::string>& args)
|
|
{
|
|
std::multimap<OID, std::string>::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<std::string, std::string>& args)
|
|
{
|
|
std::multimap<std::string, std::string>::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<OID, ASN1_String>::iterator rdn_iter;
|
|
|
|
std::pair<rdn_iter, rdn_iter> 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<OID, std::string> X509_DN::get_attributes() const
|
|
{
|
|
typedef std::multimap<OID, ASN1_String>::const_iterator rdn_iter;
|
|
|
|
std::multimap<OID, std::string> 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<std::string, std::string> X509_DN::contents() const
|
|
{
|
|
typedef std::multimap<OID, ASN1_String>::const_iterator rdn_iter;
|
|
|
|
std::multimap<std::string, std::string> 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<std::string> X509_DN::get_attribute(const std::string& attr) const
|
|
{
|
|
typedef std::multimap<OID, ASN1_String>::const_iterator rdn_iter;
|
|
|
|
const OID oid = OIDS::lookup(deref_info_field(attr));
|
|
std::pair<rdn_iter, rdn_iter> range = dn_info.equal_range(oid);
|
|
|
|
std::vector<std::string> 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<byte> 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<OID, std::string>::const_iterator rdn_iter;
|
|
|
|
std::multimap<OID, std::string> attr1 = dn1.get_attributes();
|
|
std::multimap<OID, std::string> 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<OID, std::string>::const_iterator rdn_iter;
|
|
|
|
std::multimap<OID, std::string> attr1 = dn1.get_attributes();
|
|
std::multimap<OID, std::string> 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<OID, std::string>::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<OID, std::string>& dn_info,
|
|
ASN1_Tag string_type, const std::string& oid_str,
|
|
bool must_exist = false)
|
|
{
|
|
typedef std::multimap<OID, std::string>::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<rdn_iter, rdn_iter> 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<OID, std::string> 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<byte> 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 <memory>
|
|
|
|
namespace Botan {
|
|
|
|
namespace {
|
|
|
|
/**
|
|
* Benchmark Buffered_Computation (hash or MAC)
|
|
*/
|
|
std::pair<u64bit, u64bit> 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<u64bit, u64bit>
|
|
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<u64bit, u64bit>
|
|
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<u64bit, u64bit>
|
|
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<u64bit, u64bit>
|
|
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<std::string, double>
|
|
algorithm_benchmark(const std::string& name,
|
|
Algorithm_Factory& af,
|
|
RandomNumberGenerator& rng,
|
|
u32bit milliseconds,
|
|
size_t buf_size)
|
|
{
|
|
std::vector<std::string> providers = af.providers_of(name);
|
|
std::map<std::string, double> all_results;
|
|
|
|
if(providers.empty()) // no providers, nothing to do
|
|
return all_results;
|
|
|
|
const u64bit ns_per_provider =
|
|
(static_cast<u64bit>(milliseconds) * 1000 * 1000) / providers.size();
|
|
|
|
std::vector<byte> 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<u64bit, u64bit> results(0, 0);
|
|
|
|
if(const BlockCipher* proto =
|
|
af.prototype_block_cipher(name, provider))
|
|
{
|
|
std::unique_ptr<BlockCipher> 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<StreamCipher> 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<HashFunction> 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<MessageAuthenticationCode> 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<u32bit>& EK,
|
|
const MemoryRegion<byte>& 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<u32bit>(in, 0) ^ EK[0];
|
|
u32bit T1 = load_be<u32bit>(in, 1) ^ EK[1];
|
|
u32bit T2 = load_be<u32bit>(in, 2) ^ EK[2];
|
|
u32bit T3 = load_be<u32bit>(in, 3) ^ EK[3];
|
|
|
|
/* 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<u32bit>& DK,
|
|
const MemoryRegion<byte>& 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<u32bit>(in, 0) ^ DK[0];
|
|
u32bit T1 = load_be<u32bit>(in, 1) ^ DK[1];
|
|
u32bit T2 = load_be<u32bit>(in, 2) ^ DK[2];
|
|
u32bit T3 = load_be<u32bit>(in, 3) ^ DK[3];
|
|
|
|
u32bit B0 = 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<u32bit>& EK,
|
|
MemoryRegion<u32bit>& DK,
|
|
MemoryRegion<byte>& ME,
|
|
MemoryRegion<byte>& MD)
|
|
{
|
|
static const u32bit RC[10] = {
|
|
0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000,
|
|
0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000 };
|
|
|
|
const size_t rounds = (length / 4) + 6;
|
|
|
|
SecureVector<u32bit> XEK(length + 32), XDK(length + 32);
|
|
|
|
const size_t X = length / 4;
|
|
for(size_t i = 0; i != X; ++i)
|
|
XEK[i] = load_be<u32bit>(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<u32bit>(in, 0);
|
|
u32bit R = load_be<u32bit>(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<u32bit>(in, 0);
|
|
u32bit R = load_be<u32bit>(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<u32bit>& 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<u32bit>(salt, (i + salt_off) % 4);
|
|
R ^= load_be<u32bit>(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<u64bit>(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<u64bit>(x1) << 32) | x2);
|
|
}
|
|
|
|
/*
|
|
* Camellia Encryption
|
|
*/
|
|
void encrypt(const byte in[], byte out[], size_t blocks,
|
|
const SecureVector<u64bit>& SK, const size_t rounds)
|
|
{
|
|
for(size_t i = 0; i != blocks; ++i)
|
|
{
|
|
u64bit D1 = load_be<u64bit>(in, 0);
|
|
u64bit D2 = load_be<u64bit>(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<u64bit>& SK, const size_t rounds)
|
|
{
|
|
for(size_t i = 0; i != blocks; ++i)
|
|
{
|
|
u64bit D1 = load_be<u64bit>(in, 0);
|
|
u64bit D2 = load_be<u64bit>(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<u64bit>& 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<u64bit>(key, 0);
|
|
const u64bit KL_L = load_be<u64bit>(key, 1);
|
|
|
|
const u64bit KR_H = (length >= 24) ? load_be<u64bit>(key, 2) : 0;
|
|
const u64bit KR_L =
|
|
(length == 32) ? load_be<u64bit>(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<u32bit>(in, 0);
|
|
u32bit R = load_be<u32bit>(in, 1);
|
|
|
|
R1(L, R, MK[ 0], RK[ 0]);
|
|
R2(R, L, MK[ 1], RK[ 1]);
|
|
R3(L, R, MK[ 2], RK[ 2]);
|
|
R1(R, L, MK[ 3], RK[ 3]);
|
|
R2(L, R, MK[ 4], RK[ 4]);
|
|
R3(R, L, MK[ 5], RK[ 5]);
|
|
R1(L, R, MK[ 6], RK[ 6]);
|
|
R2(R, L, MK[ 7], RK[ 7]);
|
|
R3(L, R, MK[ 8], RK[ 8]);
|
|
R1(R, L, MK[ 9], RK[ 9]);
|
|
R2(L, R, MK[10], RK[10]);
|
|
R3(R, L, MK[11], RK[11]);
|
|
R1(L, R, MK[12], RK[12]);
|
|
R2(R, L, MK[13], RK[13]);
|
|
R3(L, R, MK[14], RK[14]);
|
|
R1(R, L, MK[15], RK[15]);
|
|
|
|
store_be(out, R, L);
|
|
|
|
in += BLOCK_SIZE;
|
|
out += BLOCK_SIZE;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* CAST-128 Decryption
|
|
*/
|
|
void CAST_128::decrypt_n(const byte in[], byte out[], size_t blocks) const
|
|
{
|
|
for(size_t i = 0; i != blocks; ++i)
|
|
{
|
|
u32bit L = load_be<u32bit>(in, 0);
|
|
u32bit R = load_be<u32bit>(in, 1);
|
|
|
|
R1(L, R, MK[15], RK[15]);
|
|
R3(R, L, MK[14], RK[14]);
|
|
R2(L, R, MK[13], RK[13]);
|
|
R1(R, L, MK[12], RK[12]);
|
|
R3(L, R, MK[11], RK[11]);
|
|
R2(R, L, MK[10], RK[10]);
|
|
R1(L, R, MK[ 9], RK[ 9]);
|
|
R3(R, L, MK[ 8], RK[ 8]);
|
|
R2(L, R, MK[ 7], RK[ 7]);
|
|
R1(R, L, MK[ 6], RK[ 6]);
|
|
R3(L, R, MK[ 5], RK[ 5]);
|
|
R2(R, L, MK[ 4], RK[ 4]);
|
|
R1(L, R, MK[ 3], RK[ 3]);
|
|
R3(R, L, MK[ 2], RK[ 2]);
|
|
R2(L, R, MK[ 1], RK[ 1]);
|
|
R1(R, L, MK[ 0], RK[ 0]);
|
|
|
|
store_be(out, R, L);
|
|
|
|
in += BLOCK_SIZE;
|
|
out += BLOCK_SIZE;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* CAST-128 Key Schedule
|
|
*/
|
|
void CAST_128::key_schedule(const byte key[], size_t length)
|
|
{
|
|
clear();
|
|
SecureVector<u32bit> 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<u32bit>& K,
|
|
MemoryRegion<u32bit>& 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<u32bit> 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<u32bit>(in, 0);
|
|
u32bit B = load_be<u32bit>(in, 1);
|
|
u32bit C = load_be<u32bit>(in, 2);
|
|
u32bit D = load_be<u32bit>(in, 3);
|
|
|
|
round1(C, D, MK[ 0], RK[ 0]); round2(B, C, MK[ 1], RK[ 1]);
|
|
round3(A, B, MK[ 2], RK[ 2]); round1(D, A, MK[ 3], RK[ 3]);
|
|
round1(C, D, MK[ 4], RK[ 4]); round2(B, C, MK[ 5], RK[ 5]);
|
|
round3(A, B, MK[ 6], RK[ 6]); round1(D, A, MK[ 7], RK[ 7]);
|
|
round1(C, D, MK[ 8], RK[ 8]); round2(B, C, MK[ 9], RK[ 9]);
|
|
round3(A, B, MK[10], RK[10]); round1(D, A, MK[11], RK[11]);
|
|
round1(C, D, MK[12], RK[12]); round2(B, C, MK[13], RK[13]);
|
|
round3(A, B, MK[14], RK[14]); round1(D, A, MK[15], RK[15]);
|
|
round1(C, D, MK[16], RK[16]); round2(B, C, MK[17], RK[17]);
|
|
round3(A, B, MK[18], RK[18]); round1(D, A, MK[19], RK[19]);
|
|
round1(C, D, MK[20], RK[20]); round2(B, C, MK[21], RK[21]);
|
|
round3(A, B, MK[22], RK[22]); round1(D, A, MK[23], RK[23]);
|
|
round1(D, A, MK[27], RK[27]); round3(A, B, MK[26], RK[26]);
|
|
round2(B, C, MK[25], RK[25]); round1(C, D, MK[24], RK[24]);
|
|
round1(D, A, MK[31], RK[31]); round3(A, B, MK[30], RK[30]);
|
|
round2(B, C, MK[29], RK[29]); round1(C, D, MK[28], RK[28]);
|
|
round1(D, A, MK[35], RK[35]); round3(A, B, MK[34], RK[34]);
|
|
round2(B, C, MK[33], RK[33]); round1(C, D, MK[32], RK[32]);
|
|
round1(D, A, MK[39], RK[39]); round3(A, B, MK[38], RK[38]);
|
|
round2(B, C, MK[37], RK[37]); round1(C, D, MK[36], RK[36]);
|
|
round1(D, A, MK[43], RK[43]); round3(A, B, MK[42], RK[42]);
|
|
round2(B, C, MK[41], RK[41]); round1(C, D, MK[40], RK[40]);
|
|
round1(D, A, MK[47], RK[47]); round3(A, B, MK[46], RK[46]);
|
|
round2(B, C, MK[45], RK[45]); round1(C, D, MK[44], RK[44]);
|
|
|
|
store_be(out, A, B, C, D);
|
|
|
|
in += BLOCK_SIZE;
|
|
out += BLOCK_SIZE;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* CAST-256 Decryption
|
|
*/
|
|
void CAST_256::decrypt_n(const byte in[], byte out[], size_t blocks) const
|
|
{
|
|
for(size_t i = 0; i != blocks; ++i)
|
|
{
|
|
u32bit A = load_be<u32bit>(in, 0);
|
|
u32bit B = load_be<u32bit>(in, 1);
|
|
u32bit C = load_be<u32bit>(in, 2);
|
|
u32bit D = load_be<u32bit>(in, 3);
|
|
|
|
round1(C, D, MK[44], RK[44]); round2(B, C, MK[45], RK[45]);
|
|
round3(A, B, MK[46], RK[46]); round1(D, A, MK[47], RK[47]);
|
|
round1(C, D, MK[40], RK[40]); round2(B, C, MK[41], RK[41]);
|
|
round3(A, B, MK[42], RK[42]); round1(D, A, MK[43], RK[43]);
|
|
round1(C, D, MK[36], RK[36]); round2(B, C, MK[37], RK[37]);
|
|
round3(A, B, MK[38], RK[38]); round1(D, A, MK[39], RK[39]);
|
|
round1(C, D, MK[32], RK[32]); round2(B, C, MK[33], RK[33]);
|
|
round3(A, B, MK[34], RK[34]); round1(D, A, MK[35], RK[35]);
|
|
round1(C, D, MK[28], RK[28]); round2(B, C, MK[29], RK[29]);
|
|
round3(A, B, MK[30], RK[30]); round1(D, A, MK[31], RK[31]);
|
|
round1(C, D, MK[24], RK[24]); round2(B, C, MK[25], RK[25]);
|
|
round3(A, B, MK[26], RK[26]); round1(D, A, MK[27], RK[27]);
|
|
round1(D, A, MK[23], RK[23]); round3(A, B, MK[22], RK[22]);
|
|
round2(B, C, MK[21], RK[21]); round1(C, D, MK[20], RK[20]);
|
|
round1(D, A, MK[19], RK[19]); round3(A, B, MK[18], RK[18]);
|
|
round2(B, C, MK[17], RK[17]); round1(C, D, MK[16], RK[16]);
|
|
round1(D, A, MK[15], RK[15]); round3(A, B, MK[14], RK[14]);
|
|
round2(B, C, MK[13], RK[13]); round1(C, D, MK[12], RK[12]);
|
|
round1(D, A, MK[11], RK[11]); round3(A, B, MK[10], RK[10]);
|
|
round2(B, C, MK[ 9], RK[ 9]); round1(C, D, MK[ 8], RK[ 8]);
|
|
round1(D, A, MK[ 7], RK[ 7]); round3(A, B, MK[ 6], RK[ 6]);
|
|
round2(B, C, MK[ 5], RK[ 5]); round1(C, D, MK[ 4], RK[ 4]);
|
|
round1(D, A, MK[ 3], RK[ 3]); round3(A, B, MK[ 2], RK[ 2]);
|
|
round2(B, C, MK[ 1], RK[ 1]); round1(C, D, MK[ 0], RK[ 0]);
|
|
|
|
store_be(out, A, B, C, D);
|
|
|
|
in += BLOCK_SIZE;
|
|
out += BLOCK_SIZE;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* CAST-256 Key Schedule
|
|
*/
|
|
void CAST_256::key_schedule(const byte key[], size_t length)
|
|
{
|
|
SecureVector<u32bit> 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<u32bit>(T >> 32);
|
|
u32bit R = static_cast<u32bit>(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<u32bit>(T >> 32);
|
|
u32bit R = static_cast<u32bit>(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<u32bit>(T >> 32);
|
|
u32bit R = static_cast<u32bit>(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<u32bit>(T >> 32);
|
|
u32bit R = static_cast<u32bit>(T);
|
|
|
|
des_decrypt(L, R, &round_key[64]);
|
|
des_encrypt(R, L, &round_key[32]);
|
|
des_decrypt(L, R, &round_key[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<u32bit>(in, 0);
|
|
u32bit N2 = load_le<u32bit>(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<u32bit>(in, 0);
|
|
u32bit N2 = load_le<u32bit>(in, 1);
|
|
|
|
GOST_2ROUND(N1, N2, 0, 1);
|
|
GOST_2ROUND(N1, N2, 2, 3);
|
|
GOST_2ROUND(N1, N2, 4, 5);
|
|
GOST_2ROUND(N1, N2, 6, 7);
|
|
|
|
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<u32bit>(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<u32bit>(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<u16bit>(in, 0);
|
|
u16bit X2 = load_be<u16bit>(in, 1);
|
|
u16bit X3 = load_be<u16bit>(in, 2);
|
|
u16bit X4 = load_be<u16bit>(in, 3);
|
|
|
|
for(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<u16bit>(key, i);
|
|
|
|
for(size_t i = 1, j = 8, offset = 0; j != 52; i %= 8, ++i, ++j)
|
|
{
|
|
EK[i+7+offset] = static_cast<u16bit>((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<u16bit>(in, 0);
|
|
u16bit B1 = load_be<u16bit>(in, 1);
|
|
u16bit B2 = load_be<u16bit>(in, 2);
|
|
u16bit B3 = load_be<u16bit>(in, 3);
|
|
|
|
for(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<u16bit>(in, 0);
|
|
u16bit B1 = load_be<u16bit>(in, 1);
|
|
u16bit B2 = load_be<u16bit>(in, 2);
|
|
u16bit B3 = load_be<u16bit>(in, 3);
|
|
|
|
for(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<u16bit> K(16);
|
|
for(size_t i = 0; i != 8; ++i)
|
|
{
|
|
K[i] = load_be<u16bit>(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<byte> 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<byte> 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<size_t>(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<byte> 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<byte> 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<u32bit>(in, 0) + EK[0];
|
|
u32bit B = load_le<u32bit>(in, 1) + EK[1];
|
|
u32bit C = load_le<u32bit>(in, 2) + EK[2];
|
|
u32bit D = load_le<u32bit>(in, 3) + EK[3];
|
|
|
|
forward_mix(A, B, C, D);
|
|
|
|
encrypt_round(A, B, C, D, 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<u32bit>(in, 3) + EK[39];
|
|
u32bit B = load_le<u32bit>(in, 2) + EK[38];
|
|
u32bit C = load_le<u32bit>(in, 1) + EK[37];
|
|
u32bit D = load_le<u32bit>(in, 0) + EK[36];
|
|
|
|
forward_mix(A, B, C, D);
|
|
|
|
decrypt_round(A, B, C, D, 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<u32bit> T(15);
|
|
for(size_t i = 0; i != length / 4; ++i)
|
|
T[i] = load_le<u32bit>(key, i);
|
|
|
|
T[length / 4] = static_cast<u32bit>(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<u16bit>((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<u16bit>(in, 0);
|
|
u16bit B1 = load_be<u16bit>(in, 1);
|
|
u16bit B2 = load_be<u16bit>(in, 2);
|
|
u16bit B3 = load_be<u16bit>(in, 3);
|
|
|
|
for(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<u16bit>(in, 2);
|
|
u16bit B1 = load_be<u16bit>(in, 3);
|
|
u16bit B2 = load_be<u16bit>(in, 0);
|
|
u16bit B3 = load_be<u16bit>(in, 1);
|
|
|
|
for(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<u16bit> KS(32);
|
|
for(size_t i = 0; i != length / 2; ++i)
|
|
KS[i] = load_be<u16bit>(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<u32bit>(in, 0);
|
|
u32bit A1 = load_be<u32bit>(in, 1);
|
|
u32bit A2 = load_be<u32bit>(in, 2);
|
|
u32bit A3 = load_be<u32bit>(in, 3);
|
|
|
|
for(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<u32bit>(in, 0);
|
|
u32bit A1 = load_be<u32bit>(in, 1);
|
|
u32bit A2 = load_be<u32bit>(in, 2);
|
|
u32bit A3 = load_be<u32bit>(in, 3);
|
|
|
|
for(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<u32bit>(key, 0);
|
|
u32bit A1 = load_be<u32bit>(key, 1);
|
|
u32bit A2 = load_be<u32bit>(key, 2);
|
|
u32bit A3 = load_be<u32bit>(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<u32bit>& 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<u32bit>& 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<u16bit>(in, 0);
|
|
u16bit R1 = load_le<u16bit>(in, 1);
|
|
u16bit R2 = load_le<u16bit>(in, 2);
|
|
u16bit R3 = load_le<u16bit>(in, 3);
|
|
|
|
for(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<u16bit>(in, 0);
|
|
u16bit R1 = load_le<u16bit>(in, 1);
|
|
u16bit R2 = load_le<u16bit>(in, 2);
|
|
u16bit R3 = load_le<u16bit>(in, 3);
|
|
|
|
for(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<byte> 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<u16bit>(&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 <algorithm>
|
|
|
|
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<u32bit>(in, 0);
|
|
u32bit B = load_le<u32bit>(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<u32bit>(in, 0);
|
|
u32bit B = load_le<u32bit>(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<u32bit> 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 <algorithm>
|
|
|
|
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<u32bit>(in, 0);
|
|
u32bit B = load_le<u32bit>(in, 1);
|
|
u32bit C = load_le<u32bit>(in, 2);
|
|
u32bit D = load_le<u32bit>(in, 3);
|
|
|
|
B += S[0]; D += S[1];
|
|
|
|
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<u32bit>(in, 0);
|
|
u32bit B = load_le<u32bit>(in, 1);
|
|
u32bit C = load_le<u32bit>(in, 2);
|
|
u32bit D = load_le<u32bit>(in, 3);
|
|
|
|
C -= S[43]; A -= S[42];
|
|
|
|
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<u32bit> 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<byte> 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<u32bit>(in, 0);
|
|
u32bit B1 = load_be<u32bit>(in, 1);
|
|
u32bit B2 = load_be<u32bit>(in, 2);
|
|
u32bit B3 = load_be<u32bit>(in, 3);
|
|
|
|
G_FUNC G;
|
|
|
|
for(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<u32bit>(in, 0);
|
|
u32bit B1 = load_be<u32bit>(in, 1);
|
|
u32bit B2 = load_be<u32bit>(in, 2);
|
|
u32bit B3 = load_be<u32bit>(in, 3);
|
|
|
|
G_FUNC G;
|
|
|
|
for(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<u32bit> WK(4);
|
|
|
|
for(size_t i = 0; i != 4; ++i)
|
|
WK[i] = load_be<u32bit>(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<u32bit>(in, 0);
|
|
u32bit B1 = load_le<u32bit>(in, 1);
|
|
u32bit B2 = load_le<u32bit>(in, 2);
|
|
u32bit B3 = load_le<u32bit>(in, 3);
|
|
|
|
key_xor( 0,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3);
|
|
key_xor( 1,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3);
|
|
key_xor( 2,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3);
|
|
key_xor( 3,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3);
|
|
key_xor( 4,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3);
|
|
key_xor( 5,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3);
|
|
key_xor( 6,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3);
|
|
key_xor( 7,B0,B1,B2,B3); SBoxE8(B0,B1,B2,B3); transform(B0,B1,B2,B3);
|
|
key_xor( 8,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3);
|
|
key_xor( 9,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3);
|
|
key_xor(10,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3);
|
|
key_xor(11,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3);
|
|
key_xor(12,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3);
|
|
key_xor(13,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3);
|
|
key_xor(14,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3);
|
|
key_xor(15,B0,B1,B2,B3); SBoxE8(B0,B1,B2,B3); transform(B0,B1,B2,B3);
|
|
key_xor(16,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3);
|
|
key_xor(17,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3);
|
|
key_xor(18,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3);
|
|
key_xor(19,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3);
|
|
key_xor(20,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3);
|
|
key_xor(21,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3);
|
|
key_xor(22,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3);
|
|
key_xor(23,B0,B1,B2,B3); SBoxE8(B0,B1,B2,B3); transform(B0,B1,B2,B3);
|
|
key_xor(24,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3);
|
|
key_xor(25,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3);
|
|
key_xor(26,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3);
|
|
key_xor(27,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3);
|
|
key_xor(28,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3);
|
|
key_xor(29,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3);
|
|
key_xor(30,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3);
|
|
key_xor(31,B0,B1,B2,B3); SBoxE8(B0,B1,B2,B3); key_xor(32,B0,B1,B2,B3);
|
|
|
|
store_le(out, B0, B1, B2, B3);
|
|
|
|
in += BLOCK_SIZE;
|
|
out += BLOCK_SIZE;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Serpent Decryption
|
|
*/
|
|
void Serpent::decrypt_n(const byte in[], byte out[], size_t blocks) const
|
|
{
|
|
for(size_t i = 0; i != blocks; ++i)
|
|
{
|
|
u32bit B0 = load_le<u32bit>(in, 0);
|
|
u32bit B1 = load_le<u32bit>(in, 1);
|
|
u32bit B2 = load_le<u32bit>(in, 2);
|
|
u32bit B3 = load_le<u32bit>(in, 3);
|
|
|
|
key_xor(32,B0,B1,B2,B3); SBoxD8(B0,B1,B2,B3); key_xor(31,B0,B1,B2,B3);
|
|
i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor(30,B0,B1,B2,B3);
|
|
i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor(29,B0,B1,B2,B3);
|
|
i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor(28,B0,B1,B2,B3);
|
|
i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor(27,B0,B1,B2,B3);
|
|
i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor(26,B0,B1,B2,B3);
|
|
i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor(25,B0,B1,B2,B3);
|
|
i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor(24,B0,B1,B2,B3);
|
|
i_transform(B0,B1,B2,B3); SBoxD8(B0,B1,B2,B3); key_xor(23,B0,B1,B2,B3);
|
|
i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor(22,B0,B1,B2,B3);
|
|
i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor(21,B0,B1,B2,B3);
|
|
i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor(20,B0,B1,B2,B3);
|
|
i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor(19,B0,B1,B2,B3);
|
|
i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor(18,B0,B1,B2,B3);
|
|
i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor(17,B0,B1,B2,B3);
|
|
i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor(16,B0,B1,B2,B3);
|
|
i_transform(B0,B1,B2,B3); SBoxD8(B0,B1,B2,B3); key_xor(15,B0,B1,B2,B3);
|
|
i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor(14,B0,B1,B2,B3);
|
|
i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor(13,B0,B1,B2,B3);
|
|
i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor(12,B0,B1,B2,B3);
|
|
i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor(11,B0,B1,B2,B3);
|
|
i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor(10,B0,B1,B2,B3);
|
|
i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor( 9,B0,B1,B2,B3);
|
|
i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor( 8,B0,B1,B2,B3);
|
|
i_transform(B0,B1,B2,B3); SBoxD8(B0,B1,B2,B3); key_xor( 7,B0,B1,B2,B3);
|
|
i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor( 6,B0,B1,B2,B3);
|
|
i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor( 5,B0,B1,B2,B3);
|
|
i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor( 4,B0,B1,B2,B3);
|
|
i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor( 3,B0,B1,B2,B3);
|
|
i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor( 2,B0,B1,B2,B3);
|
|
i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor( 1,B0,B1,B2,B3);
|
|
i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor( 0,B0,B1,B2,B3);
|
|
|
|
store_le(out, B0, B1, B2, B3);
|
|
|
|
in += BLOCK_SIZE;
|
|
out += BLOCK_SIZE;
|
|
}
|
|
}
|
|
|
|
#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<u32bit> W(140);
|
|
for(size_t i = 0; i != length / 4; ++i)
|
|
W[i] = load_le<u32bit>(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<u16bit>(in, 3);
|
|
u16bit W2 = load_le<u16bit>(in, 2);
|
|
u16bit W3 = load_le<u16bit>(in, 1);
|
|
u16bit W4 = load_le<u16bit>(in, 0);
|
|
|
|
step_A(W1, W4, 1, 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<u16bit>(in, 3);
|
|
u16bit W2 = load_le<u16bit>(in, 2);
|
|
u16bit W3 = load_le<u16bit>(in, 1);
|
|
u16bit W4 = load_le<u16bit>(in, 0);
|
|
|
|
step_Bi(W2, W3, 32, 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<u32bit> XEK(36), XDK(36);
|
|
|
|
for(size_t i = 0; i != 4; ++i)
|
|
XEK[i] = load_be<u32bit>(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<u32bit>(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<u32bit>(in, 0);
|
|
u32bit R = load_be<u32bit>(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<u32bit>(in, 0);
|
|
u32bit R = load_be<u32bit>(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<u32bit>(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<u32bit>(in, 0) ^ RK[0];
|
|
u32bit B = load_le<u32bit>(in, 1) ^ RK[1];
|
|
u32bit C = load_le<u32bit>(in, 2) ^ RK[2];
|
|
u32bit D = load_le<u32bit>(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<u32bit>(in, 0) ^ RK[4];
|
|
u32bit B = load_le<u32bit>(in, 1) ^ RK[5];
|
|
u32bit C = load_le<u32bit>(in, 2) ^ RK[6];
|
|
u32bit D = load_le<u32bit>(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<byte> 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<u32bit>(in, 0);
|
|
u32bit R = load_be<u32bit>(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<u32bit>(in, 0);
|
|
u32bit R = load_be<u32bit>(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<u32bit> UK(4);
|
|
for(size_t i = 0; i != 4; ++i)
|
|
UK[i] = load_be<u32bit>(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<X509_Certificate>
|
|
Certificate_Store_Memory::find_cert_by_subject_and_key_id(
|
|
const X509_DN& subject_dn,
|
|
const MemoryRegion<byte>& key_id) const
|
|
{
|
|
std::vector<X509_Certificate> 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<byte> 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<X509_CRL>
|
|
Certificate_Store_Memory::find_crl_by_subject_and_key_id(
|
|
const X509_DN& issuer_dn,
|
|
const MemoryRegion<byte>& key_id) const
|
|
{
|
|
std::vector<X509_CRL> 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<byte> 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<byte> 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<OID> PKCS10_Request::ex_constraints() const
|
|
{
|
|
std::vector<std::string> oids = info.get("X509v3.ExtendedKeyUsage");
|
|
|
|
std::vector<OID> 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 <algorithm>
|
|
#include <typeinfo>
|
|
#include <iterator>
|
|
#include <memory>
|
|
#include <set>
|
|
|
|
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<Public_Key> 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<byte>& 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<CRL_Entry> 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<CRL_Entry>& new_revoked,
|
|
RandomNumberGenerator& rng,
|
|
u32bit next_update) const
|
|
{
|
|
std::vector<CRL_Entry> 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<CRL_Entry>& 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 <algorithm>
|
|
#include <memory>
|
|
|
|
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));
|
|
|
|
should_throw = other.should_throw;
|
|
|
|
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<byte> 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<byte> 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<byte>& 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<byte> 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<byte> 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<byte>& 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<byte> 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<byte>& 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<byte>& pub_key)
|
|
{
|
|
SHA_160 hash;
|
|
key_id = hash.process(pub_key);
|
|
}
|
|
|
|
/*
|
|
* Encode the extension
|
|
*/
|
|
MemoryVector<byte> 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<byte>& 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<byte> Alternative_Name::encode_inner() const
|
|
{
|
|
return DER_Encoder().encode(alt_name).get_contents();
|
|
}
|
|
|
|
/*
|
|
* Decode the extension
|
|
*/
|
|
void Alternative_Name::decode_inner(const MemoryRegion<byte>& 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<std::string, std::string> 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<byte> 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<byte>& 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<byte> Certificate_Policies::encode_inner() const
|
|
{
|
|
std::vector<Policy_Information> 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<byte>& in)
|
|
{
|
|
std::vector<Policy_Information> 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<byte> CRL_Number::encode_inner() const
|
|
{
|
|
return DER_Encoder().encode(crl_number).get_contents();
|
|
}
|
|
|
|
/*
|
|
* Decode the extension
|
|
*/
|
|
void CRL_Number::decode_inner(const MemoryRegion<byte>& 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<byte> CRL_ReasonCode::encode_inner() const
|
|
{
|
|
return DER_Encoder()
|
|
.encode(static_cast<size_t>(reason), ENUMERATED, UNIVERSAL)
|
|
.get_contents();
|
|
}
|
|
|
|
/*
|
|
* Decode the extension
|
|
*/
|
|
void CRL_ReasonCode::decode_inner(const MemoryRegion<byte>& in)
|
|
{
|
|
size_t reason_code = 0;
|
|
BER_Decoder(in).decode(reason_code, ENUMERATED, UNIVERSAL);
|
|
reason = static_cast<CRL_Code>(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 <algorithm>
|
|
#include <memory>
|
|
|
|
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<byte> 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<byte> X509_Object::tbs_data() const
|
|
{
|
|
return ASN1::put_in_sequence(tbs_bits);
|
|
}
|
|
|
|
/*
|
|
* Return the signature of this object
|
|
*/
|
|
MemoryVector<byte> 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<std::string> 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<std::string> 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<Public_Key> 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<std::string> 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<byte> X509_Object::make_signed(PK_Signer* signer,
|
|
RandomNumberGenerator& rng,
|
|
const AlgorithmIdentifier& algo,
|
|
const MemoryRegion<byte>& 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 <algorithm>
|
|
#include <iterator>
|
|
#include <sstream>
|
|
|
|
namespace Botan {
|
|
|
|
namespace {
|
|
|
|
/*
|
|
* Lookup each OID in the vector
|
|
*/
|
|
std::vector<std::string> lookup_oids(const std::vector<std::string>& in)
|
|
{
|
|
std::vector<std::string> out;
|
|
|
|
std::vector<std::string>::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<byte> 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<std::string>
|
|
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<std::string>
|
|
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<std::string> X509_Certificate::ex_constraints() const
|
|
{
|
|
return lookup_oids(subject.get("X509v3.ExtendedKeyUsage"));
|
|
}
|
|
|
|
/*
|
|
* Return the list of certificate policies
|
|
*/
|
|
std::vector<std::string> X509_Certificate::policies() const
|
|
{
|
|
return lookup_oids(subject.get("X509v3.CertificatePolicies"));
|
|
}
|
|
|
|
/*
|
|
* Return the authority key id
|
|
*/
|
|
MemoryVector<byte> X509_Certificate::authority_key_id() const
|
|
{
|
|
return issuer.get1_memvec("X509v3.AuthorityKeyIdentifier");
|
|
}
|
|
|
|
/*
|
|
* Return the subject key id
|
|
*/
|
|
MemoryVector<byte> X509_Certificate::subject_key_id() const
|
|
{
|
|
return subject.get1_memvec("X509v3.SubjectKeyIdentifier");
|
|
}
|
|
|
|
/*
|
|
* Return the certificate serial number
|
|
*/
|
|
MemoryVector<byte> 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<std::string> 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<std::string> 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<std::string> policies = this->policies();
|
|
if(policies.size())
|
|
{
|
|
out << "Policies: " << "\n";
|
|
for(size_t i = 0; i != policies.size(); i++)
|
|
out << " " << policies[i] << "\n";
|
|
}
|
|
|
|
std::vector<std::string> 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<std::string, std::string> names =
|
|
info.search_with(DN_Matcher());
|
|
|
|
X509_DN dn;
|
|
|
|
std::multimap<std::string, std::string>::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<std::string> matches;
|
|
};
|
|
|
|
std::multimap<std::string, std::string> names =
|
|
info.search_with(AltName_Matcher("RFC822/DNS/URI/IP"));
|
|
|
|
AlternativeName alt_name;
|
|
|
|
std::multimap<std::string, std::string>::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<CRL_Entry> 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<byte> 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<std::string> 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 <memory>
|
|
|
|
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<byte> pub_key = X509::BER_encode(key);
|
|
std::unique_ptr<PK_Signer> 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<byte> pub_key = X509::BER_encode(key);
|
|
std::unique_ptr<PK_Signer> 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 <algorithm>
|
|
#include <memory>
|
|
|
|
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<byte>& id1,
|
|
const MemoryVector<byte>& 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<std::string> 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<byte>& serial1 = serial;
|
|
const MemoryVector<byte>& key_id1 = auth_key_id;
|
|
const MemoryVector<byte>& serial2 = other.serial;
|
|
const MemoryVector<byte>& 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;
|
|
validation_cache_timeout = other.validation_cache_timeout;
|
|
}
|
|
|
|
/*
|
|
* 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<size_t> 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<byte>& 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<byte> 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<X509_Certificate> 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<size_t>& 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<Public_Key> pub_key(key);
|
|
|
|
try {
|
|
std::vector<std::string> 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_Certificate>
|
|
X509_Store::get_cert_chain(const X509_Certificate& cert)
|
|
{
|
|
std::vector<X509_Certificate> result;
|
|
std::vector<size_t> 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<CRL_Entry> 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<CRL_Data>::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 <stdexcept>
|
|
|
|
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<size_t>(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<byte>& 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<byte>(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<byte>(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<byte> base64_decode(const char input[],
|
|
size_t input_length,
|
|
bool ignore_ws)
|
|
{
|
|
SecureVector<byte> bin((round_up<size_t>(input_length, 4) * 3) / 4);
|
|
|
|
size_t written = base64_decode(&bin[0],
|
|
input,
|
|
input_length,
|
|
ignore_ws);
|
|
|
|
bin.resize(written);
|
|
return bin;
|
|
}
|
|
|
|
SecureVector<byte> 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 <stdexcept>
|
|
|
|
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<byte>& 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<byte>(input[i])];
|
|
|
|
if(bin >= 0x10)
|
|
{
|
|
if(bin == 0x80 && ignore_ws)
|
|
continue;
|
|
|
|
std::string bad_char(1, input[i]);
|
|
if(bad_char == "\t")
|
|
bad_char = "\\t";
|
|
else if(bad_char == "\n")
|
|
bad_char = "\\n";
|
|
|
|
throw std::invalid_argument(
|
|
std::string("hex_decode: invalid hex character '") +
|
|
bad_char + "'");
|
|
}
|
|
|
|
*out_ptr |= bin << (top_nibble*4);
|
|
|
|
top_nibble = !top_nibble;
|
|
if(top_nibble)
|
|
++out_ptr;
|
|
}
|
|
|
|
input_consumed = input_length;
|
|
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<byte> hex_decode(const char input[],
|
|
size_t input_length,
|
|
bool ignore_ws)
|
|
{
|
|
SecureVector<byte> bin(1 + input_length / 2);
|
|
|
|
size_t written = hex_decode(&bin[0],
|
|
input,
|
|
input_length,
|
|
ignore_ws);
|
|
|
|
bin.resize(written);
|
|
return bin;
|
|
}
|
|
|
|
SecureVector<byte> 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<std::string, std::string>& 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<std::string, std::string>::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<std::string, std::string> empty;
|
|
return PGP_encode(input, length, type, empty);
|
|
}
|
|
|
|
/*
|
|
* OpenPGP Base64 decoding
|
|
*/
|
|
SecureVector<byte> PGP_decode(DataSource& source,
|
|
std::string& label,
|
|
std::map<std::string, std::string>& 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<char>(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<char>(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<char>(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<byte> PGP_decode(DataSource& source, std::string& label)
|
|
{
|
|
std::map<std::string, std::string> 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<byte>& data, const std::string& label,
|
|
size_t width)
|
|
{
|
|
return encode(&data[0], data.size(), label, width);
|
|
}
|
|
|
|
/*
|
|
* Decode PEM down to raw BER/DER
|
|
*/
|
|
SecureVector<byte> decode_check_label(DataSource& source,
|
|
const std::string& label_want)
|
|
{
|
|
std::string label_got;
|
|
SecureVector<byte> 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<byte> 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<char>(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<byte> 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<byte> 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<size_t>(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<byte> package_key(BLOCK_SIZE);
|
|
SecureVector<byte> 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<size_t>(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<byte> 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<byte> 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<byte> 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<const byte*>(&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 <stdexcept>
|
|
|
|
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<byte>& tweak);
|
|
|
|
~FPE_Encryptor() { delete mac; }
|
|
|
|
BigInt operator()(size_t i, const BigInt& R);
|
|
|
|
private:
|
|
MessageAuthenticationCode* mac;
|
|
SecureVector<byte> mac_n_t;
|
|
};
|
|
|
|
FPE_Encryptor::FPE_Encryptor(const SymmetricKey& key,
|
|
const BigInt& n,
|
|
const MemoryRegion<byte>& tweak)
|
|
{
|
|
mac = new HMAC(new SHA_256);
|
|
mac->set_key(key);
|
|
|
|
SecureVector<byte> 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<u32bit>(n_bin.size()));
|
|
mac->update(&n_bin[0], n_bin.size());
|
|
|
|
mac->update_be(static_cast<u32bit>(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<byte> r_bin = BigInt::encode(R);
|
|
|
|
mac->update(mac_n_t);
|
|
mac->update_be(static_cast<u32bit>(round_no));
|
|
|
|
mac->update_be(static_cast<u32bit>(r_bin.size()));
|
|
mac->update(&r_bin[0], r_bin.size());
|
|
|
|
SecureVector<byte> 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<byte>& 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<byte>& 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 <memory>
|
|
|
|
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<byte> rfc3394_keywrap(const MemoryRegion<byte>& 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<BlockCipher> aes(make_aes(kek.length(), af));
|
|
aes->set_key(kek);
|
|
|
|
const size_t n = key.size() / 8;
|
|
|
|
SecureVector<byte> R((n + 1) * 8);
|
|
SecureVector<byte> 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<byte> rfc3394_keyunwrap(const MemoryRegion<byte>& 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<BlockCipher> aes(make_aes(kek.length(), af));
|
|
aes->set_key(kek);
|
|
|
|
const size_t n = (key.size() - 8) / 8;
|
|
|
|
SecureVector<byte> R(n * 8);
|
|
SecureVector<byte> 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<u64bit>(&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 <memory>
|
|
|
|
namespace Botan {
|
|
|
|
namespace {
|
|
|
|
BigInt hash_seq(const std::string& hash_id,
|
|
size_t pad_to,
|
|
const BigInt& in1,
|
|
const BigInt& in2)
|
|
{
|
|
std::unique_ptr<HashFunction> 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<byte>& salt)
|
|
{
|
|
std::unique_ptr<HashFunction> hash_fn(
|
|
global_state().algorithm_factory().make_hash_function(hash_id));
|
|
|
|
hash_fn->update(identifier);
|
|
hash_fn->update(":");
|
|
hash_fn->update(password);
|
|
|
|
SecureVector<byte> inner_h = hash_fn->final();
|
|
|
|
hash_fn->update(salt);
|
|
hash_fn->update(inner_h);
|
|
|
|
SecureVector<byte> 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<BigInt, SymmetricKey>
|
|
srp6_client_agree(const std::string& identifier,
|
|
const std::string& password,
|
|
const std::string& group_id,
|
|
const std::string& hash_id,
|
|
const MemoryRegion<byte>& 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<byte>& 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 <memory>
|
|
|
|
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>
|
|
RTSS_Share::split(byte M, byte N,
|
|
const byte S[], u16bit S_len,
|
|
const byte identifier[16],
|
|
RandomNumberGenerator& rng)
|
|
{
|
|
if(M == 0 || N == 0 || M > N)
|
|
throw Encoding_Error("RTSS_Share::split: M == 0 or N == 0 or M > N");
|
|
|
|
SHA_256 hash; // always use SHA-256 when generating shares
|
|
|
|
std::vector<RTSS_Share> shares(N);
|
|
|
|
// Create RTSS header in each share
|
|
for(byte i = 0; i != N; ++i)
|
|
{
|
|
shares[i].contents += 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<byte> secret(S, S_len);
|
|
secret += hash.process(S, S_len);
|
|
|
|
for(size_t i = 0; i != secret.size(); ++i)
|
|
{
|
|
std::vector<byte> coefficients(M-1);
|
|
rng.randomize(&coefficients[0], coefficients.size());
|
|
|
|
for(byte j = 0; j != N; ++j)
|
|
{
|
|
const byte X = j + 1;
|
|
|
|
byte sum = secret[i];
|
|
byte X_i = X;
|
|
|
|
for(size_t k = 0; k != coefficients.size(); ++k)
|
|
{
|
|
sum ^= gfp_mul(X_i, coefficients[k]);
|
|
X_i = gfp_mul(X_i, X);
|
|
}
|
|
|
|
shares[j].contents.push_back(sum);
|
|
}
|
|
}
|
|
|
|
return shares;
|
|
}
|
|
|
|
SecureVector<byte>
|
|
RTSS_Share::reconstruct(const std::vector<RTSS_Share>& 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<HashFunction> hash(get_rtss_hash_by_id(hash_id));
|
|
|
|
if(shares[0].size() != secret_len + hash->output_length() + RTSS_HEADER_SIZE + 1)
|
|
throw Decoding_Error("Bad RTSS length field in header");
|
|
|
|
std::vector<byte> V(shares.size());
|
|
SecureVector<byte> secret;
|
|
|
|
for(size_t i = RTSS_HEADER_SIZE + 1; i != shares[0].size(); ++i)
|
|
{
|
|
for(size_t j = 0; j != V.size(); ++j)
|
|
V[j] = shares[j].contents[i];
|
|
|
|
byte r = 0;
|
|
for(size_t k = 0; k != shares.size(); ++k)
|
|
{
|
|
// L_i function:
|
|
byte r2 = 1;
|
|
for(size_t l = 0; l != shares.size(); ++l)
|
|
{
|
|
if(k == l)
|
|
continue;
|
|
|
|
byte share_k = shares[k].share_id();
|
|
byte share_l = shares[l].share_id();
|
|
|
|
if(share_k == share_l)
|
|
throw Decoding_Error("Duplicate shares found in RTSS recovery");
|
|
|
|
byte div = 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<byte> 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<byte>(&secret[0], secret_len);
|
|
}
|
|
|
|
}
|
|
/*
|
|
* Core Engine
|
|
* (C) 1999-2007,2011 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
#include <memory>
|
|
|
|
#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<std::string> algo_info = parse_algorithm_name(mode);
|
|
std::string mode_name = algo_info[0];
|
|
if(algo_info.size() == 1)
|
|
bits = 8 * block_cipher->block_size();
|
|
else if(algo_info.size() == 2)
|
|
bits = to_u32bit(algo_info[1]);
|
|
else
|
|
return 0;
|
|
|
|
#if defined(BOTAN_HAS_CFB)
|
|
if(mode_name == "CFB")
|
|
{
|
|
if(direction == ENCRYPTION)
|
|
return new CFB_Encryption(block_cipher->clone(), bits);
|
|
else
|
|
return new CFB_Decryption(block_cipher->clone(), bits);
|
|
}
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_EAX)
|
|
if(mode_name == "EAX")
|
|
{
|
|
if(direction == ENCRYPTION)
|
|
return new EAX_Encryption(block_cipher->clone(), bits);
|
|
else
|
|
return new EAX_Decryption(block_cipher->clone(), bits);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Get a cipher object
|
|
*/
|
|
Keyed_Filter* Core_Engine::get_cipher(const std::string& algo_spec,
|
|
Cipher_Dir direction,
|
|
Algorithm_Factory& af)
|
|
{
|
|
std::vector<std::string> algo_parts = split_on(algo_spec, '/');
|
|
if(algo_parts.empty())
|
|
throw Invalid_Algorithm_Name(algo_spec);
|
|
|
|
const std::string cipher_name = algo_parts[0];
|
|
|
|
// check if it is a stream cipher first (easy case)
|
|
const StreamCipher* stream_cipher = af.prototype_stream_cipher(cipher_name);
|
|
if(stream_cipher)
|
|
return new StreamCipher_Filter(stream_cipher->clone());
|
|
|
|
const BlockCipher* block_cipher = af.prototype_block_cipher(cipher_name);
|
|
if(!block_cipher)
|
|
return 0;
|
|
|
|
if(algo_parts.size() >= 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<const RSA_PublicKey*>(&key))
|
|
return new RSA_Public_Operation(*s);
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_ELGAMAL)
|
|
if(const ElGamal_PublicKey* s = dynamic_cast<const ElGamal_PublicKey*>(&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<const RSA_PrivateKey*>(&key))
|
|
return new RSA_Private_Operation(*s);
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_ELGAMAL)
|
|
if(const ElGamal_PrivateKey* s = dynamic_cast<const ElGamal_PrivateKey*>(&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<const DH_PrivateKey*>(&key))
|
|
return new DH_KA_Operation(*dh);
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_ECDH)
|
|
if(const ECDH_PrivateKey* ecdh = dynamic_cast<const ECDH_PrivateKey*>(&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<const RSA_PrivateKey*>(&key))
|
|
return new RSA_Private_Operation(*s);
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_RW)
|
|
if(const RW_PrivateKey* s = dynamic_cast<const RW_PrivateKey*>(&key))
|
|
return new RW_Signature_Operation(*s);
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_DSA)
|
|
if(const DSA_PrivateKey* s = dynamic_cast<const DSA_PrivateKey*>(&key))
|
|
return new DSA_Signature_Operation(*s);
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_ECDSA)
|
|
if(const ECDSA_PrivateKey* s = dynamic_cast<const ECDSA_PrivateKey*>(&key))
|
|
return new ECDSA_Signature_Operation(*s);
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_GOST_34_10_2001)
|
|
if(const GOST_3410_PrivateKey* s =
|
|
dynamic_cast<const GOST_3410_PrivateKey*>(&key))
|
|
return new GOST_3410_Signature_Operation(*s);
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
|
|
if(const NR_PrivateKey* s = dynamic_cast<const NR_PrivateKey*>(&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<const RSA_PublicKey*>(&key))
|
|
return new RSA_Public_Operation(*s);
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_RW)
|
|
if(const RW_PublicKey* s = dynamic_cast<const RW_PublicKey*>(&key))
|
|
return new RW_Verification_Operation(*s);
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_DSA)
|
|
if(const DSA_PublicKey* s = dynamic_cast<const DSA_PublicKey*>(&key))
|
|
return new DSA_Verification_Operation(*s);
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_ECDSA)
|
|
if(const ECDSA_PublicKey* s = dynamic_cast<const ECDSA_PublicKey*>(&key))
|
|
return new ECDSA_Verification_Operation(*s);
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_GOST_34_10_2001)
|
|
if(const GOST_3410_PublicKey* s =
|
|
dynamic_cast<const GOST_3410_PublicKey*>(&key))
|
|
return new GOST_3410_Verification_Operation(*s);
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
|
|
if(const NR_PublicKey* s = dynamic_cast<const NR_PublicKey*>(&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 <memory>
|
|
|
|
#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<const HashFunction*> 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<HashFunction*> 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_func>("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<creator_func>("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 <windows.h>
|
|
#include <wincrypt.h>
|
|
|
|
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<DWORD>(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<byte>& 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<std::string> 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 <sys/types.h>
|
|
#include <sys/select.h>
|
|
#include <sys/stat.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <string.h>
|
|
|
|
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<size_t>(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<std::string>& 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<size_t>(
|
|
accum.desired_remaining_bits() / ENTROPY_BITS_PER_BYTE, 32);
|
|
|
|
const size_t read_wait_ms = std::max<size_t>(go_get, 100);
|
|
MemoryRegion<byte>& 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 <cstring>
|
|
#include <stdexcept>
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
|
|
#include <sys/socket.h>
|
|
#include <sys/un.h>
|
|
|
|
#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(path.length() >= sizeof(addr.sun_path))
|
|
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<struct ::sockaddr*>(&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<byte>(std::min<size_t>(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<size_t>(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<std::string>& 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<size_t>(accum.desired_remaining_bits() / 8, 32);
|
|
|
|
MemoryRegion<byte>& 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 <windows.h>
|
|
#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<u64bit>(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<u64bit>(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 <cstring>
|
|
#include <deque>
|
|
|
|
#ifndef _POSIX_C_SOURCE
|
|
#define _POSIX_C_SOURCE 199309
|
|
#endif
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <unistd.h>
|
|
#include <dirent.h>
|
|
#include <fcntl.h>
|
|
|
|
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<DIR*, std::string>(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<struct dirent*, std::string> get_next_dirent();
|
|
|
|
std::pair<DIR*, std::string> m_cur_dir;
|
|
std::deque<std::string> m_dirlist;
|
|
};
|
|
|
|
std::pair<struct dirent*, std::string> 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<DIR*, std::string>(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<struct dirent*, std::string>(0, ""); // nothing left
|
|
}
|
|
|
|
int Directory_Walker::next_fd()
|
|
{
|
|
while(true)
|
|
{
|
|
std::pair<struct dirent*, std::string> 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<byte>& 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 <algorithm>
|
|
|
|
#include <sys/time.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/resource.h>
|
|
#include <unistd.h>
|
|
|
|
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<std::string>& path) :
|
|
PATH(path)
|
|
{
|
|
std::vector<Unix_Program> 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);
|
|
if(::stat(stat_targets[i], &statbuf) == 0)
|
|
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<byte>& 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 <sys/time.h>
|
|
#include <sys/types.h>
|
|
#include <sys/wait.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <signal.h>
|
|
|
|
namespace Botan {
|
|
|
|
namespace {
|
|
|
|
/**
|
|
* Attempt to execute the command
|
|
*/
|
|
void do_exec(const std::vector<std::string>& arg_list,
|
|
const std::vector<std::string>& 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<size_t>(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<std::string>& 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<std::string>& 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_Program> Unix_EntropySource::get_default_sources()
|
|
{
|
|
std::vector<Unix_Program> 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 <windows.h>
|
|
#include <tlhelp32.h>
|
|
|
|
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 <algorithm>
|
|
|
|
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<size_t>(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<byte> output = hash->final();
|
|
if(OUTPUT_LENGTH)
|
|
send(output, std::min<size_t>(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<byte> output = mac->final();
|
|
if(OUTPUT_LENGTH)
|
|
send(output, std::min<size_t>(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 <stdexcept>
|
|
|
|
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<size_t>(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 <algorithm>
|
|
|
|
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<char*>(&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<size_t>(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<const char*>(&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<const char*>(&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 <algorithm>
|
|
|
|
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<char*>(&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<size_t>(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<const char*>(&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<const char*>(&in[0]),
|
|
position,
|
|
consumed,
|
|
checking != FULL_CHECK);
|
|
|
|
send(out, written);
|
|
|
|
const bool not_full_bytes = consumed != position;
|
|
|
|
position = 0;
|
|
|
|
if(not_full_bytes)
|
|
throw std::invalid_argument("Hex_Decoder: Input not full bytes");
|
|
}
|
|
|
|
}
|
|
/*
|
|
* DataSink
|
|
* (C) 1999-2007 Jack Lloyd
|
|
* 2005 Matthew Gregan
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
#include <fstream>
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* Write to a stream
|
|
*/
|
|
void DataSink_Stream::write(const byte out[], size_t length)
|
|
{
|
|
sink.write(reinterpret_cast<const char*>(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 <fstream>
|
|
#include <algorithm>
|
|
|
|
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<size_t>(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<byte>& in) :
|
|
source(in)
|
|
{
|
|
offset = 0;
|
|
}
|
|
|
|
/*
|
|
* DataSource_Memory Constructor
|
|
*/
|
|
DataSource_Memory::DataSource_Memory(const std::string& in) :
|
|
source(reinterpret_cast<const byte*>(in.data()), in.length())
|
|
{
|
|
offset = 0;
|
|
}
|
|
|
|
/*
|
|
* Read from a stream
|
|
*/
|
|
size_t DataSource_Stream::read(byte out[], size_t length)
|
|
{
|
|
source.read(reinterpret_cast<char*>(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<byte> buf(offset);
|
|
source.read(reinterpret_cast<char*>(&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<char*>(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 <unistd.h>
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* Write data from a pipe into a Unix fd
|
|
*/
|
|
int operator<<(int fd, Pipe& pipe)
|
|
{
|
|
SecureVector<byte> 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<byte> 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 <algorithm>
|
|
|
|
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<byte> 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<size_t>(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 <algorithm>
|
|
|
|
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 <algorithm>
|
|
|
|
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<size_t>(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<byte> 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<size_t>(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<byte> 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 <algorithm>
|
|
|
|
namespace Botan {
|
|
|
|
namespace {
|
|
|
|
/*
|
|
* EAX MAC-based PRF
|
|
*/
|
|
SecureVector<byte> 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<size_t>(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<byte> data_mac = cmac->final();
|
|
xor_buf(data_mac, nonce_mac, data_mac.size());
|
|
xor_buf(data_mac, header_mac, data_mac.size());
|
|
|
|
send(data_mac, TAG_SIZE);
|
|
}
|
|
|
|
}
|
|
/*
|
|
* EAX Mode Encryption
|
|
* (C) 1999-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
#include <algorithm>
|
|
|
|
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<size_t>(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<byte> 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<size_t>(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<byte> 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<byte> 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<byte>(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<byte>(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 <algorithm>
|
|
#include <stdexcept>
|
|
|
|
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<size_t>(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<byte> 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<byte> 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<byte> 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<byte> temp(input, length);
|
|
SecureVector<byte> 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<SecureQueue*>(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<byte>& 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<const byte*>(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<Null_Filter*>(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<SecureQueue*>(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<SecureQueue*>(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<SecureQueue*>(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<SecureQueue*>(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<Pipe::message_id>(-2);
|
|
|
|
const Pipe::message_id Pipe::DEFAULT_MESSAGE =
|
|
static_cast<Pipe::message_id>(-1);
|
|
|
|
}
|
|
/*
|
|
* Pipe I/O
|
|
* (C) 1999-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
#include <iostream>
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* Write data from a pipe into an ostream
|
|
*/
|
|
std::ostream& operator<<(std::ostream& stream, Pipe& pipe)
|
|
{
|
|
SecureVector<byte> buffer(DEFAULT_BUFFERSIZE);
|
|
while(stream.good() && pipe.remaining())
|
|
{
|
|
size_t got = pipe.read(&buffer[0], buffer.size());
|
|
stream.write(reinterpret_cast<const char*>(&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<byte> buffer(DEFAULT_BUFFERSIZE);
|
|
while(stream.good())
|
|
{
|
|
stream.read(reinterpret_cast<char*>(&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<byte>& input)
|
|
{
|
|
write(&input[0], input.size());
|
|
}
|
|
|
|
/*
|
|
* Write a string into a Pipe
|
|
*/
|
|
void Pipe::write(const std::string& str)
|
|
{
|
|
write(reinterpret_cast<const byte*>(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<byte> 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<byte> Pipe::read_all(message_id msg)
|
|
{
|
|
msg = ((msg != DEFAULT_MESSAGE) ? msg : default_msg());
|
|
SecureVector<byte> 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<byte> 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<const char*>(&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<byte>& 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<byte>& sig) :
|
|
verifier(v), signature(sig)
|
|
{
|
|
}
|
|
|
|
}
|
|
/*
|
|
* SecureQueue
|
|
* (C) 1999-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
#include <algorithm>
|
|
|
|
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<size_t>(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<byte> 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 <stdexcept>
|
|
|
|
namespace Botan {
|
|
|
|
namespace {
|
|
|
|
void comb4p_round(MemoryRegion<byte>& out,
|
|
const MemoryRegion<byte>& 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<byte> 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<byte> h1 = hash1->final();
|
|
SecureVector<byte> 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<byte> length_buf(32);
|
|
const u64bit bit_count = count * 8;
|
|
store_le(bit_count, &length_buf[0]);
|
|
|
|
SecureVector<byte> 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<u64bit>(input[0]) << (8 * (S_pos % 8));
|
|
|
|
++S_pos;
|
|
++input;
|
|
--to_take;
|
|
}
|
|
|
|
while(to_take && to_take % 8 == 0)
|
|
{
|
|
S[S_pos / 8] ^= load_le<u64bit>(input, 0);
|
|
S_pos += 8;
|
|
input += 8;
|
|
to_take -= 8;
|
|
}
|
|
|
|
while(to_take)
|
|
{
|
|
S[S_pos / 8] ^= static_cast<u64bit>(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<byte> 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<byte>(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<byte>(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<HashFunction*> 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<HashFunction*>& 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<u32bit>& 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<u32bit>(input, 0);
|
|
u32bit W01 = load_be<u32bit>(input, 1);
|
|
u32bit W02 = load_be<u32bit>(input, 2);
|
|
u32bit W03 = load_be<u32bit>(input, 3);
|
|
u32bit W04 = load_be<u32bit>(input, 4);
|
|
u32bit W05 = load_be<u32bit>(input, 5);
|
|
u32bit W06 = load_be<u32bit>(input, 6);
|
|
u32bit W07 = load_be<u32bit>(input, 7);
|
|
u32bit W08 = load_be<u32bit>(input, 8);
|
|
u32bit W09 = load_be<u32bit>(input, 9);
|
|
u32bit W10 = load_be<u32bit>(input, 10);
|
|
u32bit W11 = load_be<u32bit>(input, 11);
|
|
u32bit W12 = load_be<u32bit>(input, 12);
|
|
u32bit W13 = load_be<u32bit>(input, 13);
|
|
u32bit W14 = load_be<u32bit>(input, 14);
|
|
u32bit W15 = load_be<u32bit>(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<u64bit>& 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<u64bit>(input, 0);
|
|
u64bit W01 = load_be<u64bit>(input, 1);
|
|
u64bit W02 = load_be<u64bit>(input, 2);
|
|
u64bit W03 = load_be<u64bit>(input, 3);
|
|
u64bit W04 = load_be<u64bit>(input, 4);
|
|
u64bit W05 = load_be<u64bit>(input, 5);
|
|
u64bit W06 = load_be<u64bit>(input, 6);
|
|
u64bit W07 = load_be<u64bit>(input, 7);
|
|
u64bit W08 = load_be<u64bit>(input, 8);
|
|
u64bit W09 = load_be<u64bit>(input, 9);
|
|
u64bit W10 = load_be<u64bit>(input, 10);
|
|
u64bit W11 = load_be<u64bit>(input, 11);
|
|
u64bit W12 = load_be<u64bit>(input, 12);
|
|
u64bit W13 = load_be<u64bit>(input, 13);
|
|
u64bit W14 = load_be<u64bit>(input, 14);
|
|
u64bit W15 = load_be<u64bit>(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 <algorithm>
|
|
|
|
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<u64bit>& H,
|
|
MemoryRegion<u64bit>& T,
|
|
const byte msg[], size_t msg_len)
|
|
{
|
|
do
|
|
{
|
|
const size_t to_proc = std::min<size_t>(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<u64bit>(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<u64bit>(1) << 62);
|
|
|
|
msg_len -= to_proc;
|
|
msg += to_proc;
|
|
} while(msg_len);
|
|
}
|
|
|
|
void reset_tweak(MemoryRegion<u64bit>& T,
|
|
type_code type, bool final)
|
|
{
|
|
T[0] = 0;
|
|
|
|
T[1] = (static_cast<u64bit>(type) << 56) |
|
|
(static_cast<u64bit>(1) << 62) |
|
|
(static_cast<u64bit>(final) << 63);
|
|
}
|
|
|
|
void initial_block(MemoryRegion<u64bit>& H,
|
|
MemoryRegion<u64bit>& 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<const byte*>(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<u64bit>(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<u64bit> H_out(9);
|
|
|
|
while(out_bytes)
|
|
{
|
|
const size_t to_proc = std::min<size_t>(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<u64bit>& 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<u64bit>& 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<byte> KDF::derive_key(size_t key_len,
|
|
const MemoryRegion<byte>& secret,
|
|
const std::string& salt) const
|
|
{
|
|
return derive_key(key_len, &secret[0], secret.size(),
|
|
reinterpret_cast<const byte*>(salt.data()),
|
|
salt.length());
|
|
}
|
|
|
|
/*
|
|
* Derive a key
|
|
*/
|
|
SecureVector<byte> KDF::derive_key(size_t key_len,
|
|
const MemoryRegion<byte>& 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<byte> KDF::derive_key(size_t key_len,
|
|
const MemoryRegion<byte>& secret,
|
|
const MemoryRegion<byte>& salt) const
|
|
{
|
|
return derive_key(key_len, &secret[0], secret.size(),
|
|
&salt[0], salt.size());
|
|
}
|
|
|
|
/*
|
|
* Derive a key
|
|
*/
|
|
SecureVector<byte> 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<const byte*>(salt.data()),
|
|
salt.length());
|
|
}
|
|
|
|
/*
|
|
* Derive a key
|
|
*/
|
|
SecureVector<byte> 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<byte> 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<byte> KDF2::derive(size_t out_len,
|
|
const byte secret[], size_t secret_len,
|
|
const byte P[], size_t P_len) const
|
|
{
|
|
SecureVector<byte> output;
|
|
u32bit counter = 1;
|
|
|
|
while(out_len && counter)
|
|
{
|
|
hash->update(secret, secret_len);
|
|
hash->update_be(counter);
|
|
hash->update(P, P_len);
|
|
|
|
SecureVector<byte> 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 <algorithm>
|
|
#include <memory>
|
|
|
|
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<byte> buffer = hash->final();
|
|
|
|
size_t xored = std::min<size_t>(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 <memory>
|
|
|
|
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<byte>(ASCII_A_CHAR + where));
|
|
sha1.update(secret, secret_len);
|
|
sha1.update(seed, seed_len);
|
|
SecureVector<byte> sha1_hash = sha1.final();
|
|
|
|
md5.update(secret, secret_len);
|
|
md5.update(sha1_hash);
|
|
SecureVector<byte> md5_hash = md5.final();
|
|
|
|
return OctetString(&md5_hash[0], want);
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
* SSL3 PRF
|
|
*/
|
|
SecureVector<byte> 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<size_t>(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<byte>& output,
|
|
MessageAuthenticationCode* mac,
|
|
const byte secret[], size_t secret_len,
|
|
const byte seed[], size_t seed_len)
|
|
{
|
|
mac->set_key(secret, secret_len);
|
|
|
|
SecureVector<byte> A(seed, seed_len);
|
|
|
|
size_t offset = 0;
|
|
|
|
while(offset != output.size())
|
|
{
|
|
const size_t this_block_len =
|
|
std::min<size_t>(mac->output_length(), output.size() - offset);
|
|
|
|
A = mac->process(A);
|
|
|
|
mac->update(A);
|
|
mac->update(seed, seed_len);
|
|
SecureVector<byte> 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<byte> TLS_PRF::derive(size_t key_len,
|
|
const byte secret[], size_t secret_len,
|
|
const byte seed[], size_t seed_len) const
|
|
{
|
|
SecureVector<byte> 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<byte> TLS_12_PRF::derive(size_t key_len,
|
|
const byte secret[], size_t secret_len,
|
|
const byte seed[], size_t seed_len) const
|
|
{
|
|
SecureVector<byte> 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 <algorithm>
|
|
#include <memory>
|
|
|
|
namespace Botan {
|
|
|
|
namespace {
|
|
|
|
/*
|
|
* Encode an integer as an OCTET STRING
|
|
*/
|
|
MemoryVector<byte> 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<byte> 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<byte> 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<u32bit>(8 * key_len)))
|
|
.end_explicit()
|
|
|
|
.end_cons().get_contents()
|
|
);
|
|
|
|
SecureVector<byte> 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<std::string> 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<std::string> 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 <algorithm>
|
|
|
|
#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<std::string, Allocator*>(alloc_factory, type, 0);
|
|
|
|
if(!cached_default_allocator)
|
|
{
|
|
cached_default_allocator =
|
|
search_map<std::string, Allocator*>(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<std::string, std::string>(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<std::string, std::string>::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 {
|
|
|
|
/*
|
|
* Register an OID to string mapping
|
|
*/
|
|
void add_oid(const OID& oid, const std::string& name)
|
|
{
|
|
const std::string oid_str = oid.as_string();
|
|
|
|
if(!global_state().is_set("oid2str", oid_str))
|
|
global_state().set("oid2str", oid_str, name);
|
|
if(!global_state().is_set("str2oid", name))
|
|
global_state().set("str2oid", name, oid_str);
|
|
}
|
|
|
|
/*
|
|
* Do an OID to string lookup
|
|
*/
|
|
std::string lookup(const OID& oid)
|
|
{
|
|
std::string name = global_state().get("oid2str", oid.as_string());
|
|
if(name == "")
|
|
return oid.as_string();
|
|
return name;
|
|
}
|
|
|
|
/*
|
|
* Do a string to OID lookup
|
|
*/
|
|
OID lookup(const std::string& name)
|
|
{
|
|
std::string value = global_state().get("str2oid", name);
|
|
if(value != "")
|
|
return OID(value);
|
|
|
|
try
|
|
{
|
|
return OID(name);
|
|
}
|
|
catch(...)
|
|
{
|
|
throw Lookup_Error("No object identifier found for " + name);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Check to see if an OID exists in the table
|
|
*/
|
|
bool have_oid(const std::string& name)
|
|
{
|
|
return global_state().is_set("str2oid", name);
|
|
}
|
|
|
|
/*
|
|
* Check to see if an OID exists in the table
|
|
*/
|
|
bool name_of(const OID& oid, const std::string& name)
|
|
{
|
|
return (oid == lookup(name));
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
/*
|
|
* Default Policy
|
|
* (C) 1999-2010 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
namespace {
|
|
|
|
/*
|
|
* OID loading helper function
|
|
*/
|
|
void add_oid(Library_State& config,
|
|
const std::string& oid_str,
|
|
const std::string& name)
|
|
{
|
|
if(!config.is_set("oid2str", oid_str))
|
|
config.set("oid2str", oid_str, name);
|
|
if(!config.is_set("str2oid", name))
|
|
config.set("str2oid", name, oid_str);
|
|
}
|
|
|
|
/*
|
|
* Load all of the default OIDs
|
|
*/
|
|
void set_default_oids(Library_State& config)
|
|
{
|
|
/* Public key types */
|
|
add_oid(config, "1.2.840.113549.1.1.1", "RSA");
|
|
add_oid(config, "2.5.8.1.1", "RSA"); // RSA alternate
|
|
add_oid(config, "1.2.840.10040.4.1", "DSA");
|
|
add_oid(config, "1.2.840.10046.2.1", "DH");
|
|
add_oid(config, "1.3.6.1.4.1.3029.1.2.1", "ElGamal");
|
|
add_oid(config, "1.3.6.1.4.1.25258.1.1", "RW");
|
|
add_oid(config, "1.3.6.1.4.1.25258.1.2", "NR");
|
|
|
|
// X9.62 ecPublicKey, valid for ECDSA and ECDH (RFC 3279 sec 2.3.5)
|
|
add_oid(config, "1.2.840.10045.2.1", "ECDSA");
|
|
|
|
/*
|
|
* This is an OID defined for ECDH keys though rarely used for such.
|
|
* In this configuration it is accepted on decoding, but not used for
|
|
* encoding. You can enable it for encoding by calling
|
|
* global_state().set("str2oid", "ECDH", "1.3.132.1.12")
|
|
* from your application code.
|
|
*/
|
|
config.set("oid2str", "1.3.132.1.12", "ECDH");
|
|
|
|
add_oid(config, "1.2.643.2.2.19", "GOST-34.10"); // RFC 4491
|
|
|
|
/* Ciphers */
|
|
add_oid(config, "1.3.14.3.2.7", "DES/CBC");
|
|
add_oid(config, "1.2.840.113549.3.7", "TripleDES/CBC");
|
|
add_oid(config, "1.2.840.113549.3.2", "RC2/CBC");
|
|
add_oid(config, "1.2.840.113533.7.66.10", "CAST-128/CBC");
|
|
add_oid(config, "2.16.840.1.101.3.4.1.2", "AES-128/CBC");
|
|
add_oid(config, "2.16.840.1.101.3.4.1.22", "AES-192/CBC");
|
|
add_oid(config, "2.16.840.1.101.3.4.1.42", "AES-256/CBC");
|
|
add_oid(config, "1.2.410.200004.1.4", "SEED/CBC"); // RFC 4010
|
|
add_oid(config, "1.3.6.1.4.1.25258.3.1", "Serpent/CBC");
|
|
|
|
/* Hash Functions */
|
|
add_oid(config, "1.2.840.113549.2.5", "MD5");
|
|
add_oid(config, "1.3.6.1.4.1.11591.12.2", "Tiger(24,3)");
|
|
|
|
add_oid(config, "1.3.14.3.2.26", "SHA-160");
|
|
add_oid(config, "2.16.840.1.101.3.4.2.4", "SHA-224");
|
|
add_oid(config, "2.16.840.1.101.3.4.2.1", "SHA-256");
|
|
add_oid(config, "2.16.840.1.101.3.4.2.2", "SHA-384");
|
|
add_oid(config, "2.16.840.1.101.3.4.2.3", "SHA-512");
|
|
|
|
/* MACs */
|
|
add_oid(config, "1.2.840.113549.2.7", "HMAC(SHA-1)");
|
|
add_oid(config, "1.2.840.113549.2.8", "HMAC(SHA-224)");
|
|
add_oid(config, "1.2.840.113549.2.9", "HMAC(SHA-256)");
|
|
add_oid(config, "1.2.840.113549.2.10", "HMAC(SHA-384)");
|
|
add_oid(config, "1.2.840.113549.2.11", "HMAC(SHA-512)");
|
|
|
|
/* Key Wrap */
|
|
add_oid(config, "1.2.840.113549.1.9.16.3.6", "KeyWrap.TripleDES");
|
|
add_oid(config, "1.2.840.113549.1.9.16.3.7", "KeyWrap.RC2");
|
|
add_oid(config, "1.2.840.113533.7.66.15", "KeyWrap.CAST-128");
|
|
add_oid(config, "2.16.840.1.101.3.4.1.5", "KeyWrap.AES-128");
|
|
add_oid(config, "2.16.840.1.101.3.4.1.25", "KeyWrap.AES-192");
|
|
add_oid(config, "2.16.840.1.101.3.4.1.45", "KeyWrap.AES-256");
|
|
|
|
/* Compression */
|
|
add_oid(config, "1.2.840.113549.1.9.16.3.8", "Compression.Zlib");
|
|
|
|
/* Public key signature schemes */
|
|
add_oid(config, "1.2.840.113549.1.1.1", "RSA/EME-PKCS1-v1_5");
|
|
add_oid(config, "1.2.840.113549.1.1.2", "RSA/EMSA3(MD2)");
|
|
add_oid(config, "1.2.840.113549.1.1.4", "RSA/EMSA3(MD5)");
|
|
add_oid(config, "1.2.840.113549.1.1.5", "RSA/EMSA3(SHA-160)");
|
|
add_oid(config, "1.2.840.113549.1.1.11", "RSA/EMSA3(SHA-256)");
|
|
add_oid(config, "1.2.840.113549.1.1.12", "RSA/EMSA3(SHA-384)");
|
|
add_oid(config, "1.2.840.113549.1.1.13", "RSA/EMSA3(SHA-512)");
|
|
add_oid(config, "1.3.36.3.3.1.2", "RSA/EMSA3(RIPEMD-160)");
|
|
|
|
add_oid(config, "1.2.840.10040.4.3", "DSA/EMSA1(SHA-160)");
|
|
add_oid(config, "2.16.840.1.101.3.4.3.1", "DSA/EMSA1(SHA-224)");
|
|
add_oid(config, "2.16.840.1.101.3.4.3.2", "DSA/EMSA1(SHA-256)");
|
|
|
|
add_oid(config, "0.4.0.127.0.7.1.1.4.1.1", "ECDSA/EMSA1_BSI(SHA-160)");
|
|
add_oid(config, "0.4.0.127.0.7.1.1.4.1.2", "ECDSA/EMSA1_BSI(SHA-224)");
|
|
add_oid(config, "0.4.0.127.0.7.1.1.4.1.3", "ECDSA/EMSA1_BSI(SHA-256)");
|
|
add_oid(config, "0.4.0.127.0.7.1.1.4.1.4", "ECDSA/EMSA1_BSI(SHA-384)");
|
|
add_oid(config, "0.4.0.127.0.7.1.1.4.1.5", "ECDSA/EMSA1_BSI(SHA-512)");
|
|
add_oid(config, "0.4.0.127.0.7.1.1.4.1.6", "ECDSA/EMSA1_BSI(RIPEMD-160)");
|
|
|
|
add_oid(config, "1.2.840.10045.4.1", "ECDSA/EMSA1(SHA-160)");
|
|
add_oid(config, "1.2.840.10045.4.3.1", "ECDSA/EMSA1(SHA-224)");
|
|
add_oid(config, "1.2.840.10045.4.3.2", "ECDSA/EMSA1(SHA-256)");
|
|
add_oid(config, "1.2.840.10045.4.3.3", "ECDSA/EMSA1(SHA-384)");
|
|
add_oid(config, "1.2.840.10045.4.3.4", "ECDSA/EMSA1(SHA-512)");
|
|
|
|
add_oid(config, "1.2.643.2.2.3", "GOST-34.10/EMSA1(GOST-R-34.11-94)");
|
|
|
|
add_oid(config, "1.3.6.1.4.1.25258.2.1.1.1", "RW/EMSA2(RIPEMD-160)");
|
|
add_oid(config, "1.3.6.1.4.1.25258.2.1.1.2", "RW/EMSA2(SHA-160)");
|
|
add_oid(config, "1.3.6.1.4.1.25258.2.1.1.3", "RW/EMSA2(SHA-224)");
|
|
add_oid(config, "1.3.6.1.4.1.25258.2.1.1.4", "RW/EMSA2(SHA-256)");
|
|
add_oid(config, "1.3.6.1.4.1.25258.2.1.1.5", "RW/EMSA2(SHA-384)");
|
|
add_oid(config, "1.3.6.1.4.1.25258.2.1.1.6", "RW/EMSA2(SHA-512)");
|
|
|
|
add_oid(config, "1.3.6.1.4.1.25258.2.1.2.1", "RW/EMSA4(RIPEMD-160)");
|
|
add_oid(config, "1.3.6.1.4.1.25258.2.1.2.2", "RW/EMSA4(SHA-160)");
|
|
add_oid(config, "1.3.6.1.4.1.25258.2.1.2.3", "RW/EMSA4(SHA-224)");
|
|
add_oid(config, "1.3.6.1.4.1.25258.2.1.2.4", "RW/EMSA4(SHA-256)");
|
|
add_oid(config, "1.3.6.1.4.1.25258.2.1.2.5", "RW/EMSA4(SHA-384)");
|
|
add_oid(config, "1.3.6.1.4.1.25258.2.1.2.6", "RW/EMSA4(SHA-512)");
|
|
|
|
add_oid(config, "1.3.6.1.4.1.25258.2.2.1.1", "NR/EMSA2(RIPEMD-160)");
|
|
add_oid(config, "1.3.6.1.4.1.25258.2.2.1.2", "NR/EMSA2(SHA-160)");
|
|
add_oid(config, "1.3.6.1.4.1.25258.2.2.1.3", "NR/EMSA2(SHA-224)");
|
|
add_oid(config, "1.3.6.1.4.1.25258.2.2.1.4", "NR/EMSA2(SHA-256)");
|
|
add_oid(config, "1.3.6.1.4.1.25258.2.2.1.5", "NR/EMSA2(SHA-384)");
|
|
add_oid(config, "1.3.6.1.4.1.25258.2.2.1.6", "NR/EMSA2(SHA-512)");
|
|
|
|
add_oid(config, "2.5.4.3", "X520.CommonName");
|
|
add_oid(config, "2.5.4.4", "X520.Surname");
|
|
add_oid(config, "2.5.4.5", "X520.SerialNumber");
|
|
add_oid(config, "2.5.4.6", "X520.Country");
|
|
add_oid(config, "2.5.4.7", "X520.Locality");
|
|
add_oid(config, "2.5.4.8", "X520.State");
|
|
add_oid(config, "2.5.4.10", "X520.Organization");
|
|
add_oid(config, "2.5.4.11", "X520.OrganizationalUnit");
|
|
add_oid(config, "2.5.4.12", "X520.Title");
|
|
add_oid(config, "2.5.4.42", "X520.GivenName");
|
|
add_oid(config, "2.5.4.43", "X520.Initials");
|
|
add_oid(config, "2.5.4.44", "X520.GenerationalQualifier");
|
|
add_oid(config, "2.5.4.46", "X520.DNQualifier");
|
|
add_oid(config, "2.5.4.65", "X520.Pseudonym");
|
|
|
|
add_oid(config, "1.2.840.113549.1.5.12", "PKCS5.PBKDF2");
|
|
add_oid(config, "1.2.840.113549.1.5.1", "PBE-PKCS5v15(MD2,DES/CBC)");
|
|
add_oid(config, "1.2.840.113549.1.5.4", "PBE-PKCS5v15(MD2,RC2/CBC)");
|
|
add_oid(config, "1.2.840.113549.1.5.3", "PBE-PKCS5v15(MD5,DES/CBC)");
|
|
add_oid(config, "1.2.840.113549.1.5.6", "PBE-PKCS5v15(MD5,RC2/CBC)");
|
|
add_oid(config, "1.2.840.113549.1.5.10", "PBE-PKCS5v15(SHA-160,DES/CBC)");
|
|
add_oid(config, "1.2.840.113549.1.5.11", "PBE-PKCS5v15(SHA-160,RC2/CBC)");
|
|
add_oid(config, "1.2.840.113549.1.5.13", "PBE-PKCS5v20");
|
|
|
|
add_oid(config, "1.2.840.113549.1.9.1", "PKCS9.EmailAddress");
|
|
add_oid(config, "1.2.840.113549.1.9.2", "PKCS9.UnstructuredName");
|
|
add_oid(config, "1.2.840.113549.1.9.3", "PKCS9.ContentType");
|
|
add_oid(config, "1.2.840.113549.1.9.4", "PKCS9.MessageDigest");
|
|
add_oid(config, "1.2.840.113549.1.9.7", "PKCS9.ChallengePassword");
|
|
add_oid(config, "1.2.840.113549.1.9.14", "PKCS9.ExtensionRequest");
|
|
|
|
add_oid(config, "1.2.840.113549.1.7.1", "CMS.DataContent");
|
|
add_oid(config, "1.2.840.113549.1.7.2", "CMS.SignedData");
|
|
add_oid(config, "1.2.840.113549.1.7.3", "CMS.EnvelopedData");
|
|
add_oid(config, "1.2.840.113549.1.7.5", "CMS.DigestedData");
|
|
add_oid(config, "1.2.840.113549.1.7.6", "CMS.EncryptedData");
|
|
add_oid(config, "1.2.840.113549.1.9.16.1.2", "CMS.AuthenticatedData");
|
|
add_oid(config, "1.2.840.113549.1.9.16.1.9", "CMS.CompressedData");
|
|
|
|
add_oid(config, "2.5.29.14", "X509v3.SubjectKeyIdentifier");
|
|
add_oid(config, "2.5.29.15", "X509v3.KeyUsage");
|
|
add_oid(config, "2.5.29.17", "X509v3.SubjectAlternativeName");
|
|
add_oid(config, "2.5.29.18", "X509v3.IssuerAlternativeName");
|
|
add_oid(config, "2.5.29.19", "X509v3.BasicConstraints");
|
|
add_oid(config, "2.5.29.20", "X509v3.CRLNumber");
|
|
add_oid(config, "2.5.29.21", "X509v3.ReasonCode");
|
|
add_oid(config, "2.5.29.23", "X509v3.HoldInstructionCode");
|
|
add_oid(config, "2.5.29.24", "X509v3.InvalidityDate");
|
|
add_oid(config, "2.5.29.32", "X509v3.CertificatePolicies");
|
|
add_oid(config, "2.5.29.35", "X509v3.AuthorityKeyIdentifier");
|
|
add_oid(config, "2.5.29.36", "X509v3.PolicyConstraints");
|
|
add_oid(config, "2.5.29.37", "X509v3.ExtendedKeyUsage");
|
|
|
|
add_oid(config, "2.5.29.32.0", "X509v3.AnyPolicy");
|
|
|
|
add_oid(config, "1.3.6.1.5.5.7.3.1", "PKIX.ServerAuth");
|
|
add_oid(config, "1.3.6.1.5.5.7.3.2", "PKIX.ClientAuth");
|
|
add_oid(config, "1.3.6.1.5.5.7.3.3", "PKIX.CodeSigning");
|
|
add_oid(config, "1.3.6.1.5.5.7.3.4", "PKIX.EmailProtection");
|
|
add_oid(config, "1.3.6.1.5.5.7.3.5", "PKIX.IPsecEndSystem");
|
|
add_oid(config, "1.3.6.1.5.5.7.3.6", "PKIX.IPsecTunnel");
|
|
add_oid(config, "1.3.6.1.5.5.7.3.7", "PKIX.IPsecUser");
|
|
add_oid(config, "1.3.6.1.5.5.7.3.8", "PKIX.TimeStamping");
|
|
add_oid(config, "1.3.6.1.5.5.7.3.9", "PKIX.OCSPSigning");
|
|
|
|
add_oid(config, "1.3.6.1.5.5.7.8.5", "PKIX.XMPPAddr");
|
|
|
|
/* ECC domain parameters */
|
|
|
|
add_oid(config, "1.3.132.0.6", "secp112r1");
|
|
add_oid(config, "1.3.132.0.7", "secp112r2");
|
|
add_oid(config, "1.3.132.0.8", "secp160r1");
|
|
add_oid(config, "1.3.132.0.9", "secp160k1");
|
|
add_oid(config, "1.3.132.0.10", "secp256k1");
|
|
add_oid(config, "1.3.132.0.28", "secp128r1");
|
|
add_oid(config, "1.3.132.0.29", "secp128r2");
|
|
add_oid(config, "1.3.132.0.30", "secp160r2");
|
|
add_oid(config, "1.3.132.0.31", "secp192k1");
|
|
add_oid(config, "1.3.132.0.32", "secp224k1");
|
|
add_oid(config, "1.3.132.0.33", "secp224r1");
|
|
add_oid(config, "1.3.132.0.34", "secp384r1");
|
|
add_oid(config, "1.3.132.0.35", "secp521r1");
|
|
|
|
add_oid(config, "1.2.840.10045.3.1.1", "secp192r1");
|
|
add_oid(config, "1.2.840.10045.3.1.2", "x962_p192v2");
|
|
add_oid(config, "1.2.840.10045.3.1.3", "x962_p192v3");
|
|
add_oid(config, "1.2.840.10045.3.1.4", "x962_p239v1");
|
|
add_oid(config, "1.2.840.10045.3.1.5", "x962_p239v2");
|
|
add_oid(config, "1.2.840.10045.3.1.6", "x962_p239v3");
|
|
add_oid(config, "1.2.840.10045.3.1.7", "secp256r1");
|
|
|
|
add_oid(config, "1.3.36.3.3.2.8.1.1.1", "brainpool160r1");
|
|
add_oid(config, "1.3.36.3.3.2.8.1.1.3", "brainpool192r1");
|
|
add_oid(config, "1.3.36.3.3.2.8.1.1.5", "brainpool224r1");
|
|
add_oid(config, "1.3.36.3.3.2.8.1.1.7", "brainpool256r1");
|
|
add_oid(config, "1.3.36.3.3.2.8.1.1.9", "brainpool320r1");
|
|
add_oid(config, "1.3.36.3.3.2.8.1.1.11", "brainpool384r1");
|
|
add_oid(config, "1.3.36.3.3.2.8.1.1.13", "brainpool512r1");
|
|
|
|
add_oid(config, "1.2.643.2.2.35.1", "gost_256A");
|
|
add_oid(config, "1.2.643.2.2.36.0", "gost_256A");
|
|
|
|
/* CVC */
|
|
add_oid(config, "0.4.0.127.0.7.3.1.2.1",
|
|
"CertificateHolderAuthorizationTemplate");
|
|
}
|
|
|
|
/*
|
|
* Set the default algorithm aliases
|
|
*/
|
|
void set_default_aliases(Library_State& config)
|
|
{
|
|
config.add_alias("OpenPGP.Cipher.1", "IDEA");
|
|
config.add_alias("OpenPGP.Cipher.2", "TripleDES");
|
|
config.add_alias("OpenPGP.Cipher.3", "CAST-128");
|
|
config.add_alias("OpenPGP.Cipher.4", "Blowfish");
|
|
config.add_alias("OpenPGP.Cipher.5", "SAFER-SK(13)");
|
|
config.add_alias("OpenPGP.Cipher.7", "AES-128");
|
|
config.add_alias("OpenPGP.Cipher.8", "AES-192");
|
|
config.add_alias("OpenPGP.Cipher.9", "AES-256");
|
|
config.add_alias("OpenPGP.Cipher.10", "Twofish");
|
|
|
|
config.add_alias("OpenPGP.Digest.1", "MD5");
|
|
config.add_alias("OpenPGP.Digest.2", "SHA-1");
|
|
config.add_alias("OpenPGP.Digest.3", "RIPEMD-160");
|
|
config.add_alias("OpenPGP.Digest.5", "MD2");
|
|
config.add_alias("OpenPGP.Digest.6", "Tiger(24,3)");
|
|
config.add_alias("OpenPGP.Digest.8", "SHA-256");
|
|
|
|
config.add_alias("TLS.Digest.0", "Parallel(MD5,SHA-160)");
|
|
|
|
config.add_alias("EME-PKCS1-v1_5", "PKCS1v15");
|
|
config.add_alias("OAEP-MGF1", "EME1");
|
|
config.add_alias("EME-OAEP", "EME1");
|
|
config.add_alias("X9.31", "EMSA2");
|
|
config.add_alias("EMSA-PKCS1-v1_5", "EMSA3");
|
|
config.add_alias("PSS-MGF1", "EMSA4");
|
|
config.add_alias("EMSA-PSS", "EMSA4");
|
|
|
|
config.add_alias("3DES", "TripleDES");
|
|
config.add_alias("DES-EDE", "TripleDES");
|
|
config.add_alias("CAST5", "CAST-128");
|
|
config.add_alias("SHA1", "SHA-160");
|
|
config.add_alias("SHA-1", "SHA-160");
|
|
config.add_alias("MARK-4", "ARC4(256)");
|
|
config.add_alias("OMAC", "CMAC");
|
|
config.add_alias("GOST", "GOST-28147-89");
|
|
}
|
|
|
|
/*
|
|
* Set the built-in discrete log groups
|
|
*/
|
|
void set_default_dl_groups(Library_State& config)
|
|
{
|
|
config.set("dl", "modp/ietf/768",
|
|
"-----BEGIN X942 DH PARAMETERS-----"
|
|
"MIHIAmEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxObIlFK"
|
|
"CHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjo2IP//"
|
|
"////////AgECAmB//////////+SH7VEQtGEaYmMxRcBuDmiUgScERTPmOgEF31Md"
|
|
"ic2RKKUEPMcaAm73yozZ5p0hjZgVhTb5L4obp/Catrao4SLyQtq7MS8/Y3omIXTT"
|
|
"HRsQf/////////8="
|
|
"-----END X942 DH PARAMETERS-----");
|
|
|
|
config.set("dl", "modp/ietf/1024",
|
|
"-----BEGIN X942 DH PARAMETERS-----"
|
|
"MIIBCgKBgQD//////////8kP2qIhaMI0xMZii4DcHNEpAk4IimfMdAILvqY7E5si"
|
|
"UUoIeY40BN3vlRmzzTpDGzArCm3yXxQ3T+E1bW1RwkXkhbV2Yl5+xvRMQummN+1r"
|
|
"C/9ctvQGt+3uOGv7Womfpa6fJBF8Sx/mSShmUezmU4H//////////wIBAgKBgH//"
|
|
"////////5IftURC0YRpiYzFFwG4OaJSBJwRFM+Y6AQXfUx2JzZEopQQ8xxoCbvfK"
|
|
"jNnmnSGNmBWFNvkvihun8Jq2tqjhIvJC2rsxLz9jeiYhdNMb9rWF/65begNb9vcc"
|
|
"Nf2tRM/S10+SCL4lj/MklDMo9nMpwP//////////"
|
|
"-----END X942 DH PARAMETERS-----");
|
|
|
|
config.set("dl", "modp/srp/1024",
|
|
"-----BEGIN X942 DH PARAMETERS-----"
|
|
"MIIBCgKBgQDurwq5rbON1pwz+Ar6j8XoYHJhh3X/PAueojFMnCVldtZ033SW6oHT"
|
|
"ODtIE9aSxuDg1djiULmL5I5JXB1gidrRXcfXtGFU1rbOjvStabFdSYJVmyl7zxiF"
|
|
"xSn1ZmYOV+xo7bw8BXJswC/Uy/SXbqqa/VE4/oN2Q1ufxh0vwOsG4wIBAgKBgHdX"
|
|
"hVzW2cbrThn8BX1H4vQwOTDDuv+eBc9RGKZOErK7azpvukt1QOmcHaQJ60ljcHBq"
|
|
"7HEoXMXyRySuDrBE7Wiu4+vaMKprW2dHela02K6kwSrNlL3njELilPqzMwcr9jR2"
|
|
"3h4CuTZgF+pl+ku3VU1+qJx/Qbshrc/jDpfgdYNx"
|
|
"-----END X942 DH PARAMETERS-----");
|
|
|
|
config.set("dl", "modp/ietf/1536",
|
|
"-----BEGIN X942 DH PARAMETERS-----"
|
|
"MIIBigKBwQD//////////8kP2qIhaMI0xMZii4DcHNEpAk4IimfMdAILvqY7E5si"
|
|
"UUoIeY40BN3vlRmzzTpDGzArCm3yXxQ3T+E1bW1RwkXkhbV2Yl5+xvRMQummN+1r"
|
|
"C/9ctvQGt+3uOGv7Womfpa6fJBF8Sx/mSShmUezkWz3CAHy4oWO/BZjaSDYcVdOa"
|
|
"aRY/qP0kz1+DZV0j3KOtlhxi81YghVK7ntUpB3CWlm1nDDVOSryYBPF0bAjKI3Mn"
|
|
"//////////8CAQICgcB//////////+SH7VEQtGEaYmMxRcBuDmiUgScERTPmOgEF"
|
|
"31Mdic2RKKUEPMcaAm73yozZ5p0hjZgVhTb5L4obp/Catrao4SLyQtq7MS8/Y3om"
|
|
"IXTTG/a1hf+uW3oDW/b3HDX9rUTP0tdPkgi+JY/zJJQzKPZyLZ7hAD5cULHfgsxt"
|
|
"JBsOKunNNIsf1H6SZ6/Bsq6R7lHWyw4xeasQQqldz2qUg7hLSzazhhqnJV5MAni6"
|
|
"NgRlEbmT//////////8="
|
|
"-----END X942 DH PARAMETERS-----");
|
|
|
|
config.set("dl", "modp/srp/1536",
|
|
"-----BEGIN DH PARAMETERS-----"
|
|
"MIHHAoHBAJ3vPK+5OSd6sfEqhheke7vbpR30maxMgL7uqWFLGcxNX09fVW4ny95R"
|
|
"xqlL5GB6KRVYkDug0PhDgLZVu5oi6NzfAop87Gfw0IE0sci5eYkUm2CeC+O6tj1H"
|
|
"VIOB28Wx/HZOP0tT3Z2hFYv9PiucjPVu3wGVOTSWJ9sv1T0kt8SGZXcuQ31sf4zk"
|
|
"QnNK98y3roN8Jkrjqb64f4ov6bi1KS5aAh//XpFHnoznoowkQsbzFRgPk0maI03P"
|
|
"duP+0TX5uwIBAg=="
|
|
"-----END DH PARAMETERS-----");
|
|
|
|
config.set("dl", "modp/ietf/2048",
|
|
"-----BEGIN X942 DH PARAMETERS-----"
|
|
"MIICDAKCAQEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb"
|
|
"IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft"
|
|
"awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT"
|
|
"mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh"
|
|
"fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq"
|
|
"5RXSJhiY+gUQFXKOWoqsqmj//////////wIBAgKCAQB//////////+SH7VEQtGEa"
|
|
"YmMxRcBuDmiUgScERTPmOgEF31Mdic2RKKUEPMcaAm73yozZ5p0hjZgVhTb5L4ob"
|
|
"p/Catrao4SLyQtq7MS8/Y3omIXTTG/a1hf+uW3oDW/b3HDX9rUTP0tdPkgi+JY/z"
|
|
"JJQzKPZyLZ7hAD5cULHfgsxtJBsOKunNNIsf1H6SZ6/Bsq6R7lHWyw4xeasQQqld"
|
|
"z2qUg7hLSzazhhqnJV5MAni6NgRlDBC+GUgvIxcbZx3xzzuWDAdDAc2TwdF2A9FH"
|
|
"2uKu+DemKWTvFeX7SqwLjBzKpL51SrVyiukTDEx9AogKuUctRVZVNH//////////"
|
|
"-----END X942 DH PARAMETERS-----");
|
|
|
|
config.set("dl", "modp/srp/2048",
|
|
"-----BEGIN X942 DH PARAMETERS-----"
|
|
"MIICDAKCAQEArGvbQTJKmpvxZt5eE4lYL69ytmUZh+4H/DGSlD21YFCjcynLtKCZ"
|
|
"7YGT4HV3Z6E91SMSq0sDMQ3Nf0ip2gT9UOgIOWntt2ewz2CVF5oWOrNmGgX71fqq"
|
|
"6CkYqZYvC5O4Vfl5k+yXXuqoDXQK2/T/dHNZ0EHVwz6nHSgeRGsUdzvKl7Q6I/uA"
|
|
"Fna9IHpDbGSB8dK5B4cXRhpbnTLmiPh3SFRFI7UksNV9Xqd6J3XS7PoDLPvb9S+z"
|
|
"eGFgJ5AE5Xrmr4dOcwPOUymczAQce8MI2CpWmPOo0MOCca41+Onb+7aUtcgD2J96"
|
|
"5DXeI21SX1R1m2XjcvzWjvIPpxEfnkr/cwIBAgKCAQBWNe2gmSVNTfizby8JxKwX"
|
|
"17lbMozD9wP+GMlKHtqwKFG5lOXaUEz2wMnwOruz0J7qkYlVpYGYhua/pFTtAn6o"
|
|
"dAQctPbbs9hnsEqLzQsdWbMNAv3q/VV0FIxUyxeFydwq/LzJ9kuvdVQGugVt+n+6"
|
|
"OazoIOrhn1OOlA8iNYo7neVL2h0R/cALO16QPSG2MkD46VyDw4ujDS3OmXNEfDuk"
|
|
"KiKR2pJYar6vU70Tuul2fQGWfe36l9m8MLATyAJyvXNXw6c5gecplM5mAg494YRs"
|
|
"FStMedRoYcE41xr8dO3920pa5AHsT71yGu8RtqkvqjrNsvG5fmtHeQfTiI/PJX+5"
|
|
"-----END X942 DH PARAMETERS-----");
|
|
|
|
config.set("dl", "modp/ietf/3072",
|
|
"-----BEGIN X942 DH PARAMETERS-----"
|
|
"MIIDDAKCAYEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb"
|
|
"IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft"
|
|
"awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT"
|
|
"mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh"
|
|
"fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq"
|
|
"5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM"
|
|
"fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq"
|
|
"ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqTrS"
|
|
"yv//////////AgECAoIBgH//////////5IftURC0YRpiYzFFwG4OaJSBJwRFM+Y6"
|
|
"AQXfUx2JzZEopQQ8xxoCbvfKjNnmnSGNmBWFNvkvihun8Jq2tqjhIvJC2rsxLz9j"
|
|
"eiYhdNMb9rWF/65begNb9vccNf2tRM/S10+SCL4lj/MklDMo9nItnuEAPlxQsd+C"
|
|
"zG0kGw4q6c00ix/UfpJnr8GyrpHuUdbLDjF5qxBCqV3PapSDuEtLNrOGGqclXkwC"
|
|
"eLo2BGUMEL4ZSC8jFxtnHfHPO5YMB0MBzZPB0XYD0Ufa4q74N6YpZO8V5ftKrAuM"
|
|
"HMqkvnVKtXKK6RMMTH0CiAq5Ry1FVWIW1pmLhoIoPRnUKpDV745dMnZ9woIsbfeF"
|
|
"RXU4q66DBj7Zy4fC03DyY9X610ZthJnrj0ZKcCUSsM7ncekTDWl3NfiX/QNsxQQy"
|
|
"bDsBOZ9kNTIpD5WMC72QBl3wi6u9MK62O4TEYF1so3EEcSfQOnLVmKHtrf5wfohH"
|
|
"JcFokFSdaWV//////////w=="
|
|
"-----END X942 DH PARAMETERS-----");
|
|
|
|
config.set("dl", "modp/srp/3072",
|
|
"-----BEGIN DH PARAMETERS-----"
|
|
"MIIBiAKCAYEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb"
|
|
"IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft"
|
|
"awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT"
|
|
"mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh"
|
|
"fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq"
|
|
"5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM"
|
|
"fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq"
|
|
"ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqTrS"
|
|
"yv//////////AgEF"
|
|
"-----END DH PARAMETERS-----");
|
|
|
|
config.set("dl", "modp/ietf/4096",
|
|
"-----BEGIN X942 DH PARAMETERS-----"
|
|
"MIIEDAKCAgEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb"
|
|
"IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft"
|
|
"awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT"
|
|
"mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh"
|
|
"fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq"
|
|
"5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM"
|
|
"fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq"
|
|
"ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqSEI"
|
|
"ARpyPBKnh+bXiHGaEL26WyaZwycYavTiPBqUaDS2FQvaJYPpyirUTOjbu8LbBN6O"
|
|
"+S6O/BQfvsqmKHxZR05rwF2ZspZPoJDDoiM7oYZRW+ftH2EpcM7i16+4G912IXBI"
|
|
"HNAGkSfVsFqpk7TqmI2P3cGG/7fckKbAj030Nck0BjGZ//////////8CAQICggIA"
|
|
"f//////////kh+1RELRhGmJjMUXAbg5olIEnBEUz5joBBd9THYnNkSilBDzHGgJu"
|
|
"98qM2eadIY2YFYU2+S+KG6fwmra2qOEi8kLauzEvP2N6JiF00xv2tYX/rlt6A1v2"
|
|
"9xw1/a1Ez9LXT5IIviWP8ySUMyj2ci2e4QA+XFCx34LMbSQbDirpzTSLH9R+kmev"
|
|
"wbKuke5R1ssOMXmrEEKpXc9qlIO4S0s2s4YapyVeTAJ4ujYEZQwQvhlILyMXG2cd"
|
|
"8c87lgwHQwHNk8HRdgPRR9rirvg3pilk7xXl+0qsC4wcyqS+dUq1corpEwxMfQKI"
|
|
"CrlHLUVVYhbWmYuGgig9GdQqkNXvjl0ydn3Cgixt94VFdTirroMGPtnLh8LTcPJj"
|
|
"1frXRm2EmeuPRkpwJRKwzudx6RMNaXc1+Jf9A2zFBDJsOwE5n2Q1MikPlYwLvZAG"
|
|
"XfCLq70wrrY7hMRgXWyjcQRxJ9A6ctWYoe2t/nB+iEclwWiQVJCEAI05HglTw/Nr"
|
|
"xDjNCF7dLZNM4ZOMNXpxHg1KNBpbCoXtEsH05RVqJnRt3eFtgm9HfJdHfgoP32VT"
|
|
"FD4so6c14C7M2Usn0Ehh0RGd0MMorfP2j7CUuGdxa9fcDe67ELgkDmgDSJPq2C1U"
|
|
"ydp1TEbH7uDDf9vuSFNgR6b6GuSaAxjM//////////8="
|
|
"-----END X942 DH PARAMETERS-----");
|
|
|
|
config.set("dl", "modp/srp/4096",
|
|
"-----BEGIN DH PARAMETERS-----"
|
|
"MIICCAKCAgEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb"
|
|
"IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft"
|
|
"awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT"
|
|
"mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh"
|
|
"fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq"
|
|
"5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM"
|
|
"fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq"
|
|
"ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqSEI"
|
|
"ARpyPBKnh+bXiHGaEL26WyaZwycYavTiPBqUaDS2FQvaJYPpyirUTOjbu8LbBN6O"
|
|
"+S6O/BQfvsqmKHxZR05rwF2ZspZPoJDDoiM7oYZRW+ftH2EpcM7i16+4G912IXBI"
|
|
"HNAGkSfVsFqpk7TqmI2P3cGG/7fckKbAj030Nck0BjGZ//////////8CAQU="
|
|
"-----END DH PARAMETERS-----");
|
|
|
|
config.set("dl", "modp/ietf/6144",
|
|
"-----BEGIN X942 DH PARAMETERS-----"
|
|
"MIIGDAKCAwEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb"
|
|
"IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft"
|
|
"awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT"
|
|
"mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh"
|
|
"fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq"
|
|
"5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM"
|
|
"fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq"
|
|
"ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqSEI"
|
|
"ARpyPBKnh+bXiHGaEL26WyaZwycYavTiPBqUaDS2FQvaJYPpyirUTOjbu8LbBN6O"
|
|
"+S6O/BQfvsqmKHxZR05rwF2ZspZPoJDDoiM7oYZRW+ftH2EpcM7i16+4G912IXBI"
|
|
"HNAGkSfVsFqpk7TqmI2P3cGG/7fckKbAj030Nck0AoSSNsP6tNJ8cCbB1NyyYCZG"
|
|
"3sl1HnY9uje9+P+UBq2eUw7l2zgvQTABrrBqU+2QJ9gxF5cnsIZaiRjaPtvrz5sU"
|
|
"7UTObLrO1Lsb238UR+bMJUszIFFRK9evQm+49AE3jNK/WYPKAcZLkuzwMuoV0XId"
|
|
"A/SC185udP721V5wL0aYDIK1qEAxkAscnlnnyX++x+jzI6l6fjbMiL4PHUW3/1ha"
|
|
"xUvUB7IrQVSqzI9tfr9I4dgUzF7SD4A34KeXFe7ym+MoBqHVi7fF2nb1UKo9ih+/"
|
|
"8OsZzLGjE9Vc2lbJ7C7yljI4f+jXbjwEaAQ+j2Y/SGDuEr8tWwt0dNbmlPkebcxA"
|
|
"JP//////////AoIDAH//////////5IftURC0YRpiYzFFwG4OaJSBJwRFM+Y6AQXf"
|
|
"Ux2JzZEopQQ8xxoCbvfKjNnmnSGNmBWFNvkvihun8Jq2tqjhIvJC2rsxLz9jeiYh"
|
|
"dNMb9rWF/65begNb9vccNf2tRM/S10+SCL4lj/MklDMo9nItnuEAPlxQsd+CzG0k"
|
|
"Gw4q6c00ix/UfpJnr8GyrpHuUdbLDjF5qxBCqV3PapSDuEtLNrOGGqclXkwCeLo2"
|
|
"BGUMEL4ZSC8jFxtnHfHPO5YMB0MBzZPB0XYD0Ufa4q74N6YpZO8V5ftKrAuMHMqk"
|
|
"vnVKtXKK6RMMTH0CiAq5Ry1FVWIW1pmLhoIoPRnUKpDV745dMnZ9woIsbfeFRXU4"
|
|
"q66DBj7Zy4fC03DyY9X610ZthJnrj0ZKcCUSsM7ncekTDWl3NfiX/QNsxQQybDsB"
|
|
"OZ9kNTIpD5WMC72QBl3wi6u9MK62O4TEYF1so3EEcSfQOnLVmKHtrf5wfohHJcFo"
|
|
"kFSQhACNOR4JU8Pza8Q4zQhe3S2TTOGTjDV6cR4NSjQaWwqF7RLB9OUVaiZ0bd3h"
|
|
"bYJvR3yXR34KD99lUxQ+LKOnNeAuzNlLJ9BIYdERndDDKK3z9o+wlLhncWvX3A3u"
|
|
"uxC4JA5oA0iT6tgtVMnadUxGx+7gw3/b7khTYEem+hrkmgFCSRth/VppPjgTYOpu"
|
|
"WTATI29kuo87Ht0b3vx/ygNWzymHcu2cF6CYANdYNSn2yBPsGIvLk9hDLUSMbR9t"
|
|
"9efNinaiZzZdZ2pdje2/iiPzZhKlmZAoqJXr16E33HoAm8ZpX6zB5QDjJcl2eBl1"
|
|
"Cui5DoH6QWvnNzp/e2qvOBejTAZBWtQgGMgFjk8s8+S/32P0eZHUvT8bZkRfB46i"
|
|
"2/+sLWKl6gPZFaCqVWZHtr9fpHDsCmYvaQfAG/BTy4r3eU3xlANQ6sXb4u07eqhV"
|
|
"HsUP3/h1jOZY0Ynqrm0rZPYXeUsZHD/0a7ceAjQCH0ezH6Qwdwlflq2Fujprc0p8"
|
|
"jzbmIBJ//////////wIBAg=="
|
|
"-----END X942 DH PARAMETERS-----");
|
|
|
|
config.set("dl", "modp/srp/6144",
|
|
"-----BEGIN DH PARAMETERS-----"
|
|
"MIIDCAKCAwEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb"
|
|
"IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft"
|
|
"awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT"
|
|
"mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh"
|
|
"fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq"
|
|
"5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM"
|
|
"fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq"
|
|
"ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqSEI"
|
|
"ARpyPBKnh+bXiHGaEL26WyaZwycYavTiPBqUaDS2FQvaJYPpyirUTOjbu8LbBN6O"
|
|
"+S6O/BQfvsqmKHxZR05rwF2ZspZPoJDDoiM7oYZRW+ftH2EpcM7i16+4G912IXBI"
|
|
"HNAGkSfVsFqpk7TqmI2P3cGG/7fckKbAj030Nck0AoSSNsP6tNJ8cCbB1NyyYCZG"
|
|
"3sl1HnY9uje9+P+UBq2eUw7l2zgvQTABrrBqU+2QJ9gxF5cnsIZaiRjaPtvrz5sU"
|
|
"7UTObLrO1Lsb238UR+bMJUszIFFRK9evQm+49AE3jNK/WYPKAcZLkuzwMuoV0XId"
|
|
"A/SC185udP721V5wL0aYDIK1qEAxkAscnlnnyX++x+jzI6l6fjbMiL4PHUW3/1ha"
|
|
"xUvUB7IrQVSqzI9tfr9I4dgUzF7SD4A34KeXFe7ym+MoBqHVi7fF2nb1UKo9ih+/"
|
|
"8OsZzLGjE9Vc2lbJ7C7yljI4f+jXbjwEaAQ+j2Y/SGDuEr8tWwt0dNbmlPkebcxA"
|
|
"JP//////////AgEF"
|
|
"-----END DH PARAMETERS-----");
|
|
|
|
config.set("dl", "modp/ietf/8192",
|
|
"-----BEGIN X942 DH PARAMETERS-----"
|
|
"MIIIDAKCBAEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb"
|
|
"IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft"
|
|
"awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT"
|
|
"mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh"
|
|
"fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq"
|
|
"5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM"
|
|
"fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq"
|
|
"ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqSEI"
|
|
"ARpyPBKnh+bXiHGaEL26WyaZwycYavTiPBqUaDS2FQvaJYPpyirUTOjbu8LbBN6O"
|
|
"+S6O/BQfvsqmKHxZR05rwF2ZspZPoJDDoiM7oYZRW+ftH2EpcM7i16+4G912IXBI"
|
|
"HNAGkSfVsFqpk7TqmI2P3cGG/7fckKbAj030Nck0AoSSNsP6tNJ8cCbB1NyyYCZG"
|
|
"3sl1HnY9uje9+P+UBq2eUw7l2zgvQTABrrBqU+2QJ9gxF5cnsIZaiRjaPtvrz5sU"
|
|
"7UTObLrO1Lsb238UR+bMJUszIFFRK9evQm+49AE3jNK/WYPKAcZLkuzwMuoV0XId"
|
|
"A/SC185udP721V5wL0aYDIK1qEAxkAscnlnnyX++x+jzI6l6fjbMiL4PHUW3/1ha"
|
|
"xUvUB7IrQVSqzI9tfr9I4dgUzF7SD4A34KeXFe7ym+MoBqHVi7fF2nb1UKo9ih+/"
|
|
"8OsZzLGjE9Vc2lbJ7C7yljI4f+jXbjwEaAQ+j2Y/SGDuEr8tWwt0dNbmlPkebb4R"
|
|
"WXSjkm8S/uXkOHd8tqky34zYvsTQc7kxujvIMraNndMAdB+nv4r8R+0ldvaTa6Qk"
|
|
"ZjqrY5xa5PVoNCO0dCvxyXgjjxbL451lLeP9uL78hIrZIiIuBKQDfAcT61eoGiPw"
|
|
"xzRz/GRs6jBrS8vIhi+Dhd36nUt/osCH6HloMwPtW906Bis89bOieKZtKhP4P0T4"
|
|
"Ld8xDuB0q2o2RZfomaAlXcFk8xzFCEaFHfmrSBld7X6hsdUQvX7nTXP682vDHs+i"
|
|
"aDWQRvTrh5+SQAlDi0gcbNeImgAu1e44K8kZDab8Am5HlVjkR1Z36aqeMFDidlaU"
|
|
"38gfVuiAuW5xYMmA3Zjt09///////////wKCBAB//////////+SH7VEQtGEaYmMx"
|
|
"RcBuDmiUgScERTPmOgEF31Mdic2RKKUEPMcaAm73yozZ5p0hjZgVhTb5L4obp/Ca"
|
|
"trao4SLyQtq7MS8/Y3omIXTTG/a1hf+uW3oDW/b3HDX9rUTP0tdPkgi+JY/zJJQz"
|
|
"KPZyLZ7hAD5cULHfgsxtJBsOKunNNIsf1H6SZ6/Bsq6R7lHWyw4xeasQQqldz2qU"
|
|
"g7hLSzazhhqnJV5MAni6NgRlDBC+GUgvIxcbZx3xzzuWDAdDAc2TwdF2A9FH2uKu"
|
|
"+DemKWTvFeX7SqwLjBzKpL51SrVyiukTDEx9AogKuUctRVViFtaZi4aCKD0Z1CqQ"
|
|
"1e+OXTJ2fcKCLG33hUV1OKuugwY+2cuHwtNw8mPV+tdGbYSZ649GSnAlErDO53Hp"
|
|
"Ew1pdzX4l/0DbMUEMmw7ATmfZDUyKQ+VjAu9kAZd8IurvTCutjuExGBdbKNxBHEn"
|
|
"0Dpy1Zih7a3+cH6IRyXBaJBUkIQAjTkeCVPD82vEOM0IXt0tk0zhk4w1enEeDUo0"
|
|
"GlsKhe0SwfTlFWomdG3d4W2Cb0d8l0d+Cg/fZVMUPiyjpzXgLszZSyfQSGHREZ3Q"
|
|
"wyit8/aPsJS4Z3Fr19wN7rsQuCQOaANIk+rYLVTJ2nVMRsfu4MN/2+5IU2BHpvoa"
|
|
"5JoBQkkbYf1aaT44E2DqblkwEyNvZLqPOx7dG978f8oDVs8ph3LtnBegmADXWDUp"
|
|
"9sgT7BiLy5PYQy1EjG0fbfXnzYp2omc2XWdqXY3tv4oj82YSpZmQKKiV69ehN9x6"
|
|
"AJvGaV+sweUA4yXJdngZdQrouQ6B+kFr5zc6f3tqrzgXo0wGQVrUIBjIBY5PLPPk"
|
|
"v99j9HmR1L0/G2ZEXweOotv/rC1ipeoD2RWgqlVmR7a/X6Rw7ApmL2kHwBvwU8uK"
|
|
"93lN8ZQDUOrF2+LtO3qoVR7FD9/4dYzmWNGJ6q5tK2T2F3lLGRw/9Gu3HgI0Ah9H"
|
|
"sx+kMHcJX5athbo6a3NKfI823wisulHJN4l/cvIcO75bVJlvxmxfYmg53JjdHeQZ"
|
|
"W0bO6YA6D9PfxX4j9pK7e0m10hIzHVWxzi1yerQaEdo6FfjkvBHHi2XxzrKW8f7c"
|
|
"X35CRWyRERcCUgG+A4n1q9QNEfhjmjn+MjZ1GDWl5eRDF8HC7v1Opb/RYEP0PLQZ"
|
|
"gfat7p0DFZ562dE8UzaVCfwfonwW75iHcDpVtRsiy/RM0BKu4LJ5jmKEI0KO/NWk"
|
|
"DK72v1DY6ohev3Omuf15teGPZ9E0GsgjenXDz8kgBKHFpA42a8RNABdq9xwV5IyG"
|
|
"034BNyPKrHIjqzv01U8YKHE7K0pv5A+rdEBctziwZMBuzHbp7///////////AgEC"
|
|
"-----END X942 DH PARAMETERS-----");
|
|
|
|
config.set("dl", "modp/srp/8192",
|
|
"-----BEGIN DH PARAMETERS-----"
|
|
"MIIECAKCBAEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb"
|
|
"IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft"
|
|
"awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT"
|
|
"mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh"
|
|
"fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq"
|
|
"5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM"
|
|
"fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq"
|
|
"ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqSEI"
|
|
"ARpyPBKnh+bXiHGaEL26WyaZwycYavTiPBqUaDS2FQvaJYPpyirUTOjbu8LbBN6O"
|
|
"+S6O/BQfvsqmKHxZR05rwF2ZspZPoJDDoiM7oYZRW+ftH2EpcM7i16+4G912IXBI"
|
|
"HNAGkSfVsFqpk7TqmI2P3cGG/7fckKbAj030Nck0AoSSNsP6tNJ8cCbB1NyyYCZG"
|
|
"3sl1HnY9uje9+P+UBq2eUw7l2zgvQTABrrBqU+2QJ9gxF5cnsIZaiRjaPtvrz5sU"
|
|
"7UTObLrO1Lsb238UR+bMJUszIFFRK9evQm+49AE3jNK/WYPKAcZLkuzwMuoV0XId"
|
|
"A/SC185udP721V5wL0aYDIK1qEAxkAscnlnnyX++x+jzI6l6fjbMiL4PHUW3/1ha"
|
|
"xUvUB7IrQVSqzI9tfr9I4dgUzF7SD4A34KeXFe7ym+MoBqHVi7fF2nb1UKo9ih+/"
|
|
"8OsZzLGjE9Vc2lbJ7C7yljI4f+jXbjwEaAQ+j2Y/SGDuEr8tWwt0dNbmlPkebb4R"
|
|
"WXSjkm8S/uXkOHd8tqky34zYvsTQc7kxujvIMraNndMAdB+nv4r8R+0ldvaTa6Qk"
|
|
"ZjqrY5xa5PVoNCO0dCvxyXgjjxbL451lLeP9uL78hIrZIiIuBKQDfAcT61eoGiPw"
|
|
"xzRz/GRs6jBrS8vIhi+Dhd36nUt/osCH6HloMwPtW906Bis89bOieKZtKhP4P0T4"
|
|
"Ld8xDuB0q2o2RZfomaAlXcFk8xzFCEaFHfmrSBld7X6hsdUQvX7nTXP682vDHs+i"
|
|
"aDWQRvTrh5+SQAlDi0gcbNeImgAu1e44K8kZDab8Am5HlVjkR1Z36aqeMFDidlaU"
|
|
"38gfVuiAuW5xYMmA3Zjt09///////////wIBEw=="
|
|
"-----END DH PARAMETERS-----");
|
|
|
|
config.set("dl", "dsa/jce/512",
|
|
"-----BEGIN DSA PARAMETERS-----"
|
|
"MIGdAkEA/KaCzo4Syrom78z3EQ5SbbB4sF7ey80etKII864WF64B81uRpH5t9jQT"
|
|
"xeEu0ImbzRMqzVDZkVG9xD7nN1kuFwIVAJYu3cw2nLqOuyYO5rahJtk0bjjFAkEA"
|
|
"3gtU76vylwh+5iPVylWIxkgo70/eT/uuHs0gBndrBbEbgeo83pvDlkwWh8UyW/Q9"
|
|
"fM76DQqGvl3/3dDRFD3NdQ=="
|
|
"-----END DSA PARAMETERS-----");
|
|
|
|
config.set("dl", "dsa/jce/768",
|
|
"-----BEGIN DSA PARAMETERS-----"
|
|
"MIHdAmEA6eZCWZ01XzfJf/01ZxILjiXJzUPpJ7OpZw++xdiQFBki0sOzrSSACTeZ"
|
|
"hp0ehGqrSfqwrSbSzmoiIZ1HC859d31KIfvpwnC1f2BwAvPO+Dk2lM9F7jaIwRqM"
|
|
"VqsSej2vAhUAnNvYTJ8awvOND4D0KrlS5zOL9RECYQDe7p717RUWzn5pXmcrjO5F"
|
|
"5s17NuDmOF+JS6hhY/bz5sbU6KgRRtQBfe/dccvZD6Akdlm4i3zByJT0gmn9Txqs"
|
|
"CjBTjf9rP8ds+xMcnnlltYhYqwpDtVczWRKoqlR/lWg="
|
|
"-----END DSA PARAMETERS-----");
|
|
|
|
config.set("dl", "dsa/jce/1024",
|
|
"-----BEGIN DSA PARAMETERS-----"
|
|
"MIIBHgKBgQD9f1OBHXUSKVLfSpwu7OTn9hG3UjzvRADDHj+AtlEmaUVdQCJR+1k9"
|
|
"jVj6v8X1ujD2y5tVbNeBO4AdNG/yZmC3a5lQpaSfn+gEexAiwk+7qdf+t8Yb+DtX"
|
|
"58aophUPBPuD9tPFHsMCNVQTWhaRMvZ1864rYdcq7/IiAxmd0UgBxwIVAJdgUI8V"
|
|
"IwvMspK5gqLrhAvwWBz1AoGARpYDUS4wJ4zTlHWV2yLuyYJqYyKtyXNE9B10DDJX"
|
|
"JMj577qn1NgD/4xgnc0QDrxb38+tfGpCX66nhuogUOvpg1HqH9of3yTWlHqmuaoj"
|
|
"dmlTgC9NfUqOy6BtGXaKJJH/sW0O+cQ6mbX3FnL/bwoktETQc20E04oaEyLa9s3Y"
|
|
"jJ0="
|
|
"-----END DSA PARAMETERS-----");
|
|
|
|
config.set("dl", "dsa/botan/2048",
|
|
"-----BEGIN DSA PARAMETERS-----"
|
|
"MIICLAKCAQEAkcSKT9+898Aq6V59oSYSK13Shk9Vm4fo50oobVL1m9HeaN/WRdDg"
|
|
"DGDAgAMYkZgDdO61lKUyv9Z7mgnqxLhmOgeRDmjzlGX7cEDSXfE5MuusQ0elMOy6"
|
|
"YchU+biA08DDZgCAWHxFVm2t4mvVo5S+CTtMDyS1r/747GxbPlf7iQJam8FnaZMh"
|
|
"MeFtPJTvyrGNDfBhIDzFPmEDvHLVWUv9QMplOA9EqahR3LB1SV/AM6ilgHGhvXj+"
|
|
"BS9mVVZI60txnSr+i0iA+NrW8VgYuhePiSdMhwvpuW6wjEbEAEDMLv4d+xsYaN0x"
|
|
"nePDSjKmOrbrEiQgmkGWgMx5AtFyjU354QIhAIzX1FD4bwrZTu5M5GmodW0evRBY"
|
|
"JBlD6v+ws1RYXpJNAoIBAA2fXgdhtNvRgz1qsalhoJlsXyIwP3LYTBQPZ8Qx2Uq1"
|
|
"cVvqgaDJjTnOS8941rnryJXTT+idlAkdWEhhXvFfXobxHZb2yWniA936WDVkIKSc"
|
|
"tES1lbkBqTPP4HZ7WU8YoHt/kd7NukRriJkPePL/kfL+fNQ/0uRtGOraH3u2YCxh"
|
|
"f27zpLKE8v2boQo2BC3o+oeiyjZZf+yBFXoUheRAQd8CgwERy4gLvm7UlIFIhvll"
|
|
"zcMTX1zPE4Nyi/ZbgG+WksCxDWxMCcdabKO0ATyxarLBBfa+I66pAA6rIXiYX5cs"
|
|
"mAV+HIbkTnIYaI6krg82NtzKdFydzU5q/7Z8y8E9YTE="
|
|
"-----END DSA PARAMETERS-----");
|
|
|
|
config.set("dl", "dsa/botan/3072",
|
|
"-----BEGIN DSA PARAMETERS-----"
|
|
"MIIDLAKCAYEA5LUIgHWWY1heFCRgyi2d/xMviuTIQN2jomZoiRJP5WOLhOiim3rz"
|
|
"+hIJvmv8S1By7Tsrc4e68/hX9HioAijvNgC3az3Pth0g00RlslBtLK+H3259wM6R"
|
|
"vS0Wekb2rcwxxTHk+cervbkq3fNbCoBsZikqX14X6WTdCZkDczrEKKs12A6m9oW/"
|
|
"uovkBo5UGK5eytno/wc94rY+Tn6tNciptwtb1Hz7iNNztm83kxk5sKtxvVWVgJCG"
|
|
"2gFVM30YWg5Ps2pRmxtiArhZHmACRJzxzTpmOE9tIHOxzXO+ypO68eGmEX0COPIi"
|
|
"rh7X/tGFqJDn9n+rj+uXU8wTSlGD3+h64llfe1wtn7tCJJ/dWVE+HTOWs+sv2GaE"
|
|
"8oWoRI/nV6ApiBxAdguU75Gb35dAw4OJWZ7FGm6btRmo4GhJHpzgovz+PLYNZs8N"
|
|
"+tIKjsaEBIaEphREV1vRck1zUrRKdgB3s71r04XOWwpyUMwL92jagpI4Buuc+7E4"
|
|
"hDcxthggjHWbAiEAs+vTZOxp74zzuvZDt1c0sWM5suSeXN4bWcHp+0DuDFsCggGA"
|
|
"K+0h7vg5ZKIwrom7px2ffDnFL8gim047x+WUTTKdoQ8BDqyee69sAJ/E6ylgcj4r"
|
|
"Vt9GY+TDrIAOkljeL3ZJ0gZ4KJP4Ze/KSY0u7zAHTqXop6smJxKk2UovOwuaku5A"
|
|
"D7OKPMWaXcfkNtXABLIuNQKDgbUck0B+sy1K4P1Cy0XhLQ7O6KJiOO3iCCp7FSIR"
|
|
"PGbO+NdFxs88uUX4TS9N4W1Epx3hmCcOE/A1U8iLjTI60LlIob8hA6lJl5tu0W+1"
|
|
"88lT2Vt8jojKZ9z1pjb7nKOdkkIV96iE7Wx+48ltjZcVQnl0t8Q1EoLhPTdz99KL"
|
|
"RS8QiSoTx1hzKN6kgntrNpsqjcFyrcWD9R8qZZjFSD5bxGewL5HQWcQC0Y4sJoD3"
|
|
"dqoG9JKAoscsF8xC1bbnQMXEsas8UcLtCSviotiwU65Xc9FCXtKwjwbi3VBZLfGk"
|
|
"eMFVkc39EVZP+I/zi3IdQjkv2kcyEtz9jS2IqXagCv/m//tDCjWeZMorNRyiQSOU"
|
|
"-----END DSA PARAMETERS-----");
|
|
|
|
config.set("ec", "secp112r1",
|
|
"-----BEGIN EC PARAMETERS-----"
|
|
"MHQCAQEwGgYHKoZIzj0BAQIPANt8Kr9i415mgHa+rSCLMCAEDtt8Kr9i415mgHa+"
|
|
"rSCIBA5lnvi6BDkW7t6JEXArIgQdBAlIcjmZWl7na1X5wvCYqJzlr4ckwKI+Dg/3"
|
|
"dQACDwDbfCq/YuNedijfrGVhxQIBAQ=="
|
|
"-----END EC PARAMETERS-----");
|
|
|
|
config.set("ec", "secp112r2",
|
|
"-----BEGIN EC PARAMETERS-----"
|
|
"MHMCAQEwGgYHKoZIzj0BAQIPANt8Kr9i415mgHa+rSCLMCAEDmEnwkwF84oKqvZc"
|
|
"DvAsBA5R3vGBXbXtdPzDTIXXCQQdBEujCrXokrThZJ3QkoZDrc1G9YguN0fe826V"
|
|
"bpcCDjbfCq/YuNdZfKEFINBLAgEB"
|
|
"-----END EC PARAMETERS-----");
|
|
|
|
config.set("ec", "secp128r1",
|
|
"-----BEGIN EC PARAMETERS-----"
|
|
"MIGAAgEBMBwGByqGSM49AQECEQD////9////////////////MCQEEP////3/////"
|
|
"//////////wEEOh1ecEQefQ92CSZPCzuXtMEIQQWH/dSi4mbLQwoYHylLFuGz1rI"
|
|
"OVuv6xPALaKS3e16gwIRAP////4AAAAAdaMNG5A4oRUCAQE="
|
|
"-----END EC PARAMETERS-----");
|
|
|
|
config.set("ec", "secp128r2",
|
|
"-----BEGIN EC PARAMETERS-----"
|
|
"MH8CAQEwHAYHKoZIzj0BAQIRAP////3///////////////8wJAQQ1gMZmNGzu/6/"
|
|
"Wcybv/mu4QQQXu78o4DQKRncLGVYu22KXQQhBHtqpdheVymD5vsyp83rwUAntpFq"
|
|
"iU067nEG/oBfw0tEAhA/////f////74AJHIGE7WjAgEE"
|
|
"-----END EC PARAMETERS-----");
|
|
|
|
config.set("ec", "secp160k1",
|
|
"-----BEGIN EC PARAMETERS-----"
|
|
"MIGYAgEBMCAGByqGSM49AQECFQD////////////////////+//+sczAsBBQAAAAA"
|
|
"AAAAAAAAAAAAAAAAAAAAAAQUAAAAAAAAAAAAAAAAAAAAAAAAAAcEKQQ7TDgs43qh"
|
|
"kqQBnnYwNvT13U1+u5OM+TUxj9zta8KChlMXM8PwPE/uAhUBAAAAAAAAAAAAAbj6"
|
|
"Ft+rmsoWtrMCAQE="
|
|
"-----END EC PARAMETERS-----");
|
|
|
|
config.set("ec", "secp160r1",
|
|
"-----BEGIN EC PARAMETERS-----"
|
|
"MIGYAgEBMCAGByqGSM49AQECFQD/////////////////////f////zAsBBT/////"
|
|
"////////////////f////AQUHJe+/FS9eotlrPifgdTUrcVl+kUEKQRKlrVojvVz"
|
|
"KEZkaYlow4u5E8v8giOmKFUxaJR9WdzJEgQjUTd6xfsyAhUBAAAAAAAAAAAAAfTI"
|
|
"+Seu08p1IlcCAQE="
|
|
"-----END EC PARAMETERS-----");
|
|
|
|
config.set("ec", "secp160r2",
|
|
"-----BEGIN EC PARAMETERS-----"
|
|
"MIGYAgEBMCAGByqGSM49AQECFQD////////////////////+//+sczAsBBT/////"
|
|
"///////////////+//+scAQUtOE00/tZ64urVydJBGZNWvUDiLoEKQRS3LA0KToR"
|
|
"fh9P8Rsw9xmdMUTObf6v/vLjMfKW4HH6DfmYLP6n1D8uAhUBAAAAAAAAAAAAADUe"
|
|
"54aoGPOhoWsCAQE="
|
|
"-----END EC PARAMETERS-----");
|
|
|
|
config.set("ec", "secp192k1",
|
|
"-----BEGIN EC PARAMETERS-----"
|
|
"MIGwAgEBMCQGByqGSM49AQECGQD//////////////////////////v//7jcwNAQY"
|
|
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
|
|
"AAMEMQTbT/EOwFfpriawfQKAt/Q0HaXRsergbH2bLy9tnFYop4RBY9AVvoY0QIKq"
|
|
"iNleL50CGQD///////////////4m8vwXD2lGanTe/Y0CAQE="
|
|
"-----END EC PARAMETERS-----");
|
|
|
|
config.set("ec", "secp192r1",
|
|
"-----BEGIN EC PARAMETERS-----"
|
|
"MIGwAgEBMCQGByqGSM49AQECGQD////////////////////+//////////8wNAQY"
|
|
"/////////////////////v/////////8BBhkIQUZ5ZyA5w+n6atyJDBJ/rje7MFG"
|
|
"ubEEMQQYjagOsDCQ9ny/IOtDoYgA9P8K/YL/EBIHGSuV/8jaeGMQEe1rJM3Vc/l3"
|
|
"oR55SBECGQD///////////////+Z3vg2FGvJsbTSKDECAQE="
|
|
"-----END EC PARAMETERS-----");
|
|
|
|
config.set("ec", "secp224k1",
|
|
"-----BEGIN EC PARAMETERS-----"
|
|
"MIHIAgEBMCgGByqGSM49AQECHQD///////////////////////////////7//+Vt"
|
|
"MDwEHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEHAAAAAAAAAAAAAAAAAAA"
|
|
"AAAAAAAAAAAAAAAAAAUEOQShRVszTfCZ3zD8KKFppGfp5HB1qQ9+ZQ62t6Rcfgif"
|
|
"7X+6NEKCyvvW9+MZ98CwvVniykvbVW1hpQIdAQAAAAAAAAAAAAAAAAAB3OjS7GGE"
|
|
"yvCpcXafsfcCAQE="
|
|
"-----END EC PARAMETERS-----");
|
|
|
|
config.set("ec", "secp224r1",
|
|
"-----BEGIN EC PARAMETERS-----"
|
|
"MIHIAgEBMCgGByqGSM49AQECHQD/////////////////////AAAAAAAAAAAAAAAB"
|
|
"MDwEHP////////////////////7///////////////4EHLQFCoUMBLOr9UEyVlBE"
|
|
"sLfXv9i6Jws5QyNV/7QEOQS3Dgy9a7S/fzITkLlKA8HTVsIRIjQygNYRXB0hvTdj"
|
|
"iLX3I/tMIt/mzUN1oFoHR2RE1YGZhQB+NAIdAP//////////////////FqLguPA+"
|
|
"E90pRVxcKj0CAQE="
|
|
"-----END EC PARAMETERS-----");
|
|
|
|
config.set("ec", "secp256k1",
|
|
"-----BEGIN EC PARAMETERS-----"
|
|
"MIHgAgEBMCwGByqGSM49AQECIQD////////////////////////////////////+"
|
|
"///8LzBEBCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQgAAAAAAAA"
|
|
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcEQQR5vmZ++dy7rFWgYpXOhwsHApv8"
|
|
"2y3OKNlZ8oFbFvgXmEg62ncmo8RlXaT7/A4RCKj9F7RIpoVUGZxH0I/7ENS4AiEA"
|
|
"/////////////////////rqu3OavSKA7v9JejNA2QUECAQE="
|
|
"-----END EC PARAMETERS-----");
|
|
|
|
config.set("ec", "secp256r1",
|
|
"-----BEGIN EC PARAMETERS-----"
|
|
"MIHgAgEBMCwGByqGSM49AQECIQD/////AAAAAQAAAAAAAAAAAAAAAP//////////"
|
|
"/////zBEBCD/////AAAAAQAAAAAAAAAAAAAAAP///////////////AQgWsY12Ko6"
|
|
"k+ez671VdpiGvGUdBrDMU7D2O848PifSYEsEQQRrF9Hy4SxCR/i85uVjpEDydwN9"
|
|
"gS3rM6D0oTlF2JjClk/jQuL+Gn+bjufrSnwPnhYrzjNXazFezsu2QGg3v1H1AiEA"
|
|
"/////wAAAAD//////////7zm+q2nF56E87nKwvxjJVECAQE="
|
|
"-----END EC PARAMETERS-----");
|
|
|
|
config.set("ec", "secp384r1",
|
|
"-----BEGIN EC PARAMETERS-----"
|
|
"MIIBQAIBATA8BgcqhkjOPQEBAjEA////////////////////////////////////"
|
|
"//////7/////AAAAAAAAAAD/////MGQEMP//////////////////////////////"
|
|
"///////////+/////wAAAAAAAAAA/////AQwszEvp+I+5+SYjgVr4/gtGRgdnG7+"
|
|
"gUESAxQIj1ATh1rGVjmNii7RnSqFyO3T7CrvBGEEqofKIr6LBTeOscce8yCtdG4d"
|
|
"O2KLp5uYWfdB4IJUKjhVAvJdv1UpbDpUXjhydgq3NhfeSpYmLG9dnpi/kpLcKfj0"
|
|
"Hb0omhR86doxE7XwuMAKYLHOHX6BnXpDHXyQ6g5fAjEA////////////////////"
|
|
"////////////x2NNgfQ3Ld9YGg2ySLCneuzsGWrMxSlzAgEB"
|
|
"-----END EC PARAMETERS-----");
|
|
|
|
config.set("ec", "secp521r1",
|
|
"-----BEGIN EC PARAMETERS-----"
|
|
"MIIBrAIBATBNBgcqhkjOPQEBAkIB////////////////////////////////////"
|
|
"//////////////////////////////////////////////////8wgYgEQgH/////"
|
|
"////////////////////////////////////////////////////////////////"
|
|
"/////////////////ARCAFGVPrlhjhyaH5KaIaC2hUDuotpyW5mzFfO4tImRjvEJ"
|
|
"4VYZOVHsfpN7FlLAvTuxvwc1c9+IPSw08e9FH9RrUD8ABIGFBADGhY4GtwQE6c2e"
|
|
"PstmI5W0QpxkgTkFP7Uh+CivYGtNPbqhS1537+dZKP4dwSei/6jeM0izwYVqQpv5"
|
|
"fn4xwuW9ZgEYOSlqeJo7wARcil+0LH0b2Zj1RElXm0RoF6+9Fyc+ZiyX7nKZXvQm"
|
|
"QMVQuQE/rQdhNTxwhqJywkCIvpR2n9FmUAJCAf//////////////////////////"
|
|
"////////////////+lGGh4O/L5Zrf8wBSPcJpdA7tcm4iZxHrrtvtx6ROGQJAgEB"
|
|
"-----END EC PARAMETERS-----");
|
|
|
|
config.set("ec", "1.3.6.1.4.1.8301.3.1.2.9.0.38",
|
|
"-----BEGIN EC PARAMETERS-----"
|
|
"MIIBrAIBATBNBgcqhkjOPQEBAkIB////////////////////////////////////"
|
|
"//////////////////////////////////////////////////8wgYgEQgH/////"
|
|
"////////////////////////////////////////////////////////////////"
|
|
"/////////////////ARCAFGVPrlhjhyaH5KaIaC2hUDuotpyW5mzFfO4tImRjvEJ"
|
|
"4VYZOVHsfpN7FlLAvTuxvwc1c9+IPSw08e9FH9RrUD8ABIGFBADGhY4GtwQE6c2e"
|
|
"PstmI5W0QpxkgTkFP7Uh+CivYGtNPbqhS1537+dZKP4dwSei/6jeM0izwYVqQpv5"
|
|
"fn4xwuW9ZgEYOSlqeJo7wARcil+0LH0b2Zj1RElXm0RoF6+9Fyc+ZiyX7nKZXvQm"
|
|
"QMVQuQE/rQdhNTxwhqJywkCIvpR2n9FmUAJCAf//////////////////////////"
|
|
"////////////////+lGGh4O/L5Zrf8wBSPcJpdA7tcm4iZxHrrtvtx6ROGQJAgEB"
|
|
"-----END EC PARAMETERS-----");
|
|
|
|
config.set("ec", "brainpool160r1",
|
|
"-----BEGIN EC PARAMETERS-----"
|
|
"MIGYAgEBMCAGByqGSM49AQECFQDpXkpfc3BZ3GDfx62Vs9gTlRViDzAsBBQ0Dnvi"
|
|
"ooDrdOK+YbradF2X6PfDAAQUHliahZVCNBITT6otveyVyNhnXlgEKQS+1a8W6j9q"
|
|
"T2KTjEYx61r3vbzbwxZny0d6Go7DOPlHQWacl2MW2mMhAhUA6V5KX3NwWdxg31mR"
|
|
"1FApQJ5g/AkCAQE="
|
|
"-----END EC PARAMETERS-----");
|
|
|
|
config.set("ec", "brainpool192r1",
|
|
"-----BEGIN EC PARAMETERS-----"
|
|
"MIGwAgEBMCQGByqGSM49AQECGQDDAvQdkyo2zaejRjCT0Y23j85HbeGoYpcwNAQY"
|
|
"apEXQHax4OGcOcAx/oaFwcrgQOXGmijvBBhGmijvfCjMo9xyHQRPRJa8yn70FG+/"
|
|
"JckEMQTAoGR+qrakh1OwM8VssPCQCi9cSFM3X9YUtpCGar1buItfSCjBSQAC5nc/"
|
|
"ovopm48CGQDDAvQdkyo2zaejRi+enpFrW+jxAprErMECAQE="
|
|
"-----END EC PARAMETERS-----");
|
|
|
|
config.set("ec", "brainpool224r1",
|
|
"-----BEGIN EC PARAMETERS-----"
|
|
"MIHIAgEBMCgGByqGSM49AQECHQDXwTSqJkNmhioYMCV10deHsJ8HV5faifV+yMD/"
|
|
"MDwEHGil5iypzmwcKZgDpsFTC1FOGCrYsAQqWcrSn0MEHCWA9jzP5EE4hwcTsakj"
|
|
"aeM+ITXSZtuzcjhsQAsEOQQNkCmtLH5c9DQII7KofcaMnkzjF0webv3uEsB9WKpW"
|
|
"93LAcm8kxrieTs2sJDVLnpnKo/bTdhQCzQIdANfBNKomQ2aGKhgwJXXQ+5jRFrxL"
|
|
"bd68o6Wnk58CAQE="
|
|
"-----END EC PARAMETERS-----");
|
|
|
|
config.set("ec", "brainpool256r1",
|
|
"-----BEGIN EC PARAMETERS-----"
|
|
"MIHgAgEBMCwGByqGSM49AQECIQCp+1fboe6pvD5mCpCdg41ybjv2I9UmICggE0gd"
|
|
"H25TdzBEBCB9Wgl1/CwwV+72dTBBev/n+4BVwSbcXGzpSktE8zC12QQgJtxcbOlK"
|
|
"S0TzMLXZu9d8v5WEFilc9+HOa8zcGP+MB7YEQQSL0q65y35XyyxLSC/8gbevud4n"
|
|
"4eO9I8I6RFO9ms4yYlR++DXD2sT9l/hGGhRhHcnCd0UTLe2OVFwdVMcvBGmXAiEA"
|
|
"qftX26Huqbw+ZgqQnYONcYw5eqO1Yab3kB4OgpdIVqcCAQE="
|
|
"-----END EC PARAMETERS-----");
|
|
|
|
config.set("ec", "brainpool320r1",
|
|
"-----BEGIN EC PARAMETERS-----"
|
|
"MIIBEAIBATA0BgcqhkjOPQEBAikA015HIDa8T7fhPHhe0gHgZfmPz6b29A3vT5K5"
|
|
"7HiT7Cj81BKx8bMuJzBUBCg+4wtWj7qw+IPM69RtPzu4oqc1E/XredpmGQ6whf+p"
|
|
"9JLzdal9hg60BChSCIOUnf28QtOtGYZAaIpv4T9BNJVUtJrMMdzNiEU5gW9etKyP"
|
|
"sfGmBFEEQ71+mvtT2LhSibzEjuW/5vIBN9EKCH6254ceKhClmccQr40NOeIGERT9"
|
|
"0FVF7BzIq0CTJH93J14HQ//tEXGC6qnHeHeqrGrH01JF0WkujuECKQDTXkcgNrxP"
|
|
"t+E8eF7SAeBl+Y/PpbaPEqMtSC7H7oZY6YaRVVtExZMRAgEB"
|
|
"-----END EC PARAMETERS-----");
|
|
|
|
config.set("ec", "brainpool384r1",
|
|
"-----BEGIN EC PARAMETERS-----"
|
|
"MIIBQAIBATA8BgcqhkjOPQEBAjEAjLkegqM4bSgPXW9+UOZB3xUvcQntVFa0ErHa"
|
|
"GX+3ESOs06cpkB0acYdHABMxB+xTMGQEMHvDgsY9jBUMPHIICs4Fr6DCvqKOT7In"
|
|
"hxORZe+6kfkPiqWBSlA61OsEqMfdIs4oJgQwBKjH3SLOKCaLObVUFvBEfC+3feEH"
|
|
"3NKmLogOpT7rYtV8tDkCldvJlDq3hpb6UEwRBGEEHRxk8GjPRf+ipjqBt8E/a4hH"
|
|
"o+d+8U/j23/K/gy9EOjoJuA0NtZGqu+HsuJH1K8eir4ddSD5wqRcseuOlc/VUmK3"
|
|
"Cyn+7Fhk4ZwFT/mRKSgORkYhd5GBEUKCA0EmPFMVAjEAjLkegqM4bSgPXW9+UOZB"
|
|
"3xUvcQntVFazHxZubKwEJafPOrava3/DEDuIMgLpBGVlAgEB"
|
|
"-----END EC PARAMETERS-----");
|
|
|
|
config.set("ec", "brainpool512r1",
|
|
"-----BEGIN EC PARAMETERS-----"
|
|
"MIIBogIBATBMBgcqhkjOPQEBAkEAqt2duNvpxIs/1OauM8n8B8swjbOzydIO1mOc"
|
|
"ynAzCHF9TZsAm8ZoQq7NoSrmo4DmKIH/Ly2CxoUoqmBWWDpI8zCBhARAeDCjMYtg"
|
|
"O4niMnFFrCNMxZTL3Y09+RYQqDRByuqYY7wt7V1aqCU6oQou8cmLmsi1fxEXpyvy"
|
|
"x7nnwaxNd/yUygRAPfkWEKg0QcrqmGO8Le1dWqglOqEKLvHJi5rItX8RF6cr8se5"
|
|
"58GsTXf8lMrcCD5nmEBQt1665d0oCb1jgBb3IwSBgQSBruS92C7ZZFohMi6cTGqT"
|
|
"he2fcLXZFsG0O2Lu9NAJjv87H3ji0NSNUNFoe5O5fV98bVBHQGpeaIs1Igm8ufgi"
|
|
"fd44XVZjMuzA6r+pz3gi/fIJ9wAkpXsaoADFW4gfgRGy3N5JSl9IXlvKS9iKJ2Ou"
|
|
"0corL6jwVAZ4zR4POtgIkgJBAKrdnbjb6cSLP9TmrjPJ/AfLMI2zs8nSDtZjnMpw"
|
|
"MwhwVT5cQUypJhlBhmEZf6wQRx2x04EIXdrdtYeWgpypAGkCAQE="
|
|
"-----END EC PARAMETERS-----");
|
|
|
|
config.set("ec", "x962_p192v2",
|
|
"-----BEGIN EC PARAMETERS-----"
|
|
"MIGwAgEBMCQGByqGSM49AQECGQD////////////////////+//////////8wNAQY"
|
|
"/////////////////////v/////////8BBjMItbfuVxrJeScDWNkpOWYDDk6ohZo"
|
|
"2VMEMQTuorrn4Ul4QvLed2nP6cmJwHKtaW9IA0pldNEdabbsemcruCoIPfLysIR9"
|
|
"6XCy3hUCGQD///////////////5fsack3IBBhkjY3TECAQE="
|
|
"-----END EC PARAMETERS-----");
|
|
|
|
config.set("ec", "x962_p192v3",
|
|
"-----BEGIN EC PARAMETERS-----"
|
|
"MIGwAgEBMCQGByqGSM49AQECGQD////////////////////+//////////8wNAQY"
|
|
"/////////////////////v/////////8BBgiEj3COVoFyqdCPa7MyUdgp9RiJWvV"
|
|
"aRYEMQR9KXeBAMZaHaF4NxZYjc4ri0rujiKPGJY4qQ8iY3M3M0tJ3LZqbcj5l4rK"
|
|
"dkipQ7ACGQD///////////////96YtAxyD9ClPZA7BMCAQE="
|
|
"-----END EC PARAMETERS-----");
|
|
|
|
config.set("ec", "x962_p239v1",
|
|
"-----BEGIN EC PARAMETERS-----"
|
|
"MIHSAgEBMCkGByqGSM49AQECHn///////////////3///////4AAAAAAAH//////"
|
|
"/zBABB5///////////////9///////+AAAAAAAB///////wEHmsBbDvc8YlB0NZU"
|
|
"khR1ynGp2y+yfR03eWGFwpQsCgQ9BA/6ljzcqIFszDO4ZCvt+QXD01hXPT8n+707"
|
|
"PLmqr33r6OTpCl2ubkBUylMLoEZUs2gYziJrOfzLewLxrgIef///////////////"
|
|
"f///nl6an12QcfvRUiaIkJ0LAgEB"
|
|
"-----END EC PARAMETERS-----");
|
|
|
|
config.set("ec", "x962_p239v2",
|
|
"-----BEGIN EC PARAMETERS-----"
|
|
"MIHSAgEBMCkGByqGSM49AQECHn///////////////3///////4AAAAAAAH//////"
|
|
"/zBABB5///////////////9///////+AAAAAAAB///////wEHmF/q2gyV2y7/tUN"
|
|
"mfAknD/uWLlLoAOMeuhMjIMvLAQ9BDivCdmHJ3BRIMkhu16eJilqPNzy81dXoOr9"
|
|
"h7gw51sBJeTb6g7HIG2g/AHZsIEyn7VV3m70YCN9/4vkugIef///////////////"
|
|
"gAAAz6foWUN31BTAOCG8WCBjAgEB"
|
|
"-----END EC PARAMETERS-----");
|
|
|
|
config.set("ec", "x962_p239v3",
|
|
"-----BEGIN EC PARAMETERS-----"
|
|
"MIHSAgEBMCkGByqGSM49AQECHn///////////////3///////4AAAAAAAH//////"
|
|
"/zBABB5///////////////9///////+AAAAAAAB///////wEHiVXBfoqMGZUsfTL"
|
|
"A9anUKMMJQEC1JiHF9m6FattPgQ9BGdoro4Yu5LPzwBclJqixtlIU9DmYLv4VLHJ"
|
|
"UF/pWhYH5omPOQwGvB1VK60ibztvz+SLboGEma8Y4+1s8wIef///////////////"
|
|
"f///l13rQbOmBXw8QyFGUmVRAgEB"
|
|
"-----END EC PARAMETERS-----");
|
|
|
|
config.set("ec", "gost_256A",
|
|
"-----BEGIN EC PARAMETERS-----"
|
|
"MIHgAgEBMCwGByqGSM49AQECIQD/////////////////////////////////////"
|
|
"///9lzBEBCD////////////////////////////////////////9lAQgAAAAAAAA"
|
|
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKYEQQQAAAAAAAAAAAAAAAAAAAAAAAAA"
|
|
"AAAAAAAAAAAAAAAAAY2R5HHgmJzaJ99QWkU/K3Y1KU8t3yPjsSKsyZyenx4UAiEA"
|
|
"/////////////////////2xhEHCZWtEARYQbCbdhuJMCAQE="
|
|
"-----END EC PARAMETERS-----");
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Set the default policy
|
|
*/
|
|
void Library_State::load_default_config()
|
|
{
|
|
set_default_aliases(*this);
|
|
set_default_oids(*this);
|
|
set_default_dl_groups(*this);
|
|
}
|
|
|
|
}
|
|
/*
|
|
* SCAN Name Abstraction
|
|
* (C) 2008-2009 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
#include <stdexcept>
|
|
|
|
namespace Botan {
|
|
|
|
namespace {
|
|
|
|
std::string make_arg(
|
|
const std::vector<std::pair<size_t, std::string> >& name, size_t start)
|
|
{
|
|
std::string output = name[start].second;
|
|
size_t level = name[start].first;
|
|
|
|
size_t paren_depth = 0;
|
|
|
|
for(size_t i = start + 1; i != name.size(); ++i)
|
|
{
|
|
if(name[i].first <= name[start].first)
|
|
break;
|
|
|
|
if(name[i].first > level)
|
|
{
|
|
output += '(' + name[i].second;
|
|
++paren_depth;
|
|
}
|
|
else if(name[i].first < level)
|
|
{
|
|
output += ")," + name[i].second;
|
|
--paren_depth;
|
|
}
|
|
else
|
|
{
|
|
if(output[output.size() - 1] != '(')
|
|
output += ",";
|
|
output += name[i].second;
|
|
}
|
|
|
|
level = name[i].first;
|
|
}
|
|
|
|
for(size_t i = 0; i != paren_depth; ++i)
|
|
output += ')';
|
|
|
|
return output;
|
|
}
|
|
|
|
std::pair<size_t, std::string>
|
|
deref_aliases(const std::pair<size_t, std::string>& in)
|
|
{
|
|
return std::make_pair(in.first,
|
|
global_state().deref_alias(in.second));
|
|
}
|
|
|
|
}
|
|
|
|
SCAN_Name::SCAN_Name(std::string algo_spec)
|
|
{
|
|
orig_algo_spec = algo_spec;
|
|
|
|
std::vector<std::pair<size_t, std::string> > name;
|
|
size_t level = 0;
|
|
std::pair<size_t, std::string> accum = std::make_pair(level, "");
|
|
|
|
std::string decoding_error = "Bad SCAN name '" + algo_spec + "': ";
|
|
|
|
algo_spec = global_state().deref_alias(algo_spec);
|
|
|
|
for(size_t i = 0; i != algo_spec.size(); ++i)
|
|
{
|
|
char c = algo_spec[i];
|
|
|
|
if(c == '/' || c == ',' || c == '(' || c == ')')
|
|
{
|
|
if(c == '(')
|
|
++level;
|
|
else if(c == ')')
|
|
{
|
|
if(level == 0)
|
|
throw Decoding_Error(decoding_error + "Mismatched parens");
|
|
--level;
|
|
}
|
|
|
|
if(c == '/' && level > 0)
|
|
accum.second.push_back(c);
|
|
else
|
|
{
|
|
if(accum.second != "")
|
|
name.push_back(deref_aliases(accum));
|
|
accum = std::make_pair(level, "");
|
|
}
|
|
}
|
|
else
|
|
accum.second.push_back(c);
|
|
}
|
|
|
|
if(accum.second != "")
|
|
name.push_back(deref_aliases(accum));
|
|
|
|
if(level != 0)
|
|
throw Decoding_Error(decoding_error + "Missing close paren");
|
|
|
|
if(name.size() == 0)
|
|
throw Decoding_Error(decoding_error + "Empty name");
|
|
|
|
alg_name = name[0].second;
|
|
|
|
bool in_modes = false;
|
|
|
|
for(size_t i = 1; i != name.size(); ++i)
|
|
{
|
|
if(name[i].first == 0)
|
|
{
|
|
mode_info.push_back(make_arg(name, i));
|
|
in_modes = true;
|
|
}
|
|
else if(name[i].first == 1 && !in_modes)
|
|
args.push_back(make_arg(name, i));
|
|
}
|
|
}
|
|
|
|
std::string SCAN_Name::algo_name_and_args() const
|
|
{
|
|
std::string out;
|
|
|
|
out = algo_name();
|
|
|
|
if(arg_count())
|
|
{
|
|
out += '(';
|
|
for(size_t i = 0; i != arg_count(); ++i)
|
|
{
|
|
out += arg(i);
|
|
if(i != arg_count() - 1)
|
|
out += ',';
|
|
}
|
|
out += ')';
|
|
|
|
}
|
|
|
|
return out;
|
|
}
|
|
|
|
std::string SCAN_Name::arg(size_t i) const
|
|
{
|
|
if(i >= arg_count())
|
|
throw std::range_error("SCAN_Name::argument - i out of range");
|
|
return args[i];
|
|
}
|
|
|
|
std::string SCAN_Name::arg(size_t i, const std::string& def_value) const
|
|
{
|
|
if(i >= arg_count())
|
|
return def_value;
|
|
return args[i];
|
|
}
|
|
|
|
size_t SCAN_Name::arg_as_integer(size_t i, size_t def_value) const
|
|
{
|
|
if(i >= arg_count())
|
|
return def_value;
|
|
return to_u32bit(args[i]);
|
|
}
|
|
|
|
}
|
|
/*
|
|
* CBC-MAC
|
|
* (C) 1999-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
#include <algorithm>
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* Update an CBC-MAC Calculation
|
|
*/
|
|
void CBC_MAC::add_data(const byte input[], size_t length)
|
|
{
|
|
size_t xored = std::min(output_length() - position, length);
|
|
xor_buf(&state[position], input, xored);
|
|
position += xored;
|
|
|
|
if(position < output_length())
|
|
return;
|
|
|
|
e->encrypt(state);
|
|
input += xored;
|
|
length -= xored;
|
|
while(length >= output_length())
|
|
{
|
|
xor_buf(state, input, output_length());
|
|
e->encrypt(state);
|
|
input += output_length();
|
|
length -= output_length();
|
|
}
|
|
|
|
xor_buf(state, input, length);
|
|
position = length;
|
|
}
|
|
|
|
/*
|
|
* Finalize an CBC-MAC Calculation
|
|
*/
|
|
void CBC_MAC::final_result(byte mac[])
|
|
{
|
|
if(position)
|
|
e->encrypt(state);
|
|
|
|
copy_mem(mac, &state[0], state.size());
|
|
zeroise(state);
|
|
position = 0;
|
|
}
|
|
|
|
/*
|
|
* CBC-MAC Key Schedule
|
|
*/
|
|
void CBC_MAC::key_schedule(const byte key[], size_t length)
|
|
{
|
|
e->set_key(key, length);
|
|
}
|
|
|
|
/*
|
|
* Clear memory of sensitive data
|
|
*/
|
|
void CBC_MAC::clear()
|
|
{
|
|
e->clear();
|
|
zeroise(state);
|
|
position = 0;
|
|
}
|
|
|
|
/*
|
|
* Return the name of this type
|
|
*/
|
|
std::string CBC_MAC::name() const
|
|
{
|
|
return "CBC-MAC(" + e->name() + ")";
|
|
}
|
|
|
|
/*
|
|
* Return a clone of this object
|
|
*/
|
|
MessageAuthenticationCode* CBC_MAC::clone() const
|
|
{
|
|
return new CBC_MAC(e->clone());
|
|
}
|
|
|
|
/*
|
|
* CBC-MAC Constructor
|
|
*/
|
|
CBC_MAC::CBC_MAC(BlockCipher* e_in) :
|
|
e(e_in), state(e->block_size())
|
|
{
|
|
position = 0;
|
|
}
|
|
|
|
/*
|
|
* CBC-MAC Destructor
|
|
*/
|
|
CBC_MAC::~CBC_MAC()
|
|
{
|
|
delete e;
|
|
}
|
|
|
|
}
|
|
/*
|
|
* CMAC
|
|
* (C) 1999-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* Perform CMAC's multiplication in GF(2^n)
|
|
*/
|
|
SecureVector<byte> CMAC::poly_double(const MemoryRegion<byte>& in,
|
|
byte polynomial)
|
|
{
|
|
const byte poly_xor = (in[0] & 0x80) ? polynomial : 0;
|
|
|
|
SecureVector<byte> out = in;
|
|
|
|
byte carry = 0;
|
|
for(size_t i = out.size(); i != 0; --i)
|
|
{
|
|
byte temp = out[i-1];
|
|
out[i-1] = (temp << 1) | carry;
|
|
carry = (temp >> 7);
|
|
}
|
|
|
|
out[out.size()-1] ^= poly_xor;
|
|
|
|
return out;
|
|
}
|
|
|
|
/*
|
|
* Update an CMAC Calculation
|
|
*/
|
|
void CMAC::add_data(const byte input[], size_t length)
|
|
{
|
|
buffer.copy(position, input, length);
|
|
if(position + length > output_length())
|
|
{
|
|
xor_buf(state, buffer, output_length());
|
|
e->encrypt(state);
|
|
input += (output_length() - position);
|
|
length -= (output_length() - position);
|
|
while(length > output_length())
|
|
{
|
|
xor_buf(state, input, output_length());
|
|
e->encrypt(state);
|
|
input += output_length();
|
|
length -= output_length();
|
|
}
|
|
buffer.copy(input, length);
|
|
position = 0;
|
|
}
|
|
position += length;
|
|
}
|
|
|
|
/*
|
|
* Finalize an CMAC Calculation
|
|
*/
|
|
void CMAC::final_result(byte mac[])
|
|
{
|
|
xor_buf(state, buffer, position);
|
|
|
|
if(position == output_length())
|
|
{
|
|
xor_buf(state, B, output_length());
|
|
}
|
|
else
|
|
{
|
|
state[position] ^= 0x80;
|
|
xor_buf(state, P, output_length());
|
|
}
|
|
|
|
e->encrypt(state);
|
|
|
|
for(size_t i = 0; i != output_length(); ++i)
|
|
mac[i] = state[i];
|
|
|
|
zeroise(state);
|
|
zeroise(buffer);
|
|
position = 0;
|
|
}
|
|
|
|
/*
|
|
* CMAC Key Schedule
|
|
*/
|
|
void CMAC::key_schedule(const byte key[], size_t length)
|
|
{
|
|
clear();
|
|
e->set_key(key, length);
|
|
e->encrypt(B);
|
|
B = poly_double(B, polynomial);
|
|
P = poly_double(B, polynomial);
|
|
}
|
|
|
|
/*
|
|
* Clear memory of sensitive data
|
|
*/
|
|
void CMAC::clear()
|
|
{
|
|
e->clear();
|
|
zeroise(state);
|
|
zeroise(buffer);
|
|
zeroise(B);
|
|
zeroise(P);
|
|
position = 0;
|
|
}
|
|
|
|
/*
|
|
* Return the name of this type
|
|
*/
|
|
std::string CMAC::name() const
|
|
{
|
|
return "CMAC(" + e->name() + ")";
|
|
}
|
|
|
|
/*
|
|
* Return a clone of this object
|
|
*/
|
|
MessageAuthenticationCode* CMAC::clone() const
|
|
{
|
|
return new CMAC(e->clone());
|
|
}
|
|
|
|
/*
|
|
* CMAC Constructor
|
|
*/
|
|
CMAC::CMAC(BlockCipher* e_in) : e(e_in)
|
|
{
|
|
if(e->block_size() == 16)
|
|
polynomial = 0x87;
|
|
else if(e->block_size() == 8)
|
|
polynomial = 0x1B;
|
|
else
|
|
throw Invalid_Argument("CMAC cannot use the cipher " + e->name());
|
|
|
|
state.resize(output_length());
|
|
buffer.resize(output_length());
|
|
B.resize(output_length());
|
|
P.resize(output_length());
|
|
position = 0;
|
|
}
|
|
|
|
/*
|
|
* CMAC Destructor
|
|
*/
|
|
CMAC::~CMAC()
|
|
{
|
|
delete e;
|
|
}
|
|
|
|
}
|
|
/*
|
|
* HMAC
|
|
* (C) 1999-2007 Jack Lloyd
|
|
* 2007 Yves Jerschow
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* Update a HMAC Calculation
|
|
*/
|
|
void HMAC::add_data(const byte input[], size_t length)
|
|
{
|
|
hash->update(input, length);
|
|
}
|
|
|
|
/*
|
|
* Finalize a HMAC Calculation
|
|
*/
|
|
void HMAC::final_result(byte mac[])
|
|
{
|
|
hash->final(mac);
|
|
hash->update(o_key);
|
|
hash->update(mac, output_length());
|
|
hash->final(mac);
|
|
hash->update(i_key);
|
|
}
|
|
|
|
/*
|
|
* HMAC Key Schedule
|
|
*/
|
|
void HMAC::key_schedule(const byte key[], size_t length)
|
|
{
|
|
hash->clear();
|
|
std::fill(i_key.begin(), i_key.end(), 0x36);
|
|
std::fill(o_key.begin(), o_key.end(), 0x5C);
|
|
|
|
if(length > hash->hash_block_size())
|
|
{
|
|
SecureVector<byte> hmac_key = hash->process(key, length);
|
|
xor_buf(i_key, hmac_key, hmac_key.size());
|
|
xor_buf(o_key, hmac_key, hmac_key.size());
|
|
}
|
|
else
|
|
{
|
|
xor_buf(i_key, key, length);
|
|
xor_buf(o_key, key, length);
|
|
}
|
|
|
|
hash->update(i_key);
|
|
}
|
|
|
|
/*
|
|
* Clear memory of sensitive data
|
|
*/
|
|
void HMAC::clear()
|
|
{
|
|
hash->clear();
|
|
zeroise(i_key);
|
|
zeroise(o_key);
|
|
}
|
|
|
|
/*
|
|
* Return the name of this type
|
|
*/
|
|
std::string HMAC::name() const
|
|
{
|
|
return "HMAC(" + hash->name() + ")";
|
|
}
|
|
|
|
/*
|
|
* Return a clone of this object
|
|
*/
|
|
MessageAuthenticationCode* HMAC::clone() const
|
|
{
|
|
return new HMAC(hash->clone());
|
|
}
|
|
|
|
/*
|
|
* HMAC Constructor
|
|
*/
|
|
HMAC::HMAC(HashFunction* hash_in) : hash(hash_in)
|
|
{
|
|
if(hash->hash_block_size() == 0)
|
|
throw Invalid_Argument("HMAC cannot be used with " + hash->name());
|
|
|
|
i_key.resize(hash->hash_block_size());
|
|
o_key.resize(hash->hash_block_size());
|
|
}
|
|
|
|
}
|
|
/*
|
|
* Message Authentication Code base class
|
|
* (C) 1999-2008 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* Default (deterministic) MAC verification operation
|
|
*/
|
|
bool MessageAuthenticationCode::verify_mac(const byte mac[], size_t length)
|
|
{
|
|
SecureVector<byte> our_mac = final();
|
|
|
|
if(our_mac.size() != length)
|
|
return false;
|
|
|
|
return same_mem(&our_mac[0], &mac[0], length);
|
|
}
|
|
|
|
}
|
|
/*
|
|
* SSL3-MAC
|
|
* (C) 1999-2004 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* Update a SSL3-MAC Calculation
|
|
*/
|
|
void SSL3_MAC::add_data(const byte input[], size_t length)
|
|
{
|
|
hash->update(input, length);
|
|
}
|
|
|
|
/*
|
|
* Finalize a SSL3-MAC Calculation
|
|
*/
|
|
void SSL3_MAC::final_result(byte mac[])
|
|
{
|
|
hash->final(mac);
|
|
hash->update(o_key);
|
|
hash->update(mac, output_length());
|
|
hash->final(mac);
|
|
hash->update(i_key);
|
|
}
|
|
|
|
/*
|
|
* SSL3-MAC Key Schedule
|
|
*/
|
|
void SSL3_MAC::key_schedule(const byte key[], size_t length)
|
|
{
|
|
hash->clear();
|
|
std::fill(i_key.begin(), i_key.end(), 0x36);
|
|
std::fill(o_key.begin(), o_key.end(), 0x5C);
|
|
|
|
i_key.copy(key, length);
|
|
o_key.copy(key, length);
|
|
hash->update(i_key);
|
|
}
|
|
|
|
/*
|
|
* Clear memory of sensitive data
|
|
*/
|
|
void SSL3_MAC::clear()
|
|
{
|
|
hash->clear();
|
|
zeroise(i_key);
|
|
zeroise(o_key);
|
|
}
|
|
|
|
/*
|
|
* Return the name of this type
|
|
*/
|
|
std::string SSL3_MAC::name() const
|
|
{
|
|
return "SSL3-MAC(" + hash->name() + ")";
|
|
}
|
|
|
|
/*
|
|
* Return a clone of this object
|
|
*/
|
|
MessageAuthenticationCode* SSL3_MAC::clone() const
|
|
{
|
|
return new SSL3_MAC(hash->clone());
|
|
}
|
|
|
|
/*
|
|
* SSL3-MAC Constructor
|
|
*/
|
|
SSL3_MAC::SSL3_MAC(HashFunction* hash_in) : hash(hash_in)
|
|
{
|
|
if(hash->hash_block_size() == 0)
|
|
throw Invalid_Argument("SSL3-MAC cannot be used with " + hash->name());
|
|
|
|
// Quirk to deal with specification bug
|
|
const size_t INNER_HASH_LENGTH =
|
|
(hash->name() == "SHA-160") ? 60 : hash->hash_block_size();
|
|
|
|
i_key.resize(INNER_HASH_LENGTH);
|
|
o_key.resize(INNER_HASH_LENGTH);
|
|
}
|
|
|
|
}
|
|
/*
|
|
* ANSI X9.19 MAC
|
|
* (C) 1999-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
#include <algorithm>
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* Update an ANSI X9.19 MAC Calculation
|
|
*/
|
|
void ANSI_X919_MAC::add_data(const byte input[], size_t length)
|
|
{
|
|
size_t xored = std::min(8 - position, length);
|
|
xor_buf(&state[position], input, xored);
|
|
position += xored;
|
|
|
|
if(position < 8) return;
|
|
|
|
e->encrypt(state);
|
|
input += xored;
|
|
length -= xored;
|
|
while(length >= 8)
|
|
{
|
|
xor_buf(state, input, 8);
|
|
e->encrypt(state);
|
|
input += 8;
|
|
length -= 8;
|
|
}
|
|
|
|
xor_buf(state, input, length);
|
|
position = length;
|
|
}
|
|
|
|
/*
|
|
* Finalize an ANSI X9.19 MAC Calculation
|
|
*/
|
|
void ANSI_X919_MAC::final_result(byte mac[])
|
|
{
|
|
if(position)
|
|
e->encrypt(state);
|
|
d->decrypt(state, mac);
|
|
e->encrypt(mac);
|
|
zeroise(state);
|
|
position = 0;
|
|
}
|
|
|
|
/*
|
|
* ANSI X9.19 MAC Key Schedule
|
|
*/
|
|
void ANSI_X919_MAC::key_schedule(const byte key[], size_t length)
|
|
{
|
|
e->set_key(key, 8);
|
|
if(length == 8) d->set_key(key, 8);
|
|
else d->set_key(key + 8, 8);
|
|
}
|
|
|
|
/*
|
|
* Clear memory of sensitive data
|
|
*/
|
|
void ANSI_X919_MAC::clear()
|
|
{
|
|
e->clear();
|
|
d->clear();
|
|
zeroise(state);
|
|
position = 0;
|
|
}
|
|
|
|
std::string ANSI_X919_MAC::name() const
|
|
{
|
|
return "X9.19-MAC";
|
|
}
|
|
|
|
MessageAuthenticationCode* ANSI_X919_MAC::clone() const
|
|
{
|
|
return new ANSI_X919_MAC(e->clone());
|
|
}
|
|
|
|
/*
|
|
* ANSI X9.19 MAC Constructor
|
|
*/
|
|
ANSI_X919_MAC::ANSI_X919_MAC(BlockCipher* e_in) :
|
|
e(e_in), d(e->clone()), state(e->block_size()), position(0)
|
|
{
|
|
if(e->name() != "DES")
|
|
throw Invalid_Argument("ANSI X9.19 MAC only supports DES");
|
|
}
|
|
|
|
/*
|
|
* ANSI X9.19 MAC Destructor
|
|
le*/
|
|
ANSI_X919_MAC::~ANSI_X919_MAC()
|
|
{
|
|
delete e;
|
|
delete d;
|
|
}
|
|
|
|
}
|
|
/*
|
|
* BigInt Encoding/Decoding
|
|
* (C) 1999-2010 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* Encode a BigInt
|
|
*/
|
|
void BigInt::encode(byte output[], const BigInt& n, Base base)
|
|
{
|
|
if(base == Binary)
|
|
n.binary_encode(output);
|
|
else if(base == Hexadecimal)
|
|
{
|
|
SecureVector<byte> binary(n.encoded_size(Binary));
|
|
n.binary_encode(&binary[0]);
|
|
|
|
hex_encode(reinterpret_cast<char*>(output),
|
|
&binary[0], binary.size());
|
|
}
|
|
else if(base == Octal)
|
|
{
|
|
BigInt copy = n;
|
|
const size_t output_size = n.encoded_size(Octal);
|
|
for(size_t j = 0; j != output_size; ++j)
|
|
{
|
|
output[output_size - 1 - j] =
|
|
Charset::digit2char(static_cast<byte>(copy % 8));
|
|
|
|
copy /= 8;
|
|
}
|
|
}
|
|
else if(base == Decimal)
|
|
{
|
|
BigInt copy = n;
|
|
BigInt remainder;
|
|
copy.set_sign(Positive);
|
|
const size_t output_size = n.encoded_size(Decimal);
|
|
for(size_t j = 0; j != output_size; ++j)
|
|
{
|
|
divide(copy, 10, copy, remainder);
|
|
output[output_size - 1 - j] =
|
|
Charset::digit2char(static_cast<byte>(remainder.word_at(0)));
|
|
if(copy.is_zero())
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
throw Invalid_Argument("Unknown BigInt encoding method");
|
|
}
|
|
|
|
/*
|
|
* Encode a BigInt
|
|
*/
|
|
SecureVector<byte> BigInt::encode(const BigInt& n, Base base)
|
|
{
|
|
SecureVector<byte> output(n.encoded_size(base));
|
|
encode(&output[0], n, base);
|
|
if(base != Binary)
|
|
for(size_t j = 0; j != output.size(); ++j)
|
|
if(output[j] == 0)
|
|
output[j] = '0';
|
|
return output;
|
|
}
|
|
|
|
/*
|
|
* Encode a BigInt, with leading 0s if needed
|
|
*/
|
|
SecureVector<byte> BigInt::encode_1363(const BigInt& n, size_t bytes)
|
|
{
|
|
const size_t n_bytes = n.bytes();
|
|
if(n_bytes > bytes)
|
|
throw Encoding_Error("encode_1363: n is too large to encode properly");
|
|
|
|
const size_t leading_0s = bytes - n_bytes;
|
|
|
|
SecureVector<byte> output(bytes);
|
|
encode(&output[leading_0s], n, Binary);
|
|
return output;
|
|
}
|
|
|
|
/*
|
|
* Decode a BigInt
|
|
*/
|
|
BigInt BigInt::decode(const MemoryRegion<byte>& buf, Base base)
|
|
{
|
|
return BigInt::decode(&buf[0], buf.size(), base);
|
|
}
|
|
|
|
/*
|
|
* Decode a BigInt
|
|
*/
|
|
BigInt BigInt::decode(const byte buf[], size_t length, Base base)
|
|
{
|
|
BigInt r;
|
|
if(base == Binary)
|
|
r.binary_decode(buf, length);
|
|
else if(base == Hexadecimal)
|
|
{
|
|
SecureVector<byte> binary;
|
|
const char *cbuf = reinterpret_cast<const char *>(buf);
|
|
|
|
if(length % 2)
|
|
{
|
|
// Handle lack of leading 0
|
|
const char buf0_with_leading_0[2] = { '0', cbuf[0] };
|
|
binary = hex_decode(buf0_with_leading_0, 2);
|
|
|
|
binary += hex_decode(&cbuf[1], length - 1, false);
|
|
}
|
|
else
|
|
binary = hex_decode(cbuf, length, false);
|
|
|
|
r.binary_decode(&binary[0], binary.size());
|
|
}
|
|
else if(base == Decimal || base == Octal)
|
|
{
|
|
const size_t RADIX = ((base == Decimal) ? 10 : 8);
|
|
for(size_t j = 0; j != length; ++j)
|
|
{
|
|
if(Charset::is_space(buf[j]))
|
|
continue;
|
|
|
|
if(!Charset::is_digit(buf[j]))
|
|
throw Invalid_Argument("BigInt::decode: "
|
|
"Invalid character in decimal input");
|
|
|
|
byte x = Charset::char2digit(buf[j]);
|
|
if(x >= RADIX)
|
|
{
|
|
if(RADIX == 10)
|
|
throw Invalid_Argument("BigInt: Invalid decimal string");
|
|
else
|
|
throw Invalid_Argument("BigInt: Invalid octal string");
|
|
}
|
|
|
|
r *= RADIX;
|
|
r += x;
|
|
}
|
|
}
|
|
else
|
|
throw Invalid_Argument("Unknown BigInt decoding method");
|
|
return r;
|
|
}
|
|
|
|
}
|
|
/*
|
|
* BigInt Input/Output
|
|
* (C) 1999-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
#include <iostream>
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* Write the BigInt into a stream
|
|
*/
|
|
std::ostream& operator<<(std::ostream& stream, const BigInt& n)
|
|
{
|
|
BigInt::Base base = BigInt::Decimal;
|
|
if(stream.flags() & std::ios::hex)
|
|
base = BigInt::Hexadecimal;
|
|
else if(stream.flags() & std::ios::oct)
|
|
base = BigInt::Octal;
|
|
|
|
if(n == 0)
|
|
stream.write("0", 1);
|
|
else
|
|
{
|
|
if(n < 0)
|
|
stream.write("-", 1);
|
|
SecureVector<byte> buffer = BigInt::encode(n, base);
|
|
size_t skip = 0;
|
|
while(buffer[skip] == '0' && skip < buffer.size())
|
|
++skip;
|
|
stream.write(reinterpret_cast<const char*>(&buffer[0]) + skip,
|
|
buffer.size() - skip);
|
|
}
|
|
if(!stream.good())
|
|
throw Stream_IO_Error("BigInt output operator has failed");
|
|
return stream;
|
|
}
|
|
|
|
/*
|
|
* Read the BigInt from a stream
|
|
*/
|
|
std::istream& operator>>(std::istream& stream, BigInt& n)
|
|
{
|
|
std::string str;
|
|
std::getline(stream, str);
|
|
if(stream.bad() || (stream.fail() && !stream.eof()))
|
|
throw Stream_IO_Error("BigInt input operator has failed");
|
|
n = BigInt(str);
|
|
return stream;
|
|
}
|
|
|
|
}
|
|
/*
|
|
* BigInt Assignment Operators
|
|
* (C) 1999-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
#include <algorithm>
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* Addition Operator
|
|
*/
|
|
BigInt& BigInt::operator+=(const BigInt& y)
|
|
{
|
|
const size_t x_sw = sig_words(), y_sw = y.sig_words();
|
|
|
|
const size_t reg_size = std::max(x_sw, y_sw) + 1;
|
|
grow_to(reg_size);
|
|
|
|
if(sign() == y.sign())
|
|
bigint_add2(get_reg(), reg_size - 1, y.data(), y_sw);
|
|
else
|
|
{
|
|
s32bit relative_size = bigint_cmp(data(), x_sw, y.data(), y_sw);
|
|
|
|
if(relative_size < 0)
|
|
{
|
|
SecureVector<word> z(reg_size - 1);
|
|
bigint_sub3(z, y.data(), reg_size - 1, data(), x_sw);
|
|
copy_mem(®[0], &z[0], z.size());
|
|
set_sign(y.sign());
|
|
}
|
|
else if(relative_size == 0)
|
|
{
|
|
zeroise(reg);
|
|
set_sign(Positive);
|
|
}
|
|
else if(relative_size > 0)
|
|
bigint_sub2(get_reg(), x_sw, y.data(), y_sw);
|
|
}
|
|
|
|
return (*this);
|
|
}
|
|
|
|
/*
|
|
* Subtraction Operator
|
|
*/
|
|
BigInt& BigInt::operator-=(const BigInt& y)
|
|
{
|
|
const size_t x_sw = sig_words(), y_sw = y.sig_words();
|
|
|
|
s32bit relative_size = bigint_cmp(data(), x_sw, y.data(), y_sw);
|
|
|
|
const size_t reg_size = std::max(x_sw, y_sw) + 1;
|
|
grow_to(reg_size);
|
|
|
|
if(relative_size < 0)
|
|
{
|
|
if(sign() == y.sign())
|
|
bigint_sub2_rev(get_reg(), y.data(), y_sw);
|
|
else
|
|
bigint_add2(get_reg(), reg_size - 1, y.data(), y_sw);
|
|
|
|
set_sign(y.reverse_sign());
|
|
}
|
|
else if(relative_size == 0)
|
|
{
|
|
if(sign() == y.sign())
|
|
{
|
|
clear();
|
|
set_sign(Positive);
|
|
}
|
|
else
|
|
bigint_shl1(get_reg(), x_sw, 0, 1);
|
|
}
|
|
else if(relative_size > 0)
|
|
{
|
|
if(sign() == y.sign())
|
|
bigint_sub2(get_reg(), x_sw, y.data(), y_sw);
|
|
else
|
|
bigint_add2(get_reg(), reg_size - 1, y.data(), y_sw);
|
|
}
|
|
|
|
return (*this);
|
|
}
|
|
|
|
/*
|
|
* Multiplication Operator
|
|
*/
|
|
BigInt& BigInt::operator*=(const BigInt& y)
|
|
{
|
|
const size_t x_sw = sig_words(), y_sw = y.sig_words();
|
|
set_sign((sign() == y.sign()) ? Positive : Negative);
|
|
|
|
if(x_sw == 0 || y_sw == 0)
|
|
{
|
|
clear();
|
|
set_sign(Positive);
|
|
}
|
|
else if(x_sw == 1 && y_sw)
|
|
{
|
|
grow_to(y_sw + 2);
|
|
bigint_linmul3(get_reg(), y.data(), y_sw, word_at(0));
|
|
}
|
|
else if(y_sw == 1 && x_sw)
|
|
{
|
|
grow_to(x_sw + 2);
|
|
bigint_linmul2(get_reg(), x_sw, y.word_at(0));
|
|
}
|
|
else
|
|
{
|
|
grow_to(size() + y.size());
|
|
|
|
SecureVector<word> z(data(), x_sw);
|
|
SecureVector<word> workspace(size());
|
|
|
|
bigint_mul(get_reg(), size(), workspace,
|
|
z, z.size(), x_sw,
|
|
y.data(), y.size(), y_sw);
|
|
}
|
|
|
|
return (*this);
|
|
}
|
|
|
|
/*
|
|
* Division Operator
|
|
*/
|
|
BigInt& BigInt::operator/=(const BigInt& y)
|
|
{
|
|
if(y.sig_words() == 1 && power_of_2(y.word_at(0)))
|
|
(*this) >>= (y.bits() - 1);
|
|
else
|
|
(*this) = (*this) / y;
|
|
return (*this);
|
|
}
|
|
|
|
/*
|
|
* Modulo Operator
|
|
*/
|
|
BigInt& BigInt::operator%=(const BigInt& mod)
|
|
{
|
|
return (*this = (*this) % mod);
|
|
}
|
|
|
|
/*
|
|
* Modulo Operator
|
|
*/
|
|
word BigInt::operator%=(word mod)
|
|
{
|
|
if(mod == 0)
|
|
throw BigInt::DivideByZero();
|
|
if(power_of_2(mod))
|
|
{
|
|
word result = (word_at(0) & (mod - 1));
|
|
clear();
|
|
grow_to(2);
|
|
get_reg()[0] = result;
|
|
return result;
|
|
}
|
|
|
|
word remainder = 0;
|
|
|
|
for(size_t j = sig_words(); j > 0; --j)
|
|
remainder = bigint_modop(remainder, word_at(j-1), mod);
|
|
clear();
|
|
grow_to(2);
|
|
|
|
if(remainder && sign() == BigInt::Negative)
|
|
get_reg()[0] = mod - remainder;
|
|
else
|
|
get_reg()[0] = remainder;
|
|
|
|
set_sign(BigInt::Positive);
|
|
|
|
return word_at(0);
|
|
}
|
|
|
|
/*
|
|
* Left Shift Operator
|
|
*/
|
|
BigInt& BigInt::operator<<=(size_t shift)
|
|
{
|
|
if(shift)
|
|
{
|
|
const size_t shift_words = shift / MP_WORD_BITS,
|
|
shift_bits = shift % MP_WORD_BITS,
|
|
words = sig_words();
|
|
|
|
grow_to(words + shift_words + (shift_bits ? 1 : 0));
|
|
bigint_shl1(get_reg(), words, shift_words, shift_bits);
|
|
}
|
|
|
|
return (*this);
|
|
}
|
|
|
|
/*
|
|
* Right Shift Operator
|
|
*/
|
|
BigInt& BigInt::operator>>=(size_t shift)
|
|
{
|
|
if(shift)
|
|
{
|
|
const size_t shift_words = shift / MP_WORD_BITS,
|
|
shift_bits = shift % MP_WORD_BITS;
|
|
|
|
bigint_shr1(get_reg(), sig_words(), shift_words, shift_bits);
|
|
|
|
if(is_zero())
|
|
set_sign(Positive);
|
|
}
|
|
|
|
return (*this);
|
|
}
|
|
|
|
}
|
|
/*
|
|
* BigInt Binary Operators
|
|
* (C) 1999-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
#include <algorithm>
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* Addition Operator
|
|
*/
|
|
BigInt operator+(const BigInt& x, const BigInt& y)
|
|
{
|
|
const size_t x_sw = x.sig_words(), y_sw = y.sig_words();
|
|
|
|
BigInt z(x.sign(), std::max(x_sw, y_sw) + 1);
|
|
|
|
if((x.sign() == y.sign()))
|
|
bigint_add3(z.get_reg(), x.data(), x_sw, y.data(), y_sw);
|
|
else
|
|
{
|
|
s32bit relative_size = bigint_cmp(x.data(), x_sw, y.data(), y_sw);
|
|
|
|
if(relative_size < 0)
|
|
{
|
|
bigint_sub3(z.get_reg(), y.data(), y_sw, x.data(), x_sw);
|
|
z.set_sign(y.sign());
|
|
}
|
|
else if(relative_size == 0)
|
|
z.set_sign(BigInt::Positive);
|
|
else if(relative_size > 0)
|
|
bigint_sub3(z.get_reg(), x.data(), x_sw, y.data(), y_sw);
|
|
}
|
|
|
|
return z;
|
|
}
|
|
|
|
/*
|
|
* Subtraction Operator
|
|
*/
|
|
BigInt operator-(const BigInt& x, const BigInt& y)
|
|
{
|
|
const size_t x_sw = x.sig_words(), y_sw = y.sig_words();
|
|
|
|
s32bit relative_size = bigint_cmp(x.data(), x_sw, y.data(), y_sw);
|
|
|
|
BigInt z(BigInt::Positive, std::max(x_sw, y_sw) + 1);
|
|
|
|
if(relative_size < 0)
|
|
{
|
|
if(x.sign() == y.sign())
|
|
bigint_sub3(z.get_reg(), y.data(), y_sw, x.data(), x_sw);
|
|
else
|
|
bigint_add3(z.get_reg(), x.data(), x_sw, y.data(), y_sw);
|
|
z.set_sign(y.reverse_sign());
|
|
}
|
|
else if(relative_size == 0)
|
|
{
|
|
if(x.sign() != y.sign())
|
|
bigint_shl2(z.get_reg(), x.data(), x_sw, 0, 1);
|
|
}
|
|
else if(relative_size > 0)
|
|
{
|
|
if(x.sign() == y.sign())
|
|
bigint_sub3(z.get_reg(), x.data(), x_sw, y.data(), y_sw);
|
|
else
|
|
bigint_add3(z.get_reg(), x.data(), x_sw, y.data(), y_sw);
|
|
z.set_sign(x.sign());
|
|
}
|
|
return z;
|
|
}
|
|
|
|
/*
|
|
* Multiplication Operator
|
|
*/
|
|
BigInt operator*(const BigInt& x, const BigInt& y)
|
|
{
|
|
const size_t x_sw = x.sig_words(), y_sw = y.sig_words();
|
|
|
|
BigInt z(BigInt::Positive, x.size() + y.size());
|
|
|
|
if(x_sw == 1 && y_sw)
|
|
bigint_linmul3(z.get_reg(), y.data(), y_sw, x.word_at(0));
|
|
else if(y_sw == 1 && x_sw)
|
|
bigint_linmul3(z.get_reg(), x.data(), x_sw, y.word_at(0));
|
|
else if(x_sw && y_sw)
|
|
{
|
|
SecureVector<word> workspace(z.size());
|
|
bigint_mul(z.get_reg(), z.size(), workspace,
|
|
x.data(), x.size(), x_sw,
|
|
y.data(), y.size(), y_sw);
|
|
}
|
|
|
|
if(x_sw && y_sw && x.sign() != y.sign())
|
|
z.flip_sign();
|
|
return z;
|
|
}
|
|
|
|
/*
|
|
* Division Operator
|
|
*/
|
|
BigInt operator/(const BigInt& x, const BigInt& y)
|
|
{
|
|
BigInt q, r;
|
|
divide(x, y, q, r);
|
|
return q;
|
|
}
|
|
|
|
/*
|
|
* Modulo Operator
|
|
*/
|
|
BigInt operator%(const BigInt& n, const BigInt& mod)
|
|
{
|
|
if(mod.is_zero())
|
|
throw BigInt::DivideByZero();
|
|
if(mod.is_negative())
|
|
throw Invalid_Argument("BigInt::operator%: modulus must be > 0");
|
|
if(n.is_positive() && mod.is_positive() && n < mod)
|
|
return n;
|
|
|
|
BigInt q, r;
|
|
divide(n, mod, q, r);
|
|
return r;
|
|
}
|
|
|
|
/*
|
|
* Modulo Operator
|
|
*/
|
|
word operator%(const BigInt& n, word mod)
|
|
{
|
|
if(mod == 0)
|
|
throw BigInt::DivideByZero();
|
|
if(power_of_2(mod))
|
|
return (n.word_at(0) & (mod - 1));
|
|
|
|
word remainder = 0;
|
|
|
|
for(size_t j = n.sig_words(); j > 0; --j)
|
|
remainder = bigint_modop(remainder, n.word_at(j-1), mod);
|
|
|
|
if(remainder && n.sign() == BigInt::Negative)
|
|
return mod - remainder;
|
|
return remainder;
|
|
}
|
|
|
|
/*
|
|
* Left Shift Operator
|
|
*/
|
|
BigInt operator<<(const BigInt& x, size_t shift)
|
|
{
|
|
if(shift == 0)
|
|
return x;
|
|
|
|
const size_t shift_words = shift / MP_WORD_BITS,
|
|
shift_bits = shift % MP_WORD_BITS;
|
|
|
|
const size_t x_sw = x.sig_words();
|
|
|
|
BigInt y(x.sign(), x_sw + shift_words + (shift_bits ? 1 : 0));
|
|
bigint_shl2(y.get_reg(), x.data(), x_sw, shift_words, shift_bits);
|
|
return y;
|
|
}
|
|
|
|
/*
|
|
* Right Shift Operator
|
|
*/
|
|
BigInt operator>>(const BigInt& x, size_t shift)
|
|
{
|
|
if(shift == 0)
|
|
return x;
|
|
if(x.bits() <= shift)
|
|
return 0;
|
|
|
|
const size_t shift_words = shift / MP_WORD_BITS,
|
|
shift_bits = shift % MP_WORD_BITS,
|
|
x_sw = x.sig_words();
|
|
|
|
BigInt y(x.sign(), x_sw - shift_words);
|
|
bigint_shr2(y.get_reg(), x.data(), x_sw, shift_words, shift_bits);
|
|
return y;
|
|
}
|
|
|
|
}
|
|
/*
|
|
* BigInt Random Generation
|
|
* (C) 1999-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* Construct a BigInt of a specific form
|
|
*/
|
|
BigInt::BigInt(NumberType type, size_t bits)
|
|
{
|
|
set_sign(Positive);
|
|
|
|
if(type == Power2)
|
|
set_bit(bits);
|
|
else
|
|
throw Invalid_Argument("BigInt(NumberType): Unknown type");
|
|
}
|
|
|
|
/*
|
|
* Randomize this number
|
|
*/
|
|
void BigInt::randomize(RandomNumberGenerator& rng,
|
|
size_t bitsize)
|
|
{
|
|
set_sign(Positive);
|
|
|
|
if(bitsize == 0)
|
|
clear();
|
|
else
|
|
{
|
|
SecureVector<byte> array = rng.random_vec((bitsize + 7) / 8);
|
|
|
|
if(bitsize % 8)
|
|
array[0] &= 0xFF >> (8 - (bitsize % 8));
|
|
array[0] |= 0x80 >> ((bitsize % 8) ? (8 - bitsize % 8) : 0);
|
|
binary_decode(&array[0], array.size());
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Generate a random integer within given range
|
|
*/
|
|
BigInt BigInt::random_integer(RandomNumberGenerator& rng,
|
|
const BigInt& min, const BigInt& max)
|
|
{
|
|
BigInt range = max - min;
|
|
|
|
if(range <= 0)
|
|
throw Invalid_Argument("random_integer: invalid min/max values");
|
|
|
|
return (min + (BigInt(rng, range.bits() + 2) % range));
|
|
}
|
|
|
|
}
|
|
/*
|
|
* BigInt Base
|
|
* (C) 1999-2011 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* Construct a BigInt from a regular number
|
|
*/
|
|
BigInt::BigInt(u64bit n)
|
|
{
|
|
set_sign(Positive);
|
|
|
|
if(n == 0)
|
|
return;
|
|
|
|
const size_t limbs_needed = sizeof(u64bit) / sizeof(word);
|
|
|
|
reg.resize(4*limbs_needed);
|
|
for(size_t i = 0; i != limbs_needed; ++i)
|
|
reg[i] = ((n >> (i*MP_WORD_BITS)) & MP_WORD_MASK);
|
|
}
|
|
|
|
/*
|
|
* Construct a BigInt of the specified size
|
|
*/
|
|
BigInt::BigInt(Sign s, size_t size)
|
|
{
|
|
reg.resize(round_up<size_t>(size, 8));
|
|
signedness = s;
|
|
}
|
|
|
|
/*
|
|
* Construct a BigInt from a "raw" BigInt
|
|
*/
|
|
BigInt::BigInt(const BigInt& b)
|
|
{
|
|
const size_t b_words = b.sig_words();
|
|
|
|
if(b_words)
|
|
{
|
|
reg.resize(round_up<size_t>(b_words, 8));
|
|
reg.copy(b.data(), b_words);
|
|
set_sign(b.sign());
|
|
}
|
|
else
|
|
{
|
|
reg.resize(2);
|
|
set_sign(Positive);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Construct a BigInt from a string
|
|
*/
|
|
BigInt::BigInt(const std::string& str)
|
|
{
|
|
Base base = Decimal;
|
|
size_t markers = 0;
|
|
bool negative = false;
|
|
if(str.length() > 0 && str[0] == '-') { markers += 1; negative = true; }
|
|
|
|
if(str.length() > markers + 2 && str[markers ] == '0' &&
|
|
str[markers + 1] == 'x')
|
|
{ markers += 2; base = Hexadecimal; }
|
|
else if(str.length() > markers + 1 && str[markers] == '0')
|
|
{ markers += 1; base = Octal; }
|
|
|
|
*this = decode(reinterpret_cast<const byte*>(str.data()) + markers,
|
|
str.length() - markers, base);
|
|
|
|
if(negative) set_sign(Negative);
|
|
else set_sign(Positive);
|
|
}
|
|
|
|
/*
|
|
* Construct a BigInt from an encoded BigInt
|
|
*/
|
|
BigInt::BigInt(const byte input[], size_t length, Base base)
|
|
{
|
|
set_sign(Positive);
|
|
*this = decode(input, length, base);
|
|
}
|
|
|
|
/*
|
|
* Construct a BigInt from an encoded BigInt
|
|
*/
|
|
BigInt::BigInt(RandomNumberGenerator& rng, size_t bits)
|
|
{
|
|
set_sign(Positive);
|
|
randomize(rng, bits);
|
|
}
|
|
|
|
/*
|
|
* Swap this BigInt with another
|
|
*/
|
|
void BigInt::swap(BigInt& other)
|
|
{
|
|
reg.swap(other.reg);
|
|
std::swap(signedness, other.signedness);
|
|
}
|
|
|
|
/*
|
|
* Grow the internal storage
|
|
*/
|
|
void BigInt::grow_reg(size_t n)
|
|
{
|
|
reg.resize(round_up<size_t>(size() + n, 8));
|
|
}
|
|
|
|
/*
|
|
* Grow the internal storage
|
|
*/
|
|
void BigInt::grow_to(size_t n)
|
|
{
|
|
if(n > size())
|
|
reg.resize(round_up<size_t>(n, 8));
|
|
}
|
|
|
|
/*
|
|
* Comparison Function
|
|
*/
|
|
s32bit BigInt::cmp(const BigInt& n, bool check_signs) const
|
|
{
|
|
if(check_signs)
|
|
{
|
|
if(n.is_positive() && this->is_negative()) return -1;
|
|
if(n.is_negative() && this->is_positive()) return 1;
|
|
if(n.is_negative() && this->is_negative())
|
|
return (-bigint_cmp(data(), sig_words(), n.data(), n.sig_words()));
|
|
}
|
|
return bigint_cmp(data(), sig_words(), n.data(), n.sig_words());
|
|
}
|
|
|
|
/*
|
|
* Return byte n of this number
|
|
*/
|
|
byte BigInt::byte_at(size_t n) const
|
|
{
|
|
const size_t WORD_BYTES = sizeof(word);
|
|
size_t word_num = n / WORD_BYTES, byte_num = n % WORD_BYTES;
|
|
if(word_num >= size())
|
|
return 0;
|
|
else
|
|
return get_byte(WORD_BYTES - byte_num - 1, reg[word_num]);
|
|
}
|
|
|
|
/*
|
|
* Return bit n of this number
|
|
*/
|
|
bool BigInt::get_bit(size_t n) const
|
|
{
|
|
return ((word_at(n / MP_WORD_BITS) >> (n % MP_WORD_BITS)) & 1);
|
|
}
|
|
|
|
/*
|
|
* Return bits {offset...offset+length}
|
|
*/
|
|
u32bit BigInt::get_substring(size_t offset, size_t length) const
|
|
{
|
|
if(length > 32)
|
|
throw Invalid_Argument("BigInt::get_substring: Substring size too big");
|
|
|
|
u64bit piece = 0;
|
|
for(size_t i = 0; i != 8; ++i)
|
|
{
|
|
const byte part = byte_at((offset / 8) + (7-i));
|
|
piece = (piece << 8) | part;
|
|
}
|
|
|
|
const u64bit mask = (static_cast<u64bit>(1) << length) - 1;
|
|
const size_t shift = (offset % 8);
|
|
|
|
return static_cast<u32bit>((piece >> shift) & mask);
|
|
}
|
|
|
|
/*
|
|
* Convert this number to a u32bit, if possible
|
|
*/
|
|
u32bit BigInt::to_u32bit() const
|
|
{
|
|
if(is_negative())
|
|
throw Encoding_Error("BigInt::to_u32bit: Number is negative");
|
|
if(bits() >= 32)
|
|
throw Encoding_Error("BigInt::to_u32bit: Number is too big to convert");
|
|
|
|
u32bit out = 0;
|
|
for(u32bit j = 0; j != 4; ++j)
|
|
out = (out << 8) | byte_at(3-j);
|
|
return out;
|
|
}
|
|
|
|
/*
|
|
* Set bit number n
|
|
*/
|
|
void BigInt::set_bit(size_t n)
|
|
{
|
|
const size_t which = n / MP_WORD_BITS;
|
|
const word mask = static_cast<word>(1) << (n % MP_WORD_BITS);
|
|
if(which >= size()) grow_to(which + 1);
|
|
reg[which] |= mask;
|
|
}
|
|
|
|
/*
|
|
* Clear bit number n
|
|
*/
|
|
void BigInt::clear_bit(size_t n)
|
|
{
|
|
const size_t which = n / MP_WORD_BITS;
|
|
const word mask = static_cast<word>(1) << (n % MP_WORD_BITS);
|
|
if(which < size())
|
|
reg[which] &= ~mask;
|
|
}
|
|
|
|
/*
|
|
* Clear all but the lowest n bits
|
|
*/
|
|
void BigInt::mask_bits(size_t n)
|
|
{
|
|
if(n == 0) { clear(); return; }
|
|
if(n >= bits()) return;
|
|
|
|
const size_t top_word = n / MP_WORD_BITS;
|
|
const word mask = (static_cast<word>(1) << (n % MP_WORD_BITS)) - 1;
|
|
|
|
if(top_word < size())
|
|
for(size_t i = top_word + 1; i != size(); ++i)
|
|
reg[i] = 0;
|
|
|
|
reg[top_word] &= mask;
|
|
}
|
|
|
|
/*
|
|
* Count how many bytes are being used
|
|
*/
|
|
size_t BigInt::bytes() const
|
|
{
|
|
return (bits() + 7) / 8;
|
|
}
|
|
|
|
/*
|
|
* Count how many bits are being used
|
|
*/
|
|
size_t BigInt::bits() const
|
|
{
|
|
const size_t words = sig_words();
|
|
|
|
if(words == 0)
|
|
return 0;
|
|
|
|
size_t full_words = words - 1, top_bits = MP_WORD_BITS;
|
|
word top_word = word_at(full_words), mask = MP_WORD_TOP_BIT;
|
|
|
|
while(top_bits && ((top_word & mask) == 0))
|
|
{ mask >>= 1; top_bits--; }
|
|
|
|
return (full_words * MP_WORD_BITS + top_bits);
|
|
}
|
|
|
|
/*
|
|
* Calcluate the size in a certain base
|
|
*/
|
|
size_t BigInt::encoded_size(Base base) const
|
|
{
|
|
static const double LOG_2_BASE_10 = 0.30102999566;
|
|
|
|
if(base == Binary)
|
|
return bytes();
|
|
else if(base == Hexadecimal)
|
|
return 2*bytes();
|
|
else if(base == Octal)
|
|
return ((bits() + 2) / 3);
|
|
else if(base == Decimal)
|
|
return static_cast<size_t>((bits() * LOG_2_BASE_10) + 1);
|
|
else
|
|
throw Invalid_Argument("Unknown base for BigInt encoding");
|
|
}
|
|
|
|
/*
|
|
* Set the sign
|
|
*/
|
|
void BigInt::set_sign(Sign s)
|
|
{
|
|
if(is_zero())
|
|
signedness = Positive;
|
|
else
|
|
signedness = s;
|
|
}
|
|
|
|
/*
|
|
* Reverse the value of the sign flag
|
|
*/
|
|
void BigInt::flip_sign()
|
|
{
|
|
set_sign(reverse_sign());
|
|
}
|
|
|
|
/*
|
|
* Return the opposite value of the current sign
|
|
*/
|
|
BigInt::Sign BigInt::reverse_sign() const
|
|
{
|
|
if(sign() == Positive)
|
|
return Negative;
|
|
return Positive;
|
|
}
|
|
|
|
/*
|
|
* Return the negation of this number
|
|
*/
|
|
BigInt BigInt::operator-() const
|
|
{
|
|
BigInt x = (*this);
|
|
x.flip_sign();
|
|
return x;
|
|
}
|
|
|
|
/*
|
|
* Return the absolute value of this number
|
|
*/
|
|
BigInt BigInt::abs() const
|
|
{
|
|
BigInt x = (*this);
|
|
x.set_sign(Positive);
|
|
return x;
|
|
}
|
|
|
|
/*
|
|
* Encode this number into bytes
|
|
*/
|
|
void BigInt::binary_encode(byte output[]) const
|
|
{
|
|
const size_t sig_bytes = bytes();
|
|
for(size_t i = 0; i != sig_bytes; ++i)
|
|
output[sig_bytes-i-1] = byte_at(i);
|
|
}
|
|
|
|
/*
|
|
* Set this number to the value in buf
|
|
*/
|
|
void BigInt::binary_decode(const byte buf[], size_t length)
|
|
{
|
|
const size_t WORD_BYTES = sizeof(word);
|
|
|
|
clear();
|
|
reg.resize(round_up<size_t>((length / WORD_BYTES) + 1, 8));
|
|
|
|
for(size_t i = 0; i != length / WORD_BYTES; ++i)
|
|
{
|
|
const size_t top = length - WORD_BYTES*i;
|
|
for(size_t j = WORD_BYTES; j > 0; --j)
|
|
reg[i] = (reg[i] << 8) | buf[top - j];
|
|
}
|
|
|
|
for(size_t i = 0; i != length % WORD_BYTES; ++i)
|
|
reg[length / WORD_BYTES] = (reg[length / WORD_BYTES] << 8) | buf[i];
|
|
}
|
|
|
|
/*
|
|
* Set this number to the value in buf
|
|
*/
|
|
void BigInt::binary_decode(const MemoryRegion<byte>& buf)
|
|
{
|
|
binary_decode(buf, buf.size());
|
|
}
|
|
|
|
}
|
|
/*
|
|
* Division Algorithm
|
|
* (C) 1999-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
namespace {
|
|
|
|
/*
|
|
* Handle signed operands, if necessary
|
|
*/
|
|
void sign_fixup(const BigInt& x, const BigInt& y, BigInt& q, BigInt& r)
|
|
{
|
|
if(x.sign() == BigInt::Negative)
|
|
{
|
|
q.flip_sign();
|
|
if(r.is_nonzero()) { --q; r = y.abs() - r; }
|
|
}
|
|
if(y.sign() == BigInt::Negative)
|
|
q.flip_sign();
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
* Solve x = q * y + r
|
|
*/
|
|
void divide(const BigInt& x, const BigInt& y_arg, BigInt& q, BigInt& r)
|
|
{
|
|
if(y_arg.is_zero())
|
|
throw BigInt::DivideByZero();
|
|
|
|
BigInt y = y_arg;
|
|
const size_t y_words = y.sig_words();
|
|
|
|
r = x;
|
|
q = 0;
|
|
|
|
r.set_sign(BigInt::Positive);
|
|
y.set_sign(BigInt::Positive);
|
|
|
|
s32bit compare = r.cmp(y);
|
|
|
|
if(compare == 0)
|
|
{
|
|
q = 1;
|
|
r = 0;
|
|
}
|
|
else if(compare > 0)
|
|
{
|
|
size_t shifts = 0;
|
|
word y_top = y[y.sig_words()-1];
|
|
while(y_top < MP_WORD_TOP_BIT) { y_top <<= 1; ++shifts; }
|
|
y <<= shifts;
|
|
r <<= shifts;
|
|
|
|
const size_t n = r.sig_words() - 1, t = y_words - 1;
|
|
|
|
if(n < t)
|
|
throw Internal_Error("BigInt division word sizes");
|
|
|
|
q.get_reg().resize(n - t + 1);
|
|
if(n <= t)
|
|
{
|
|
while(r > y) { r -= y; ++q; }
|
|
r >>= shifts;
|
|
sign_fixup(x, y_arg, q, r);
|
|
return;
|
|
}
|
|
|
|
BigInt temp = y << (MP_WORD_BITS * (n-t));
|
|
|
|
while(r >= temp) { r -= temp; ++q[n-t]; }
|
|
|
|
for(size_t j = n; j != t; --j)
|
|
{
|
|
const word x_j0 = r.word_at(j);
|
|
const word x_j1 = r.word_at(j-1);
|
|
const word y_t = y.word_at(t);
|
|
|
|
if(x_j0 == y_t)
|
|
q[j-t-1] = MP_WORD_MAX;
|
|
else
|
|
q[j-t-1] = bigint_divop(x_j0, x_j1, y_t);
|
|
|
|
while(bigint_divcore(q[j-t-1], y_t, y.word_at(t-1),
|
|
x_j0, x_j1, r.word_at(j-2)))
|
|
--q[j-t-1];
|
|
|
|
r -= (q[j-t-1] * y) << (MP_WORD_BITS * (j-t-1));
|
|
if(r.is_negative())
|
|
{
|
|
r += y << (MP_WORD_BITS * (j-t-1));
|
|
--q[j-t-1];
|
|
}
|
|
}
|
|
r >>= shifts;
|
|
}
|
|
|
|
sign_fixup(x, y_arg, q, r);
|
|
}
|
|
|
|
}
|
|
/*
|
|
* Point arithmetic on elliptic curves over GF(p)
|
|
*
|
|
* (C) 2007 Martin Doering, Christoph Ludwig, Falko Strenzke
|
|
* 2008-2011 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
PointGFp::PointGFp(const CurveGFp& curve) :
|
|
curve(curve), ws(2 * (curve.get_p_words() + 2))
|
|
{
|
|
coord_x = 0;
|
|
coord_y = monty_mult(1, curve.get_r2());
|
|
coord_z = 0;
|
|
}
|
|
|
|
PointGFp::PointGFp(const CurveGFp& curve, const BigInt& x, const BigInt& y) :
|
|
curve(curve), ws(2 * (curve.get_p_words() + 2))
|
|
{
|
|
coord_x = monty_mult(x, curve.get_r2());
|
|
coord_y = monty_mult(y, curve.get_r2());
|
|
coord_z = monty_mult(1, curve.get_r2());
|
|
}
|
|
|
|
// Montgomery multiplication
|
|
void PointGFp::monty_mult(BigInt& z, const BigInt& x, const BigInt& y) const
|
|
{
|
|
//assert(&z != &x && &z != &y);
|
|
|
|
if(x.is_zero() || y.is_zero())
|
|
{
|
|
z = 0;
|
|
return;
|
|
}
|
|
|
|
const BigInt& p = curve.get_p();
|
|
const size_t p_size = curve.get_p_words();
|
|
const word p_dash = curve.get_p_dash();
|
|
|
|
SecureVector<word>& z_reg = z.get_reg();
|
|
z_reg.resize(2*p_size+1);
|
|
zeroise(z_reg);
|
|
|
|
bigint_monty_mul(&z_reg[0], z_reg.size(),
|
|
x.data(), x.size(), x.sig_words(),
|
|
y.data(), y.size(), y.sig_words(),
|
|
p.data(), p_size, p_dash,
|
|
&ws[0]);
|
|
}
|
|
|
|
// Montgomery squaring
|
|
void PointGFp::monty_sqr(BigInt& z, const BigInt& x) const
|
|
{
|
|
//assert(&z != &x);
|
|
|
|
if(x.is_zero())
|
|
{
|
|
z = 0;
|
|
return;
|
|
}
|
|
|
|
const BigInt& p = curve.get_p();
|
|
const size_t p_size = curve.get_p_words();
|
|
const word p_dash = curve.get_p_dash();
|
|
|
|
SecureVector<word>& z_reg = z.get_reg();
|
|
z_reg.resize(2*p_size+1);
|
|
zeroise(z_reg);
|
|
|
|
bigint_monty_sqr(&z_reg[0], z_reg.size(),
|
|
x.data(), x.size(), x.sig_words(),
|
|
p.data(), p_size, p_dash,
|
|
&ws[0]);
|
|
}
|
|
|
|
// Point addition
|
|
void PointGFp::add(const PointGFp& rhs, std::vector<BigInt>& ws_bn)
|
|
{
|
|
if(is_zero())
|
|
{
|
|
coord_x = rhs.coord_x;
|
|
coord_y = rhs.coord_y;
|
|
coord_z = rhs.coord_z;
|
|
return;
|
|
}
|
|
else if(rhs.is_zero())
|
|
return;
|
|
|
|
const BigInt& p = curve.get_p();
|
|
|
|
BigInt& rhs_z2 = ws_bn[0];
|
|
BigInt& U1 = ws_bn[1];
|
|
BigInt& S1 = ws_bn[2];
|
|
|
|
BigInt& lhs_z2 = ws_bn[3];
|
|
BigInt& U2 = ws_bn[4];
|
|
BigInt& S2 = ws_bn[5];
|
|
|
|
BigInt& H = ws_bn[6];
|
|
BigInt& r = ws_bn[7];
|
|
|
|
monty_sqr(rhs_z2, rhs.coord_z);
|
|
monty_mult(U1, coord_x, rhs_z2);
|
|
monty_mult(S1, coord_y, monty_mult(rhs.coord_z, rhs_z2));
|
|
|
|
monty_sqr(lhs_z2, coord_z);
|
|
monty_mult(U2, rhs.coord_x, lhs_z2);
|
|
monty_mult(S2, rhs.coord_y, monty_mult(coord_z, lhs_z2));
|
|
|
|
H = U2;
|
|
H -= U1;
|
|
if(H.is_negative())
|
|
H += p;
|
|
|
|
r = S2;
|
|
r -= S1;
|
|
if(r.is_negative())
|
|
r += p;
|
|
|
|
if(H.is_zero())
|
|
{
|
|
if(r.is_zero())
|
|
{
|
|
mult2(ws_bn);
|
|
return;
|
|
}
|
|
|
|
*this = PointGFp(curve); // setting myself to zero
|
|
return;
|
|
}
|
|
|
|
monty_sqr(U2, H);
|
|
|
|
monty_mult(S2, U2, H);
|
|
|
|
U2 = monty_mult(U1, U2);
|
|
|
|
monty_sqr(coord_x, r);
|
|
coord_x -= S2;
|
|
coord_x -= (U2 << 1);
|
|
while(coord_x.is_negative())
|
|
coord_x += p;
|
|
|
|
U2 -= coord_x;
|
|
if(U2.is_negative())
|
|
U2 += p;
|
|
|
|
monty_mult(coord_y, r, U2);
|
|
coord_y -= monty_mult(S1, S2);
|
|
if(coord_y.is_negative())
|
|
coord_y += p;
|
|
|
|
monty_mult(coord_z, monty_mult(coord_z, rhs.coord_z), H);
|
|
}
|
|
|
|
// *this *= 2
|
|
void PointGFp::mult2(std::vector<BigInt>& ws_bn)
|
|
{
|
|
if(is_zero())
|
|
return;
|
|
else if(coord_y.is_zero())
|
|
{
|
|
*this = PointGFp(curve); // setting myself to zero
|
|
return;
|
|
}
|
|
|
|
const BigInt& p = curve.get_p();
|
|
|
|
BigInt& y_2 = ws_bn[0];
|
|
BigInt& S = ws_bn[1];
|
|
BigInt& z4 = ws_bn[2];
|
|
BigInt& a_z4 = ws_bn[3];
|
|
BigInt& M = ws_bn[4];
|
|
BigInt& U = ws_bn[5];
|
|
BigInt& x = ws_bn[6];
|
|
BigInt& y = ws_bn[7];
|
|
BigInt& z = ws_bn[8];
|
|
|
|
monty_sqr(y_2, coord_y);
|
|
|
|
monty_mult(S, coord_x, y_2);
|
|
S <<= 2; // * 4
|
|
while(S >= p)
|
|
S -= p;
|
|
|
|
monty_sqr(z4, monty_sqr(coord_z));
|
|
monty_mult(a_z4, curve.get_a_r(), z4);
|
|
|
|
M = 3 * monty_sqr(coord_x);
|
|
M += a_z4;
|
|
while(M >= p)
|
|
M -= p;
|
|
|
|
monty_sqr(x, M);
|
|
x -= (S << 1);
|
|
while(x.is_negative())
|
|
x += p;
|
|
|
|
monty_sqr(U, y_2);
|
|
U <<= 3;
|
|
while(U >= p)
|
|
U -= p;
|
|
|
|
S -= x;
|
|
while(S.is_negative())
|
|
S += p;
|
|
|
|
monty_mult(y, M, S);
|
|
y -= U;
|
|
if(y.is_negative())
|
|
y += p;
|
|
|
|
monty_mult(z, coord_y, coord_z);
|
|
z <<= 1;
|
|
if(z >= p)
|
|
z -= p;
|
|
|
|
coord_x = x;
|
|
coord_y = y;
|
|
coord_z = z;
|
|
}
|
|
|
|
// arithmetic operators
|
|
PointGFp& PointGFp::operator+=(const PointGFp& rhs)
|
|
{
|
|
std::vector<BigInt> ws(9);
|
|
add(rhs, ws);
|
|
return *this;
|
|
}
|
|
|
|
PointGFp& PointGFp::operator-=(const PointGFp& rhs)
|
|
{
|
|
PointGFp minus_rhs = PointGFp(rhs).negate();
|
|
|
|
if(is_zero())
|
|
*this = minus_rhs;
|
|
else
|
|
*this += minus_rhs;
|
|
|
|
return *this;
|
|
}
|
|
|
|
PointGFp& PointGFp::operator*=(const BigInt& scalar)
|
|
{
|
|
*this = scalar * *this;
|
|
return *this;
|
|
}
|
|
|
|
PointGFp multi_exponentiate(const PointGFp& p1, const BigInt& z1,
|
|
const PointGFp& p2, const BigInt& z2)
|
|
{
|
|
const PointGFp p3 = p1 + p2;
|
|
|
|
PointGFp H(p1.curve); // create as zero
|
|
size_t bits_left = std::max(z1.bits(), z2.bits());
|
|
|
|
std::vector<BigInt> ws(9);
|
|
|
|
while(bits_left)
|
|
{
|
|
H.mult2(ws);
|
|
|
|
const bool z1_b = z1.get_bit(bits_left - 1);
|
|
const bool z2_b = z2.get_bit(bits_left - 1);
|
|
|
|
if(z1_b == true && z2_b == true)
|
|
H.add(p3, ws);
|
|
else if(z1_b)
|
|
H.add(p1, ws);
|
|
else if(z2_b)
|
|
H.add(p2, ws);
|
|
|
|
--bits_left;
|
|
}
|
|
|
|
if(z1.is_negative() != z2.is_negative())
|
|
H.negate();
|
|
|
|
return H;
|
|
}
|
|
|
|
PointGFp operator*(const BigInt& scalar, const PointGFp& point)
|
|
{
|
|
const CurveGFp& curve = point.get_curve();
|
|
|
|
if(scalar.is_zero())
|
|
return PointGFp(curve); // zero point
|
|
|
|
std::vector<BigInt> ws(9);
|
|
|
|
if(scalar.abs() <= 2) // special cases for small values
|
|
{
|
|
byte value = scalar.abs().byte_at(0);
|
|
|
|
PointGFp result = point;
|
|
|
|
if(value == 2)
|
|
result.mult2(ws);
|
|
|
|
if(scalar.is_negative())
|
|
result.negate();
|
|
|
|
return result;
|
|
}
|
|
|
|
const size_t scalar_bits = scalar.bits();
|
|
|
|
#if 0
|
|
|
|
PointGFp x1 = PointGFp(curve);
|
|
PointGFp x2 = point;
|
|
|
|
size_t bits_left = scalar_bits;
|
|
|
|
// Montgomery Ladder
|
|
while(bits_left)
|
|
{
|
|
const bool bit_set = scalar.get_bit(bits_left - 1);
|
|
|
|
if(bit_set)
|
|
{
|
|
x1.add(x2, ws);
|
|
x2.mult2(ws);
|
|
}
|
|
else
|
|
{
|
|
x2.add(x1, ws);
|
|
x1.mult2(ws);
|
|
}
|
|
|
|
--bits_left;
|
|
}
|
|
|
|
if(scalar.is_negative())
|
|
x1.negate();
|
|
|
|
return x1;
|
|
|
|
#else
|
|
const size_t window_size = 4;
|
|
|
|
std::vector<PointGFp> Ps(1 << window_size);
|
|
Ps[0] = PointGFp(curve);
|
|
Ps[1] = point;
|
|
|
|
for(size_t i = 2; i != Ps.size(); ++i)
|
|
{
|
|
Ps[i] = Ps[i-1];
|
|
Ps[i].add(point, ws);
|
|
}
|
|
|
|
PointGFp H(curve); // create as zero
|
|
size_t bits_left = scalar_bits;
|
|
|
|
while(bits_left >= window_size)
|
|
{
|
|
for(size_t i = 0; i != window_size; ++i)
|
|
H.mult2(ws);
|
|
|
|
const u32bit nibble = scalar.get_substring(bits_left - window_size,
|
|
window_size);
|
|
|
|
H.add(Ps[nibble], ws);
|
|
|
|
bits_left -= window_size;
|
|
}
|
|
|
|
while(bits_left)
|
|
{
|
|
H.mult2(ws);
|
|
if(scalar.get_bit(bits_left-1))
|
|
H.add(point, ws);
|
|
|
|
--bits_left;
|
|
}
|
|
|
|
if(scalar.is_negative())
|
|
H.negate();
|
|
|
|
return H;
|
|
#endif
|
|
}
|
|
|
|
BigInt PointGFp::get_affine_x() const
|
|
{
|
|
if(is_zero())
|
|
throw Illegal_Transformation("Cannot convert zero point to affine");
|
|
|
|
const BigInt& r2 = curve.get_r2();
|
|
|
|
BigInt z2 = monty_sqr(coord_z);
|
|
z2 = inverse_mod(z2, curve.get_p());
|
|
|
|
z2 = monty_mult(z2, r2);
|
|
return monty_mult(coord_x, z2);
|
|
}
|
|
|
|
BigInt PointGFp::get_affine_y() const
|
|
{
|
|
if(is_zero())
|
|
throw Illegal_Transformation("Cannot convert zero point to affine");
|
|
|
|
const BigInt& r2 = curve.get_r2();
|
|
|
|
BigInt z3 = monty_mult(coord_z, monty_sqr(coord_z));
|
|
z3 = inverse_mod(z3, curve.get_p());
|
|
z3 = monty_mult(z3, r2);
|
|
return monty_mult(coord_y, z3);
|
|
}
|
|
|
|
bool PointGFp::on_the_curve() const
|
|
{
|
|
/*
|
|
Is the point still on the curve?? (If everything is correct, the
|
|
point is always on its curve; then the function will return true.
|
|
If somehow the state is corrupted, which suggests a fault attack
|
|
(or internal computational error), then return false.
|
|
*/
|
|
|
|
if(is_zero())
|
|
return true;
|
|
|
|
BigInt y2 = monty_mult(monty_sqr(coord_y), 1);
|
|
BigInt x3 = monty_mult(coord_x, monty_sqr(coord_x));
|
|
|
|
BigInt ax = monty_mult(coord_x, curve.get_a_r());
|
|
|
|
const BigInt& b_r = curve.get_b_r();
|
|
|
|
BigInt z2 = monty_sqr(coord_z);
|
|
|
|
if(coord_z == z2) // Is z equal to 1 (in Montgomery form)?
|
|
{
|
|
if(y2 != monty_mult(x3 + ax + b_r, 1))
|
|
return false;
|
|
}
|
|
|
|
BigInt z3 = monty_mult(coord_z, z2);
|
|
|
|
BigInt ax_z4 = monty_mult(ax, monty_sqr(z2));
|
|
|
|
BigInt b_z6 = monty_mult(b_r, monty_sqr(z3));
|
|
|
|
if(y2 != monty_mult(x3 + ax_z4 + b_z6, 1))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
// swaps the states of *this and other, does not throw!
|
|
void PointGFp::swap(PointGFp& other)
|
|
{
|
|
curve.swap(other.curve);
|
|
coord_x.swap(other.coord_x);
|
|
coord_y.swap(other.coord_y);
|
|
coord_z.swap(other.coord_z);
|
|
ws.swap(other.ws);
|
|
}
|
|
|
|
bool PointGFp::operator==(const PointGFp& other) const
|
|
{
|
|
if(get_curve() != other.get_curve())
|
|
return false;
|
|
|
|
// If this is zero, only equal if other is also zero
|
|
if(is_zero())
|
|
return other.is_zero();
|
|
|
|
return (get_affine_x() == other.get_affine_x() &&
|
|
get_affine_y() == other.get_affine_y());
|
|
}
|
|
|
|
// encoding and decoding
|
|
SecureVector<byte> EC2OSP(const PointGFp& point, byte format)
|
|
{
|
|
if(point.is_zero())
|
|
return SecureVector<byte>(1); // single 0 byte
|
|
|
|
const size_t p_bytes = point.get_curve().get_p().bytes();
|
|
|
|
BigInt x = point.get_affine_x();
|
|
BigInt y = point.get_affine_y();
|
|
|
|
SecureVector<byte> bX = BigInt::encode_1363(x, p_bytes);
|
|
SecureVector<byte> bY = BigInt::encode_1363(y, p_bytes);
|
|
|
|
if(format == PointGFp::UNCOMPRESSED)
|
|
{
|
|
SecureVector<byte> result;
|
|
result.push_back(0x04);
|
|
|
|
result += bX;
|
|
result += bY;
|
|
|
|
return result;
|
|
}
|
|
else if(format == PointGFp::COMPRESSED)
|
|
{
|
|
SecureVector<byte> result;
|
|
result.push_back(0x02 | static_cast<byte>(y.get_bit(0)));
|
|
|
|
result += bX;
|
|
|
|
return result;
|
|
}
|
|
else if(format == PointGFp::HYBRID)
|
|
{
|
|
SecureVector<byte> result;
|
|
result.push_back(0x06 | static_cast<byte>(y.get_bit(0)));
|
|
|
|
result += bX;
|
|
result += bY;
|
|
|
|
return result;
|
|
}
|
|
else
|
|
throw Invalid_Argument("illegal point encoding format specification");
|
|
}
|
|
|
|
namespace {
|
|
|
|
BigInt decompress_point(bool yMod2,
|
|
const BigInt& x,
|
|
const CurveGFp& curve)
|
|
{
|
|
BigInt xpow3 = x * x * x;
|
|
|
|
BigInt g = curve.get_a() * x;
|
|
g += xpow3;
|
|
g += curve.get_b();
|
|
g = g % curve.get_p();
|
|
|
|
BigInt z = ressol(g, curve.get_p());
|
|
|
|
if(z < 0)
|
|
throw Illegal_Point("error during decompression");
|
|
|
|
if(z.get_bit(0) != yMod2)
|
|
z = curve.get_p() - z;
|
|
|
|
return z;
|
|
}
|
|
|
|
}
|
|
|
|
PointGFp OS2ECP(const byte data[], size_t data_len,
|
|
const CurveGFp& curve)
|
|
{
|
|
if(data_len <= 1)
|
|
return PointGFp(curve); // return zero
|
|
|
|
const byte pc = data[0];
|
|
|
|
BigInt x, y;
|
|
|
|
if(pc == 2 || pc == 3)
|
|
{
|
|
//compressed form
|
|
x = BigInt::decode(&data[1], data_len - 1);
|
|
|
|
const bool y_mod_2 = ((pc & 0x01) == 1);
|
|
y = decompress_point(y_mod_2, x, curve);
|
|
}
|
|
else if(pc == 4)
|
|
{
|
|
const size_t l = (data_len - 1) / 2;
|
|
|
|
// uncompressed form
|
|
x = BigInt::decode(&data[1], l);
|
|
y = BigInt::decode(&data[l+1], l);
|
|
}
|
|
else if(pc == 6 || pc == 7)
|
|
{
|
|
const size_t l = (data_len - 1) / 2;
|
|
|
|
// hybrid form
|
|
x = BigInt::decode(&data[1], l);
|
|
y = BigInt::decode(&data[l+1], l);
|
|
|
|
const bool y_mod_2 = ((pc & 0x01) == 1);
|
|
|
|
if(decompress_point(y_mod_2, x, curve) != y)
|
|
throw Illegal_Point("OS2ECP: Decoding error in hybrid format");
|
|
}
|
|
else
|
|
throw Invalid_Argument("OS2ECP: Unknown format type");
|
|
|
|
PointGFp result(curve, x, y);
|
|
|
|
if(!result.on_the_curve())
|
|
throw Illegal_Point("OS2ECP: Decoded point was not on the curve");
|
|
|
|
return result;
|
|
}
|
|
|
|
}
|
|
/*
|
|
* Lowest Level MPI Algorithms
|
|
* (C) 1999-2010 Jack Lloyd
|
|
* 2006 Luca Piccarreta
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
extern "C" {
|
|
|
|
/*
|
|
* Two Operand Addition, No Carry
|
|
*/
|
|
word bigint_add2_nc(word x[], size_t x_size, const word y[], size_t y_size)
|
|
{
|
|
word carry = 0;
|
|
|
|
const size_t blocks = y_size - (y_size % 8);
|
|
|
|
for(size_t i = 0; i != blocks; i += 8)
|
|
carry = word8_add2(x + i, y + i, carry);
|
|
|
|
for(size_t i = blocks; i != y_size; ++i)
|
|
x[i] = word_add(x[i], y[i], &carry);
|
|
|
|
for(size_t i = y_size; i != x_size; ++i)
|
|
x[i] = word_add(x[i], 0, &carry);
|
|
|
|
return carry;
|
|
}
|
|
|
|
/*
|
|
* Three Operand Addition, No Carry
|
|
*/
|
|
word bigint_add3_nc(word z[], const word x[], size_t x_size,
|
|
const word y[], size_t y_size)
|
|
{
|
|
if(x_size < y_size)
|
|
{ return bigint_add3_nc(z, y, y_size, x, x_size); }
|
|
|
|
word carry = 0;
|
|
|
|
const size_t blocks = y_size - (y_size % 8);
|
|
|
|
for(size_t i = 0; i != blocks; i += 8)
|
|
carry = word8_add3(z + i, x + i, y + i, carry);
|
|
|
|
for(size_t i = blocks; i != y_size; ++i)
|
|
z[i] = word_add(x[i], y[i], &carry);
|
|
|
|
for(size_t i = y_size; i != x_size; ++i)
|
|
z[i] = word_add(x[i], 0, &carry);
|
|
|
|
return carry;
|
|
}
|
|
|
|
/*
|
|
* Two Operand Addition
|
|
*/
|
|
void bigint_add2(word x[], size_t x_size, const word y[], size_t y_size)
|
|
{
|
|
if(bigint_add2_nc(x, x_size, y, y_size))
|
|
x[x_size] += 1;
|
|
}
|
|
|
|
/*
|
|
* Three Operand Addition
|
|
*/
|
|
void bigint_add3(word z[], const word x[], size_t x_size,
|
|
const word y[], size_t y_size)
|
|
{
|
|
z[(x_size > y_size ? x_size : y_size)] +=
|
|
bigint_add3_nc(z, x, x_size, y, y_size);
|
|
}
|
|
|
|
/*
|
|
* Two Operand Subtraction
|
|
*/
|
|
word bigint_sub2(word x[], size_t x_size, const word y[], size_t y_size)
|
|
{
|
|
word borrow = 0;
|
|
|
|
const size_t blocks = y_size - (y_size % 8);
|
|
|
|
for(size_t i = 0; i != blocks; i += 8)
|
|
borrow = word8_sub2(x + i, y + i, borrow);
|
|
|
|
for(size_t i = blocks; i != y_size; ++i)
|
|
x[i] = word_sub(x[i], y[i], &borrow);
|
|
|
|
for(size_t i = y_size; i != x_size; ++i)
|
|
x[i] = word_sub(x[i], 0, &borrow);
|
|
|
|
return borrow;
|
|
}
|
|
|
|
/*
|
|
* Two Operand Subtraction x = y - x
|
|
*/
|
|
void bigint_sub2_rev(word x[], const word y[], size_t y_size)
|
|
{
|
|
word borrow = 0;
|
|
|
|
const size_t blocks = y_size - (y_size % 8);
|
|
|
|
for(size_t i = 0; i != blocks; i += 8)
|
|
borrow = word8_sub2_rev(x + i, y + i, borrow);
|
|
|
|
for(size_t i = blocks; i != y_size; ++i)
|
|
x[i] = word_sub(y[i], x[i], &borrow);
|
|
|
|
if(borrow)
|
|
throw Internal_Error("bigint_sub2_rev: x >= y");
|
|
}
|
|
|
|
/*
|
|
* Three Operand Subtraction
|
|
*/
|
|
word bigint_sub3(word z[], const word x[], size_t x_size,
|
|
const word y[], size_t y_size)
|
|
{
|
|
word borrow = 0;
|
|
|
|
const size_t blocks = y_size - (y_size % 8);
|
|
|
|
for(size_t i = 0; i != blocks; i += 8)
|
|
borrow = word8_sub3(z + i, x + i, y + i, borrow);
|
|
|
|
for(size_t i = blocks; i != y_size; ++i)
|
|
z[i] = word_sub(x[i], y[i], &borrow);
|
|
|
|
for(size_t i = y_size; i != x_size; ++i)
|
|
z[i] = word_sub(x[i], 0, &borrow);
|
|
|
|
return borrow;
|
|
}
|
|
|
|
/*
|
|
* Two Operand Linear Multiply
|
|
*/
|
|
void bigint_linmul2(word x[], size_t x_size, word y)
|
|
{
|
|
const size_t blocks = x_size - (x_size % 8);
|
|
|
|
word carry = 0;
|
|
|
|
for(size_t i = 0; i != blocks; i += 8)
|
|
carry = word8_linmul2(x + i, y, carry);
|
|
|
|
for(size_t i = blocks; i != x_size; ++i)
|
|
x[i] = word_madd2(x[i], y, &carry);
|
|
|
|
x[x_size] = carry;
|
|
}
|
|
|
|
/*
|
|
* Three Operand Linear Multiply
|
|
*/
|
|
void bigint_linmul3(word z[], const word x[], size_t x_size, word y)
|
|
{
|
|
const size_t blocks = x_size - (x_size % 8);
|
|
|
|
word carry = 0;
|
|
|
|
for(size_t i = 0; i != blocks; i += 8)
|
|
carry = word8_linmul3(z + i, x + i, y, carry);
|
|
|
|
for(size_t i = blocks; i != x_size; ++i)
|
|
z[i] = word_madd2(x[i], y, &carry);
|
|
|
|
z[x_size] = carry;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
/*
|
|
* Comba Multiplication and Squaring
|
|
* (C) 1999-2007,2011 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
extern "C" {
|
|
|
|
/*
|
|
* Comba 4x4 Squaring
|
|
*/
|
|
void bigint_comba_sqr4(word z[8], const word x[4])
|
|
{
|
|
word w2 = 0, w1 = 0, w0 = 0;
|
|
|
|
word3_muladd(&w2, &w1, &w0, x[ 0], x[ 0]);
|
|
z[ 0] = w0; w0 = 0;
|
|
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 0], x[ 1]);
|
|
z[ 1] = w1; w1 = 0;
|
|
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 0], x[ 2]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 1], x[ 1]);
|
|
z[ 2] = w2; w2 = 0;
|
|
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 0], x[ 3]);
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 1], x[ 2]);
|
|
z[ 3] = w0; w0 = 0;
|
|
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 1], x[ 3]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 2], x[ 2]);
|
|
z[ 4] = w1; w1 = 0;
|
|
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 2], x[ 3]);
|
|
z[ 5] = w2; w2 = 0;
|
|
|
|
word3_muladd(&w2, &w1, &w0, x[ 3], x[ 3]);
|
|
z[ 6] = w0;
|
|
z[ 7] = w1;
|
|
}
|
|
|
|
/*
|
|
* Comba 4x4 Multiplication
|
|
*/
|
|
void bigint_comba_mul4(word z[8], const word x[4], const word y[4])
|
|
{
|
|
word w2 = 0, w1 = 0, w0 = 0;
|
|
|
|
word3_muladd(&w2, &w1, &w0, x[ 0], y[ 0]);
|
|
z[ 0] = w0; w0 = 0;
|
|
|
|
word3_muladd(&w0, &w2, &w1, x[ 0], y[ 1]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 1], y[ 0]);
|
|
z[ 1] = w1; w1 = 0;
|
|
|
|
word3_muladd(&w1, &w0, &w2, x[ 0], y[ 2]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 1], y[ 1]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 2], y[ 0]);
|
|
z[ 2] = w2; w2 = 0;
|
|
|
|
word3_muladd(&w2, &w1, &w0, x[ 0], y[ 3]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 1], y[ 2]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 2], y[ 1]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 3], y[ 0]);
|
|
z[ 3] = w0; w0 = 0;
|
|
|
|
word3_muladd(&w0, &w2, &w1, x[ 1], y[ 3]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 2], y[ 2]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 3], y[ 1]);
|
|
z[ 4] = w1; w1 = 0;
|
|
|
|
word3_muladd(&w1, &w0, &w2, x[ 2], y[ 3]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 3], y[ 2]);
|
|
z[ 5] = w2; w2 = 0;
|
|
|
|
word3_muladd(&w2, &w1, &w0, x[ 3], y[ 3]);
|
|
z[ 6] = w0;
|
|
z[ 7] = w1;
|
|
}
|
|
|
|
/*
|
|
* Comba 6x6 Squaring
|
|
*/
|
|
void bigint_comba_sqr6(word z[12], const word x[6])
|
|
{
|
|
word w2 = 0, w1 = 0, w0 = 0;
|
|
|
|
word3_muladd(&w2, &w1, &w0, x[ 0], x[ 0]);
|
|
z[ 0] = w0; w0 = 0;
|
|
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 0], x[ 1]);
|
|
z[ 1] = w1; w1 = 0;
|
|
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 0], x[ 2]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 1], x[ 1]);
|
|
z[ 2] = w2; w2 = 0;
|
|
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 0], x[ 3]);
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 1], x[ 2]);
|
|
z[ 3] = w0; w0 = 0;
|
|
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 0], x[ 4]);
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 1], x[ 3]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 2], x[ 2]);
|
|
z[ 4] = w1; w1 = 0;
|
|
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 0], x[ 5]);
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 1], x[ 4]);
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 2], x[ 3]);
|
|
z[ 5] = w2; w2 = 0;
|
|
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 1], x[ 5]);
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 2], x[ 4]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 3], x[ 3]);
|
|
z[ 6] = w0; w0 = 0;
|
|
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 2], x[ 5]);
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 3], x[ 4]);
|
|
z[ 7] = w1; w1 = 0;
|
|
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 3], x[ 5]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 4], x[ 4]);
|
|
z[ 8] = w2; w2 = 0;
|
|
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 4], x[ 5]);
|
|
z[ 9] = w0; w0 = 0;
|
|
|
|
word3_muladd(&w0, &w2, &w1, x[ 5], x[ 5]);
|
|
z[10] = w1;
|
|
z[11] = w2;
|
|
}
|
|
|
|
/*
|
|
* Comba 6x6 Multiplication
|
|
*/
|
|
void bigint_comba_mul6(word z[12], const word x[6], const word y[6])
|
|
{
|
|
word w2 = 0, w1 = 0, w0 = 0;
|
|
|
|
word3_muladd(&w2, &w1, &w0, x[ 0], y[ 0]);
|
|
z[ 0] = w0; w0 = 0;
|
|
|
|
word3_muladd(&w0, &w2, &w1, x[ 0], y[ 1]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 1], y[ 0]);
|
|
z[ 1] = w1; w1 = 0;
|
|
|
|
word3_muladd(&w1, &w0, &w2, x[ 0], y[ 2]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 1], y[ 1]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 2], y[ 0]);
|
|
z[ 2] = w2; w2 = 0;
|
|
|
|
word3_muladd(&w2, &w1, &w0, x[ 0], y[ 3]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 1], y[ 2]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 2], y[ 1]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 3], y[ 0]);
|
|
z[ 3] = w0; w0 = 0;
|
|
|
|
word3_muladd(&w0, &w2, &w1, x[ 0], y[ 4]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 1], y[ 3]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 2], y[ 2]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 3], y[ 1]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 4], y[ 0]);
|
|
z[ 4] = w1; w1 = 0;
|
|
|
|
word3_muladd(&w1, &w0, &w2, x[ 0], y[ 5]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 1], y[ 4]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 2], y[ 3]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 3], y[ 2]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 4], y[ 1]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 5], y[ 0]);
|
|
z[ 5] = w2; w2 = 0;
|
|
|
|
word3_muladd(&w2, &w1, &w0, x[ 1], y[ 5]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 2], y[ 4]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 3], y[ 3]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 4], y[ 2]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 5], y[ 1]);
|
|
z[ 6] = w0; w0 = 0;
|
|
|
|
word3_muladd(&w0, &w2, &w1, x[ 2], y[ 5]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 3], y[ 4]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 4], y[ 3]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 5], y[ 2]);
|
|
z[ 7] = w1; w1 = 0;
|
|
|
|
word3_muladd(&w1, &w0, &w2, x[ 3], y[ 5]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 4], y[ 4]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 5], y[ 3]);
|
|
z[ 8] = w2; w2 = 0;
|
|
|
|
word3_muladd(&w2, &w1, &w0, x[ 4], y[ 5]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 5], y[ 4]);
|
|
z[ 9] = w0; w0 = 0;
|
|
|
|
word3_muladd(&w0, &w2, &w1, x[ 5], y[ 5]);
|
|
z[10] = w1;
|
|
z[11] = w2;
|
|
}
|
|
|
|
/*
|
|
* Comba 8x8 Squaring
|
|
*/
|
|
void bigint_comba_sqr8(word z[16], const word x[8])
|
|
{
|
|
word w2 = 0, w1 = 0, w0 = 0;
|
|
|
|
word3_muladd(&w2, &w1, &w0, x[ 0], x[ 0]);
|
|
z[ 0] = w0; w0 = 0;
|
|
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 0], x[ 1]);
|
|
z[ 1] = w1; w1 = 0;
|
|
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 0], x[ 2]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 1], x[ 1]);
|
|
z[ 2] = w2; w2 = 0;
|
|
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 0], x[ 3]);
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 1], x[ 2]);
|
|
z[ 3] = w0; w0 = 0;
|
|
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 0], x[ 4]);
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 1], x[ 3]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 2], x[ 2]);
|
|
z[ 4] = w1; w1 = 0;
|
|
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 0], x[ 5]);
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 1], x[ 4]);
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 2], x[ 3]);
|
|
z[ 5] = w2; w2 = 0;
|
|
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 0], x[ 6]);
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 1], x[ 5]);
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 2], x[ 4]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 3], x[ 3]);
|
|
z[ 6] = w0; w0 = 0;
|
|
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 0], x[ 7]);
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 1], x[ 6]);
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 2], x[ 5]);
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 3], x[ 4]);
|
|
z[ 7] = w1; w1 = 0;
|
|
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 1], x[ 7]);
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 2], x[ 6]);
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 3], x[ 5]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 4], x[ 4]);
|
|
z[ 8] = w2; w2 = 0;
|
|
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 2], x[ 7]);
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 3], x[ 6]);
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 4], x[ 5]);
|
|
z[ 9] = w0; w0 = 0;
|
|
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 3], x[ 7]);
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 4], x[ 6]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 5], x[ 5]);
|
|
z[10] = w1; w1 = 0;
|
|
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 4], x[ 7]);
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 5], x[ 6]);
|
|
z[11] = w2; w2 = 0;
|
|
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 5], x[ 7]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 6], x[ 6]);
|
|
z[12] = w0; w0 = 0;
|
|
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 6], x[ 7]);
|
|
z[13] = w1; w1 = 0;
|
|
|
|
word3_muladd(&w1, &w0, &w2, x[ 7], x[ 7]);
|
|
z[14] = w2;
|
|
z[15] = w0;
|
|
}
|
|
|
|
/*
|
|
* Comba 8x8 Multiplication
|
|
*/
|
|
void bigint_comba_mul8(word z[16], const word x[8], const word y[8])
|
|
{
|
|
word w2 = 0, w1 = 0, w0 = 0;
|
|
|
|
word3_muladd(&w2, &w1, &w0, x[ 0], y[ 0]);
|
|
z[ 0] = w0; w0 = 0;
|
|
|
|
word3_muladd(&w0, &w2, &w1, x[ 0], y[ 1]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 1], y[ 0]);
|
|
z[ 1] = w1; w1 = 0;
|
|
|
|
word3_muladd(&w1, &w0, &w2, x[ 0], y[ 2]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 1], y[ 1]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 2], y[ 0]);
|
|
z[ 2] = w2; w2 = 0;
|
|
|
|
word3_muladd(&w2, &w1, &w0, x[ 0], y[ 3]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 1], y[ 2]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 2], y[ 1]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 3], y[ 0]);
|
|
z[ 3] = w0; w0 = 0;
|
|
|
|
word3_muladd(&w0, &w2, &w1, x[ 0], y[ 4]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 1], y[ 3]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 2], y[ 2]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 3], y[ 1]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 4], y[ 0]);
|
|
z[ 4] = w1; w1 = 0;
|
|
|
|
word3_muladd(&w1, &w0, &w2, x[ 0], y[ 5]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 1], y[ 4]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 2], y[ 3]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 3], y[ 2]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 4], y[ 1]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 5], y[ 0]);
|
|
z[ 5] = w2; w2 = 0;
|
|
|
|
word3_muladd(&w2, &w1, &w0, x[ 0], y[ 6]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 1], y[ 5]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 2], y[ 4]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 3], y[ 3]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 4], y[ 2]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 5], y[ 1]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 6], y[ 0]);
|
|
z[ 6] = w0; w0 = 0;
|
|
|
|
word3_muladd(&w0, &w2, &w1, x[ 0], y[ 7]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 1], y[ 6]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 2], y[ 5]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 3], y[ 4]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 4], y[ 3]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 5], y[ 2]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 6], y[ 1]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 7], y[ 0]);
|
|
z[ 7] = w1; w1 = 0;
|
|
|
|
word3_muladd(&w1, &w0, &w2, x[ 1], y[ 7]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 2], y[ 6]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 3], y[ 5]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 4], y[ 4]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 5], y[ 3]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 6], y[ 2]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 7], y[ 1]);
|
|
z[ 8] = w2; w2 = 0;
|
|
|
|
word3_muladd(&w2, &w1, &w0, x[ 2], y[ 7]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 3], y[ 6]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 4], y[ 5]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 5], y[ 4]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 6], y[ 3]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 7], y[ 2]);
|
|
z[ 9] = w0; w0 = 0;
|
|
|
|
word3_muladd(&w0, &w2, &w1, x[ 3], y[ 7]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 4], y[ 6]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 5], y[ 5]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 6], y[ 4]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 7], y[ 3]);
|
|
z[10] = w1; w1 = 0;
|
|
|
|
word3_muladd(&w1, &w0, &w2, x[ 4], y[ 7]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 5], y[ 6]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 6], y[ 5]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 7], y[ 4]);
|
|
z[11] = w2; w2 = 0;
|
|
|
|
word3_muladd(&w2, &w1, &w0, x[ 5], y[ 7]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 6], y[ 6]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 7], y[ 5]);
|
|
z[12] = w0; w0 = 0;
|
|
|
|
word3_muladd(&w0, &w2, &w1, x[ 6], y[ 7]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 7], y[ 6]);
|
|
z[13] = w1; w1 = 0;
|
|
|
|
word3_muladd(&w1, &w0, &w2, x[ 7], y[ 7]);
|
|
z[14] = w2;
|
|
z[15] = w0;
|
|
}
|
|
|
|
/*
|
|
* Comba 16x16 Squaring
|
|
*/
|
|
void bigint_comba_sqr16(word z[32], const word x[16])
|
|
{
|
|
word w2 = 0, w1 = 0, w0 = 0;
|
|
|
|
word3_muladd(&w2, &w1, &w0, x[ 0], x[ 0]);
|
|
z[ 0] = w0; w0 = 0;
|
|
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 0], x[ 1]);
|
|
z[ 1] = w1; w1 = 0;
|
|
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 0], x[ 2]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 1], x[ 1]);
|
|
z[ 2] = w2; w2 = 0;
|
|
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 0], x[ 3]);
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 1], x[ 2]);
|
|
z[ 3] = w0; w0 = 0;
|
|
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 0], x[ 4]);
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 1], x[ 3]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 2], x[ 2]);
|
|
z[ 4] = w1; w1 = 0;
|
|
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 0], x[ 5]);
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 1], x[ 4]);
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 2], x[ 3]);
|
|
z[ 5] = w2; w2 = 0;
|
|
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 0], x[ 6]);
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 1], x[ 5]);
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 2], x[ 4]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 3], x[ 3]);
|
|
z[ 6] = w0; w0 = 0;
|
|
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 0], x[ 7]);
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 1], x[ 6]);
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 2], x[ 5]);
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 3], x[ 4]);
|
|
z[ 7] = w1; w1 = 0;
|
|
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 0], x[ 8]);
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 1], x[ 7]);
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 2], x[ 6]);
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 3], x[ 5]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 4], x[ 4]);
|
|
z[ 8] = w2; w2 = 0;
|
|
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 0], x[ 9]);
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 1], x[ 8]);
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 2], x[ 7]);
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 3], x[ 6]);
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 4], x[ 5]);
|
|
z[ 9] = w0; w0 = 0;
|
|
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 0], x[10]);
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 1], x[ 9]);
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 2], x[ 8]);
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 3], x[ 7]);
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 4], x[ 6]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 5], x[ 5]);
|
|
z[10] = w1; w1 = 0;
|
|
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 0], x[11]);
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 1], x[10]);
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 2], x[ 9]);
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 3], x[ 8]);
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 4], x[ 7]);
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 5], x[ 6]);
|
|
z[11] = w2; w2 = 0;
|
|
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 0], x[12]);
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 1], x[11]);
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 2], x[10]);
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 3], x[ 9]);
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 4], x[ 8]);
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 5], x[ 7]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 6], x[ 6]);
|
|
z[12] = w0; w0 = 0;
|
|
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 0], x[13]);
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 1], x[12]);
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 2], x[11]);
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 3], x[10]);
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 4], x[ 9]);
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 5], x[ 8]);
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 6], x[ 7]);
|
|
z[13] = w1; w1 = 0;
|
|
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 0], x[14]);
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 1], x[13]);
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 2], x[12]);
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 3], x[11]);
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 4], x[10]);
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 5], x[ 9]);
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 6], x[ 8]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 7], x[ 7]);
|
|
z[14] = w2; w2 = 0;
|
|
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 0], x[15]);
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 1], x[14]);
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 2], x[13]);
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 3], x[12]);
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 4], x[11]);
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 5], x[10]);
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 6], x[ 9]);
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 7], x[ 8]);
|
|
z[15] = w0; w0 = 0;
|
|
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 1], x[15]);
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 2], x[14]);
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 3], x[13]);
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 4], x[12]);
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 5], x[11]);
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 6], x[10]);
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 7], x[ 9]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 8], x[ 8]);
|
|
z[16] = w1; w1 = 0;
|
|
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 2], x[15]);
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 3], x[14]);
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 4], x[13]);
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 5], x[12]);
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 6], x[11]);
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 7], x[10]);
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 8], x[ 9]);
|
|
z[17] = w2; w2 = 0;
|
|
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 3], x[15]);
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 4], x[14]);
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 5], x[13]);
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 6], x[12]);
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 7], x[11]);
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 8], x[10]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 9], x[ 9]);
|
|
z[18] = w0; w0 = 0;
|
|
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 4], x[15]);
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 5], x[14]);
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 6], x[13]);
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 7], x[12]);
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 8], x[11]);
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 9], x[10]);
|
|
z[19] = w1; w1 = 0;
|
|
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 5], x[15]);
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 6], x[14]);
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 7], x[13]);
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 8], x[12]);
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 9], x[11]);
|
|
word3_muladd(&w1, &w0, &w2, x[10], x[10]);
|
|
z[20] = w2; w2 = 0;
|
|
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 6], x[15]);
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 7], x[14]);
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 8], x[13]);
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 9], x[12]);
|
|
word3_muladd_2(&w2, &w1, &w0, x[10], x[11]);
|
|
z[21] = w0; w0 = 0;
|
|
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 7], x[15]);
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 8], x[14]);
|
|
word3_muladd_2(&w0, &w2, &w1, x[ 9], x[13]);
|
|
word3_muladd_2(&w0, &w2, &w1, x[10], x[12]);
|
|
word3_muladd(&w0, &w2, &w1, x[11], x[11]);
|
|
z[22] = w1; w1 = 0;
|
|
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 8], x[15]);
|
|
word3_muladd_2(&w1, &w0, &w2, x[ 9], x[14]);
|
|
word3_muladd_2(&w1, &w0, &w2, x[10], x[13]);
|
|
word3_muladd_2(&w1, &w0, &w2, x[11], x[12]);
|
|
z[23] = w2; w2 = 0;
|
|
|
|
word3_muladd_2(&w2, &w1, &w0, x[ 9], x[15]);
|
|
word3_muladd_2(&w2, &w1, &w0, x[10], x[14]);
|
|
word3_muladd_2(&w2, &w1, &w0, x[11], x[13]);
|
|
word3_muladd(&w2, &w1, &w0, x[12], x[12]);
|
|
z[24] = w0; w0 = 0;
|
|
|
|
word3_muladd_2(&w0, &w2, &w1, x[10], x[15]);
|
|
word3_muladd_2(&w0, &w2, &w1, x[11], x[14]);
|
|
word3_muladd_2(&w0, &w2, &w1, x[12], x[13]);
|
|
z[25] = w1; w1 = 0;
|
|
|
|
word3_muladd_2(&w1, &w0, &w2, x[11], x[15]);
|
|
word3_muladd_2(&w1, &w0, &w2, x[12], x[14]);
|
|
word3_muladd(&w1, &w0, &w2, x[13], x[13]);
|
|
z[26] = w2; w2 = 0;
|
|
|
|
word3_muladd_2(&w2, &w1, &w0, x[12], x[15]);
|
|
word3_muladd_2(&w2, &w1, &w0, x[13], x[14]);
|
|
z[27] = w0; w0 = 0;
|
|
|
|
word3_muladd_2(&w0, &w2, &w1, x[13], x[15]);
|
|
word3_muladd(&w0, &w2, &w1, x[14], x[14]);
|
|
z[28] = w1; w1 = 0;
|
|
|
|
word3_muladd_2(&w1, &w0, &w2, x[14], x[15]);
|
|
z[29] = w2; w2 = 0;
|
|
|
|
word3_muladd(&w2, &w1, &w0, x[15], x[15]);
|
|
z[30] = w0;
|
|
z[31] = w1;
|
|
}
|
|
|
|
/*
|
|
* Comba 16x16 Multiplication
|
|
*/
|
|
void bigint_comba_mul16(word z[32], const word x[16], const word y[16])
|
|
{
|
|
word w2 = 0, w1 = 0, w0 = 0;
|
|
|
|
word3_muladd(&w2, &w1, &w0, x[ 0], y[ 0]);
|
|
z[ 0] = w0; w0 = 0;
|
|
|
|
word3_muladd(&w0, &w2, &w1, x[ 0], y[ 1]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 1], y[ 0]);
|
|
z[ 1] = w1; w1 = 0;
|
|
|
|
word3_muladd(&w1, &w0, &w2, x[ 0], y[ 2]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 1], y[ 1]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 2], y[ 0]);
|
|
z[ 2] = w2; w2 = 0;
|
|
|
|
word3_muladd(&w2, &w1, &w0, x[ 0], y[ 3]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 1], y[ 2]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 2], y[ 1]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 3], y[ 0]);
|
|
z[ 3] = w0; w0 = 0;
|
|
|
|
word3_muladd(&w0, &w2, &w1, x[ 0], y[ 4]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 1], y[ 3]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 2], y[ 2]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 3], y[ 1]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 4], y[ 0]);
|
|
z[ 4] = w1; w1 = 0;
|
|
|
|
word3_muladd(&w1, &w0, &w2, x[ 0], y[ 5]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 1], y[ 4]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 2], y[ 3]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 3], y[ 2]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 4], y[ 1]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 5], y[ 0]);
|
|
z[ 5] = w2; w2 = 0;
|
|
|
|
word3_muladd(&w2, &w1, &w0, x[ 0], y[ 6]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 1], y[ 5]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 2], y[ 4]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 3], y[ 3]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 4], y[ 2]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 5], y[ 1]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 6], y[ 0]);
|
|
z[ 6] = w0; w0 = 0;
|
|
|
|
word3_muladd(&w0, &w2, &w1, x[ 0], y[ 7]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 1], y[ 6]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 2], y[ 5]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 3], y[ 4]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 4], y[ 3]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 5], y[ 2]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 6], y[ 1]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 7], y[ 0]);
|
|
z[ 7] = w1; w1 = 0;
|
|
|
|
word3_muladd(&w1, &w0, &w2, x[ 0], y[ 8]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 1], y[ 7]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 2], y[ 6]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 3], y[ 5]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 4], y[ 4]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 5], y[ 3]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 6], y[ 2]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 7], y[ 1]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 8], y[ 0]);
|
|
z[ 8] = w2; w2 = 0;
|
|
|
|
word3_muladd(&w2, &w1, &w0, x[ 0], y[ 9]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 1], y[ 8]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 2], y[ 7]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 3], y[ 6]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 4], y[ 5]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 5], y[ 4]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 6], y[ 3]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 7], y[ 2]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 8], y[ 1]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 9], y[ 0]);
|
|
z[ 9] = w0; w0 = 0;
|
|
|
|
word3_muladd(&w0, &w2, &w1, x[ 0], y[10]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 1], y[ 9]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 2], y[ 8]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 3], y[ 7]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 4], y[ 6]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 5], y[ 5]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 6], y[ 4]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 7], y[ 3]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 8], y[ 2]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 9], y[ 1]);
|
|
word3_muladd(&w0, &w2, &w1, x[10], y[ 0]);
|
|
z[10] = w1; w1 = 0;
|
|
|
|
word3_muladd(&w1, &w0, &w2, x[ 0], y[11]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 1], y[10]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 2], y[ 9]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 3], y[ 8]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 4], y[ 7]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 5], y[ 6]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 6], y[ 5]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 7], y[ 4]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 8], y[ 3]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 9], y[ 2]);
|
|
word3_muladd(&w1, &w0, &w2, x[10], y[ 1]);
|
|
word3_muladd(&w1, &w0, &w2, x[11], y[ 0]);
|
|
z[11] = w2; w2 = 0;
|
|
|
|
word3_muladd(&w2, &w1, &w0, x[ 0], y[12]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 1], y[11]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 2], y[10]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 3], y[ 9]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 4], y[ 8]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 5], y[ 7]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 6], y[ 6]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 7], y[ 5]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 8], y[ 4]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 9], y[ 3]);
|
|
word3_muladd(&w2, &w1, &w0, x[10], y[ 2]);
|
|
word3_muladd(&w2, &w1, &w0, x[11], y[ 1]);
|
|
word3_muladd(&w2, &w1, &w0, x[12], y[ 0]);
|
|
z[12] = w0; w0 = 0;
|
|
|
|
word3_muladd(&w0, &w2, &w1, x[ 0], y[13]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 1], y[12]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 2], y[11]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 3], y[10]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 4], y[ 9]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 5], y[ 8]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 6], y[ 7]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 7], y[ 6]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 8], y[ 5]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 9], y[ 4]);
|
|
word3_muladd(&w0, &w2, &w1, x[10], y[ 3]);
|
|
word3_muladd(&w0, &w2, &w1, x[11], y[ 2]);
|
|
word3_muladd(&w0, &w2, &w1, x[12], y[ 1]);
|
|
word3_muladd(&w0, &w2, &w1, x[13], y[ 0]);
|
|
z[13] = w1; w1 = 0;
|
|
|
|
word3_muladd(&w1, &w0, &w2, x[ 0], y[14]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 1], y[13]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 2], y[12]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 3], y[11]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 4], y[10]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 5], y[ 9]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 6], y[ 8]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 7], y[ 7]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 8], y[ 6]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 9], y[ 5]);
|
|
word3_muladd(&w1, &w0, &w2, x[10], y[ 4]);
|
|
word3_muladd(&w1, &w0, &w2, x[11], y[ 3]);
|
|
word3_muladd(&w1, &w0, &w2, x[12], y[ 2]);
|
|
word3_muladd(&w1, &w0, &w2, x[13], y[ 1]);
|
|
word3_muladd(&w1, &w0, &w2, x[14], y[ 0]);
|
|
z[14] = w2; w2 = 0;
|
|
|
|
word3_muladd(&w2, &w1, &w0, x[ 0], y[15]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 1], y[14]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 2], y[13]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 3], y[12]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 4], y[11]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 5], y[10]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 6], y[ 9]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 7], y[ 8]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 8], y[ 7]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 9], y[ 6]);
|
|
word3_muladd(&w2, &w1, &w0, x[10], y[ 5]);
|
|
word3_muladd(&w2, &w1, &w0, x[11], y[ 4]);
|
|
word3_muladd(&w2, &w1, &w0, x[12], y[ 3]);
|
|
word3_muladd(&w2, &w1, &w0, x[13], y[ 2]);
|
|
word3_muladd(&w2, &w1, &w0, x[14], y[ 1]);
|
|
word3_muladd(&w2, &w1, &w0, x[15], y[ 0]);
|
|
z[15] = w0; w0 = 0;
|
|
|
|
word3_muladd(&w0, &w2, &w1, x[ 1], y[15]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 2], y[14]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 3], y[13]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 4], y[12]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 5], y[11]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 6], y[10]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 7], y[ 9]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 8], y[ 8]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 9], y[ 7]);
|
|
word3_muladd(&w0, &w2, &w1, x[10], y[ 6]);
|
|
word3_muladd(&w0, &w2, &w1, x[11], y[ 5]);
|
|
word3_muladd(&w0, &w2, &w1, x[12], y[ 4]);
|
|
word3_muladd(&w0, &w2, &w1, x[13], y[ 3]);
|
|
word3_muladd(&w0, &w2, &w1, x[14], y[ 2]);
|
|
word3_muladd(&w0, &w2, &w1, x[15], y[ 1]);
|
|
z[16] = w1; w1 = 0;
|
|
|
|
word3_muladd(&w1, &w0, &w2, x[ 2], y[15]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 3], y[14]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 4], y[13]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 5], y[12]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 6], y[11]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 7], y[10]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 8], y[ 9]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 9], y[ 8]);
|
|
word3_muladd(&w1, &w0, &w2, x[10], y[ 7]);
|
|
word3_muladd(&w1, &w0, &w2, x[11], y[ 6]);
|
|
word3_muladd(&w1, &w0, &w2, x[12], y[ 5]);
|
|
word3_muladd(&w1, &w0, &w2, x[13], y[ 4]);
|
|
word3_muladd(&w1, &w0, &w2, x[14], y[ 3]);
|
|
word3_muladd(&w1, &w0, &w2, x[15], y[ 2]);
|
|
z[17] = w2; w2 = 0;
|
|
|
|
word3_muladd(&w2, &w1, &w0, x[ 3], y[15]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 4], y[14]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 5], y[13]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 6], y[12]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 7], y[11]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 8], y[10]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 9], y[ 9]);
|
|
word3_muladd(&w2, &w1, &w0, x[10], y[ 8]);
|
|
word3_muladd(&w2, &w1, &w0, x[11], y[ 7]);
|
|
word3_muladd(&w2, &w1, &w0, x[12], y[ 6]);
|
|
word3_muladd(&w2, &w1, &w0, x[13], y[ 5]);
|
|
word3_muladd(&w2, &w1, &w0, x[14], y[ 4]);
|
|
word3_muladd(&w2, &w1, &w0, x[15], y[ 3]);
|
|
z[18] = w0; w0 = 0;
|
|
|
|
word3_muladd(&w0, &w2, &w1, x[ 4], y[15]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 5], y[14]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 6], y[13]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 7], y[12]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 8], y[11]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 9], y[10]);
|
|
word3_muladd(&w0, &w2, &w1, x[10], y[ 9]);
|
|
word3_muladd(&w0, &w2, &w1, x[11], y[ 8]);
|
|
word3_muladd(&w0, &w2, &w1, x[12], y[ 7]);
|
|
word3_muladd(&w0, &w2, &w1, x[13], y[ 6]);
|
|
word3_muladd(&w0, &w2, &w1, x[14], y[ 5]);
|
|
word3_muladd(&w0, &w2, &w1, x[15], y[ 4]);
|
|
z[19] = w1; w1 = 0;
|
|
|
|
word3_muladd(&w1, &w0, &w2, x[ 5], y[15]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 6], y[14]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 7], y[13]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 8], y[12]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 9], y[11]);
|
|
word3_muladd(&w1, &w0, &w2, x[10], y[10]);
|
|
word3_muladd(&w1, &w0, &w2, x[11], y[ 9]);
|
|
word3_muladd(&w1, &w0, &w2, x[12], y[ 8]);
|
|
word3_muladd(&w1, &w0, &w2, x[13], y[ 7]);
|
|
word3_muladd(&w1, &w0, &w2, x[14], y[ 6]);
|
|
word3_muladd(&w1, &w0, &w2, x[15], y[ 5]);
|
|
z[20] = w2; w2 = 0;
|
|
|
|
word3_muladd(&w2, &w1, &w0, x[ 6], y[15]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 7], y[14]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 8], y[13]);
|
|
word3_muladd(&w2, &w1, &w0, x[ 9], y[12]);
|
|
word3_muladd(&w2, &w1, &w0, x[10], y[11]);
|
|
word3_muladd(&w2, &w1, &w0, x[11], y[10]);
|
|
word3_muladd(&w2, &w1, &w0, x[12], y[ 9]);
|
|
word3_muladd(&w2, &w1, &w0, x[13], y[ 8]);
|
|
word3_muladd(&w2, &w1, &w0, x[14], y[ 7]);
|
|
word3_muladd(&w2, &w1, &w0, x[15], y[ 6]);
|
|
z[21] = w0; w0 = 0;
|
|
|
|
word3_muladd(&w0, &w2, &w1, x[ 7], y[15]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 8], y[14]);
|
|
word3_muladd(&w0, &w2, &w1, x[ 9], y[13]);
|
|
word3_muladd(&w0, &w2, &w1, x[10], y[12]);
|
|
word3_muladd(&w0, &w2, &w1, x[11], y[11]);
|
|
word3_muladd(&w0, &w2, &w1, x[12], y[10]);
|
|
word3_muladd(&w0, &w2, &w1, x[13], y[ 9]);
|
|
word3_muladd(&w0, &w2, &w1, x[14], y[ 8]);
|
|
word3_muladd(&w0, &w2, &w1, x[15], y[ 7]);
|
|
z[22] = w1; w1 = 0;
|
|
|
|
word3_muladd(&w1, &w0, &w2, x[ 8], y[15]);
|
|
word3_muladd(&w1, &w0, &w2, x[ 9], y[14]);
|
|
word3_muladd(&w1, &w0, &w2, x[10], y[13]);
|
|
word3_muladd(&w1, &w0, &w2, x[11], y[12]);
|
|
word3_muladd(&w1, &w0, &w2, x[12], y[11]);
|
|
word3_muladd(&w1, &w0, &w2, x[13], y[10]);
|
|
word3_muladd(&w1, &w0, &w2, x[14], y[ 9]);
|
|
word3_muladd(&w1, &w0, &w2, x[15], y[ 8]);
|
|
z[23] = w2; w2 = 0;
|
|
|
|
word3_muladd(&w2, &w1, &w0, x[ 9], y[15]);
|
|
word3_muladd(&w2, &w1, &w0, x[10], y[14]);
|
|
word3_muladd(&w2, &w1, &w0, x[11], y[13]);
|
|
word3_muladd(&w2, &w1, &w0, x[12], y[12]);
|
|
word3_muladd(&w2, &w1, &w0, x[13], y[11]);
|
|
word3_muladd(&w2, &w1, &w0, x[14], y[10]);
|
|
word3_muladd(&w2, &w1, &w0, x[15], y[ 9]);
|
|
z[24] = w0; w0 = 0;
|
|
|
|
word3_muladd(&w0, &w2, &w1, x[10], y[15]);
|
|
word3_muladd(&w0, &w2, &w1, x[11], y[14]);
|
|
word3_muladd(&w0, &w2, &w1, x[12], y[13]);
|
|
word3_muladd(&w0, &w2, &w1, x[13], y[12]);
|
|
word3_muladd(&w0, &w2, &w1, x[14], y[11]);
|
|
word3_muladd(&w0, &w2, &w1, x[15], y[10]);
|
|
z[25] = w1; w1 = 0;
|
|
|
|
word3_muladd(&w1, &w0, &w2, x[11], y[15]);
|
|
word3_muladd(&w1, &w0, &w2, x[12], y[14]);
|
|
word3_muladd(&w1, &w0, &w2, x[13], y[13]);
|
|
word3_muladd(&w1, &w0, &w2, x[14], y[12]);
|
|
word3_muladd(&w1, &w0, &w2, x[15], y[11]);
|
|
z[26] = w2; w2 = 0;
|
|
|
|
word3_muladd(&w2, &w1, &w0, x[12], y[15]);
|
|
word3_muladd(&w2, &w1, &w0, x[13], y[14]);
|
|
word3_muladd(&w2, &w1, &w0, x[14], y[13]);
|
|
word3_muladd(&w2, &w1, &w0, x[15], y[12]);
|
|
z[27] = w0; w0 = 0;
|
|
|
|
word3_muladd(&w0, &w2, &w1, x[13], y[15]);
|
|
word3_muladd(&w0, &w2, &w1, x[14], y[14]);
|
|
word3_muladd(&w0, &w2, &w1, x[15], y[13]);
|
|
z[28] = w1; w1 = 0;
|
|
|
|
word3_muladd(&w1, &w0, &w2, x[14], y[15]);
|
|
word3_muladd(&w1, &w0, &w2, x[15], y[14]);
|
|
z[29] = w2; w2 = 0;
|
|
|
|
word3_muladd(&w2, &w1, &w0, x[15], y[15]);
|
|
z[30] = w0;
|
|
z[31] = w1;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
/*
|
|
* Karatsuba Multiplication/Squaring
|
|
* (C) 1999-2010 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
namespace {
|
|
|
|
/*
|
|
* Karatsuba Multiplication Operation
|
|
*/
|
|
void karatsuba_mul(word z[], const word x[], const word y[], size_t N,
|
|
word workspace[])
|
|
{
|
|
if(N < BOTAN_KARAT_MUL_THRESHOLD || N % 2)
|
|
{
|
|
if(N == 6)
|
|
return bigint_comba_mul6(z, x, y);
|
|
else if(N == 8)
|
|
return bigint_comba_mul8(z, x, y);
|
|
else if(N == 16)
|
|
return bigint_comba_mul16(z, x, y);
|
|
else
|
|
return bigint_simple_mul(z, x, N, y, N);
|
|
}
|
|
|
|
const size_t N2 = N / 2;
|
|
|
|
const word* x0 = x;
|
|
const word* x1 = x + N2;
|
|
const word* y0 = y;
|
|
const word* y1 = y + N2;
|
|
word* z0 = z;
|
|
word* z1 = z + N;
|
|
|
|
const s32bit cmp0 = bigint_cmp(x0, N2, x1, N2);
|
|
const s32bit cmp1 = bigint_cmp(y1, N2, y0, N2);
|
|
|
|
clear_mem(workspace, 2*N);
|
|
|
|
if(cmp0 && cmp1)
|
|
{
|
|
if(cmp0 > 0)
|
|
bigint_sub3(z0, x0, N2, x1, N2);
|
|
else
|
|
bigint_sub3(z0, x1, N2, x0, N2);
|
|
|
|
if(cmp1 > 0)
|
|
bigint_sub3(z1, y1, N2, y0, N2);
|
|
else
|
|
bigint_sub3(z1, y0, N2, y1, N2);
|
|
|
|
karatsuba_mul(workspace, z0, z1, N2, workspace+N);
|
|
}
|
|
|
|
karatsuba_mul(z0, x0, y0, N2, workspace+N);
|
|
karatsuba_mul(z1, x1, y1, N2, workspace+N);
|
|
|
|
const size_t blocks_of_8 = N - (N % 8);
|
|
|
|
word ws_carry = 0;
|
|
|
|
for(size_t j = 0; j != blocks_of_8; j += 8)
|
|
ws_carry = word8_add3(workspace + N + j, z0 + j, z1 + j, ws_carry);
|
|
|
|
for(size_t j = blocks_of_8; j != N; ++j)
|
|
workspace[N + j] = word_add(z0[j], z1[j], &ws_carry);
|
|
|
|
word z_carry = 0;
|
|
|
|
for(size_t j = 0; j != blocks_of_8; j += 8)
|
|
z_carry = word8_add2(z + N2 + j, workspace + N + j, z_carry);
|
|
|
|
for(size_t j = blocks_of_8; j != N; ++j)
|
|
z[N2 + j] = word_add(z[N2 + j], workspace[N + j], &z_carry);
|
|
|
|
z[N + N2] = word_add(z[N + N2], ws_carry, &z_carry);
|
|
|
|
if(z_carry)
|
|
for(size_t j = 1; j != N2; ++j)
|
|
if(++z[N + N2 + j])
|
|
break;
|
|
|
|
if((cmp0 == cmp1) || (cmp0 == 0) || (cmp1 == 0))
|
|
bigint_add2(z + N2, 2*N-N2, workspace, N);
|
|
else
|
|
bigint_sub2(z + N2, 2*N-N2, workspace, N);
|
|
}
|
|
|
|
/*
|
|
* Karatsuba Squaring Operation
|
|
*/
|
|
void karatsuba_sqr(word z[], const word x[], size_t N, word workspace[])
|
|
{
|
|
if(N < BOTAN_KARAT_SQR_THRESHOLD || N % 2)
|
|
{
|
|
if(N == 6)
|
|
return bigint_comba_sqr6(z, x);
|
|
else if(N == 8)
|
|
return bigint_comba_sqr8(z, x);
|
|
else if(N == 16)
|
|
return bigint_comba_sqr16(z, x);
|
|
else
|
|
return bigint_simple_sqr(z, x, N);
|
|
}
|
|
|
|
const size_t N2 = N / 2;
|
|
|
|
const word* x0 = x;
|
|
const word* x1 = x + N2;
|
|
word* z0 = z;
|
|
word* z1 = z + N;
|
|
|
|
const s32bit cmp = bigint_cmp(x0, N2, x1, N2);
|
|
|
|
clear_mem(workspace, 2*N);
|
|
|
|
if(cmp)
|
|
{
|
|
if(cmp > 0)
|
|
bigint_sub3(z0, x0, N2, x1, N2);
|
|
else
|
|
bigint_sub3(z0, x1, N2, x0, N2);
|
|
|
|
karatsuba_sqr(workspace, z0, N2, workspace+N);
|
|
}
|
|
|
|
karatsuba_sqr(z0, x0, N2, workspace+N);
|
|
karatsuba_sqr(z1, x1, N2, workspace+N);
|
|
|
|
const size_t blocks_of_8 = N - (N % 8);
|
|
|
|
word ws_carry = 0;
|
|
|
|
for(size_t j = 0; j != blocks_of_8; j += 8)
|
|
ws_carry = word8_add3(workspace + N + j, z0 + j, z1 + j, ws_carry);
|
|
|
|
for(size_t j = blocks_of_8; j != N; ++j)
|
|
workspace[N + j] = word_add(z0[j], z1[j], &ws_carry);
|
|
|
|
word z_carry = 0;
|
|
|
|
for(size_t j = 0; j != blocks_of_8; j += 8)
|
|
z_carry = word8_add2(z + N2 + j, workspace + N + j, z_carry);
|
|
|
|
for(size_t j = blocks_of_8; j != N; ++j)
|
|
z[N2 + j] = word_add(z[N2 + j], workspace[N + j], &z_carry);
|
|
|
|
z[N + N2] = word_add(z[N + N2], ws_carry, &z_carry);
|
|
|
|
if(z_carry)
|
|
for(size_t j = 1; j != N2; ++j)
|
|
if(++z[N + N2 + j])
|
|
break;
|
|
|
|
/*
|
|
* This is only actually required if cmp is != 0, however
|
|
* if cmp==0 then workspace[0:N] == 0 and avoiding the jump
|
|
* hides a timing channel.
|
|
*/
|
|
bigint_sub2(z + N2, 2*N-N2, workspace, N);
|
|
}
|
|
|
|
/*
|
|
* Pick a good size for the Karatsuba multiply
|
|
*/
|
|
size_t karatsuba_size(size_t z_size,
|
|
size_t x_size, size_t x_sw,
|
|
size_t y_size, size_t y_sw)
|
|
{
|
|
if(x_sw > x_size || x_sw > y_size || y_sw > x_size || y_sw > y_size)
|
|
return 0;
|
|
|
|
if(((x_size == x_sw) && (x_size % 2)) ||
|
|
((y_size == y_sw) && (y_size % 2)))
|
|
return 0;
|
|
|
|
const size_t start = (x_sw > y_sw) ? x_sw : y_sw;
|
|
const size_t end = (x_size < y_size) ? x_size : y_size;
|
|
|
|
if(start == end)
|
|
{
|
|
if(start % 2)
|
|
return 0;
|
|
return start;
|
|
}
|
|
|
|
for(size_t j = start; j <= end; ++j)
|
|
{
|
|
if(j % 2)
|
|
continue;
|
|
|
|
if(2*j > z_size)
|
|
return 0;
|
|
|
|
if(x_sw <= j && j <= x_size && y_sw <= j && j <= y_size)
|
|
{
|
|
if(j % 4 == 2 &&
|
|
(j+2) <= x_size && (j+2) <= y_size && 2*(j+2) <= z_size)
|
|
return j+2;
|
|
return j;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Pick a good size for the Karatsuba squaring
|
|
*/
|
|
size_t karatsuba_size(size_t z_size, size_t x_size, size_t x_sw)
|
|
{
|
|
if(x_sw == x_size)
|
|
{
|
|
if(x_sw % 2)
|
|
return 0;
|
|
return x_sw;
|
|
}
|
|
|
|
for(size_t j = x_sw; j <= x_size; ++j)
|
|
{
|
|
if(j % 2)
|
|
continue;
|
|
|
|
if(2*j > z_size)
|
|
return 0;
|
|
|
|
if(j % 4 == 2 && (j+2) <= x_size && 2*(j+2) <= z_size)
|
|
return j+2;
|
|
return j;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
* Multiplication Algorithm Dispatcher
|
|
*/
|
|
void bigint_mul(word z[], size_t z_size, word workspace[],
|
|
const word x[], size_t x_size, size_t x_sw,
|
|
const word y[], size_t y_size, size_t y_sw)
|
|
{
|
|
if(x_sw == 1)
|
|
{
|
|
bigint_linmul3(z, y, y_sw, x[0]);
|
|
}
|
|
else if(y_sw == 1)
|
|
{
|
|
bigint_linmul3(z, x, x_sw, y[0]);
|
|
}
|
|
else if(x_sw <= 4 && x_size >= 4 &&
|
|
y_sw <= 4 && y_size >= 4 && z_size >= 8)
|
|
{
|
|
bigint_comba_mul4(z, x, y);
|
|
}
|
|
else if(x_sw <= 6 && x_size >= 6 &&
|
|
y_sw <= 6 && y_size >= 6 && z_size >= 12)
|
|
{
|
|
bigint_comba_mul6(z, x, y);
|
|
}
|
|
else if(x_sw <= 8 && x_size >= 8 &&
|
|
y_sw <= 8 && y_size >= 8 && z_size >= 16)
|
|
{
|
|
bigint_comba_mul8(z, x, y);
|
|
}
|
|
else if(x_sw <= 16 && x_size >= 16 &&
|
|
y_sw <= 16 && y_size >= 16 && z_size >= 32)
|
|
{
|
|
bigint_comba_mul16(z, x, y);
|
|
}
|
|
else if(x_sw < BOTAN_KARAT_MUL_THRESHOLD ||
|
|
y_sw < BOTAN_KARAT_MUL_THRESHOLD ||
|
|
!workspace)
|
|
{
|
|
bigint_simple_mul(z, x, x_sw, y, y_sw);
|
|
}
|
|
else
|
|
{
|
|
const size_t N = karatsuba_size(z_size, x_size, x_sw, y_size, y_sw);
|
|
|
|
if(N)
|
|
{
|
|
clear_mem(workspace, 2*N);
|
|
karatsuba_mul(z, x, y, N, workspace);
|
|
}
|
|
else
|
|
bigint_simple_mul(z, x, x_sw, y, y_sw);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Squaring Algorithm Dispatcher
|
|
*/
|
|
void bigint_sqr(word z[], size_t z_size, word workspace[],
|
|
const word x[], size_t x_size, size_t x_sw)
|
|
{
|
|
if(x_sw == 1)
|
|
{
|
|
bigint_linmul3(z, x, x_sw, x[0]);
|
|
}
|
|
else if(x_sw <= 4 && x_size >= 4 && z_size >= 8)
|
|
{
|
|
bigint_comba_sqr4(z, x);
|
|
}
|
|
else if(x_sw <= 6 && x_size >= 6 && z_size >= 12)
|
|
{
|
|
bigint_comba_sqr6(z, x);
|
|
}
|
|
else if(x_sw <= 8 && x_size >= 8 && z_size >= 16)
|
|
{
|
|
bigint_comba_sqr8(z, x);
|
|
}
|
|
else if(x_sw <= 16 && x_size >= 16 && z_size >= 32)
|
|
{
|
|
bigint_comba_sqr16(z, x);
|
|
}
|
|
else if(x_size < BOTAN_KARAT_SQR_THRESHOLD || !workspace)
|
|
{
|
|
bigint_simple_sqr(z, x, x_sw);
|
|
}
|
|
else
|
|
{
|
|
const size_t N = karatsuba_size(z_size, x_size, x_sw);
|
|
|
|
if(N)
|
|
{
|
|
clear_mem(workspace, 2*N);
|
|
karatsuba_sqr(z, x, N, workspace);
|
|
}
|
|
else
|
|
bigint_simple_sqr(z, x, x_sw);
|
|
}
|
|
}
|
|
|
|
}
|
|
/*
|
|
* MP Misc Functions
|
|
* (C) 1999-2008 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
extern "C" {
|
|
|
|
/*
|
|
* Core Division Operation
|
|
*/
|
|
size_t bigint_divcore(word q, word y2, word y1,
|
|
word x3, word x2, word x1)
|
|
{
|
|
// Compute (y2,y1) * q
|
|
|
|
word y3 = 0;
|
|
y1 = word_madd2(q, y1, &y3);
|
|
y2 = word_madd2(q, y2, &y3);
|
|
|
|
// Return (y3,y2,y1) >? (x3,x2,x1)
|
|
|
|
if(y3 > x3) return 1;
|
|
if(y3 < x3) return 0;
|
|
if(y2 > x2) return 1;
|
|
if(y2 < x2) return 0;
|
|
if(y1 > x1) return 1;
|
|
if(y1 < x1) return 0;
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Compare two MP integers
|
|
*/
|
|
s32bit bigint_cmp(const word x[], size_t x_size,
|
|
const word y[], size_t y_size)
|
|
{
|
|
if(x_size < y_size) { return (-bigint_cmp(y, y_size, x, x_size)); }
|
|
|
|
while(x_size > y_size)
|
|
{
|
|
if(x[x_size-1])
|
|
return 1;
|
|
x_size--;
|
|
}
|
|
|
|
for(size_t j = x_size; j > 0; --j)
|
|
{
|
|
if(x[j-1] > y[j-1])
|
|
return 1;
|
|
if(x[j-1] < y[j-1])
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Do a 2-word/1-word Division
|
|
*/
|
|
word bigint_divop(word n1, word n0, word d)
|
|
{
|
|
word high = n1 % d, quotient = 0;
|
|
|
|
for(size_t j = 0; j != MP_WORD_BITS; ++j)
|
|
{
|
|
word high_top_bit = (high & MP_WORD_TOP_BIT);
|
|
|
|
high <<= 1;
|
|
high |= (n0 >> (MP_WORD_BITS-1-j)) & 1;
|
|
quotient <<= 1;
|
|
|
|
if(high_top_bit || high >= d)
|
|
{
|
|
high -= d;
|
|
quotient |= 1;
|
|
}
|
|
}
|
|
|
|
return quotient;
|
|
}
|
|
|
|
/*
|
|
* Do a 2-word/1-word Modulo
|
|
*/
|
|
word bigint_modop(word n1, word n0, word d)
|
|
{
|
|
word z = bigint_divop(n1, n0, d);
|
|
word dummy = 0;
|
|
z = word_madd2(z, d, &dummy);
|
|
return (n0-z);
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
/*
|
|
* Montgomery Reduction
|
|
* (C) 1999-2011 Jack Lloyd
|
|
* 2006 Luca Piccarreta
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
extern "C" {
|
|
|
|
/*
|
|
* Montgomery Reduction Algorithm
|
|
*/
|
|
void bigint_monty_redc(word z[], size_t z_size,
|
|
const word p[], size_t p_size,
|
|
word p_dash, word ws[])
|
|
{
|
|
const size_t blocks_of_8 = p_size - (p_size % 8);
|
|
|
|
for(size_t i = 0; i != p_size; ++i)
|
|
{
|
|
word* z_i = z + i;
|
|
|
|
const word y = z_i[0] * p_dash;
|
|
|
|
/*
|
|
bigint_linmul3(ws, p, p_size, y);
|
|
bigint_add2(z_i, z_size - i, ws, p_size+1);
|
|
*/
|
|
|
|
word carry = 0;
|
|
|
|
for(size_t j = 0; j != blocks_of_8; j += 8)
|
|
carry = word8_madd3(z_i + j, p + j, y, carry);
|
|
|
|
for(size_t j = blocks_of_8; j != p_size; ++j)
|
|
z_i[j] = word_madd3(p[j], y, z_i[j], &carry);
|
|
|
|
word z_sum = z_i[p_size] + carry;
|
|
carry = (z_sum < z_i[p_size]);
|
|
z_i[p_size] = z_sum;
|
|
|
|
for(size_t j = p_size + 1; carry && j != z_size - i; ++j)
|
|
{
|
|
++z_i[j];
|
|
carry = !z_i[j];
|
|
}
|
|
}
|
|
|
|
word borrow = 0;
|
|
for(size_t i = 0; i != p_size; ++i)
|
|
ws[i] = word_sub(z[p_size + i], p[i], &borrow);
|
|
|
|
ws[p_size] = word_sub(z[p_size+p_size], 0, &borrow);
|
|
|
|
copy_mem(ws + p_size + 1, z + p_size, p_size + 1);
|
|
|
|
copy_mem(z, ws + borrow*(p_size+1), p_size + 1);
|
|
clear_mem(z + p_size + 1, z_size - p_size - 1);
|
|
}
|
|
|
|
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 ws[])
|
|
{
|
|
bigint_mul(&z[0], z_size, &ws[0],
|
|
&x[0], x_size, x_sw,
|
|
&y[0], y_size, y_sw);
|
|
|
|
bigint_monty_redc(&z[0], z_size,
|
|
&p[0], p_size, p_dash,
|
|
&ws[0]);
|
|
}
|
|
|
|
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 ws[])
|
|
{
|
|
bigint_sqr(&z[0], z_size, &ws[0],
|
|
&x[0], x_size, x_sw);
|
|
|
|
bigint_monty_redc(&z[0], z_size,
|
|
&p[0], p_size, p_dash,
|
|
&ws[0]);
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
/*
|
|
* Simple O(N^2) Multiplication and Squaring
|
|
* (C) 1999-2008 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
extern "C" {
|
|
|
|
/*
|
|
* Simple O(N^2) Multiplication
|
|
*/
|
|
void bigint_simple_mul(word z[], const word x[], size_t x_size,
|
|
const word y[], size_t y_size)
|
|
{
|
|
const size_t x_size_8 = x_size - (x_size % 8);
|
|
|
|
clear_mem(z, x_size + y_size);
|
|
|
|
for(size_t i = 0; i != y_size; ++i)
|
|
{
|
|
const word y_i = y[i];
|
|
|
|
word carry = 0;
|
|
|
|
for(size_t j = 0; j != x_size_8; j += 8)
|
|
carry = word8_madd3(z + i + j, x + j, y_i, carry);
|
|
|
|
for(size_t j = x_size_8; j != x_size; ++j)
|
|
z[i+j] = word_madd3(x[j], y_i, z[i+j], &carry);
|
|
|
|
z[x_size+i] = carry;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Simple O(N^2) Squaring
|
|
*
|
|
* This is exactly the same algorithm as bigint_simple_mul, however
|
|
* because C/C++ compilers suck at alias analysis it is good to have
|
|
* the version where the compiler knows that x == y
|
|
*
|
|
* There is an O(n^1.5) squaring algorithm specified in Handbook of
|
|
* Applied Cryptography, chapter 14
|
|
*
|
|
*/
|
|
void bigint_simple_sqr(word z[], const word x[], size_t x_size)
|
|
{
|
|
const size_t x_size_8 = x_size - (x_size % 8);
|
|
|
|
clear_mem(z, 2*x_size);
|
|
|
|
for(size_t i = 0; i != x_size; ++i)
|
|
{
|
|
const word x_i = x[i];
|
|
word carry = 0;
|
|
|
|
for(size_t j = 0; j != x_size_8; j += 8)
|
|
carry = word8_madd3(z + i + j, x + j, x_i, carry);
|
|
|
|
for(size_t j = x_size_8; j != x_size; ++j)
|
|
z[i+j] = word_madd3(x[j], x_i, z[i+j], &carry);
|
|
|
|
z[x_size+i] = carry;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
/*
|
|
* MP Shift Algorithms
|
|
* (C) 1999-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
extern "C" {
|
|
|
|
/*
|
|
* Single Operand Left Shift
|
|
*/
|
|
void bigint_shl1(word x[], size_t x_size, size_t word_shift, size_t bit_shift)
|
|
{
|
|
if(word_shift)
|
|
{
|
|
for(size_t j = 1; j != x_size + 1; ++j)
|
|
x[(x_size - j) + word_shift] = x[x_size - j];
|
|
clear_mem(x, word_shift);
|
|
}
|
|
|
|
if(bit_shift)
|
|
{
|
|
word carry = 0;
|
|
for(size_t j = word_shift; j != x_size + word_shift + 1; ++j)
|
|
{
|
|
word temp = x[j];
|
|
x[j] = (temp << bit_shift) | carry;
|
|
carry = (temp >> (MP_WORD_BITS - bit_shift));
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Single Operand Right Shift
|
|
*/
|
|
void bigint_shr1(word x[], size_t x_size, size_t word_shift, size_t bit_shift)
|
|
{
|
|
if(x_size < word_shift)
|
|
{
|
|
clear_mem(x, x_size);
|
|
return;
|
|
}
|
|
|
|
if(word_shift)
|
|
{
|
|
copy_mem(x, x + word_shift, x_size - word_shift);
|
|
clear_mem(x + x_size - word_shift, word_shift);
|
|
}
|
|
|
|
if(bit_shift)
|
|
{
|
|
word carry = 0;
|
|
|
|
size_t top = x_size - word_shift;
|
|
|
|
while(top >= 4)
|
|
{
|
|
word w = x[top-1];
|
|
x[top-1] = (w >> bit_shift) | carry;
|
|
carry = (w << (MP_WORD_BITS - bit_shift));
|
|
|
|
w = x[top-2];
|
|
x[top-2] = (w >> bit_shift) | carry;
|
|
carry = (w << (MP_WORD_BITS - bit_shift));
|
|
|
|
w = x[top-3];
|
|
x[top-3] = (w >> bit_shift) | carry;
|
|
carry = (w << (MP_WORD_BITS - bit_shift));
|
|
|
|
w = x[top-4];
|
|
x[top-4] = (w >> bit_shift) | carry;
|
|
carry = (w << (MP_WORD_BITS - bit_shift));
|
|
|
|
top -= 4;
|
|
}
|
|
|
|
while(top)
|
|
{
|
|
word w = x[top-1];
|
|
x[top-1] = (w >> bit_shift) | carry;
|
|
carry = (w << (MP_WORD_BITS - bit_shift));
|
|
|
|
top--;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Two Operand Left Shift
|
|
*/
|
|
void bigint_shl2(word y[], const word x[], size_t x_size,
|
|
size_t word_shift, size_t bit_shift)
|
|
{
|
|
for(size_t j = 0; j != x_size; ++j)
|
|
y[j + word_shift] = x[j];
|
|
if(bit_shift)
|
|
{
|
|
word carry = 0;
|
|
for(size_t j = word_shift; j != x_size + word_shift + 1; ++j)
|
|
{
|
|
word w = y[j];
|
|
y[j] = (w << bit_shift) | carry;
|
|
carry = (w >> (MP_WORD_BITS - bit_shift));
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Two Operand Right Shift
|
|
*/
|
|
void bigint_shr2(word y[], const word x[], size_t x_size,
|
|
size_t word_shift, size_t bit_shift)
|
|
{
|
|
if(x_size < word_shift) return;
|
|
|
|
for(size_t j = 0; j != x_size - word_shift; ++j)
|
|
y[j] = x[j + word_shift];
|
|
if(bit_shift)
|
|
{
|
|
word carry = 0;
|
|
for(size_t j = x_size - word_shift; j > 0; --j)
|
|
{
|
|
word w = y[j-1];
|
|
y[j-1] = (w >> bit_shift) | carry;
|
|
carry = (w << (MP_WORD_BITS - bit_shift));
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
/*
|
|
* DSA Parameter Generation
|
|
* (C) 1999-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
#include <algorithm>
|
|
#include <memory>
|
|
|
|
namespace Botan {
|
|
|
|
namespace {
|
|
|
|
/*
|
|
* Check if this size is allowed by FIPS 186-3
|
|
*/
|
|
bool fips186_3_valid_size(size_t pbits, size_t qbits)
|
|
{
|
|
if(qbits == 160)
|
|
return (pbits == 512 || pbits == 768 || pbits == 1024);
|
|
|
|
if(qbits == 224)
|
|
return (pbits == 2048);
|
|
|
|
if(qbits == 256)
|
|
return (pbits == 2048 || pbits == 3072);
|
|
|
|
return false;
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
* Attempt DSA prime generation with given seed
|
|
*/
|
|
bool generate_dsa_primes(RandomNumberGenerator& rng,
|
|
Algorithm_Factory& af,
|
|
BigInt& p, BigInt& q,
|
|
size_t pbits, size_t qbits,
|
|
const MemoryRegion<byte>& seed_c)
|
|
{
|
|
if(!fips186_3_valid_size(pbits, qbits))
|
|
throw Invalid_Argument(
|
|
"FIPS 186-3 does not allow DSA domain parameters of " +
|
|
to_string(pbits) + "/" + to_string(qbits) + " bits long");
|
|
|
|
if(seed_c.size() * 8 < qbits)
|
|
throw Invalid_Argument(
|
|
"Generating a DSA parameter set with a " + to_string(qbits) +
|
|
"long q requires a seed at least as many bits long");
|
|
|
|
std::unique_ptr<HashFunction> hash(
|
|
af.make_hash_function("SHA-" + to_string(qbits)));
|
|
|
|
const size_t HASH_SIZE = hash->output_length();
|
|
|
|
class Seed
|
|
{
|
|
public:
|
|
Seed(const MemoryRegion<byte>& s) : seed(s) {}
|
|
|
|
operator MemoryRegion<byte>& () { return seed; }
|
|
|
|
Seed& operator++()
|
|
{
|
|
for(size_t j = seed.size(); j > 0; --j)
|
|
if(++seed[j-1])
|
|
break;
|
|
return (*this);
|
|
}
|
|
private:
|
|
SecureVector<byte> seed;
|
|
};
|
|
|
|
Seed seed(seed_c);
|
|
|
|
q.binary_decode(hash->process(seed));
|
|
q.set_bit(qbits-1);
|
|
q.set_bit(0);
|
|
|
|
if(!check_prime(q, rng))
|
|
return false;
|
|
|
|
const size_t n = (pbits-1) / (HASH_SIZE * 8),
|
|
b = (pbits-1) % (HASH_SIZE * 8);
|
|
|
|
BigInt X;
|
|
SecureVector<byte> V(HASH_SIZE * (n+1));
|
|
|
|
for(size_t j = 0; j != 4096; ++j)
|
|
{
|
|
for(size_t k = 0; k <= n; ++k)
|
|
{
|
|
++seed;
|
|
hash->update(seed);
|
|
hash->final(&V[HASH_SIZE * (n-k)]);
|
|
}
|
|
|
|
X.binary_decode(&V[HASH_SIZE - 1 - b/8],
|
|
V.size() - (HASH_SIZE - 1 - b/8));
|
|
X.set_bit(pbits-1);
|
|
|
|
p = X - (X % (2*q) - 1);
|
|
|
|
if(p.bits() == pbits && check_prime(p, rng))
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
* Generate DSA Primes
|
|
*/
|
|
SecureVector<byte> generate_dsa_primes(RandomNumberGenerator& rng,
|
|
Algorithm_Factory& af,
|
|
BigInt& p, BigInt& q,
|
|
size_t pbits, size_t qbits)
|
|
{
|
|
while(true)
|
|
{
|
|
SecureVector<byte> seed = rng.random_vec(qbits / 8);
|
|
|
|
if(generate_dsa_primes(rng, af, p, q, pbits, qbits, seed))
|
|
return seed;
|
|
}
|
|
}
|
|
|
|
}
|
|
/*
|
|
* Jacobi Function
|
|
* (C) 1999-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* Calculate the Jacobi symbol
|
|
*/
|
|
s32bit jacobi(const BigInt& a, const BigInt& n)
|
|
{
|
|
if(a.is_negative())
|
|
throw Invalid_Argument("jacobi: first argument must be non-negative");
|
|
if(n.is_even() || n < 2)
|
|
throw Invalid_Argument("jacobi: second argument must be odd and > 1");
|
|
|
|
BigInt x = a, y = n;
|
|
s32bit J = 1;
|
|
|
|
while(y > 1)
|
|
{
|
|
x %= y;
|
|
if(x > y / 2)
|
|
{
|
|
x = y - x;
|
|
if(y % 4 == 3)
|
|
J = -J;
|
|
}
|
|
if(x.is_zero())
|
|
return 0;
|
|
|
|
size_t shifts = low_zero_bits(x);
|
|
x >>= shifts;
|
|
if(shifts % 2)
|
|
{
|
|
word y_mod_8 = y % 8;
|
|
if(y_mod_8 == 3 || y_mod_8 == 5)
|
|
J = -J;
|
|
}
|
|
|
|
if(x % 4 == 3 && y % 4 == 3)
|
|
J = -J;
|
|
std::swap(x, y);
|
|
}
|
|
return J;
|
|
}
|
|
|
|
}
|
|
/*
|
|
* Prime Generation
|
|
* (C) 1999-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
#include <algorithm>
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* Generate a random prime
|
|
*/
|
|
BigInt random_prime(RandomNumberGenerator& rng,
|
|
size_t bits, const BigInt& coprime,
|
|
size_t equiv, size_t modulo)
|
|
{
|
|
if(bits <= 1)
|
|
throw Invalid_Argument("random_prime: Can't make a prime of " +
|
|
to_string(bits) + " bits");
|
|
else if(bits == 2)
|
|
return ((rng.next_byte() % 2) ? 2 : 3);
|
|
else if(bits == 3)
|
|
return ((rng.next_byte() % 2) ? 5 : 7);
|
|
else if(bits == 4)
|
|
return ((rng.next_byte() % 2) ? 11 : 13);
|
|
|
|
if(coprime <= 0)
|
|
throw Invalid_Argument("random_prime: coprime must be > 0");
|
|
if(modulo % 2 == 1 || modulo == 0)
|
|
throw Invalid_Argument("random_prime: Invalid modulo value");
|
|
if(equiv >= modulo || equiv % 2 == 0)
|
|
throw Invalid_Argument("random_prime: equiv must be < modulo, and odd");
|
|
|
|
while(true)
|
|
{
|
|
BigInt p(rng, bits);
|
|
|
|
// Force lowest and two top bits on
|
|
p.set_bit(bits - 1);
|
|
p.set_bit(bits - 2);
|
|
p.set_bit(0);
|
|
|
|
if(p % modulo != equiv)
|
|
p += (modulo - p % modulo) + equiv;
|
|
|
|
const size_t sieve_size = std::min(bits / 2, PRIME_TABLE_SIZE);
|
|
SecureVector<size_t> sieve(sieve_size);
|
|
|
|
for(size_t j = 0; j != sieve.size(); ++j)
|
|
sieve[j] = p % PRIMES[j];
|
|
|
|
size_t counter = 0;
|
|
while(true)
|
|
{
|
|
if(counter == 4096 || p.bits() > bits)
|
|
break;
|
|
|
|
bool passes_sieve = true;
|
|
++counter;
|
|
p += modulo;
|
|
|
|
if(p.bits() > bits)
|
|
break;
|
|
|
|
for(size_t j = 0; j != sieve.size(); ++j)
|
|
{
|
|
sieve[j] = (sieve[j] + modulo) % PRIMES[j];
|
|
if(sieve[j] == 0)
|
|
passes_sieve = false;
|
|
}
|
|
|
|
if(!passes_sieve || gcd(p - 1, coprime) != 1)
|
|
continue;
|
|
if(check_prime(p, rng))
|
|
return p;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Generate a random safe prime
|
|
*/
|
|
BigInt random_safe_prime(RandomNumberGenerator& rng, size_t bits)
|
|
{
|
|
if(bits <= 64)
|
|
throw Invalid_Argument("random_safe_prime: Can't make a prime of " +
|
|
to_string(bits) + " bits");
|
|
|
|
BigInt p;
|
|
do
|
|
p = (random_prime(rng, bits - 1) << 1) + 1;
|
|
while(!check_prime(p, rng));
|
|
return p;
|
|
}
|
|
|
|
}
|
|
/*
|
|
* Fused and Important MP Algorithms
|
|
* (C) 1999-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
#include <algorithm>
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* Square a BigInt
|
|
*/
|
|
BigInt square(const BigInt& x)
|
|
{
|
|
const size_t x_sw = x.sig_words();
|
|
|
|
BigInt z(BigInt::Positive, round_up<size_t>(2*x_sw, 16));
|
|
SecureVector<word> workspace(z.size());
|
|
|
|
bigint_sqr(z.get_reg(), z.size(), workspace,
|
|
x.data(), x.size(), x_sw);
|
|
return z;
|
|
}
|
|
|
|
/*
|
|
* Multiply-Add Operation
|
|
*/
|
|
BigInt mul_add(const BigInt& a, const BigInt& b, const BigInt& c)
|
|
{
|
|
if(c.is_negative() || c.is_zero())
|
|
throw Invalid_Argument("mul_add: Third argument must be > 0");
|
|
|
|
BigInt::Sign sign = BigInt::Positive;
|
|
if(a.sign() != b.sign())
|
|
sign = BigInt::Negative;
|
|
|
|
const size_t a_sw = a.sig_words();
|
|
const size_t b_sw = b.sig_words();
|
|
const size_t c_sw = c.sig_words();
|
|
|
|
BigInt r(sign, std::max(a.size() + b.size(), c_sw) + 1);
|
|
SecureVector<word> workspace(r.size());
|
|
|
|
bigint_mul(r.get_reg(), r.size(), workspace,
|
|
a.data(), a.size(), a_sw,
|
|
b.data(), b.size(), b_sw);
|
|
const size_t r_size = std::max(r.sig_words(), c_sw);
|
|
bigint_add2(r.get_reg(), r_size, c.data(), c_sw);
|
|
return r;
|
|
}
|
|
|
|
/*
|
|
* Subtract-Multiply Operation
|
|
*/
|
|
BigInt sub_mul(const BigInt& a, const BigInt& b, const BigInt& c)
|
|
{
|
|
if(a.is_negative() || b.is_negative())
|
|
throw Invalid_Argument("sub_mul: First two arguments must be >= 0");
|
|
|
|
BigInt r = a;
|
|
r -= b;
|
|
r *= c;
|
|
return r;
|
|
}
|
|
|
|
}
|
|
/*
|
|
* Number Theory Functions
|
|
* (C) 1999-2011 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
#include <algorithm>
|
|
|
|
namespace Botan {
|
|
|
|
namespace {
|
|
|
|
/*
|
|
* Miller-Rabin Primality Tester
|
|
*/
|
|
class MillerRabin_Test
|
|
{
|
|
public:
|
|
bool is_witness(const BigInt& nonce);
|
|
MillerRabin_Test(const BigInt& num);
|
|
private:
|
|
BigInt n, r, n_minus_1;
|
|
size_t s;
|
|
Fixed_Exponent_Power_Mod pow_mod;
|
|
Modular_Reducer reducer;
|
|
};
|
|
|
|
/*
|
|
* Miller-Rabin Test, as described in Handbook of Applied Cryptography
|
|
* section 4.24
|
|
*/
|
|
bool MillerRabin_Test::is_witness(const BigInt& a)
|
|
{
|
|
if(a < 2 || a >= n_minus_1)
|
|
throw Invalid_Argument("Bad size for nonce in Miller-Rabin test");
|
|
|
|
BigInt y = pow_mod(a);
|
|
if(y == 1 || y == n_minus_1)
|
|
return false;
|
|
|
|
for(size_t i = 1; i != s; ++i)
|
|
{
|
|
y = reducer.square(y);
|
|
|
|
if(y == 1) // found a non-trivial square root
|
|
return true;
|
|
|
|
if(y == n_minus_1) // -1, trivial square root, so give up
|
|
return false;
|
|
}
|
|
|
|
if(y != n_minus_1) // fails Fermat test
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
* Miller-Rabin Constructor
|
|
*/
|
|
MillerRabin_Test::MillerRabin_Test(const BigInt& num)
|
|
{
|
|
if(num.is_even() || num < 3)
|
|
throw Invalid_Argument("MillerRabin_Test: Invalid number for testing");
|
|
|
|
n = num;
|
|
n_minus_1 = n - 1;
|
|
s = low_zero_bits(n_minus_1);
|
|
r = n_minus_1 >> s;
|
|
|
|
pow_mod = Fixed_Exponent_Power_Mod(r, n);
|
|
reducer = Modular_Reducer(n);
|
|
}
|
|
|
|
/*
|
|
* Miller-Rabin Iterations
|
|
*/
|
|
size_t miller_rabin_test_iterations(size_t bits, size_t level)
|
|
{
|
|
struct mapping { size_t bits; size_t verify_iter; size_t check_iter; };
|
|
|
|
static const mapping tests[] = {
|
|
{ 50, 55, 25 },
|
|
{ 100, 38, 22 },
|
|
{ 160, 32, 18 },
|
|
{ 163, 31, 17 },
|
|
{ 168, 30, 16 },
|
|
{ 177, 29, 16 },
|
|
{ 181, 28, 15 },
|
|
{ 185, 27, 15 },
|
|
{ 190, 26, 15 },
|
|
{ 195, 25, 14 },
|
|
{ 201, 24, 14 },
|
|
{ 208, 23, 14 },
|
|
{ 215, 22, 13 },
|
|
{ 222, 21, 13 },
|
|
{ 231, 20, 13 },
|
|
{ 241, 19, 12 },
|
|
{ 252, 18, 12 },
|
|
{ 264, 17, 12 },
|
|
{ 278, 16, 11 },
|
|
{ 294, 15, 10 },
|
|
{ 313, 14, 9 },
|
|
{ 334, 13, 8 },
|
|
{ 360, 12, 8 },
|
|
{ 392, 11, 7 },
|
|
{ 430, 10, 7 },
|
|
{ 479, 9, 6 },
|
|
{ 542, 8, 6 },
|
|
{ 626, 7, 5 },
|
|
{ 746, 6, 4 },
|
|
{ 926, 5, 3 },
|
|
{ 1232, 4, 2 },
|
|
{ 1853, 3, 2 },
|
|
{ 0, 0, 0 }
|
|
};
|
|
|
|
for(size_t i = 0; tests[i].bits; ++i)
|
|
{
|
|
if(bits <= tests[i].bits)
|
|
{
|
|
if(level >= 2)
|
|
return tests[i].verify_iter;
|
|
else if(level == 1)
|
|
return tests[i].check_iter;
|
|
else if(level == 0)
|
|
return std::max<size_t>(tests[i].check_iter / 4, 1);
|
|
}
|
|
}
|
|
|
|
return level > 0 ? 2 : 1; // for large inputs
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
* Return the number of 0 bits at the end of n
|
|
*/
|
|
size_t low_zero_bits(const BigInt& n)
|
|
{
|
|
size_t low_zero = 0;
|
|
|
|
if(n.is_positive() && n.is_nonzero())
|
|
{
|
|
for(size_t i = 0; i != n.size(); ++i)
|
|
{
|
|
word x = n[i];
|
|
|
|
if(x)
|
|
{
|
|
low_zero += ctz(x);
|
|
break;
|
|
}
|
|
else
|
|
low_zero += BOTAN_MP_WORD_BITS;
|
|
}
|
|
}
|
|
|
|
return low_zero;
|
|
}
|
|
|
|
/*
|
|
* Calculate the GCD
|
|
*/
|
|
BigInt gcd(const BigInt& a, const BigInt& b)
|
|
{
|
|
if(a.is_zero() || b.is_zero()) return 0;
|
|
if(a == 1 || b == 1) return 1;
|
|
|
|
BigInt x = a, y = b;
|
|
x.set_sign(BigInt::Positive);
|
|
y.set_sign(BigInt::Positive);
|
|
size_t shift = std::min(low_zero_bits(x), low_zero_bits(y));
|
|
|
|
x >>= shift;
|
|
y >>= shift;
|
|
|
|
while(x.is_nonzero())
|
|
{
|
|
x >>= low_zero_bits(x);
|
|
y >>= low_zero_bits(y);
|
|
if(x >= y) { x -= y; x >>= 1; }
|
|
else { y -= x; y >>= 1; }
|
|
}
|
|
|
|
return (y << shift);
|
|
}
|
|
|
|
/*
|
|
* Calculate the LCM
|
|
*/
|
|
BigInt lcm(const BigInt& a, const BigInt& b)
|
|
{
|
|
return ((a * b) / gcd(a, b));
|
|
}
|
|
|
|
/*
|
|
* Find the Modular Inverse
|
|
*/
|
|
BigInt inverse_mod(const BigInt& n, const BigInt& mod)
|
|
{
|
|
if(mod.is_zero())
|
|
throw BigInt::DivideByZero();
|
|
if(mod.is_negative() || n.is_negative())
|
|
throw Invalid_Argument("inverse_mod: arguments must be non-negative");
|
|
|
|
if(n.is_zero() || (n.is_even() && mod.is_even()))
|
|
return 0;
|
|
|
|
BigInt x = mod, y = n, u = mod, v = n;
|
|
BigInt A = 1, B = 0, C = 0, D = 1;
|
|
|
|
while(u.is_nonzero())
|
|
{
|
|
size_t zero_bits = low_zero_bits(u);
|
|
u >>= zero_bits;
|
|
for(size_t i = 0; i != zero_bits; ++i)
|
|
{
|
|
if(A.is_odd() || B.is_odd())
|
|
{ A += y; B -= x; }
|
|
A >>= 1; B >>= 1;
|
|
}
|
|
|
|
zero_bits = low_zero_bits(v);
|
|
v >>= zero_bits;
|
|
for(size_t i = 0; i != zero_bits; ++i)
|
|
{
|
|
if(C.is_odd() || D.is_odd())
|
|
{ C += y; D -= x; }
|
|
C >>= 1; D >>= 1;
|
|
}
|
|
|
|
if(u >= v) { u -= v; A -= C; B -= D; }
|
|
else { v -= u; C -= A; D -= B; }
|
|
}
|
|
|
|
if(v != 1)
|
|
return 0;
|
|
|
|
while(D.is_negative()) D += mod;
|
|
while(D >= mod) D -= mod;
|
|
|
|
return D;
|
|
}
|
|
|
|
/*
|
|
* Modular Exponentiation
|
|
*/
|
|
BigInt power_mod(const BigInt& base, const BigInt& exp, const BigInt& mod)
|
|
{
|
|
Power_Mod pow_mod(mod);
|
|
pow_mod.set_base(base);
|
|
pow_mod.set_exponent(exp);
|
|
return pow_mod.execute();
|
|
}
|
|
|
|
/*
|
|
* Test for primaility using Miller-Rabin
|
|
*/
|
|
bool primality_test(const BigInt& n,
|
|
RandomNumberGenerator& rng,
|
|
size_t level)
|
|
{
|
|
const size_t PREF_NONCE_BITS = 64;
|
|
|
|
if(n == 2)
|
|
return true;
|
|
if(n <= 1 || n.is_even())
|
|
return false;
|
|
|
|
// Fast path testing for small numbers (<= 65521)
|
|
if(n <= PRIMES[PRIME_TABLE_SIZE-1])
|
|
{
|
|
const word num = n.word_at(0);
|
|
|
|
for(size_t i = 0; PRIMES[i]; ++i)
|
|
{
|
|
if(num == PRIMES[i])
|
|
return true;
|
|
if(num < PRIMES[i])
|
|
return false;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
if(level > 2)
|
|
level = 2;
|
|
|
|
const size_t NONCE_BITS = std::min(n.bits() - 2, PREF_NONCE_BITS);
|
|
|
|
MillerRabin_Test mr(n);
|
|
|
|
const size_t tests = miller_rabin_test_iterations(n.bits(), level);
|
|
|
|
BigInt nonce;
|
|
for(size_t i = 0; i != tests; ++i)
|
|
{
|
|
while(nonce < 2 || nonce >= (n-1))
|
|
nonce.randomize(rng, NONCE_BITS);
|
|
|
|
if(mr.is_witness(nonce))
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
}
|
|
/*
|
|
* Modular Exponentiation Proxy
|
|
* (C) 1999-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* Power_Mod Constructor
|
|
*/
|
|
Power_Mod::Power_Mod(const BigInt& n, Usage_Hints hints)
|
|
{
|
|
core = 0;
|
|
set_modulus(n, hints);
|
|
hints = NO_HINTS;
|
|
}
|
|
|
|
/*
|
|
* Power_Mod Copy Constructor
|
|
*/
|
|
Power_Mod::Power_Mod(const Power_Mod& other)
|
|
{
|
|
Q_UNUSED(hints);
|
|
core = 0;
|
|
hints = other.hints;
|
|
if(other.core)
|
|
core = other.core->copy();
|
|
}
|
|
|
|
/*
|
|
* Power_Mod Assignment Operator
|
|
*/
|
|
Power_Mod& Power_Mod::operator=(const Power_Mod& other)
|
|
{
|
|
delete core;
|
|
core = 0;
|
|
if(other.core)
|
|
core = other.core->copy();
|
|
return (*this);
|
|
}
|
|
|
|
/*
|
|
* Power_Mod Destructor
|
|
*/
|
|
Power_Mod::~Power_Mod()
|
|
{
|
|
delete core;
|
|
}
|
|
|
|
/*
|
|
* Set the modulus
|
|
*/
|
|
void Power_Mod::set_modulus(const BigInt& n, Usage_Hints hints) const
|
|
{
|
|
delete core;
|
|
core = 0;
|
|
|
|
if(n != 0)
|
|
{
|
|
Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory());
|
|
|
|
while(const Engine* engine = i.next())
|
|
{
|
|
core = engine->mod_exp(n, hints);
|
|
|
|
if(core)
|
|
break;
|
|
}
|
|
|
|
if(!core)
|
|
throw Lookup_Error("Power_Mod: Unable to find a working engine");
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Set the base
|
|
*/
|
|
void Power_Mod::set_base(const BigInt& b) const
|
|
{
|
|
if(b.is_zero() || b.is_negative())
|
|
throw Invalid_Argument("Power_Mod::set_base: arg must be > 0");
|
|
|
|
if(!core)
|
|
throw Internal_Error("Power_Mod::set_base: core was NULL");
|
|
core->set_base(b);
|
|
}
|
|
|
|
/*
|
|
* Set the exponent
|
|
*/
|
|
void Power_Mod::set_exponent(const BigInt& e) const
|
|
{
|
|
if(e.is_negative())
|
|
throw Invalid_Argument("Power_Mod::set_exponent: arg must be > 0");
|
|
|
|
if(!core)
|
|
throw Internal_Error("Power_Mod::set_exponent: core was NULL");
|
|
core->set_exponent(e);
|
|
}
|
|
|
|
/*
|
|
* Compute the result
|
|
*/
|
|
BigInt Power_Mod::execute() const
|
|
{
|
|
if(!core)
|
|
throw Internal_Error("Power_Mod::execute: core was NULL");
|
|
return core->execute();
|
|
}
|
|
|
|
/*
|
|
* Try to choose a good window size
|
|
*/
|
|
size_t Power_Mod::window_bits(size_t exp_bits, size_t,
|
|
Power_Mod::Usage_Hints hints)
|
|
{
|
|
static const size_t wsize[][2] = {
|
|
{ 1434, 7 },
|
|
{ 539, 6 },
|
|
{ 197, 4 },
|
|
{ 70, 3 },
|
|
{ 25, 2 },
|
|
{ 0, 0 }
|
|
};
|
|
|
|
size_t window_bits = 1;
|
|
|
|
if(exp_bits)
|
|
{
|
|
for(size_t j = 0; wsize[j][0]; ++j)
|
|
{
|
|
if(exp_bits >= wsize[j][0])
|
|
{
|
|
window_bits += wsize[j][1];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(hints & Power_Mod::BASE_IS_FIXED)
|
|
window_bits += 2;
|
|
if(hints & Power_Mod::EXP_IS_LARGE)
|
|
++window_bits;
|
|
|
|
return window_bits;
|
|
}
|
|
|
|
namespace {
|
|
|
|
/*
|
|
* Choose potentially useful hints
|
|
*/
|
|
Power_Mod::Usage_Hints choose_base_hints(const BigInt& b, const BigInt& n)
|
|
{
|
|
if(b == 2)
|
|
return Power_Mod::Usage_Hints(Power_Mod::BASE_IS_2 |
|
|
Power_Mod::BASE_IS_SMALL);
|
|
|
|
const size_t b_bits = b.bits();
|
|
const size_t n_bits = n.bits();
|
|
|
|
if(b_bits < n_bits / 32)
|
|
return Power_Mod::BASE_IS_SMALL;
|
|
if(b_bits > n_bits / 4)
|
|
return Power_Mod::BASE_IS_LARGE;
|
|
|
|
return Power_Mod::NO_HINTS;
|
|
}
|
|
|
|
/*
|
|
* Choose potentially useful hints
|
|
*/
|
|
Power_Mod::Usage_Hints choose_exp_hints(const BigInt& e, const BigInt& n)
|
|
{
|
|
const size_t e_bits = e.bits();
|
|
const size_t n_bits = n.bits();
|
|
|
|
if(e_bits < n_bits / 32)
|
|
return Power_Mod::BASE_IS_SMALL;
|
|
if(e_bits > n_bits / 4)
|
|
return Power_Mod::BASE_IS_LARGE;
|
|
return Power_Mod::NO_HINTS;
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
* Fixed_Exponent_Power_Mod Constructor
|
|
*/
|
|
Fixed_Exponent_Power_Mod::Fixed_Exponent_Power_Mod(const BigInt& e,
|
|
const BigInt& n,
|
|
Usage_Hints hints) :
|
|
Power_Mod(n, Usage_Hints(hints | EXP_IS_FIXED | choose_exp_hints(e, n)))
|
|
{
|
|
set_exponent(e);
|
|
}
|
|
|
|
/*
|
|
* Fixed_Base_Power_Mod Constructor
|
|
*/
|
|
Fixed_Base_Power_Mod::Fixed_Base_Power_Mod(const BigInt& b, const BigInt& n,
|
|
Usage_Hints hints) :
|
|
Power_Mod(n, Usage_Hints(hints | BASE_IS_FIXED | choose_base_hints(b, n)))
|
|
{
|
|
set_base(b);
|
|
}
|
|
|
|
}
|
|
/*
|
|
* Fixed Window Exponentiation
|
|
* (C) 1999-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
#include <vector>
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* Set the exponent
|
|
*/
|
|
void Fixed_Window_Exponentiator::set_exponent(const BigInt& e)
|
|
{
|
|
exp = e;
|
|
}
|
|
|
|
/*
|
|
* Set the base
|
|
*/
|
|
void Fixed_Window_Exponentiator::set_base(const BigInt& base)
|
|
{
|
|
window_bits = Power_Mod::window_bits(exp.bits(), base.bits(), hints);
|
|
|
|
g.resize((1 << window_bits) - 1);
|
|
g[0] = base;
|
|
for(size_t j = 1; j != g.size(); ++j)
|
|
g[j] = reducer.multiply(g[j-1], g[0]);
|
|
}
|
|
|
|
/*
|
|
* Compute the result
|
|
*/
|
|
BigInt Fixed_Window_Exponentiator::execute() const
|
|
{
|
|
const size_t exp_nibbles = (exp.bits() + window_bits - 1) / window_bits;
|
|
|
|
BigInt x = 1;
|
|
for(size_t j = exp_nibbles; j > 0; --j)
|
|
{
|
|
for(size_t k = 0; k != window_bits; ++k)
|
|
x = reducer.square(x);
|
|
|
|
if(u32bit nibble = exp.get_substring(window_bits*(j-1), window_bits))
|
|
x = reducer.multiply(x, g[nibble-1]);
|
|
}
|
|
return x;
|
|
}
|
|
|
|
/*
|
|
* Fixed_Window_Exponentiator Constructor
|
|
*/
|
|
Fixed_Window_Exponentiator::Fixed_Window_Exponentiator(const BigInt& n,
|
|
Power_Mod::Usage_Hints hints)
|
|
{
|
|
reducer = Modular_Reducer(n);
|
|
this->hints = hints;
|
|
window_bits = 0;
|
|
}
|
|
|
|
}
|
|
/*
|
|
* Montgomery Exponentiation
|
|
* (C) 1999-2010 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* Set the exponent
|
|
*/
|
|
void Montgomery_Exponentiator::set_exponent(const BigInt& exp)
|
|
{
|
|
this->exp = exp;
|
|
exp_bits = exp.bits();
|
|
}
|
|
|
|
/*
|
|
* Set the base
|
|
*/
|
|
void Montgomery_Exponentiator::set_base(const BigInt& base)
|
|
{
|
|
window_bits = Power_Mod::window_bits(exp.bits(), base.bits(), hints);
|
|
|
|
g.resize((1 << window_bits) - 1);
|
|
|
|
SecureVector<word> z(2 * (mod_words + 1));
|
|
SecureVector<word> workspace(z.size());
|
|
|
|
g[0] = (base >= modulus) ? (base % modulus) : base;
|
|
|
|
bigint_monty_mul(&z[0], z.size(),
|
|
g[0].data(), g[0].size(), g[0].sig_words(),
|
|
R2.data(), R2.size(), R2.sig_words(),
|
|
modulus.data(), mod_words, mod_prime,
|
|
&workspace[0]);
|
|
|
|
g[0].assign(&z[0], mod_words + 1);
|
|
|
|
const BigInt& x = g[0];
|
|
const size_t x_sig = x.sig_words();
|
|
|
|
for(size_t i = 1; i != g.size(); ++i)
|
|
{
|
|
const BigInt& y = g[i-1];
|
|
const size_t y_sig = y.sig_words();
|
|
|
|
zeroise(z);
|
|
bigint_monty_mul(&z[0], z.size(),
|
|
x.data(), x.size(), x_sig,
|
|
y.data(), y.size(), y_sig,
|
|
modulus.data(), mod_words, mod_prime,
|
|
&workspace[0]);
|
|
|
|
g[i].assign(&z[0], mod_words + 1);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Compute the result
|
|
*/
|
|
BigInt Montgomery_Exponentiator::execute() const
|
|
{
|
|
const size_t exp_nibbles = (exp_bits + window_bits - 1) / window_bits;
|
|
|
|
BigInt x = R_mod;
|
|
SecureVector<word> z(2 * (mod_words + 1));
|
|
SecureVector<word> workspace(2 * (mod_words + 1));
|
|
|
|
for(size_t i = exp_nibbles; i > 0; --i)
|
|
{
|
|
for(size_t k = 0; k != window_bits; ++k)
|
|
{
|
|
zeroise(z);
|
|
|
|
bigint_monty_sqr(&z[0], z.size(),
|
|
x.data(), x.size(), x.sig_words(),
|
|
modulus.data(), mod_words, mod_prime,
|
|
&workspace[0]);
|
|
|
|
x.assign(&z[0], mod_words + 1);
|
|
}
|
|
|
|
if(u32bit nibble = exp.get_substring(window_bits*(i-1), window_bits))
|
|
{
|
|
const BigInt& y = g[nibble-1];
|
|
|
|
zeroise(z);
|
|
bigint_monty_mul(&z[0], z.size(),
|
|
x.data(), x.size(), x.sig_words(),
|
|
y.data(), y.size(), y.sig_words(),
|
|
modulus.data(), mod_words, mod_prime,
|
|
&workspace[0]);
|
|
|
|
x.assign(&z[0], mod_words + 1);
|
|
}
|
|
}
|
|
|
|
x.get_reg().resize(2*mod_words+1);
|
|
|
|
bigint_monty_redc(&x[0], x.size(),
|
|
modulus.data(), mod_words, mod_prime,
|
|
&workspace[0]);
|
|
|
|
x.get_reg().resize(mod_words+1);
|
|
|
|
return x;
|
|
}
|
|
|
|
/*
|
|
* Montgomery_Exponentiator Constructor
|
|
*/
|
|
Montgomery_Exponentiator::Montgomery_Exponentiator(const BigInt& mod,
|
|
Power_Mod::Usage_Hints hints)
|
|
{
|
|
// Montgomery reduction only works for positive odd moduli
|
|
if(!mod.is_positive() || mod.is_even())
|
|
throw Invalid_Argument("Montgomery_Exponentiator: invalid modulus");
|
|
|
|
window_bits = 0;
|
|
this->hints = hints;
|
|
modulus = mod;
|
|
exp_bits = 0;
|
|
|
|
mod_words = modulus.sig_words();
|
|
|
|
BigInt r(BigInt::Power2, mod_words * BOTAN_MP_WORD_BITS);
|
|
mod_prime = (((r * inverse_mod(r, mod)) - 1) / mod).word_at(0);
|
|
|
|
R_mod = r % modulus;
|
|
|
|
R2 = (R_mod * R_mod) % modulus;
|
|
}
|
|
|
|
}
|
|
/*
|
|
* Small Primes Table
|
|
* (C) 1999-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
const u16bit PRIMES[PRIME_TABLE_SIZE+1] = {
|
|
3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37,
|
|
41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83,
|
|
89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139,
|
|
149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197,
|
|
199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263,
|
|
269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331,
|
|
337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397,
|
|
401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461,
|
|
463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541,
|
|
547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607,
|
|
613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673,
|
|
677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751,
|
|
757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827,
|
|
829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907,
|
|
911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983,
|
|
991, 997, 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051,
|
|
1061, 1063, 1069, 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123,
|
|
1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217,
|
|
1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291,
|
|
1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381,
|
|
1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459,
|
|
1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, 1523, 1531, 1543,
|
|
1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601, 1607, 1609,
|
|
1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, 1697,
|
|
1699, 1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783,
|
|
1787, 1789, 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, 1873,
|
|
1877, 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973,
|
|
1979, 1987, 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039,
|
|
2053, 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129,
|
|
2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, 2221,
|
|
2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287, 2293, 2297,
|
|
2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, 2371, 2377, 2381,
|
|
2383, 2389, 2393, 2399, 2411, 2417, 2423, 2437, 2441, 2447, 2459,
|
|
2467, 2473, 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, 2557,
|
|
2579, 2591, 2593, 2609, 2617, 2621, 2633, 2647, 2657, 2659, 2663,
|
|
2671, 2677, 2683, 2687, 2689, 2693, 2699, 2707, 2711, 2713, 2719,
|
|
2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801,
|
|
2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897,
|
|
2903, 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999,
|
|
3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, 3083,
|
|
3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181, 3187, 3191,
|
|
3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271, 3299,
|
|
3301, 3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347, 3359, 3361,
|
|
3371, 3373, 3389, 3391, 3407, 3413, 3433, 3449, 3457, 3461, 3463,
|
|
3467, 3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533, 3539, 3541,
|
|
3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, 3613, 3617, 3623,
|
|
3631, 3637, 3643, 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709,
|
|
3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803,
|
|
3821, 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907,
|
|
3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, 4001,
|
|
4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, 4073, 4079,
|
|
4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159,
|
|
4177, 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259,
|
|
4261, 4271, 4273, 4283, 4289, 4297, 4327, 4337, 4339, 4349, 4357,
|
|
4363, 4373, 4391, 4397, 4409, 4421, 4423, 4441, 4447, 4451, 4457,
|
|
4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547, 4549,
|
|
4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649,
|
|
4651, 4657, 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733,
|
|
4751, 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831,
|
|
4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937, 4943,
|
|
4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011,
|
|
5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, 5101, 5107,
|
|
5113, 5119, 5147, 5153, 5167, 5171, 5179, 5189, 5197, 5209, 5227,
|
|
5231, 5233, 5237, 5261, 5273, 5279, 5281, 5297, 5303, 5309, 5323,
|
|
5333, 5347, 5351, 5381, 5387, 5393, 5399, 5407, 5413, 5417, 5419,
|
|
5431, 5437, 5441, 5443, 5449, 5471, 5477, 5479, 5483, 5501, 5503,
|
|
5507, 5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591,
|
|
5623, 5639, 5641, 5647, 5651, 5653, 5657, 5659, 5669, 5683, 5689,
|
|
5693, 5701, 5711, 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791,
|
|
5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857, 5861,
|
|
5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953, 5981,
|
|
5987, 6007, 6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, 6079,
|
|
6089, 6091, 6101, 6113, 6121, 6131, 6133, 6143, 6151, 6163, 6173,
|
|
6197, 6199, 6203, 6211, 6217, 6221, 6229, 6247, 6257, 6263, 6269,
|
|
6271, 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, 6337, 6343,
|
|
6353, 6359, 6361, 6367, 6373, 6379, 6389, 6397, 6421, 6427, 6449,
|
|
6451, 6469, 6473, 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563,
|
|
6569, 6571, 6577, 6581, 6599, 6607, 6619, 6637, 6653, 6659, 6661,
|
|
6673, 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, 6737, 6761,
|
|
6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, 6841,
|
|
6857, 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, 6947, 6949,
|
|
6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997, 7001, 7013, 7019,
|
|
7027, 7039, 7043, 7057, 7069, 7079, 7103, 7109, 7121, 7127, 7129,
|
|
7151, 7159, 7177, 7187, 7193, 7207, 7211, 7213, 7219, 7229, 7237,
|
|
7243, 7247, 7253, 7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349,
|
|
7351, 7369, 7393, 7411, 7417, 7433, 7451, 7457, 7459, 7477, 7481,
|
|
7487, 7489, 7499, 7507, 7517, 7523, 7529, 7537, 7541, 7547, 7549,
|
|
7559, 7561, 7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, 7639,
|
|
7643, 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723,
|
|
7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, 7841,
|
|
7853, 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919, 7927, 7933,
|
|
7937, 7949, 7951, 7963, 7993, 8009, 8011, 8017, 8039, 8053, 8059,
|
|
8069, 8081, 8087, 8089, 8093, 8101, 8111, 8117, 8123, 8147, 8161,
|
|
8167, 8171, 8179, 8191, 8209, 8219, 8221, 8231, 8233, 8237, 8243,
|
|
8263, 8269, 8273, 8287, 8291, 8293, 8297, 8311, 8317, 8329, 8353,
|
|
8363, 8369, 8377, 8387, 8389, 8419, 8423, 8429, 8431, 8443, 8447,
|
|
8461, 8467, 8501, 8513, 8521, 8527, 8537, 8539, 8543, 8563, 8573,
|
|
8581, 8597, 8599, 8609, 8623, 8627, 8629, 8641, 8647, 8663, 8669,
|
|
8677, 8681, 8689, 8693, 8699, 8707, 8713, 8719, 8731, 8737, 8741,
|
|
8747, 8753, 8761, 8779, 8783, 8803, 8807, 8819, 8821, 8831, 8837,
|
|
8839, 8849, 8861, 8863, 8867, 8887, 8893, 8923, 8929, 8933, 8941,
|
|
8951, 8963, 8969, 8971, 8999, 9001, 9007, 9011, 9013, 9029, 9041,
|
|
9043, 9049, 9059, 9067, 9091, 9103, 9109, 9127, 9133, 9137, 9151,
|
|
9157, 9161, 9173, 9181, 9187, 9199, 9203, 9209, 9221, 9227, 9239,
|
|
9241, 9257, 9277, 9281, 9283, 9293, 9311, 9319, 9323, 9337, 9341,
|
|
9343, 9349, 9371, 9377, 9391, 9397, 9403, 9413, 9419, 9421, 9431,
|
|
9433, 9437, 9439, 9461, 9463, 9467, 9473, 9479, 9491, 9497, 9511,
|
|
9521, 9533, 9539, 9547, 9551, 9587, 9601, 9613, 9619, 9623, 9629,
|
|
9631, 9643, 9649, 9661, 9677, 9679, 9689, 9697, 9719, 9721, 9733,
|
|
9739, 9743, 9749, 9767, 9769, 9781, 9787, 9791, 9803, 9811, 9817,
|
|
9829, 9833, 9839, 9851, 9857, 9859, 9871, 9883, 9887, 9901, 9907,
|
|
9923, 9929, 9931, 9941, 9949, 9967, 9973, 10007, 10009, 10037, 10039,
|
|
10061, 10067, 10069, 10079, 10091, 10093, 10099, 10103, 10111, 10133, 10139,
|
|
10141, 10151, 10159, 10163, 10169, 10177, 10181, 10193, 10211, 10223, 10243,
|
|
10247, 10253, 10259, 10267, 10271, 10273, 10289, 10301, 10303, 10313, 10321,
|
|
10331, 10333, 10337, 10343, 10357, 10369, 10391, 10399, 10427, 10429, 10433,
|
|
10453, 10457, 10459, 10463, 10477, 10487, 10499, 10501, 10513, 10529, 10531,
|
|
10559, 10567, 10589, 10597, 10601, 10607, 10613, 10627, 10631, 10639, 10651,
|
|
10657, 10663, 10667, 10687, 10691, 10709, 10711, 10723, 10729, 10733, 10739,
|
|
10753, 10771, 10781, 10789, 10799, 10831, 10837, 10847, 10853, 10859, 10861,
|
|
10867, 10883, 10889, 10891, 10903, 10909, 10937, 10939, 10949, 10957, 10973,
|
|
10979, 10987, 10993, 11003, 11027, 11047, 11057, 11059, 11069, 11071, 11083,
|
|
11087, 11093, 11113, 11117, 11119, 11131, 11149, 11159, 11161, 11171, 11173,
|
|
11177, 11197, 11213, 11239, 11243, 11251, 11257, 11261, 11273, 11279, 11287,
|
|
11299, 11311, 11317, 11321, 11329, 11351, 11353, 11369, 11383, 11393, 11399,
|
|
11411, 11423, 11437, 11443, 11447, 11467, 11471, 11483, 11489, 11491, 11497,
|
|
11503, 11519, 11527, 11549, 11551, 11579, 11587, 11593, 11597, 11617, 11621,
|
|
11633, 11657, 11677, 11681, 11689, 11699, 11701, 11717, 11719, 11731, 11743,
|
|
11777, 11779, 11783, 11789, 11801, 11807, 11813, 11821, 11827, 11831, 11833,
|
|
11839, 11863, 11867, 11887, 11897, 11903, 11909, 11923, 11927, 11933, 11939,
|
|
11941, 11953, 11959, 11969, 11971, 11981, 11987, 12007, 12011, 12037, 12041,
|
|
12043, 12049, 12071, 12073, 12097, 12101, 12107, 12109, 12113, 12119, 12143,
|
|
12149, 12157, 12161, 12163, 12197, 12203, 12211, 12227, 12239, 12241, 12251,
|
|
12253, 12263, 12269, 12277, 12281, 12289, 12301, 12323, 12329, 12343, 12347,
|
|
12373, 12377, 12379, 12391, 12401, 12409, 12413, 12421, 12433, 12437, 12451,
|
|
12457, 12473, 12479, 12487, 12491, 12497, 12503, 12511, 12517, 12527, 12539,
|
|
12541, 12547, 12553, 12569, 12577, 12583, 12589, 12601, 12611, 12613, 12619,
|
|
12637, 12641, 12647, 12653, 12659, 12671, 12689, 12697, 12703, 12713, 12721,
|
|
12739, 12743, 12757, 12763, 12781, 12791, 12799, 12809, 12821, 12823, 12829,
|
|
12841, 12853, 12889, 12893, 12899, 12907, 12911, 12917, 12919, 12923, 12941,
|
|
12953, 12959, 12967, 12973, 12979, 12983, 13001, 13003, 13007, 13009, 13033,
|
|
13037, 13043, 13049, 13063, 13093, 13099, 13103, 13109, 13121, 13127, 13147,
|
|
13151, 13159, 13163, 13171, 13177, 13183, 13187, 13217, 13219, 13229, 13241,
|
|
13249, 13259, 13267, 13291, 13297, 13309, 13313, 13327, 13331, 13337, 13339,
|
|
13367, 13381, 13397, 13399, 13411, 13417, 13421, 13441, 13451, 13457, 13463,
|
|
13469, 13477, 13487, 13499, 13513, 13523, 13537, 13553, 13567, 13577, 13591,
|
|
13597, 13613, 13619, 13627, 13633, 13649, 13669, 13679, 13681, 13687, 13691,
|
|
13693, 13697, 13709, 13711, 13721, 13723, 13729, 13751, 13757, 13759, 13763,
|
|
13781, 13789, 13799, 13807, 13829, 13831, 13841, 13859, 13873, 13877, 13879,
|
|
13883, 13901, 13903, 13907, 13913, 13921, 13931, 13933, 13963, 13967, 13997,
|
|
13999, 14009, 14011, 14029, 14033, 14051, 14057, 14071, 14081, 14083, 14087,
|
|
14107, 14143, 14149, 14153, 14159, 14173, 14177, 14197, 14207, 14221, 14243,
|
|
14249, 14251, 14281, 14293, 14303, 14321, 14323, 14327, 14341, 14347, 14369,
|
|
14387, 14389, 14401, 14407, 14411, 14419, 14423, 14431, 14437, 14447, 14449,
|
|
14461, 14479, 14489, 14503, 14519, 14533, 14537, 14543, 14549, 14551, 14557,
|
|
14561, 14563, 14591, 14593, 14621, 14627, 14629, 14633, 14639, 14653, 14657,
|
|
14669, 14683, 14699, 14713, 14717, 14723, 14731, 14737, 14741, 14747, 14753,
|
|
14759, 14767, 14771, 14779, 14783, 14797, 14813, 14821, 14827, 14831, 14843,
|
|
14851, 14867, 14869, 14879, 14887, 14891, 14897, 14923, 14929, 14939, 14947,
|
|
14951, 14957, 14969, 14983, 15013, 15017, 15031, 15053, 15061, 15073, 15077,
|
|
15083, 15091, 15101, 15107, 15121, 15131, 15137, 15139, 15149, 15161, 15173,
|
|
15187, 15193, 15199, 15217, 15227, 15233, 15241, 15259, 15263, 15269, 15271,
|
|
15277, 15287, 15289, 15299, 15307, 15313, 15319, 15329, 15331, 15349, 15359,
|
|
15361, 15373, 15377, 15383, 15391, 15401, 15413, 15427, 15439, 15443, 15451,
|
|
15461, 15467, 15473, 15493, 15497, 15511, 15527, 15541, 15551, 15559, 15569,
|
|
15581, 15583, 15601, 15607, 15619, 15629, 15641, 15643, 15647, 15649, 15661,
|
|
15667, 15671, 15679, 15683, 15727, 15731, 15733, 15737, 15739, 15749, 15761,
|
|
15767, 15773, 15787, 15791, 15797, 15803, 15809, 15817, 15823, 15859, 15877,
|
|
15881, 15887, 15889, 15901, 15907, 15913, 15919, 15923, 15937, 15959, 15971,
|
|
15973, 15991, 16001, 16007, 16033, 16057, 16061, 16063, 16067, 16069, 16073,
|
|
16087, 16091, 16097, 16103, 16111, 16127, 16139, 16141, 16183, 16187, 16189,
|
|
16193, 16217, 16223, 16229, 16231, 16249, 16253, 16267, 16273, 16301, 16319,
|
|
16333, 16339, 16349, 16361, 16363, 16369, 16381, 16411, 16417, 16421, 16427,
|
|
16433, 16447, 16451, 16453, 16477, 16481, 16487, 16493, 16519, 16529, 16547,
|
|
16553, 16561, 16567, 16573, 16603, 16607, 16619, 16631, 16633, 16649, 16651,
|
|
16657, 16661, 16673, 16691, 16693, 16699, 16703, 16729, 16741, 16747, 16759,
|
|
16763, 16787, 16811, 16823, 16829, 16831, 16843, 16871, 16879, 16883, 16889,
|
|
16901, 16903, 16921, 16927, 16931, 16937, 16943, 16963, 16979, 16981, 16987,
|
|
16993, 17011, 17021, 17027, 17029, 17033, 17041, 17047, 17053, 17077, 17093,
|
|
17099, 17107, 17117, 17123, 17137, 17159, 17167, 17183, 17189, 17191, 17203,
|
|
17207, 17209, 17231, 17239, 17257, 17291, 17293, 17299, 17317, 17321, 17327,
|
|
17333, 17341, 17351, 17359, 17377, 17383, 17387, 17389, 17393, 17401, 17417,
|
|
17419, 17431, 17443, 17449, 17467, 17471, 17477, 17483, 17489, 17491, 17497,
|
|
17509, 17519, 17539, 17551, 17569, 17573, 17579, 17581, 17597, 17599, 17609,
|
|
17623, 17627, 17657, 17659, 17669, 17681, 17683, 17707, 17713, 17729, 17737,
|
|
17747, 17749, 17761, 17783, 17789, 17791, 17807, 17827, 17837, 17839, 17851,
|
|
17863, 17881, 17891, 17903, 17909, 17911, 17921, 17923, 17929, 17939, 17957,
|
|
17959, 17971, 17977, 17981, 17987, 17989, 18013, 18041, 18043, 18047, 18049,
|
|
18059, 18061, 18077, 18089, 18097, 18119, 18121, 18127, 18131, 18133, 18143,
|
|
18149, 18169, 18181, 18191, 18199, 18211, 18217, 18223, 18229, 18233, 18251,
|
|
18253, 18257, 18269, 18287, 18289, 18301, 18307, 18311, 18313, 18329, 18341,
|
|
18353, 18367, 18371, 18379, 18397, 18401, 18413, 18427, 18433, 18439, 18443,
|
|
18451, 18457, 18461, 18481, 18493, 18503, 18517, 18521, 18523, 18539, 18541,
|
|
18553, 18583, 18587, 18593, 18617, 18637, 18661, 18671, 18679, 18691, 18701,
|
|
18713, 18719, 18731, 18743, 18749, 18757, 18773, 18787, 18793, 18797, 18803,
|
|
18839, 18859, 18869, 18899, 18911, 18913, 18917, 18919, 18947, 18959, 18973,
|
|
18979, 19001, 19009, 19013, 19031, 19037, 19051, 19069, 19073, 19079, 19081,
|
|
19087, 19121, 19139, 19141, 19157, 19163, 19181, 19183, 19207, 19211, 19213,
|
|
19219, 19231, 19237, 19249, 19259, 19267, 19273, 19289, 19301, 19309, 19319,
|
|
19333, 19373, 19379, 19381, 19387, 19391, 19403, 19417, 19421, 19423, 19427,
|
|
19429, 19433, 19441, 19447, 19457, 19463, 19469, 19471, 19477, 19483, 19489,
|
|
19501, 19507, 19531, 19541, 19543, 19553, 19559, 19571, 19577, 19583, 19597,
|
|
19603, 19609, 19661, 19681, 19687, 19697, 19699, 19709, 19717, 19727, 19739,
|
|
19751, 19753, 19759, 19763, 19777, 19793, 19801, 19813, 19819, 19841, 19843,
|
|
19853, 19861, 19867, 19889, 19891, 19913, 19919, 19927, 19937, 19949, 19961,
|
|
19963, 19973, 19979, 19991, 19993, 19997, 20011, 20021, 20023, 20029, 20047,
|
|
20051, 20063, 20071, 20089, 20101, 20107, 20113, 20117, 20123, 20129, 20143,
|
|
20147, 20149, 20161, 20173, 20177, 20183, 20201, 20219, 20231, 20233, 20249,
|
|
20261, 20269, 20287, 20297, 20323, 20327, 20333, 20341, 20347, 20353, 20357,
|
|
20359, 20369, 20389, 20393, 20399, 20407, 20411, 20431, 20441, 20443, 20477,
|
|
20479, 20483, 20507, 20509, 20521, 20533, 20543, 20549, 20551, 20563, 20593,
|
|
20599, 20611, 20627, 20639, 20641, 20663, 20681, 20693, 20707, 20717, 20719,
|
|
20731, 20743, 20747, 20749, 20753, 20759, 20771, 20773, 20789, 20807, 20809,
|
|
20849, 20857, 20873, 20879, 20887, 20897, 20899, 20903, 20921, 20929, 20939,
|
|
20947, 20959, 20963, 20981, 20983, 21001, 21011, 21013, 21017, 21019, 21023,
|
|
21031, 21059, 21061, 21067, 21089, 21101, 21107, 21121, 21139, 21143, 21149,
|
|
21157, 21163, 21169, 21179, 21187, 21191, 21193, 21211, 21221, 21227, 21247,
|
|
21269, 21277, 21283, 21313, 21317, 21319, 21323, 21341, 21347, 21377, 21379,
|
|
21383, 21391, 21397, 21401, 21407, 21419, 21433, 21467, 21481, 21487, 21491,
|
|
21493, 21499, 21503, 21517, 21521, 21523, 21529, 21557, 21559, 21563, 21569,
|
|
21577, 21587, 21589, 21599, 21601, 21611, 21613, 21617, 21647, 21649, 21661,
|
|
21673, 21683, 21701, 21713, 21727, 21737, 21739, 21751, 21757, 21767, 21773,
|
|
21787, 21799, 21803, 21817, 21821, 21839, 21841, 21851, 21859, 21863, 21871,
|
|
21881, 21893, 21911, 21929, 21937, 21943, 21961, 21977, 21991, 21997, 22003,
|
|
22013, 22027, 22031, 22037, 22039, 22051, 22063, 22067, 22073, 22079, 22091,
|
|
22093, 22109, 22111, 22123, 22129, 22133, 22147, 22153, 22157, 22159, 22171,
|
|
22189, 22193, 22229, 22247, 22259, 22271, 22273, 22277, 22279, 22283, 22291,
|
|
22303, 22307, 22343, 22349, 22367, 22369, 22381, 22391, 22397, 22409, 22433,
|
|
22441, 22447, 22453, 22469, 22481, 22483, 22501, 22511, 22531, 22541, 22543,
|
|
22549, 22567, 22571, 22573, 22613, 22619, 22621, 22637, 22639, 22643, 22651,
|
|
22669, 22679, 22691, 22697, 22699, 22709, 22717, 22721, 22727, 22739, 22741,
|
|
22751, 22769, 22777, 22783, 22787, 22807, 22811, 22817, 22853, 22859, 22861,
|
|
22871, 22877, 22901, 22907, 22921, 22937, 22943, 22961, 22963, 22973, 22993,
|
|
23003, 23011, 23017, 23021, 23027, 23029, 23039, 23041, 23053, 23057, 23059,
|
|
23063, 23071, 23081, 23087, 23099, 23117, 23131, 23143, 23159, 23167, 23173,
|
|
23189, 23197, 23201, 23203, 23209, 23227, 23251, 23269, 23279, 23291, 23293,
|
|
23297, 23311, 23321, 23327, 23333, 23339, 23357, 23369, 23371, 23399, 23417,
|
|
23431, 23447, 23459, 23473, 23497, 23509, 23531, 23537, 23539, 23549, 23557,
|
|
23561, 23563, 23567, 23581, 23593, 23599, 23603, 23609, 23623, 23627, 23629,
|
|
23633, 23663, 23669, 23671, 23677, 23687, 23689, 23719, 23741, 23743, 23747,
|
|
23753, 23761, 23767, 23773, 23789, 23801, 23813, 23819, 23827, 23831, 23833,
|
|
23857, 23869, 23873, 23879, 23887, 23893, 23899, 23909, 23911, 23917, 23929,
|
|
23957, 23971, 23977, 23981, 23993, 24001, 24007, 24019, 24023, 24029, 24043,
|
|
24049, 24061, 24071, 24077, 24083, 24091, 24097, 24103, 24107, 24109, 24113,
|
|
24121, 24133, 24137, 24151, 24169, 24179, 24181, 24197, 24203, 24223, 24229,
|
|
24239, 24247, 24251, 24281, 24317, 24329, 24337, 24359, 24371, 24373, 24379,
|
|
24391, 24407, 24413, 24419, 24421, 24439, 24443, 24469, 24473, 24481, 24499,
|
|
24509, 24517, 24527, 24533, 24547, 24551, 24571, 24593, 24611, 24623, 24631,
|
|
24659, 24671, 24677, 24683, 24691, 24697, 24709, 24733, 24749, 24763, 24767,
|
|
24781, 24793, 24799, 24809, 24821, 24841, 24847, 24851, 24859, 24877, 24889,
|
|
24907, 24917, 24919, 24923, 24943, 24953, 24967, 24971, 24977, 24979, 24989,
|
|
25013, 25031, 25033, 25037, 25057, 25073, 25087, 25097, 25111, 25117, 25121,
|
|
25127, 25147, 25153, 25163, 25169, 25171, 25183, 25189, 25219, 25229, 25237,
|
|
25243, 25247, 25253, 25261, 25301, 25303, 25307, 25309, 25321, 25339, 25343,
|
|
25349, 25357, 25367, 25373, 25391, 25409, 25411, 25423, 25439, 25447, 25453,
|
|
25457, 25463, 25469, 25471, 25523, 25537, 25541, 25561, 25577, 25579, 25583,
|
|
25589, 25601, 25603, 25609, 25621, 25633, 25639, 25643, 25657, 25667, 25673,
|
|
25679, 25693, 25703, 25717, 25733, 25741, 25747, 25759, 25763, 25771, 25793,
|
|
25799, 25801, 25819, 25841, 25847, 25849, 25867, 25873, 25889, 25903, 25913,
|
|
25919, 25931, 25933, 25939, 25943, 25951, 25969, 25981, 25997, 25999, 26003,
|
|
26017, 26021, 26029, 26041, 26053, 26083, 26099, 26107, 26111, 26113, 26119,
|
|
26141, 26153, 26161, 26171, 26177, 26183, 26189, 26203, 26209, 26227, 26237,
|
|
26249, 26251, 26261, 26263, 26267, 26293, 26297, 26309, 26317, 26321, 26339,
|
|
26347, 26357, 26371, 26387, 26393, 26399, 26407, 26417, 26423, 26431, 26437,
|
|
26449, 26459, 26479, 26489, 26497, 26501, 26513, 26539, 26557, 26561, 26573,
|
|
26591, 26597, 26627, 26633, 26641, 26647, 26669, 26681, 26683, 26687, 26693,
|
|
26699, 26701, 26711, 26713, 26717, 26723, 26729, 26731, 26737, 26759, 26777,
|
|
26783, 26801, 26813, 26821, 26833, 26839, 26849, 26861, 26863, 26879, 26881,
|
|
26891, 26893, 26903, 26921, 26927, 26947, 26951, 26953, 26959, 26981, 26987,
|
|
26993, 27011, 27017, 27031, 27043, 27059, 27061, 27067, 27073, 27077, 27091,
|
|
27103, 27107, 27109, 27127, 27143, 27179, 27191, 27197, 27211, 27239, 27241,
|
|
27253, 27259, 27271, 27277, 27281, 27283, 27299, 27329, 27337, 27361, 27367,
|
|
27397, 27407, 27409, 27427, 27431, 27437, 27449, 27457, 27479, 27481, 27487,
|
|
27509, 27527, 27529, 27539, 27541, 27551, 27581, 27583, 27611, 27617, 27631,
|
|
27647, 27653, 27673, 27689, 27691, 27697, 27701, 27733, 27737, 27739, 27743,
|
|
27749, 27751, 27763, 27767, 27773, 27779, 27791, 27793, 27799, 27803, 27809,
|
|
27817, 27823, 27827, 27847, 27851, 27883, 27893, 27901, 27917, 27919, 27941,
|
|
27943, 27947, 27953, 27961, 27967, 27983, 27997, 28001, 28019, 28027, 28031,
|
|
28051, 28057, 28069, 28081, 28087, 28097, 28099, 28109, 28111, 28123, 28151,
|
|
28163, 28181, 28183, 28201, 28211, 28219, 28229, 28277, 28279, 28283, 28289,
|
|
28297, 28307, 28309, 28319, 28349, 28351, 28387, 28393, 28403, 28409, 28411,
|
|
28429, 28433, 28439, 28447, 28463, 28477, 28493, 28499, 28513, 28517, 28537,
|
|
28541, 28547, 28549, 28559, 28571, 28573, 28579, 28591, 28597, 28603, 28607,
|
|
28619, 28621, 28627, 28631, 28643, 28649, 28657, 28661, 28663, 28669, 28687,
|
|
28697, 28703, 28711, 28723, 28729, 28751, 28753, 28759, 28771, 28789, 28793,
|
|
28807, 28813, 28817, 28837, 28843, 28859, 28867, 28871, 28879, 28901, 28909,
|
|
28921, 28927, 28933, 28949, 28961, 28979, 29009, 29017, 29021, 29023, 29027,
|
|
29033, 29059, 29063, 29077, 29101, 29123, 29129, 29131, 29137, 29147, 29153,
|
|
29167, 29173, 29179, 29191, 29201, 29207, 29209, 29221, 29231, 29243, 29251,
|
|
29269, 29287, 29297, 29303, 29311, 29327, 29333, 29339, 29347, 29363, 29383,
|
|
29387, 29389, 29399, 29401, 29411, 29423, 29429, 29437, 29443, 29453, 29473,
|
|
29483, 29501, 29527, 29531, 29537, 29567, 29569, 29573, 29581, 29587, 29599,
|
|
29611, 29629, 29633, 29641, 29663, 29669, 29671, 29683, 29717, 29723, 29741,
|
|
29753, 29759, 29761, 29789, 29803, 29819, 29833, 29837, 29851, 29863, 29867,
|
|
29873, 29879, 29881, 29917, 29921, 29927, 29947, 29959, 29983, 29989, 30011,
|
|
30013, 30029, 30047, 30059, 30071, 30089, 30091, 30097, 30103, 30109, 30113,
|
|
30119, 30133, 30137, 30139, 30161, 30169, 30181, 30187, 30197, 30203, 30211,
|
|
30223, 30241, 30253, 30259, 30269, 30271, 30293, 30307, 30313, 30319, 30323,
|
|
30341, 30347, 30367, 30389, 30391, 30403, 30427, 30431, 30449, 30467, 30469,
|
|
30491, 30493, 30497, 30509, 30517, 30529, 30539, 30553, 30557, 30559, 30577,
|
|
30593, 30631, 30637, 30643, 30649, 30661, 30671, 30677, 30689, 30697, 30703,
|
|
30707, 30713, 30727, 30757, 30763, 30773, 30781, 30803, 30809, 30817, 30829,
|
|
30839, 30841, 30851, 30853, 30859, 30869, 30871, 30881, 30893, 30911, 30931,
|
|
30937, 30941, 30949, 30971, 30977, 30983, 31013, 31019, 31033, 31039, 31051,
|
|
31063, 31069, 31079, 31081, 31091, 31121, 31123, 31139, 31147, 31151, 31153,
|
|
31159, 31177, 31181, 31183, 31189, 31193, 31219, 31223, 31231, 31237, 31247,
|
|
31249, 31253, 31259, 31267, 31271, 31277, 31307, 31319, 31321, 31327, 31333,
|
|
31337, 31357, 31379, 31387, 31391, 31393, 31397, 31469, 31477, 31481, 31489,
|
|
31511, 31513, 31517, 31531, 31541, 31543, 31547, 31567, 31573, 31583, 31601,
|
|
31607, 31627, 31643, 31649, 31657, 31663, 31667, 31687, 31699, 31721, 31723,
|
|
31727, 31729, 31741, 31751, 31769, 31771, 31793, 31799, 31817, 31847, 31849,
|
|
31859, 31873, 31883, 31891, 31907, 31957, 31963, 31973, 31981, 31991, 32003,
|
|
32009, 32027, 32029, 32051, 32057, 32059, 32063, 32069, 32077, 32083, 32089,
|
|
32099, 32117, 32119, 32141, 32143, 32159, 32173, 32183, 32189, 32191, 32203,
|
|
32213, 32233, 32237, 32251, 32257, 32261, 32297, 32299, 32303, 32309, 32321,
|
|
32323, 32327, 32341, 32353, 32359, 32363, 32369, 32371, 32377, 32381, 32401,
|
|
32411, 32413, 32423, 32429, 32441, 32443, 32467, 32479, 32491, 32497, 32503,
|
|
32507, 32531, 32533, 32537, 32561, 32563, 32569, 32573, 32579, 32587, 32603,
|
|
32609, 32611, 32621, 32633, 32647, 32653, 32687, 32693, 32707, 32713, 32717,
|
|
32719, 32749, 32771, 32779, 32783, 32789, 32797, 32801, 32803, 32831, 32833,
|
|
32839, 32843, 32869, 32887, 32909, 32911, 32917, 32933, 32939, 32941, 32957,
|
|
32969, 32971, 32983, 32987, 32993, 32999, 33013, 33023, 33029, 33037, 33049,
|
|
33053, 33071, 33073, 33083, 33091, 33107, 33113, 33119, 33149, 33151, 33161,
|
|
33179, 33181, 33191, 33199, 33203, 33211, 33223, 33247, 33287, 33289, 33301,
|
|
33311, 33317, 33329, 33331, 33343, 33347, 33349, 33353, 33359, 33377, 33391,
|
|
33403, 33409, 33413, 33427, 33457, 33461, 33469, 33479, 33487, 33493, 33503,
|
|
33521, 33529, 33533, 33547, 33563, 33569, 33577, 33581, 33587, 33589, 33599,
|
|
33601, 33613, 33617, 33619, 33623, 33629, 33637, 33641, 33647, 33679, 33703,
|
|
33713, 33721, 33739, 33749, 33751, 33757, 33767, 33769, 33773, 33791, 33797,
|
|
33809, 33811, 33827, 33829, 33851, 33857, 33863, 33871, 33889, 33893, 33911,
|
|
33923, 33931, 33937, 33941, 33961, 33967, 33997, 34019, 34031, 34033, 34039,
|
|
34057, 34061, 34123, 34127, 34129, 34141, 34147, 34157, 34159, 34171, 34183,
|
|
34211, 34213, 34217, 34231, 34253, 34259, 34261, 34267, 34273, 34283, 34297,
|
|
34301, 34303, 34313, 34319, 34327, 34337, 34351, 34361, 34367, 34369, 34381,
|
|
34403, 34421, 34429, 34439, 34457, 34469, 34471, 34483, 34487, 34499, 34501,
|
|
34511, 34513, 34519, 34537, 34543, 34549, 34583, 34589, 34591, 34603, 34607,
|
|
34613, 34631, 34649, 34651, 34667, 34673, 34679, 34687, 34693, 34703, 34721,
|
|
34729, 34739, 34747, 34757, 34759, 34763, 34781, 34807, 34819, 34841, 34843,
|
|
34847, 34849, 34871, 34877, 34883, 34897, 34913, 34919, 34939, 34949, 34961,
|
|
34963, 34981, 35023, 35027, 35051, 35053, 35059, 35069, 35081, 35083, 35089,
|
|
35099, 35107, 35111, 35117, 35129, 35141, 35149, 35153, 35159, 35171, 35201,
|
|
35221, 35227, 35251, 35257, 35267, 35279, 35281, 35291, 35311, 35317, 35323,
|
|
35327, 35339, 35353, 35363, 35381, 35393, 35401, 35407, 35419, 35423, 35437,
|
|
35447, 35449, 35461, 35491, 35507, 35509, 35521, 35527, 35531, 35533, 35537,
|
|
35543, 35569, 35573, 35591, 35593, 35597, 35603, 35617, 35671, 35677, 35729,
|
|
35731, 35747, 35753, 35759, 35771, 35797, 35801, 35803, 35809, 35831, 35837,
|
|
35839, 35851, 35863, 35869, 35879, 35897, 35899, 35911, 35923, 35933, 35951,
|
|
35963, 35969, 35977, 35983, 35993, 35999, 36007, 36011, 36013, 36017, 36037,
|
|
36061, 36067, 36073, 36083, 36097, 36107, 36109, 36131, 36137, 36151, 36161,
|
|
36187, 36191, 36209, 36217, 36229, 36241, 36251, 36263, 36269, 36277, 36293,
|
|
36299, 36307, 36313, 36319, 36341, 36343, 36353, 36373, 36383, 36389, 36433,
|
|
36451, 36457, 36467, 36469, 36473, 36479, 36493, 36497, 36523, 36527, 36529,
|
|
36541, 36551, 36559, 36563, 36571, 36583, 36587, 36599, 36607, 36629, 36637,
|
|
36643, 36653, 36671, 36677, 36683, 36691, 36697, 36709, 36713, 36721, 36739,
|
|
36749, 36761, 36767, 36779, 36781, 36787, 36791, 36793, 36809, 36821, 36833,
|
|
36847, 36857, 36871, 36877, 36887, 36899, 36901, 36913, 36919, 36923, 36929,
|
|
36931, 36943, 36947, 36973, 36979, 36997, 37003, 37013, 37019, 37021, 37039,
|
|
37049, 37057, 37061, 37087, 37097, 37117, 37123, 37139, 37159, 37171, 37181,
|
|
37189, 37199, 37201, 37217, 37223, 37243, 37253, 37273, 37277, 37307, 37309,
|
|
37313, 37321, 37337, 37339, 37357, 37361, 37363, 37369, 37379, 37397, 37409,
|
|
37423, 37441, 37447, 37463, 37483, 37489, 37493, 37501, 37507, 37511, 37517,
|
|
37529, 37537, 37547, 37549, 37561, 37567, 37571, 37573, 37579, 37589, 37591,
|
|
37607, 37619, 37633, 37643, 37649, 37657, 37663, 37691, 37693, 37699, 37717,
|
|
37747, 37781, 37783, 37799, 37811, 37813, 37831, 37847, 37853, 37861, 37871,
|
|
37879, 37889, 37897, 37907, 37951, 37957, 37963, 37967, 37987, 37991, 37993,
|
|
37997, 38011, 38039, 38047, 38053, 38069, 38083, 38113, 38119, 38149, 38153,
|
|
38167, 38177, 38183, 38189, 38197, 38201, 38219, 38231, 38237, 38239, 38261,
|
|
38273, 38281, 38287, 38299, 38303, 38317, 38321, 38327, 38329, 38333, 38351,
|
|
38371, 38377, 38393, 38431, 38447, 38449, 38453, 38459, 38461, 38501, 38543,
|
|
38557, 38561, 38567, 38569, 38593, 38603, 38609, 38611, 38629, 38639, 38651,
|
|
38653, 38669, 38671, 38677, 38693, 38699, 38707, 38711, 38713, 38723, 38729,
|
|
38737, 38747, 38749, 38767, 38783, 38791, 38803, 38821, 38833, 38839, 38851,
|
|
38861, 38867, 38873, 38891, 38903, 38917, 38921, 38923, 38933, 38953, 38959,
|
|
38971, 38977, 38993, 39019, 39023, 39041, 39043, 39047, 39079, 39089, 39097,
|
|
39103, 39107, 39113, 39119, 39133, 39139, 39157, 39161, 39163, 39181, 39191,
|
|
39199, 39209, 39217, 39227, 39229, 39233, 39239, 39241, 39251, 39293, 39301,
|
|
39313, 39317, 39323, 39341, 39343, 39359, 39367, 39371, 39373, 39383, 39397,
|
|
39409, 39419, 39439, 39443, 39451, 39461, 39499, 39503, 39509, 39511, 39521,
|
|
39541, 39551, 39563, 39569, 39581, 39607, 39619, 39623, 39631, 39659, 39667,
|
|
39671, 39679, 39703, 39709, 39719, 39727, 39733, 39749, 39761, 39769, 39779,
|
|
39791, 39799, 39821, 39827, 39829, 39839, 39841, 39847, 39857, 39863, 39869,
|
|
39877, 39883, 39887, 39901, 39929, 39937, 39953, 39971, 39979, 39983, 39989,
|
|
40009, 40013, 40031, 40037, 40039, 40063, 40087, 40093, 40099, 40111, 40123,
|
|
40127, 40129, 40151, 40153, 40163, 40169, 40177, 40189, 40193, 40213, 40231,
|
|
40237, 40241, 40253, 40277, 40283, 40289, 40343, 40351, 40357, 40361, 40387,
|
|
40423, 40427, 40429, 40433, 40459, 40471, 40483, 40487, 40493, 40499, 40507,
|
|
40519, 40529, 40531, 40543, 40559, 40577, 40583, 40591, 40597, 40609, 40627,
|
|
40637, 40639, 40693, 40697, 40699, 40709, 40739, 40751, 40759, 40763, 40771,
|
|
40787, 40801, 40813, 40819, 40823, 40829, 40841, 40847, 40849, 40853, 40867,
|
|
40879, 40883, 40897, 40903, 40927, 40933, 40939, 40949, 40961, 40973, 40993,
|
|
41011, 41017, 41023, 41039, 41047, 41051, 41057, 41077, 41081, 41113, 41117,
|
|
41131, 41141, 41143, 41149, 41161, 41177, 41179, 41183, 41189, 41201, 41203,
|
|
41213, 41221, 41227, 41231, 41233, 41243, 41257, 41263, 41269, 41281, 41299,
|
|
41333, 41341, 41351, 41357, 41381, 41387, 41389, 41399, 41411, 41413, 41443,
|
|
41453, 41467, 41479, 41491, 41507, 41513, 41519, 41521, 41539, 41543, 41549,
|
|
41579, 41593, 41597, 41603, 41609, 41611, 41617, 41621, 41627, 41641, 41647,
|
|
41651, 41659, 41669, 41681, 41687, 41719, 41729, 41737, 41759, 41761, 41771,
|
|
41777, 41801, 41809, 41813, 41843, 41849, 41851, 41863, 41879, 41887, 41893,
|
|
41897, 41903, 41911, 41927, 41941, 41947, 41953, 41957, 41959, 41969, 41981,
|
|
41983, 41999, 42013, 42017, 42019, 42023, 42043, 42061, 42071, 42073, 42083,
|
|
42089, 42101, 42131, 42139, 42157, 42169, 42179, 42181, 42187, 42193, 42197,
|
|
42209, 42221, 42223, 42227, 42239, 42257, 42281, 42283, 42293, 42299, 42307,
|
|
42323, 42331, 42337, 42349, 42359, 42373, 42379, 42391, 42397, 42403, 42407,
|
|
42409, 42433, 42437, 42443, 42451, 42457, 42461, 42463, 42467, 42473, 42487,
|
|
42491, 42499, 42509, 42533, 42557, 42569, 42571, 42577, 42589, 42611, 42641,
|
|
42643, 42649, 42667, 42677, 42683, 42689, 42697, 42701, 42703, 42709, 42719,
|
|
42727, 42737, 42743, 42751, 42767, 42773, 42787, 42793, 42797, 42821, 42829,
|
|
42839, 42841, 42853, 42859, 42863, 42899, 42901, 42923, 42929, 42937, 42943,
|
|
42953, 42961, 42967, 42979, 42989, 43003, 43013, 43019, 43037, 43049, 43051,
|
|
43063, 43067, 43093, 43103, 43117, 43133, 43151, 43159, 43177, 43189, 43201,
|
|
43207, 43223, 43237, 43261, 43271, 43283, 43291, 43313, 43319, 43321, 43331,
|
|
43391, 43397, 43399, 43403, 43411, 43427, 43441, 43451, 43457, 43481, 43487,
|
|
43499, 43517, 43541, 43543, 43573, 43577, 43579, 43591, 43597, 43607, 43609,
|
|
43613, 43627, 43633, 43649, 43651, 43661, 43669, 43691, 43711, 43717, 43721,
|
|
43753, 43759, 43777, 43781, 43783, 43787, 43789, 43793, 43801, 43853, 43867,
|
|
43889, 43891, 43913, 43933, 43943, 43951, 43961, 43963, 43969, 43973, 43987,
|
|
43991, 43997, 44017, 44021, 44027, 44029, 44041, 44053, 44059, 44071, 44087,
|
|
44089, 44101, 44111, 44119, 44123, 44129, 44131, 44159, 44171, 44179, 44189,
|
|
44201, 44203, 44207, 44221, 44249, 44257, 44263, 44267, 44269, 44273, 44279,
|
|
44281, 44293, 44351, 44357, 44371, 44381, 44383, 44389, 44417, 44449, 44453,
|
|
44483, 44491, 44497, 44501, 44507, 44519, 44531, 44533, 44537, 44543, 44549,
|
|
44563, 44579, 44587, 44617, 44621, 44623, 44633, 44641, 44647, 44651, 44657,
|
|
44683, 44687, 44699, 44701, 44711, 44729, 44741, 44753, 44771, 44773, 44777,
|
|
44789, 44797, 44809, 44819, 44839, 44843, 44851, 44867, 44879, 44887, 44893,
|
|
44909, 44917, 44927, 44939, 44953, 44959, 44963, 44971, 44983, 44987, 45007,
|
|
45013, 45053, 45061, 45077, 45083, 45119, 45121, 45127, 45131, 45137, 45139,
|
|
45161, 45179, 45181, 45191, 45197, 45233, 45247, 45259, 45263, 45281, 45289,
|
|
45293, 45307, 45317, 45319, 45329, 45337, 45341, 45343, 45361, 45377, 45389,
|
|
45403, 45413, 45427, 45433, 45439, 45481, 45491, 45497, 45503, 45523, 45533,
|
|
45541, 45553, 45557, 45569, 45587, 45589, 45599, 45613, 45631, 45641, 45659,
|
|
45667, 45673, 45677, 45691, 45697, 45707, 45737, 45751, 45757, 45763, 45767,
|
|
45779, 45817, 45821, 45823, 45827, 45833, 45841, 45853, 45863, 45869, 45887,
|
|
45893, 45943, 45949, 45953, 45959, 45971, 45979, 45989, 46021, 46027, 46049,
|
|
46051, 46061, 46073, 46091, 46093, 46099, 46103, 46133, 46141, 46147, 46153,
|
|
46171, 46181, 46183, 46187, 46199, 46219, 46229, 46237, 46261, 46271, 46273,
|
|
46279, 46301, 46307, 46309, 46327, 46337, 46349, 46351, 46381, 46399, 46411,
|
|
46439, 46441, 46447, 46451, 46457, 46471, 46477, 46489, 46499, 46507, 46511,
|
|
46523, 46549, 46559, 46567, 46573, 46589, 46591, 46601, 46619, 46633, 46639,
|
|
46643, 46649, 46663, 46679, 46681, 46687, 46691, 46703, 46723, 46727, 46747,
|
|
46751, 46757, 46769, 46771, 46807, 46811, 46817, 46819, 46829, 46831, 46853,
|
|
46861, 46867, 46877, 46889, 46901, 46919, 46933, 46957, 46993, 46997, 47017,
|
|
47041, 47051, 47057, 47059, 47087, 47093, 47111, 47119, 47123, 47129, 47137,
|
|
47143, 47147, 47149, 47161, 47189, 47207, 47221, 47237, 47251, 47269, 47279,
|
|
47287, 47293, 47297, 47303, 47309, 47317, 47339, 47351, 47353, 47363, 47381,
|
|
47387, 47389, 47407, 47417, 47419, 47431, 47441, 47459, 47491, 47497, 47501,
|
|
47507, 47513, 47521, 47527, 47533, 47543, 47563, 47569, 47581, 47591, 47599,
|
|
47609, 47623, 47629, 47639, 47653, 47657, 47659, 47681, 47699, 47701, 47711,
|
|
47713, 47717, 47737, 47741, 47743, 47777, 47779, 47791, 47797, 47807, 47809,
|
|
47819, 47837, 47843, 47857, 47869, 47881, 47903, 47911, 47917, 47933, 47939,
|
|
47947, 47951, 47963, 47969, 47977, 47981, 48017, 48023, 48029, 48049, 48073,
|
|
48079, 48091, 48109, 48119, 48121, 48131, 48157, 48163, 48179, 48187, 48193,
|
|
48197, 48221, 48239, 48247, 48259, 48271, 48281, 48299, 48311, 48313, 48337,
|
|
48341, 48353, 48371, 48383, 48397, 48407, 48409, 48413, 48437, 48449, 48463,
|
|
48473, 48479, 48481, 48487, 48491, 48497, 48523, 48527, 48533, 48539, 48541,
|
|
48563, 48571, 48589, 48593, 48611, 48619, 48623, 48647, 48649, 48661, 48673,
|
|
48677, 48679, 48731, 48733, 48751, 48757, 48761, 48767, 48779, 48781, 48787,
|
|
48799, 48809, 48817, 48821, 48823, 48847, 48857, 48859, 48869, 48871, 48883,
|
|
48889, 48907, 48947, 48953, 48973, 48989, 48991, 49003, 49009, 49019, 49031,
|
|
49033, 49037, 49043, 49057, 49069, 49081, 49103, 49109, 49117, 49121, 49123,
|
|
49139, 49157, 49169, 49171, 49177, 49193, 49199, 49201, 49207, 49211, 49223,
|
|
49253, 49261, 49277, 49279, 49297, 49307, 49331, 49333, 49339, 49363, 49367,
|
|
49369, 49391, 49393, 49409, 49411, 49417, 49429, 49433, 49451, 49459, 49463,
|
|
49477, 49481, 49499, 49523, 49529, 49531, 49537, 49547, 49549, 49559, 49597,
|
|
49603, 49613, 49627, 49633, 49639, 49663, 49667, 49669, 49681, 49697, 49711,
|
|
49727, 49739, 49741, 49747, 49757, 49783, 49787, 49789, 49801, 49807, 49811,
|
|
49823, 49831, 49843, 49853, 49871, 49877, 49891, 49919, 49921, 49927, 49937,
|
|
49939, 49943, 49957, 49991, 49993, 49999, 50021, 50023, 50033, 50047, 50051,
|
|
50053, 50069, 50077, 50087, 50093, 50101, 50111, 50119, 50123, 50129, 50131,
|
|
50147, 50153, 50159, 50177, 50207, 50221, 50227, 50231, 50261, 50263, 50273,
|
|
50287, 50291, 50311, 50321, 50329, 50333, 50341, 50359, 50363, 50377, 50383,
|
|
50387, 50411, 50417, 50423, 50441, 50459, 50461, 50497, 50503, 50513, 50527,
|
|
50539, 50543, 50549, 50551, 50581, 50587, 50591, 50593, 50599, 50627, 50647,
|
|
50651, 50671, 50683, 50707, 50723, 50741, 50753, 50767, 50773, 50777, 50789,
|
|
50821, 50833, 50839, 50849, 50857, 50867, 50873, 50891, 50893, 50909, 50923,
|
|
50929, 50951, 50957, 50969, 50971, 50989, 50993, 51001, 51031, 51043, 51047,
|
|
51059, 51061, 51071, 51109, 51131, 51133, 51137, 51151, 51157, 51169, 51193,
|
|
51197, 51199, 51203, 51217, 51229, 51239, 51241, 51257, 51263, 51283, 51287,
|
|
51307, 51329, 51341, 51343, 51347, 51349, 51361, 51383, 51407, 51413, 51419,
|
|
51421, 51427, 51431, 51437, 51439, 51449, 51461, 51473, 51479, 51481, 51487,
|
|
51503, 51511, 51517, 51521, 51539, 51551, 51563, 51577, 51581, 51593, 51599,
|
|
51607, 51613, 51631, 51637, 51647, 51659, 51673, 51679, 51683, 51691, 51713,
|
|
51719, 51721, 51749, 51767, 51769, 51787, 51797, 51803, 51817, 51827, 51829,
|
|
51839, 51853, 51859, 51869, 51871, 51893, 51899, 51907, 51913, 51929, 51941,
|
|
51949, 51971, 51973, 51977, 51991, 52009, 52021, 52027, 52051, 52057, 52067,
|
|
52069, 52081, 52103, 52121, 52127, 52147, 52153, 52163, 52177, 52181, 52183,
|
|
52189, 52201, 52223, 52237, 52249, 52253, 52259, 52267, 52289, 52291, 52301,
|
|
52313, 52321, 52361, 52363, 52369, 52379, 52387, 52391, 52433, 52453, 52457,
|
|
52489, 52501, 52511, 52517, 52529, 52541, 52543, 52553, 52561, 52567, 52571,
|
|
52579, 52583, 52609, 52627, 52631, 52639, 52667, 52673, 52691, 52697, 52709,
|
|
52711, 52721, 52727, 52733, 52747, 52757, 52769, 52783, 52807, 52813, 52817,
|
|
52837, 52859, 52861, 52879, 52883, 52889, 52901, 52903, 52919, 52937, 52951,
|
|
52957, 52963, 52967, 52973, 52981, 52999, 53003, 53017, 53047, 53051, 53069,
|
|
53077, 53087, 53089, 53093, 53101, 53113, 53117, 53129, 53147, 53149, 53161,
|
|
53171, 53173, 53189, 53197, 53201, 53231, 53233, 53239, 53267, 53269, 53279,
|
|
53281, 53299, 53309, 53323, 53327, 53353, 53359, 53377, 53381, 53401, 53407,
|
|
53411, 53419, 53437, 53441, 53453, 53479, 53503, 53507, 53527, 53549, 53551,
|
|
53569, 53591, 53593, 53597, 53609, 53611, 53617, 53623, 53629, 53633, 53639,
|
|
53653, 53657, 53681, 53693, 53699, 53717, 53719, 53731, 53759, 53773, 53777,
|
|
53783, 53791, 53813, 53819, 53831, 53849, 53857, 53861, 53881, 53887, 53891,
|
|
53897, 53899, 53917, 53923, 53927, 53939, 53951, 53959, 53987, 53993, 54001,
|
|
54011, 54013, 54037, 54049, 54059, 54083, 54091, 54101, 54121, 54133, 54139,
|
|
54151, 54163, 54167, 54181, 54193, 54217, 54251, 54269, 54277, 54287, 54293,
|
|
54311, 54319, 54323, 54331, 54347, 54361, 54367, 54371, 54377, 54401, 54403,
|
|
54409, 54413, 54419, 54421, 54437, 54443, 54449, 54469, 54493, 54497, 54499,
|
|
54503, 54517, 54521, 54539, 54541, 54547, 54559, 54563, 54577, 54581, 54583,
|
|
54601, 54617, 54623, 54629, 54631, 54647, 54667, 54673, 54679, 54709, 54713,
|
|
54721, 54727, 54751, 54767, 54773, 54779, 54787, 54799, 54829, 54833, 54851,
|
|
54869, 54877, 54881, 54907, 54917, 54919, 54941, 54949, 54959, 54973, 54979,
|
|
54983, 55001, 55009, 55021, 55049, 55051, 55057, 55061, 55073, 55079, 55103,
|
|
55109, 55117, 55127, 55147, 55163, 55171, 55201, 55207, 55213, 55217, 55219,
|
|
55229, 55243, 55249, 55259, 55291, 55313, 55331, 55333, 55337, 55339, 55343,
|
|
55351, 55373, 55381, 55399, 55411, 55439, 55441, 55457, 55469, 55487, 55501,
|
|
55511, 55529, 55541, 55547, 55579, 55589, 55603, 55609, 55619, 55621, 55631,
|
|
55633, 55639, 55661, 55663, 55667, 55673, 55681, 55691, 55697, 55711, 55717,
|
|
55721, 55733, 55763, 55787, 55793, 55799, 55807, 55813, 55817, 55819, 55823,
|
|
55829, 55837, 55843, 55849, 55871, 55889, 55897, 55901, 55903, 55921, 55927,
|
|
55931, 55933, 55949, 55967, 55987, 55997, 56003, 56009, 56039, 56041, 56053,
|
|
56081, 56087, 56093, 56099, 56101, 56113, 56123, 56131, 56149, 56167, 56171,
|
|
56179, 56197, 56207, 56209, 56237, 56239, 56249, 56263, 56267, 56269, 56299,
|
|
56311, 56333, 56359, 56369, 56377, 56383, 56393, 56401, 56417, 56431, 56437,
|
|
56443, 56453, 56467, 56473, 56477, 56479, 56489, 56501, 56503, 56509, 56519,
|
|
56527, 56531, 56533, 56543, 56569, 56591, 56597, 56599, 56611, 56629, 56633,
|
|
56659, 56663, 56671, 56681, 56687, 56701, 56711, 56713, 56731, 56737, 56747,
|
|
56767, 56773, 56779, 56783, 56807, 56809, 56813, 56821, 56827, 56843, 56857,
|
|
56873, 56891, 56893, 56897, 56909, 56911, 56921, 56923, 56929, 56941, 56951,
|
|
56957, 56963, 56983, 56989, 56993, 56999, 57037, 57041, 57047, 57059, 57073,
|
|
57077, 57089, 57097, 57107, 57119, 57131, 57139, 57143, 57149, 57163, 57173,
|
|
57179, 57191, 57193, 57203, 57221, 57223, 57241, 57251, 57259, 57269, 57271,
|
|
57283, 57287, 57301, 57329, 57331, 57347, 57349, 57367, 57373, 57383, 57389,
|
|
57397, 57413, 57427, 57457, 57467, 57487, 57493, 57503, 57527, 57529, 57557,
|
|
57559, 57571, 57587, 57593, 57601, 57637, 57641, 57649, 57653, 57667, 57679,
|
|
57689, 57697, 57709, 57713, 57719, 57727, 57731, 57737, 57751, 57773, 57781,
|
|
57787, 57791, 57793, 57803, 57809, 57829, 57839, 57847, 57853, 57859, 57881,
|
|
57899, 57901, 57917, 57923, 57943, 57947, 57973, 57977, 57991, 58013, 58027,
|
|
58031, 58043, 58049, 58057, 58061, 58067, 58073, 58099, 58109, 58111, 58129,
|
|
58147, 58151, 58153, 58169, 58171, 58189, 58193, 58199, 58207, 58211, 58217,
|
|
58229, 58231, 58237, 58243, 58271, 58309, 58313, 58321, 58337, 58363, 58367,
|
|
58369, 58379, 58391, 58393, 58403, 58411, 58417, 58427, 58439, 58441, 58451,
|
|
58453, 58477, 58481, 58511, 58537, 58543, 58549, 58567, 58573, 58579, 58601,
|
|
58603, 58613, 58631, 58657, 58661, 58679, 58687, 58693, 58699, 58711, 58727,
|
|
58733, 58741, 58757, 58763, 58771, 58787, 58789, 58831, 58889, 58897, 58901,
|
|
58907, 58909, 58913, 58921, 58937, 58943, 58963, 58967, 58979, 58991, 58997,
|
|
59009, 59011, 59021, 59023, 59029, 59051, 59053, 59063, 59069, 59077, 59083,
|
|
59093, 59107, 59113, 59119, 59123, 59141, 59149, 59159, 59167, 59183, 59197,
|
|
59207, 59209, 59219, 59221, 59233, 59239, 59243, 59263, 59273, 59281, 59333,
|
|
59341, 59351, 59357, 59359, 59369, 59377, 59387, 59393, 59399, 59407, 59417,
|
|
59419, 59441, 59443, 59447, 59453, 59467, 59471, 59473, 59497, 59509, 59513,
|
|
59539, 59557, 59561, 59567, 59581, 59611, 59617, 59621, 59627, 59629, 59651,
|
|
59659, 59663, 59669, 59671, 59693, 59699, 59707, 59723, 59729, 59743, 59747,
|
|
59753, 59771, 59779, 59791, 59797, 59809, 59833, 59863, 59879, 59887, 59921,
|
|
59929, 59951, 59957, 59971, 59981, 59999, 60013, 60017, 60029, 60037, 60041,
|
|
60077, 60083, 60089, 60091, 60101, 60103, 60107, 60127, 60133, 60139, 60149,
|
|
60161, 60167, 60169, 60209, 60217, 60223, 60251, 60257, 60259, 60271, 60289,
|
|
60293, 60317, 60331, 60337, 60343, 60353, 60373, 60383, 60397, 60413, 60427,
|
|
60443, 60449, 60457, 60493, 60497, 60509, 60521, 60527, 60539, 60589, 60601,
|
|
60607, 60611, 60617, 60623, 60631, 60637, 60647, 60649, 60659, 60661, 60679,
|
|
60689, 60703, 60719, 60727, 60733, 60737, 60757, 60761, 60763, 60773, 60779,
|
|
60793, 60811, 60821, 60859, 60869, 60887, 60889, 60899, 60901, 60913, 60917,
|
|
60919, 60923, 60937, 60943, 60953, 60961, 61001, 61007, 61027, 61031, 61043,
|
|
61051, 61057, 61091, 61099, 61121, 61129, 61141, 61151, 61153, 61169, 61211,
|
|
61223, 61231, 61253, 61261, 61283, 61291, 61297, 61331, 61333, 61339, 61343,
|
|
61357, 61363, 61379, 61381, 61403, 61409, 61417, 61441, 61463, 61469, 61471,
|
|
61483, 61487, 61493, 61507, 61511, 61519, 61543, 61547, 61553, 61559, 61561,
|
|
61583, 61603, 61609, 61613, 61627, 61631, 61637, 61643, 61651, 61657, 61667,
|
|
61673, 61681, 61687, 61703, 61717, 61723, 61729, 61751, 61757, 61781, 61813,
|
|
61819, 61837, 61843, 61861, 61871, 61879, 61909, 61927, 61933, 61949, 61961,
|
|
61967, 61979, 61981, 61987, 61991, 62003, 62011, 62017, 62039, 62047, 62053,
|
|
62057, 62071, 62081, 62099, 62119, 62129, 62131, 62137, 62141, 62143, 62171,
|
|
62189, 62191, 62201, 62207, 62213, 62219, 62233, 62273, 62297, 62299, 62303,
|
|
62311, 62323, 62327, 62347, 62351, 62383, 62401, 62417, 62423, 62459, 62467,
|
|
62473, 62477, 62483, 62497, 62501, 62507, 62533, 62539, 62549, 62563, 62581,
|
|
62591, 62597, 62603, 62617, 62627, 62633, 62639, 62653, 62659, 62683, 62687,
|
|
62701, 62723, 62731, 62743, 62753, 62761, 62773, 62791, 62801, 62819, 62827,
|
|
62851, 62861, 62869, 62873, 62897, 62903, 62921, 62927, 62929, 62939, 62969,
|
|
62971, 62981, 62983, 62987, 62989, 63029, 63031, 63059, 63067, 63073, 63079,
|
|
63097, 63103, 63113, 63127, 63131, 63149, 63179, 63197, 63199, 63211, 63241,
|
|
63247, 63277, 63281, 63299, 63311, 63313, 63317, 63331, 63337, 63347, 63353,
|
|
63361, 63367, 63377, 63389, 63391, 63397, 63409, 63419, 63421, 63439, 63443,
|
|
63463, 63467, 63473, 63487, 63493, 63499, 63521, 63527, 63533, 63541, 63559,
|
|
63577, 63587, 63589, 63599, 63601, 63607, 63611, 63617, 63629, 63647, 63649,
|
|
63659, 63667, 63671, 63689, 63691, 63697, 63703, 63709, 63719, 63727, 63737,
|
|
63743, 63761, 63773, 63781, 63793, 63799, 63803, 63809, 63823, 63839, 63841,
|
|
63853, 63857, 63863, 63901, 63907, 63913, 63929, 63949, 63977, 63997, 64007,
|
|
64013, 64019, 64033, 64037, 64063, 64067, 64081, 64091, 64109, 64123, 64151,
|
|
64153, 64157, 64171, 64187, 64189, 64217, 64223, 64231, 64237, 64271, 64279,
|
|
64283, 64301, 64303, 64319, 64327, 64333, 64373, 64381, 64399, 64403, 64433,
|
|
64439, 64451, 64453, 64483, 64489, 64499, 64513, 64553, 64567, 64577, 64579,
|
|
64591, 64601, 64609, 64613, 64621, 64627, 64633, 64661, 64663, 64667, 64679,
|
|
64693, 64709, 64717, 64747, 64763, 64781, 64783, 64793, 64811, 64817, 64849,
|
|
64853, 64871, 64877, 64879, 64891, 64901, 64919, 64921, 64927, 64937, 64951,
|
|
64969, 64997, 65003, 65011, 65027, 65029, 65033, 65053, 65063, 65071, 65089,
|
|
65099, 65101, 65111, 65119, 65123, 65129, 65141, 65147, 65167, 65171, 65173,
|
|
65179, 65183, 65203, 65213, 65239, 65257, 65267, 65269, 65287, 65293, 65309,
|
|
65323, 65327, 65353, 65357, 65371, 65381, 65393, 65407, 65413, 65419, 65423,
|
|
65437, 65447, 65449, 65479, 65497, 65519, 65521, 0 };
|
|
|
|
}
|
|
/*
|
|
* Modular Reducer
|
|
* (C) 1999-2011 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* Modular_Reducer Constructor
|
|
*/
|
|
Modular_Reducer::Modular_Reducer(const BigInt& mod)
|
|
{
|
|
if(mod <= 0)
|
|
throw Invalid_Argument("Modular_Reducer: modulus must be positive");
|
|
|
|
modulus = mod;
|
|
mod_words = modulus.sig_words();
|
|
|
|
modulus_2 = Botan::square(modulus);
|
|
|
|
mu = BigInt(BigInt::Power2, 2 * MP_WORD_BITS * mod_words) / modulus;
|
|
}
|
|
|
|
/*
|
|
* Barrett Reduction
|
|
*/
|
|
BigInt Modular_Reducer::reduce(const BigInt& x) const
|
|
{
|
|
if(mod_words == 0)
|
|
throw Invalid_State("Modular_Reducer: Never initalized");
|
|
|
|
if(x.cmp(modulus, false) < 0)
|
|
{
|
|
if(x.is_negative())
|
|
return x + modulus; // make positive
|
|
return x;
|
|
}
|
|
else if(x.cmp(modulus_2, false) < 0)
|
|
{
|
|
BigInt t1 = x;
|
|
t1.set_sign(BigInt::Positive);
|
|
t1 >>= (MP_WORD_BITS * (mod_words - 1));
|
|
t1 *= mu;
|
|
|
|
t1 >>= (MP_WORD_BITS * (mod_words + 1));
|
|
t1 *= modulus;
|
|
|
|
t1.mask_bits(MP_WORD_BITS * (mod_words + 1));
|
|
|
|
BigInt t2 = x;
|
|
t2.set_sign(BigInt::Positive);
|
|
t2.mask_bits(MP_WORD_BITS * (mod_words + 1));
|
|
|
|
t2 -= t1;
|
|
|
|
if(t2.is_negative())
|
|
{
|
|
BigInt b_to_k1(BigInt::Power2, MP_WORD_BITS * (mod_words + 1));
|
|
t2 += b_to_k1;
|
|
}
|
|
|
|
while(t2 >= modulus)
|
|
t2 -= modulus;
|
|
|
|
if(x.is_positive())
|
|
return t2;
|
|
else
|
|
return (modulus - t2);
|
|
}
|
|
else
|
|
{
|
|
// too big, fall back to normal division
|
|
return (x % modulus);
|
|
}
|
|
}
|
|
|
|
}
|
|
/*
|
|
* Shanks-Tonnelli (RESSOL)
|
|
* (C) 2007-2008 Falko Strenzke, FlexSecure GmbH
|
|
* (C) 2008 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* Shanks-Tonnelli algorithm
|
|
*/
|
|
BigInt ressol(const BigInt& a, const BigInt& p)
|
|
{
|
|
if(a < 0)
|
|
throw Invalid_Argument("ressol(): a to solve for must be positive");
|
|
if(p <= 1)
|
|
throw Invalid_Argument("ressol(): prime must be > 1");
|
|
|
|
if(a == 0)
|
|
return 0;
|
|
if(p == 2)
|
|
return a;
|
|
|
|
if(jacobi(a, p) != 1) // not a quadratic residue
|
|
return -BigInt(1);
|
|
|
|
if(p % 4 == 3)
|
|
return power_mod(a, ((p+1) >> 2), p);
|
|
|
|
size_t s = low_zero_bits(p - 1);
|
|
BigInt q = p >> s;
|
|
|
|
q -= 1;
|
|
q >>= 1;
|
|
|
|
Modular_Reducer mod_p(p);
|
|
|
|
BigInt r = power_mod(a, q, p);
|
|
BigInt n = mod_p.multiply(a, mod_p.square(r));
|
|
r = mod_p.multiply(r, a);
|
|
|
|
if(n == 1)
|
|
return r;
|
|
|
|
// find random non quadratic residue z
|
|
BigInt z = 2;
|
|
while(jacobi(z, p) == 1) // while z quadratic residue
|
|
++z;
|
|
|
|
BigInt c = power_mod(z, (q << 1) + 1, p);
|
|
|
|
while(n > 1)
|
|
{
|
|
q = n;
|
|
|
|
size_t i = 0;
|
|
while(q != 1)
|
|
{
|
|
q = mod_p.square(q);
|
|
++i;
|
|
}
|
|
|
|
if(s <= i)
|
|
return -BigInt(1);
|
|
|
|
c = power_mod(c, BigInt(BigInt::Power2, s-i-1), p);
|
|
r = mod_p.multiply(r, c);
|
|
c = mod_p.square(c);
|
|
n = mod_p.multiply(n, c);
|
|
s = i;
|
|
}
|
|
|
|
return r;
|
|
}
|
|
|
|
}
|
|
/*
|
|
* No-Op Mutex Factory
|
|
* (C) 1999-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* No-Op Mutex Factory
|
|
*/
|
|
Mutex* Noop_Mutex_Factory::make()
|
|
{
|
|
class Noop_Mutex : public Mutex
|
|
{
|
|
public:
|
|
class Mutex_State_Error : public Internal_Error
|
|
{
|
|
public:
|
|
Mutex_State_Error(const std::string& where) :
|
|
Internal_Error("Noop_Mutex::" + where + ": " +
|
|
"Mutex is already " + where + "ed") {}
|
|
};
|
|
|
|
void lock()
|
|
{
|
|
if(locked)
|
|
throw Mutex_State_Error("lock");
|
|
locked = true;
|
|
}
|
|
|
|
void unlock()
|
|
{
|
|
if(!locked)
|
|
throw Mutex_State_Error("unlock");
|
|
locked = false;
|
|
}
|
|
|
|
Noop_Mutex() { locked = false; }
|
|
private:
|
|
bool locked;
|
|
};
|
|
|
|
return new Noop_Mutex;
|
|
}
|
|
|
|
}
|
|
|
|
#ifdef Q_OS_WIN
|
|
/*
|
|
* Win32 Mutex
|
|
* (C) 2006 Luca Piccarreta
|
|
* 2006-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
#include <windows.h>
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* Win32 Mutex Factory
|
|
*/
|
|
Mutex* Win32_Mutex_Factory::make()
|
|
{
|
|
class Win32_Mutex : public Mutex
|
|
{
|
|
public:
|
|
void lock() { EnterCriticalSection(&mutex); }
|
|
void unlock() { LeaveCriticalSection(&mutex); }
|
|
|
|
Win32_Mutex() { InitializeCriticalSection(&mutex); }
|
|
~Win32_Mutex() { DeleteCriticalSection(&mutex); }
|
|
private:
|
|
CRITICAL_SECTION mutex;
|
|
};
|
|
|
|
return new Win32_Mutex();
|
|
}
|
|
|
|
}
|
|
#endif
|
|
|
|
#ifdef Q_OS_UNIX
|
|
/*
|
|
* Pthread Mutex
|
|
* (C) 1999-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
#ifndef _POSIX_C_SOURCE
|
|
#define _POSIX_C_SOURCE 199506
|
|
#endif
|
|
|
|
#include <pthread.h>
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* Pthread Mutex Factory
|
|
*/
|
|
Mutex* Pthread_Mutex_Factory::make()
|
|
{
|
|
|
|
class Pthread_Mutex : public Mutex
|
|
{
|
|
public:
|
|
void lock()
|
|
{
|
|
if(pthread_mutex_lock(&mutex) != 0)
|
|
throw Invalid_State("Pthread_Mutex::lock: Error occured");
|
|
}
|
|
|
|
void unlock()
|
|
{
|
|
if(pthread_mutex_unlock(&mutex) != 0)
|
|
throw Invalid_State("Pthread_Mutex::unlock: Error occured");
|
|
}
|
|
|
|
Pthread_Mutex()
|
|
{
|
|
if(pthread_mutex_init(&mutex, 0) != 0)
|
|
throw Invalid_State("Pthread_Mutex: initialization failed");
|
|
}
|
|
|
|
~Pthread_Mutex()
|
|
{
|
|
if(pthread_mutex_destroy(&mutex) != 0)
|
|
throw Invalid_State("~Pthread_Mutex: mutex is still locked");
|
|
}
|
|
private:
|
|
pthread_mutex_t mutex;
|
|
};
|
|
|
|
return new Pthread_Mutex();
|
|
}
|
|
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* Bcrypt Password Hashing
|
|
* (C) 2010 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
namespace {
|
|
|
|
std::string bcrypt_base64_encode(const byte input[], size_t length)
|
|
{
|
|
// Bcrypt uses a non-standard base64 alphabet
|
|
const byte OPENBSD_BASE64_SUB[256] = {
|
|
0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
|
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
|
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
|
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x38, 0x80, 0x80, 0x80, 0x39,
|
|
0x79, 0x7A, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x80, 0x80,
|
|
0x80, 0x80, 0x80, 0x80, 0x80, 0x2E, 0x2F, 0x41, 0x42, 0x43, 0x44, 0x45,
|
|
0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51,
|
|
0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x80, 0x80, 0x80, 0x80, 0x80,
|
|
0x80, 0x59, 0x5A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
|
|
0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75,
|
|
0x76, 0x77, 0x78, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
|
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
|
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
|
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
|
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
|
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
|
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
|
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
|
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
|
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
|
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
|
0x80, 0x80, 0x80, 0x80
|
|
};
|
|
|
|
std::string b64 = base64_encode(input, length);
|
|
|
|
while(b64.size() && b64[b64.size()-1] == '=')
|
|
b64 = b64.substr(0, b64.size() - 1);
|
|
|
|
for(size_t i = 0; i != b64.size(); ++i)
|
|
b64[i] = OPENBSD_BASE64_SUB[static_cast<byte>(b64[i])];
|
|
|
|
return b64;
|
|
}
|
|
|
|
MemoryVector<byte> bcrypt_base64_decode(std::string input)
|
|
{
|
|
const byte OPENBSD_BASE64_SUB[256] = {
|
|
0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
|
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
|
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
|
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x41, 0x42,
|
|
0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2B, 0x2F, 0x80, 0x80,
|
|
0x80, 0x80, 0x80, 0x80, 0x80, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
|
|
0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55,
|
|
0x56, 0x57, 0x58, 0x59, 0x5A, 0x61, 0x62, 0x80, 0x80, 0x80, 0x80, 0x80,
|
|
0x80, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D,
|
|
0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
|
|
0x7A, 0x30, 0x31, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
|
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
|
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
|
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
|
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
|
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
|
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
|
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
|
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
|
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
|
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
|
0x80, 0x80, 0x80, 0x80
|
|
};
|
|
|
|
for(size_t i = 0; i != input.size(); ++i)
|
|
input[i] = OPENBSD_BASE64_SUB[static_cast<byte>(input[i])];
|
|
|
|
return base64_decode(input);
|
|
}
|
|
|
|
std::string make_bcrypt(const std::string& pass,
|
|
const MemoryRegion<byte>& salt,
|
|
u16bit work_factor)
|
|
{
|
|
const byte magic[24] = {
|
|
0x4F, 0x72, 0x70, 0x68, 0x65, 0x61, 0x6E, 0x42,
|
|
0x65, 0x68, 0x6F, 0x6C, 0x64, 0x65, 0x72, 0x53,
|
|
0x63, 0x72, 0x79, 0x44, 0x6F, 0x75, 0x62, 0x74
|
|
};
|
|
|
|
MemoryVector<byte> ctext(magic, 24);
|
|
|
|
Blowfish blowfish;
|
|
|
|
// Include the trailing NULL byte
|
|
blowfish.eks_key_schedule(reinterpret_cast<const byte*>(pass.c_str()),
|
|
pass.length() + 1,
|
|
salt,
|
|
work_factor);
|
|
|
|
for(size_t i = 0; i != 64; ++i)
|
|
blowfish.encrypt_n(&ctext[0], &ctext[0], 3);
|
|
|
|
std::string salt_b64 = bcrypt_base64_encode(&salt[0], salt.size());
|
|
|
|
return "$2a$" + to_string(work_factor, 2) + "$" + salt_b64.substr(0, 22) +
|
|
bcrypt_base64_encode(&ctext[0], ctext.size() - 1);
|
|
}
|
|
|
|
}
|
|
|
|
std::string generate_bcrypt(const std::string& pass,
|
|
RandomNumberGenerator& rng,
|
|
u16bit work_factor)
|
|
{
|
|
return make_bcrypt(pass, rng.random_vec(16), work_factor);
|
|
}
|
|
|
|
bool check_bcrypt(const std::string& pass, const std::string& hash)
|
|
{
|
|
if(hash.size() != 60 ||
|
|
hash[0] != '$' || hash[1] != '2' || hash[2] != 'a' ||
|
|
hash[3] != '$' || hash[6] != '$')
|
|
{
|
|
return false;
|
|
}
|
|
|
|
const u16bit workfactor = to_u32bit(hash.substr(4, 2));
|
|
|
|
MemoryVector<byte> salt = bcrypt_base64_decode(hash.substr(7, 22));
|
|
|
|
const std::string compare = make_bcrypt(pass, salt, workfactor);
|
|
|
|
return (hash == compare);
|
|
}
|
|
|
|
}
|
|
/*
|
|
* Passhash9 Password Hashing
|
|
* (C) 2010 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
namespace {
|
|
|
|
const std::string MAGIC_PREFIX = "$9$";
|
|
|
|
const size_t WORKFACTOR_BYTES = 2;
|
|
const size_t ALGID_BYTES = 1;
|
|
const size_t SALT_BYTES = 12; // 96 bits of salt
|
|
const size_t PASSHASH9_PBKDF_OUTPUT_LEN = 24; // 192 bits output
|
|
|
|
const size_t WORK_FACTOR_SCALE = 10000;
|
|
|
|
MessageAuthenticationCode* get_pbkdf_prf(byte alg_id)
|
|
{
|
|
Algorithm_Factory& af = global_state().algorithm_factory();
|
|
|
|
try
|
|
{
|
|
if(alg_id == 0)
|
|
return af.make_mac("HMAC(SHA-1)");
|
|
else if(alg_id == 1)
|
|
return af.make_mac("HMAC(SHA-256)");
|
|
else if(alg_id == 2)
|
|
return af.make_mac("CMAC(Blowfish)");
|
|
}
|
|
catch(Algorithm_Not_Found) {}
|
|
|
|
return 0;
|
|
}
|
|
|
|
}
|
|
|
|
std::string generate_passhash9(const std::string& pass,
|
|
RandomNumberGenerator& rng,
|
|
u16bit work_factor,
|
|
byte alg_id)
|
|
{
|
|
MessageAuthenticationCode* prf = get_pbkdf_prf(alg_id);
|
|
|
|
if(!prf)
|
|
throw Invalid_Argument("Passhash9: Algorithm id " + to_string(alg_id) +
|
|
" is not defined");
|
|
|
|
PKCS5_PBKDF2 kdf(prf); // takes ownership of pointer
|
|
|
|
SecureVector<byte> salt(SALT_BYTES);
|
|
rng.randomize(&salt[0], salt.size());
|
|
|
|
const size_t kdf_iterations = WORK_FACTOR_SCALE * work_factor;
|
|
|
|
SecureVector<byte> pbkdf2_output =
|
|
kdf.derive_key(PASSHASH9_PBKDF_OUTPUT_LEN,
|
|
pass,
|
|
&salt[0], salt.size(),
|
|
kdf_iterations).bits_of();
|
|
|
|
Pipe pipe(new Base64_Encoder);
|
|
pipe.start_msg();
|
|
pipe.write(alg_id);
|
|
pipe.write(get_byte(0, work_factor));
|
|
pipe.write(get_byte(1, work_factor));
|
|
pipe.write(salt);
|
|
pipe.write(pbkdf2_output);
|
|
pipe.end_msg();
|
|
|
|
return MAGIC_PREFIX + pipe.read_all_as_string();
|
|
}
|
|
|
|
bool check_passhash9(const std::string& pass, const std::string& hash)
|
|
{
|
|
const size_t BINARY_LENGTH =
|
|
ALGID_BYTES +
|
|
WORKFACTOR_BYTES +
|
|
PASSHASH9_PBKDF_OUTPUT_LEN +
|
|
SALT_BYTES;
|
|
|
|
const size_t BASE64_LENGTH =
|
|
MAGIC_PREFIX.size() + (BINARY_LENGTH * 8) / 6;
|
|
|
|
if(hash.size() != BASE64_LENGTH)
|
|
return false;
|
|
|
|
for(size_t i = 0; i != MAGIC_PREFIX.size(); ++i)
|
|
if(hash[i] != MAGIC_PREFIX[i])
|
|
return false;
|
|
|
|
Pipe pipe(new Base64_Decoder);
|
|
pipe.start_msg();
|
|
pipe.write(hash.c_str() + MAGIC_PREFIX.size());
|
|
pipe.end_msg();
|
|
|
|
SecureVector<byte> bin = pipe.read_all();
|
|
|
|
if(bin.size() != BINARY_LENGTH)
|
|
return false;
|
|
|
|
byte alg_id = bin[0];
|
|
|
|
const size_t kdf_iterations =
|
|
WORK_FACTOR_SCALE * load_be<u16bit>(&bin[ALGID_BYTES], 0);
|
|
|
|
if(kdf_iterations == 0)
|
|
return false;
|
|
|
|
MessageAuthenticationCode* pbkdf_prf = get_pbkdf_prf(alg_id);
|
|
|
|
if(pbkdf_prf == 0)
|
|
return false; // unknown algorithm, reject
|
|
|
|
PKCS5_PBKDF2 kdf(pbkdf_prf); // takes ownership of pointer
|
|
|
|
SecureVector<byte> cmp = kdf.derive_key(
|
|
PASSHASH9_PBKDF_OUTPUT_LEN,
|
|
pass,
|
|
&bin[ALGID_BYTES + WORKFACTOR_BYTES], SALT_BYTES,
|
|
kdf_iterations).bits_of();
|
|
|
|
return same_mem(&cmp[0],
|
|
&bin[ALGID_BYTES + WORKFACTOR_BYTES + SALT_BYTES],
|
|
PASSHASH9_PBKDF_OUTPUT_LEN);
|
|
}
|
|
|
|
}
|
|
/*
|
|
* PBE Retrieval
|
|
* (C) 1999-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
#if defined(BOTAN_HAS_PBE_PKCS_V15)
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_PBE_PKCS_V20)
|
|
#endif
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* Get an encryption PBE, set new parameters
|
|
*/
|
|
PBE* get_pbe(const std::string& algo_spec)
|
|
{
|
|
SCAN_Name request(algo_spec);
|
|
|
|
const std::string pbe = request.algo_name();
|
|
std::string digest_name = request.arg(0);
|
|
const std::string cipher = request.arg(1);
|
|
|
|
std::vector<std::string> cipher_spec = split_on(cipher, '/');
|
|
if(cipher_spec.size() != 2)
|
|
throw Invalid_Argument("PBE: Invalid cipher spec " + cipher);
|
|
|
|
const std::string cipher_algo = global_state().deref_alias(cipher_spec[0]);
|
|
const std::string cipher_mode = cipher_spec[1];
|
|
|
|
if(cipher_mode != "CBC")
|
|
throw Invalid_Argument("PBE: Invalid cipher mode " + cipher);
|
|
|
|
Algorithm_Factory& af = global_state().algorithm_factory();
|
|
|
|
const BlockCipher* block_cipher = af.prototype_block_cipher(cipher_algo);
|
|
if(!block_cipher)
|
|
throw Algorithm_Not_Found(cipher_algo);
|
|
|
|
const HashFunction* hash_function = af.prototype_hash_function(digest_name);
|
|
if(!hash_function)
|
|
throw Algorithm_Not_Found(digest_name);
|
|
|
|
if(request.arg_count() != 2)
|
|
throw Invalid_Algorithm_Name(algo_spec);
|
|
|
|
#if defined(BOTAN_HAS_PBE_PKCS_V15)
|
|
if(pbe == "PBE-PKCS5v15")
|
|
return new PBE_PKCS5v15(block_cipher->clone(),
|
|
hash_function->clone(),
|
|
ENCRYPTION);
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_PBE_PKCS_V20)
|
|
if(pbe == "PBE-PKCS5v20")
|
|
return new PBE_PKCS5v20(block_cipher->clone(),
|
|
hash_function->clone());
|
|
#endif
|
|
|
|
throw Algorithm_Not_Found(algo_spec);
|
|
}
|
|
|
|
/*
|
|
* Get a decryption PBE, decode parameters
|
|
*/
|
|
PBE* get_pbe(const OID& pbe_oid, DataSource& params)
|
|
{
|
|
SCAN_Name request(OIDS::lookup(pbe_oid));
|
|
|
|
const std::string pbe = request.algo_name();
|
|
|
|
#if defined(BOTAN_HAS_PBE_PKCS_V15)
|
|
if(pbe == "PBE-PKCS5v15")
|
|
{
|
|
if(request.arg_count() != 2)
|
|
throw Invalid_Algorithm_Name(request.as_string());
|
|
|
|
std::string digest_name = request.arg(0);
|
|
const std::string cipher = request.arg(1);
|
|
|
|
std::vector<std::string> cipher_spec = split_on(cipher, '/');
|
|
if(cipher_spec.size() != 2)
|
|
throw Invalid_Argument("PBE: Invalid cipher spec " + cipher);
|
|
|
|
const std::string cipher_algo = global_state().deref_alias(cipher_spec[0]);
|
|
const std::string cipher_mode = cipher_spec[1];
|
|
|
|
if(cipher_mode != "CBC")
|
|
throw Invalid_Argument("PBE: Invalid cipher mode " + cipher);
|
|
|
|
Algorithm_Factory& af = global_state().algorithm_factory();
|
|
|
|
const BlockCipher* block_cipher = af.prototype_block_cipher(cipher_algo);
|
|
if(!block_cipher)
|
|
throw Algorithm_Not_Found(cipher_algo);
|
|
|
|
const HashFunction* hash_function =
|
|
af.prototype_hash_function(digest_name);
|
|
|
|
if(!hash_function)
|
|
throw Algorithm_Not_Found(digest_name);
|
|
|
|
PBE* pbe = new PBE_PKCS5v15(block_cipher->clone(),
|
|
hash_function->clone(),
|
|
DECRYPTION);
|
|
pbe->decode_params(params);
|
|
return pbe;
|
|
}
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_PBE_PKCS_V20)
|
|
if(pbe == "PBE-PKCS5v20")
|
|
return new PBE_PKCS5v20(params);
|
|
#endif
|
|
|
|
throw Algorithm_Not_Found(pbe_oid.as_string());
|
|
}
|
|
|
|
}
|
|
/*
|
|
* PKCS #5 PBES1
|
|
* (C) 1999-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
#include <algorithm>
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* Encrypt some bytes using PBES1
|
|
*/
|
|
void PBE_PKCS5v15::write(const byte input[], size_t length)
|
|
{
|
|
pipe.write(input, length);
|
|
flush_pipe(true);
|
|
}
|
|
|
|
/*
|
|
* Start encrypting with PBES1
|
|
*/
|
|
void PBE_PKCS5v15::start_msg()
|
|
{
|
|
if(direction == ENCRYPTION)
|
|
pipe.append(new CBC_Encryption(block_cipher->clone(),
|
|
new PKCS7_Padding,
|
|
key, iv));
|
|
else
|
|
pipe.append(new CBC_Decryption(block_cipher->clone(),
|
|
new PKCS7_Padding,
|
|
key, iv));
|
|
|
|
pipe.start_msg();
|
|
if(pipe.message_count() > 1)
|
|
pipe.set_default_msg(pipe.default_msg() + 1);
|
|
}
|
|
|
|
/*
|
|
* Finish encrypting with PBES1
|
|
*/
|
|
void PBE_PKCS5v15::end_msg()
|
|
{
|
|
pipe.end_msg();
|
|
flush_pipe(false);
|
|
pipe.reset();
|
|
}
|
|
|
|
/*
|
|
* Flush the pipe
|
|
*/
|
|
void PBE_PKCS5v15::flush_pipe(bool safe_to_skip)
|
|
{
|
|
if(safe_to_skip && pipe.remaining() < 64)
|
|
return;
|
|
|
|
SecureVector<byte> buffer(DEFAULT_BUFFERSIZE);
|
|
while(pipe.remaining())
|
|
{
|
|
size_t got = pipe.read(&buffer[0], buffer.size());
|
|
send(buffer, got);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Set the passphrase to use
|
|
*/
|
|
void PBE_PKCS5v15::set_key(const std::string& passphrase)
|
|
{
|
|
PKCS5_PBKDF1 pbkdf(hash_function->clone());
|
|
|
|
SecureVector<byte> key_and_iv = pbkdf.derive_key(16, passphrase,
|
|
&salt[0], salt.size(),
|
|
iterations).bits_of();
|
|
|
|
key.resize(8);
|
|
iv.resize(8);
|
|
copy_mem(&key[0], &key_and_iv[0], 8);
|
|
copy_mem(&iv[0], &key_and_iv[8], 8);
|
|
}
|
|
|
|
/*
|
|
* Create a new set of PBES1 parameters
|
|
*/
|
|
void PBE_PKCS5v15::new_params(RandomNumberGenerator& rng)
|
|
{
|
|
iterations = 50000;
|
|
salt = rng.random_vec(8);
|
|
}
|
|
|
|
/*
|
|
* Encode PKCS#5 PBES1 parameters
|
|
*/
|
|
MemoryVector<byte> PBE_PKCS5v15::encode_params() const
|
|
{
|
|
return DER_Encoder()
|
|
.start_cons(SEQUENCE)
|
|
.encode(salt, OCTET_STRING)
|
|
.encode(iterations)
|
|
.end_cons()
|
|
.get_contents();
|
|
}
|
|
|
|
/*
|
|
* Decode PKCS#5 PBES1 parameters
|
|
*/
|
|
void PBE_PKCS5v15::decode_params(DataSource& source)
|
|
{
|
|
BER_Decoder(source)
|
|
.start_cons(SEQUENCE)
|
|
.decode(salt, OCTET_STRING)
|
|
.decode(iterations)
|
|
.verify_end()
|
|
.end_cons();
|
|
|
|
if(salt.size() != 8)
|
|
throw Decoding_Error("PBES1: Encoded salt is not 8 octets");
|
|
}
|
|
|
|
/*
|
|
* Return an OID for this PBES1 type
|
|
*/
|
|
OID PBE_PKCS5v15::get_oid() const
|
|
{
|
|
const OID base_pbes1_oid("1.2.840.113549.1.5");
|
|
|
|
const std::string cipher = block_cipher->name();
|
|
const std::string digest = hash_function->name();
|
|
|
|
if(cipher == "DES" && digest == "MD2")
|
|
return (base_pbes1_oid + 1);
|
|
else if(cipher == "DES" && digest == "MD5")
|
|
return (base_pbes1_oid + 3);
|
|
else if(cipher == "DES" && digest == "SHA-160")
|
|
return (base_pbes1_oid + 10);
|
|
else if(cipher == "RC2" && digest == "MD2")
|
|
return (base_pbes1_oid + 4);
|
|
else if(cipher == "RC2" && digest == "MD5")
|
|
return (base_pbes1_oid + 6);
|
|
else if(cipher == "RC2" && digest == "SHA-160")
|
|
return (base_pbes1_oid + 11);
|
|
else
|
|
throw Internal_Error("PBE-PKCS5 v1.5: get_oid() has run out of options");
|
|
}
|
|
|
|
std::string PBE_PKCS5v15::name() const
|
|
{
|
|
return "PBE-PKCS5v15(" + block_cipher->name() + "," +
|
|
hash_function->name() + ")";
|
|
}
|
|
|
|
/*
|
|
* PKCS#5 v1.5 PBE Constructor
|
|
*/
|
|
PBE_PKCS5v15::PBE_PKCS5v15(BlockCipher* cipher,
|
|
HashFunction* hash,
|
|
Cipher_Dir dir) :
|
|
direction(dir), block_cipher(cipher), hash_function(hash), iterations(0)
|
|
{
|
|
if(cipher->name() != "DES" && cipher->name() != "RC2")
|
|
{
|
|
throw Invalid_Argument("PBE_PKCS5v1.5: Unknown cipher " +
|
|
cipher->name());
|
|
}
|
|
|
|
if(hash->name() != "MD2" && hash->name() != "MD5" &&
|
|
hash->name() != "SHA-160")
|
|
{
|
|
throw Invalid_Argument("PBE_PKCS5v1.5: Unknown hash " +
|
|
hash->name());
|
|
}
|
|
}
|
|
|
|
PBE_PKCS5v15::~PBE_PKCS5v15()
|
|
{
|
|
delete block_cipher;
|
|
delete hash_function;
|
|
}
|
|
|
|
}
|
|
/*
|
|
* PKCS #5 PBES2
|
|
* (C) 1999-2008 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
#include <algorithm>
|
|
#include <memory>
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* Encrypt some bytes using PBES2
|
|
*/
|
|
void PBE_PKCS5v20::write(const byte input[], size_t length)
|
|
{
|
|
pipe.write(input, length);
|
|
flush_pipe(true);
|
|
}
|
|
|
|
/*
|
|
* Start encrypting with PBES2
|
|
*/
|
|
void PBE_PKCS5v20::start_msg()
|
|
{
|
|
if(direction == ENCRYPTION)
|
|
pipe.append(new CBC_Encryption(block_cipher->clone(),
|
|
new PKCS7_Padding,
|
|
key, iv));
|
|
else
|
|
pipe.append(new CBC_Decryption(block_cipher->clone(),
|
|
new PKCS7_Padding,
|
|
key, iv));
|
|
|
|
pipe.start_msg();
|
|
if(pipe.message_count() > 1)
|
|
pipe.set_default_msg(pipe.default_msg() + 1);
|
|
}
|
|
|
|
/*
|
|
* Finish encrypting with PBES2
|
|
*/
|
|
void PBE_PKCS5v20::end_msg()
|
|
{
|
|
pipe.end_msg();
|
|
flush_pipe(false);
|
|
pipe.reset();
|
|
}
|
|
|
|
/*
|
|
* Flush the pipe
|
|
*/
|
|
void PBE_PKCS5v20::flush_pipe(bool safe_to_skip)
|
|
{
|
|
if(safe_to_skip && pipe.remaining() < 64)
|
|
return;
|
|
|
|
SecureVector<byte> buffer(DEFAULT_BUFFERSIZE);
|
|
while(pipe.remaining())
|
|
{
|
|
size_t got = pipe.read(&buffer[0], buffer.size());
|
|
send(buffer, got);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Set the passphrase to use
|
|
*/
|
|
void PBE_PKCS5v20::set_key(const std::string& passphrase)
|
|
{
|
|
PKCS5_PBKDF2 pbkdf(new HMAC(hash_function->clone()));
|
|
|
|
key = pbkdf.derive_key(key_length, passphrase,
|
|
&salt[0], salt.size(),
|
|
iterations).bits_of();
|
|
}
|
|
|
|
/*
|
|
* Create a new set of PBES2 parameters
|
|
*/
|
|
void PBE_PKCS5v20::new_params(RandomNumberGenerator& rng)
|
|
{
|
|
iterations = 50000;
|
|
key_length = block_cipher->maximum_keylength();
|
|
|
|
salt = rng.random_vec(12);
|
|
iv = rng.random_vec(block_cipher->block_size());
|
|
}
|
|
|
|
/*
|
|
* Encode PKCS#5 PBES2 parameters
|
|
*/
|
|
MemoryVector<byte> PBE_PKCS5v20::encode_params() const
|
|
{
|
|
return DER_Encoder()
|
|
.start_cons(SEQUENCE)
|
|
.encode(
|
|
AlgorithmIdentifier("PKCS5.PBKDF2",
|
|
DER_Encoder()
|
|
.start_cons(SEQUENCE)
|
|
.encode(salt, OCTET_STRING)
|
|
.encode(iterations)
|
|
.encode(key_length)
|
|
.end_cons()
|
|
.get_contents()
|
|
)
|
|
)
|
|
.encode(
|
|
AlgorithmIdentifier(block_cipher->name() + "/CBC",
|
|
DER_Encoder()
|
|
.encode(iv, OCTET_STRING)
|
|
.get_contents()
|
|
)
|
|
)
|
|
.end_cons()
|
|
.get_contents();
|
|
}
|
|
|
|
/*
|
|
* Decode PKCS#5 PBES2 parameters
|
|
*/
|
|
void PBE_PKCS5v20::decode_params(DataSource& source)
|
|
{
|
|
AlgorithmIdentifier kdf_algo, enc_algo;
|
|
|
|
BER_Decoder(source)
|
|
.start_cons(SEQUENCE)
|
|
.decode(kdf_algo)
|
|
.decode(enc_algo)
|
|
.verify_end()
|
|
.end_cons();
|
|
|
|
if(kdf_algo.oid == OIDS::lookup("PKCS5.PBKDF2"))
|
|
{
|
|
BER_Decoder(kdf_algo.parameters)
|
|
.start_cons(SEQUENCE)
|
|
.decode(salt, OCTET_STRING)
|
|
.decode(iterations)
|
|
.decode_optional(key_length, INTEGER, UNIVERSAL)
|
|
.verify_end()
|
|
.end_cons();
|
|
}
|
|
else
|
|
throw Decoding_Error("PBE-PKCS5 v2.0: Unknown KDF algorithm " +
|
|
kdf_algo.oid.as_string());
|
|
|
|
Algorithm_Factory& af = global_state().algorithm_factory();
|
|
|
|
std::string cipher = OIDS::lookup(enc_algo.oid);
|
|
std::vector<std::string> cipher_spec = split_on(cipher, '/');
|
|
if(cipher_spec.size() != 2)
|
|
throw Decoding_Error("PBE-PKCS5 v2.0: Invalid cipher spec " + cipher);
|
|
|
|
if(!known_cipher(cipher_spec[0]) || cipher_spec[1] != "CBC")
|
|
throw Decoding_Error("PBE-PKCS5 v2.0: Don't know param format for " +
|
|
cipher);
|
|
|
|
BER_Decoder(enc_algo.parameters).decode(iv, OCTET_STRING).verify_end();
|
|
|
|
block_cipher = af.make_block_cipher(cipher_spec[0]);
|
|
hash_function = af.make_hash_function("SHA-160");
|
|
|
|
if(key_length == 0)
|
|
key_length = block_cipher->maximum_keylength();
|
|
|
|
if(salt.size() < 8)
|
|
throw Decoding_Error("PBE-PKCS5 v2.0: Encoded salt is too small");
|
|
}
|
|
|
|
/*
|
|
* Return an OID for PBES2
|
|
*/
|
|
OID PBE_PKCS5v20::get_oid() const
|
|
{
|
|
return OIDS::lookup("PBE-PKCS5v20");
|
|
}
|
|
|
|
/*
|
|
* Check if this is a known PBES2 cipher
|
|
*/
|
|
bool PBE_PKCS5v20::known_cipher(const std::string& algo)
|
|
{
|
|
if(algo == "AES-128" || algo == "AES-192" || algo == "AES-256")
|
|
return true;
|
|
if(algo == "DES" || algo == "TripleDES")
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
std::string PBE_PKCS5v20::name() const
|
|
{
|
|
return "PBE-PKCS5v20(" + block_cipher->name() + "," +
|
|
hash_function->name() + ")";
|
|
}
|
|
|
|
/*
|
|
* PKCS#5 v2.0 PBE Constructor
|
|
*/
|
|
PBE_PKCS5v20::PBE_PKCS5v20(BlockCipher* cipher,
|
|
HashFunction* digest) :
|
|
direction(ENCRYPTION),
|
|
block_cipher(cipher),
|
|
hash_function(digest),
|
|
iterations(0),
|
|
key_length(0)
|
|
{
|
|
if(!known_cipher(block_cipher->name()))
|
|
throw Invalid_Argument("PBE-PKCS5 v2.0: Invalid cipher " + cipher->name());
|
|
if(hash_function->name() != "SHA-160")
|
|
throw Invalid_Argument("PBE-PKCS5 v2.0: Invalid digest " + digest->name());
|
|
}
|
|
|
|
/*
|
|
* PKCS#5 v2.0 PBE Constructor
|
|
*/
|
|
PBE_PKCS5v20::PBE_PKCS5v20(DataSource& params) : direction(DECRYPTION)
|
|
{
|
|
hash_function = 0;
|
|
block_cipher = 0;
|
|
decode_params(params);
|
|
}
|
|
|
|
PBE_PKCS5v20::~PBE_PKCS5v20()
|
|
{
|
|
delete hash_function;
|
|
delete block_cipher;
|
|
}
|
|
|
|
}
|
|
/*
|
|
* PBKDF1
|
|
* (C) 1999-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* Return a PKCS#5 PBKDF1 derived key
|
|
*/
|
|
OctetString PKCS5_PBKDF1::derive_key(size_t key_len,
|
|
const std::string& passphrase,
|
|
const byte salt[], size_t salt_size,
|
|
size_t iterations) const
|
|
{
|
|
if(iterations == 0)
|
|
throw Invalid_Argument("PKCS5_PBKDF1: Invalid iteration count");
|
|
|
|
if(key_len > hash->output_length())
|
|
throw Invalid_Argument("PKCS5_PBKDF1: Requested output length too long");
|
|
|
|
hash->update(passphrase);
|
|
hash->update(salt, salt_size);
|
|
SecureVector<byte> key = hash->final();
|
|
|
|
for(size_t j = 1; j != iterations; ++j)
|
|
{
|
|
hash->update(key);
|
|
hash->final(&key[0]);
|
|
}
|
|
|
|
return OctetString(&key[0], std::min<size_t>(key_len, key.size()));
|
|
}
|
|
|
|
}
|
|
/*
|
|
* PBKDF2
|
|
* (C) 1999-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* Return a PKCS #5 PBKDF2 derived key
|
|
*/
|
|
OctetString PKCS5_PBKDF2::derive_key(size_t key_len,
|
|
const std::string& passphrase,
|
|
const byte salt[], size_t salt_size,
|
|
size_t iterations) const
|
|
{
|
|
if(iterations == 0)
|
|
throw Invalid_Argument("PKCS#5 PBKDF2: Invalid iteration count");
|
|
|
|
try
|
|
{
|
|
mac->set_key(reinterpret_cast<const byte*>(passphrase.data()),
|
|
passphrase.length());
|
|
}
|
|
catch(Invalid_Key_Length)
|
|
{
|
|
throw Exception(name() + " cannot accept passphrases of length " +
|
|
to_string(passphrase.length()));
|
|
}
|
|
|
|
SecureVector<byte> key(key_len);
|
|
|
|
byte* T = &key[0];
|
|
|
|
SecureVector<byte> U(mac->output_length());
|
|
|
|
u32bit counter = 1;
|
|
while(key_len)
|
|
{
|
|
size_t T_size = std::min<size_t>(mac->output_length(), key_len);
|
|
|
|
mac->update(salt, salt_size);
|
|
mac->update_be(counter);
|
|
mac->final(&U[0]);
|
|
|
|
xor_buf(T, U, T_size);
|
|
|
|
for(size_t j = 1; j != iterations; ++j)
|
|
{
|
|
mac->update(U);
|
|
mac->final(&U[0]);
|
|
xor_buf(T, U, T_size);
|
|
}
|
|
|
|
key_len -= T_size;
|
|
T += T_size;
|
|
++counter;
|
|
}
|
|
|
|
return key;
|
|
}
|
|
|
|
}
|
|
/*
|
|
* OpenPGP S2K
|
|
* (C) 1999-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* Derive a key using the OpenPGP S2K algorithm
|
|
*/
|
|
OctetString OpenPGP_S2K::derive_key(size_t key_len,
|
|
const std::string& passphrase,
|
|
const byte salt_buf[], size_t salt_size,
|
|
size_t iterations) const
|
|
{
|
|
SecureVector<byte> key(key_len), hash_buf;
|
|
|
|
size_t pass = 0, generated = 0,
|
|
total_size = passphrase.size() + salt_size;
|
|
size_t to_hash = std::max(iterations, total_size);
|
|
|
|
hash->clear();
|
|
while(key_len > generated)
|
|
{
|
|
for(size_t j = 0; j != pass; ++j)
|
|
hash->update(0);
|
|
|
|
size_t left = to_hash;
|
|
while(left >= total_size)
|
|
{
|
|
hash->update(salt_buf, salt_size);
|
|
hash->update(passphrase);
|
|
left -= total_size;
|
|
}
|
|
if(left <= salt_size)
|
|
hash->update(salt_buf, left);
|
|
else
|
|
{
|
|
hash->update(salt_buf, salt_size);
|
|
left -= salt_size;
|
|
hash->update(reinterpret_cast<const byte*>(passphrase.data()), left);
|
|
}
|
|
|
|
hash_buf = hash->final();
|
|
key.copy(generated, &hash_buf[0], hash->output_length());
|
|
generated += hash->output_length();
|
|
++pass;
|
|
}
|
|
|
|
return key;
|
|
}
|
|
|
|
}
|
|
/*
|
|
* EME Base Class
|
|
* (C) 1999-2008 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* Encode a message
|
|
*/
|
|
SecureVector<byte> EME::encode(const byte msg[], size_t msg_len,
|
|
size_t key_bits,
|
|
RandomNumberGenerator& rng) const
|
|
{
|
|
return pad(msg, msg_len, key_bits, rng);
|
|
}
|
|
|
|
/*
|
|
* Encode a message
|
|
*/
|
|
SecureVector<byte> EME::encode(const MemoryRegion<byte>& msg,
|
|
size_t key_bits,
|
|
RandomNumberGenerator& rng) const
|
|
{
|
|
return pad(&msg[0], msg.size(), key_bits, rng);
|
|
}
|
|
|
|
/*
|
|
* Decode a message
|
|
*/
|
|
SecureVector<byte> EME::decode(const byte msg[], size_t msg_len,
|
|
size_t key_bits) const
|
|
{
|
|
return unpad(msg, msg_len, key_bits);
|
|
}
|
|
|
|
/*
|
|
* Decode a message
|
|
*/
|
|
SecureVector<byte> EME::decode(const MemoryRegion<byte>& msg,
|
|
size_t key_bits) const
|
|
{
|
|
return unpad(&msg[0], msg.size(), key_bits);
|
|
}
|
|
|
|
}
|
|
/*
|
|
* EME1 (aka OAEP)
|
|
* (C) 1999-2010 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
#include <memory>
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* EME1 Pad Operation
|
|
*/
|
|
SecureVector<byte> EME1::pad(const byte in[], size_t in_length,
|
|
size_t key_length,
|
|
RandomNumberGenerator& rng) const
|
|
{
|
|
key_length /= 8;
|
|
|
|
if(in_length > key_length - 2*Phash.size() - 1)
|
|
throw Invalid_Argument("EME1: Input is too large");
|
|
|
|
SecureVector<byte> out(key_length);
|
|
|
|
rng.randomize(&out[0], Phash.size());
|
|
|
|
out.copy(Phash.size(), &Phash[0], Phash.size());
|
|
out[out.size() - in_length - 1] = 0x01;
|
|
out.copy(out.size() - in_length, in, in_length);
|
|
|
|
mgf->mask(&out[0], Phash.size(),
|
|
&out[Phash.size()], out.size() - Phash.size());
|
|
|
|
mgf->mask(&out[Phash.size()], out.size() - Phash.size(),
|
|
&out[0], Phash.size());
|
|
|
|
return out;
|
|
}
|
|
|
|
/*
|
|
* EME1 Unpad Operation
|
|
*/
|
|
SecureVector<byte> EME1::unpad(const byte in[], size_t in_length,
|
|
size_t key_length) const
|
|
{
|
|
/*
|
|
Must be careful about error messages here; if an attacker can
|
|
distinguish them, it is easy to use the differences as an oracle to
|
|
find the secret key, as described in "A Chosen Ciphertext Attack on
|
|
RSA Optimal Asymmetric Encryption Padding (OAEP) as Standardized in
|
|
PKCS #1 v2.0", James Manger, Crypto 2001
|
|
|
|
Also have to be careful about timing attacks! Pointed out by Falko
|
|
Strenzke.
|
|
*/
|
|
|
|
key_length /= 8;
|
|
|
|
// Invalid input: truncate to zero length input, causing later
|
|
// checks to fail
|
|
if(in_length > key_length)
|
|
in_length = 0;
|
|
|
|
SecureVector<byte> input(key_length);
|
|
input.copy(key_length - in_length, in, in_length);
|
|
|
|
mgf->mask(&input[Phash.size()], input.size() - Phash.size(),
|
|
&input[0], Phash.size());
|
|
mgf->mask(&input[0], Phash.size(),
|
|
&input[Phash.size()], input.size() - Phash.size());
|
|
|
|
bool waiting_for_delim = true;
|
|
bool bad_input = false;
|
|
size_t delim_idx = 2 * Phash.size();
|
|
|
|
/*
|
|
* GCC 4.5 on x86-64 compiles this in a way that is still vunerable
|
|
* to timing analysis. Other compilers, or GCC on other platforms,
|
|
* may or may not.
|
|
*/
|
|
for(size_t i = delim_idx; i != input.size(); ++i)
|
|
{
|
|
const bool zero_p = !input[i];
|
|
const bool one_p = input[i] == 0x01;
|
|
|
|
const bool add_1 = waiting_for_delim && zero_p;
|
|
|
|
bad_input |= waiting_for_delim && !(zero_p || one_p);
|
|
|
|
delim_idx += add_1;
|
|
|
|
waiting_for_delim &= zero_p;
|
|
}
|
|
|
|
// If we never saw any non-zero byte, then it's not valid input
|
|
bad_input |= waiting_for_delim;
|
|
|
|
bad_input |= !same_mem(&input[Phash.size()], &Phash[0], Phash.size());
|
|
|
|
if(bad_input)
|
|
throw Decoding_Error("Invalid EME1 encoding");
|
|
|
|
return SecureVector<byte>(input + delim_idx + 1,
|
|
input.size() - delim_idx - 1);
|
|
}
|
|
|
|
/*
|
|
* Return the max input size for a given key size
|
|
*/
|
|
size_t EME1::maximum_input_size(size_t keybits) const
|
|
{
|
|
if(keybits / 8 > 2*Phash.size() + 1)
|
|
return ((keybits / 8) - 2*Phash.size() - 1);
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* EME1 Constructor
|
|
*/
|
|
EME1::EME1(HashFunction* hash, const std::string& P)
|
|
{
|
|
Phash = hash->process(P);
|
|
mgf = new MGF1(hash);
|
|
}
|
|
|
|
}
|
|
/*
|
|
* PKCS1 EME
|
|
* (C) 1999-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* PKCS1 Pad Operation
|
|
*/
|
|
SecureVector<byte> EME_PKCS1v15::pad(const byte in[], size_t inlen,
|
|
size_t olen,
|
|
RandomNumberGenerator& rng) const
|
|
{
|
|
olen /= 8;
|
|
|
|
if(olen < 10)
|
|
throw Encoding_Error("PKCS1: Output space too small");
|
|
if(inlen > olen - 10)
|
|
throw Encoding_Error("PKCS1: Input is too large");
|
|
|
|
SecureVector<byte> out(olen);
|
|
|
|
out[0] = 0x02;
|
|
for(size_t j = 1; j != olen - inlen - 1; ++j)
|
|
while(out[j] == 0)
|
|
out[j] = rng.next_byte();
|
|
out.copy(olen - inlen, in, inlen);
|
|
|
|
return out;
|
|
}
|
|
|
|
/*
|
|
* PKCS1 Unpad Operation
|
|
*/
|
|
SecureVector<byte> EME_PKCS1v15::unpad(const byte in[], size_t inlen,
|
|
size_t key_len) const
|
|
{
|
|
if(inlen != key_len / 8 || inlen < 10 || in[0] != 0x02)
|
|
throw Decoding_Error("PKCS1::unpad");
|
|
|
|
size_t seperator = 0;
|
|
for(size_t j = 0; j != inlen; ++j)
|
|
if(in[j] == 0)
|
|
{
|
|
seperator = j;
|
|
break;
|
|
}
|
|
if(seperator < 9)
|
|
throw Decoding_Error("PKCS1::unpad");
|
|
|
|
return SecureVector<byte>(in + seperator + 1, inlen - seperator - 1);
|
|
}
|
|
|
|
/*
|
|
* Return the max input size for a given key size
|
|
*/
|
|
size_t EME_PKCS1v15::maximum_input_size(size_t keybits) const
|
|
{
|
|
if(keybits / 8 > 10)
|
|
return ((keybits / 8) - 10);
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
}
|
|
/*
|
|
* EMSA1
|
|
* (C) 1999-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
namespace {
|
|
|
|
SecureVector<byte> emsa1_encoding(const MemoryRegion<byte>& msg,
|
|
size_t output_bits)
|
|
{
|
|
if(8*msg.size() <= output_bits)
|
|
return msg;
|
|
|
|
size_t shift = 8*msg.size() - output_bits;
|
|
|
|
size_t byte_shift = shift / 8, bit_shift = shift % 8;
|
|
SecureVector<byte> digest(msg.size() - byte_shift);
|
|
|
|
for(size_t j = 0; j != msg.size() - byte_shift; ++j)
|
|
digest[j] = msg[j];
|
|
|
|
if(bit_shift)
|
|
{
|
|
byte carry = 0;
|
|
for(size_t j = 0; j != digest.size(); ++j)
|
|
{
|
|
byte temp = digest[j];
|
|
digest[j] = (temp >> bit_shift) | carry;
|
|
carry = (temp << (8 - bit_shift));
|
|
}
|
|
}
|
|
return digest;
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
* EMSA1 Update Operation
|
|
*/
|
|
void EMSA1::update(const byte input[], size_t length)
|
|
{
|
|
hash->update(input, length);
|
|
}
|
|
|
|
/*
|
|
* Return the raw (unencoded) data
|
|
*/
|
|
SecureVector<byte> EMSA1::raw_data()
|
|
{
|
|
return hash->final();
|
|
}
|
|
|
|
/*
|
|
* EMSA1 Encode Operation
|
|
*/
|
|
SecureVector<byte> EMSA1::encoding_of(const MemoryRegion<byte>& msg,
|
|
size_t output_bits,
|
|
RandomNumberGenerator&)
|
|
{
|
|
if(msg.size() != hash->output_length())
|
|
throw Encoding_Error("EMSA1::encoding_of: Invalid size for input");
|
|
return emsa1_encoding(msg, output_bits);
|
|
}
|
|
|
|
/*
|
|
* EMSA1 Decode/Verify Operation
|
|
*/
|
|
bool EMSA1::verify(const MemoryRegion<byte>& coded,
|
|
const MemoryRegion<byte>& raw, size_t key_bits)
|
|
{
|
|
try {
|
|
if(raw.size() != hash->output_length())
|
|
throw Encoding_Error("EMSA1::encoding_of: Invalid size for input");
|
|
|
|
SecureVector<byte> our_coding = emsa1_encoding(raw, key_bits);
|
|
|
|
if(our_coding == coded) return true;
|
|
if(our_coding[0] != 0) return false;
|
|
if(our_coding.size() <= coded.size()) return false;
|
|
|
|
size_t offset = 0;
|
|
while(our_coding[offset] == 0 && offset < our_coding.size())
|
|
++offset;
|
|
if(our_coding.size() - offset != coded.size())
|
|
return false;
|
|
|
|
for(size_t j = 0; j != coded.size(); ++j)
|
|
if(coded[j] != our_coding[j+offset])
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
catch(Invalid_Argument)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
}
|
|
/*
|
|
* EMSA1 BSI
|
|
* (C) 1999-2008 Jack Lloyd
|
|
* 2008 Falko Strenzke, FlexSecure GmbH
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* EMSA1 BSI Encode Operation
|
|
*/
|
|
SecureVector<byte> EMSA1_BSI::encoding_of(const MemoryRegion<byte>& msg,
|
|
size_t output_bits,
|
|
RandomNumberGenerator&)
|
|
{
|
|
if(msg.size() != hash_ptr()->output_length())
|
|
throw Encoding_Error("EMSA1_BSI::encoding_of: Invalid size for input");
|
|
|
|
if(8*msg.size() <= output_bits)
|
|
return msg;
|
|
|
|
throw Encoding_Error("EMSA1_BSI::encoding_of: max key input size exceeded");
|
|
}
|
|
|
|
}
|
|
/*
|
|
* EMSA2
|
|
* (C) 1999-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
namespace {
|
|
|
|
/*
|
|
* EMSA2 Encode Operation
|
|
*/
|
|
SecureVector<byte> emsa2_encoding(const MemoryRegion<byte>& msg,
|
|
size_t output_bits,
|
|
const MemoryRegion<byte>& empty_hash,
|
|
byte hash_id)
|
|
{
|
|
const size_t HASH_SIZE = empty_hash.size();
|
|
|
|
size_t output_length = (output_bits + 1) / 8;
|
|
|
|
if(msg.size() != HASH_SIZE)
|
|
throw Encoding_Error("EMSA2::encoding_of: Bad input length");
|
|
if(output_length < HASH_SIZE + 4)
|
|
throw Encoding_Error("EMSA2::encoding_of: Output length is too small");
|
|
|
|
bool empty = true;
|
|
for(size_t j = 0; j != HASH_SIZE; ++j)
|
|
if(empty_hash[j] != msg[j])
|
|
empty = false;
|
|
|
|
SecureVector<byte> output(output_length);
|
|
|
|
output[0] = (empty ? 0x4B : 0x6B);
|
|
output[output_length - 3 - HASH_SIZE] = 0xBA;
|
|
set_mem(&output[1], output_length - 4 - HASH_SIZE, 0xBB);
|
|
output.copy(output_length - (HASH_SIZE + 2), &msg[0], msg.size());
|
|
output[output_length-2] = hash_id;
|
|
output[output_length-1] = 0xCC;
|
|
|
|
return output;
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
* EMSA2 Update Operation
|
|
*/
|
|
void EMSA2::update(const byte input[], size_t length)
|
|
{
|
|
hash->update(input, length);
|
|
}
|
|
|
|
/*
|
|
* Return the raw (unencoded) data
|
|
*/
|
|
SecureVector<byte> EMSA2::raw_data()
|
|
{
|
|
return hash->final();
|
|
}
|
|
|
|
/*
|
|
* EMSA2 Encode Operation
|
|
*/
|
|
SecureVector<byte> EMSA2::encoding_of(const MemoryRegion<byte>& msg,
|
|
size_t output_bits,
|
|
RandomNumberGenerator&)
|
|
{
|
|
return emsa2_encoding(msg, output_bits, empty_hash, hash_id);
|
|
}
|
|
|
|
/*
|
|
* EMSA2 Verify Operation
|
|
*/
|
|
bool EMSA2::verify(const MemoryRegion<byte>& coded,
|
|
const MemoryRegion<byte>& raw,
|
|
size_t key_bits)
|
|
{
|
|
try
|
|
{
|
|
return (coded == emsa2_encoding(raw, key_bits,
|
|
empty_hash, hash_id));
|
|
}
|
|
catch(...)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* EMSA2 Constructor
|
|
*/
|
|
EMSA2::EMSA2(HashFunction* hash_in) : hash(hash_in)
|
|
{
|
|
empty_hash = hash->final();
|
|
|
|
hash_id = ieee1363_hash_id(hash->name());
|
|
|
|
if(hash_id == 0)
|
|
{
|
|
const std::string hashName = hash->name();
|
|
delete hash;
|
|
throw Encoding_Error("EMSA2 cannot be used with " + hashName);
|
|
}
|
|
}
|
|
|
|
}
|
|
/*
|
|
* EMSA3 and EMSA3_Raw
|
|
* (C) 1999-2008 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
namespace {
|
|
|
|
/*
|
|
* EMSA3 Encode Operation
|
|
*/
|
|
SecureVector<byte> emsa3_encoding(const MemoryRegion<byte>& msg,
|
|
size_t output_bits,
|
|
const byte hash_id[],
|
|
size_t hash_id_length)
|
|
{
|
|
size_t output_length = output_bits / 8;
|
|
if(output_length < hash_id_length + msg.size() + 10)
|
|
throw Encoding_Error("emsa3_encoding: Output length is too small");
|
|
|
|
SecureVector<byte> T(output_length);
|
|
const size_t P_LENGTH = output_length - msg.size() - hash_id_length - 2;
|
|
|
|
T[0] = 0x01;
|
|
set_mem(&T[1], P_LENGTH, 0xFF);
|
|
T[P_LENGTH+1] = 0x00;
|
|
T.copy(P_LENGTH+2, hash_id, hash_id_length);
|
|
T.copy(output_length-msg.size(), &msg[0], msg.size());
|
|
return T;
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
* EMSA3 Update Operation
|
|
*/
|
|
void EMSA3::update(const byte input[], size_t length)
|
|
{
|
|
hash->update(input, length);
|
|
}
|
|
|
|
/*
|
|
* Return the raw (unencoded) data
|
|
*/
|
|
SecureVector<byte> EMSA3::raw_data()
|
|
{
|
|
return hash->final();
|
|
}
|
|
|
|
/*
|
|
* EMSA3 Encode Operation
|
|
*/
|
|
SecureVector<byte> EMSA3::encoding_of(const MemoryRegion<byte>& msg,
|
|
size_t output_bits,
|
|
RandomNumberGenerator&)
|
|
{
|
|
if(msg.size() != hash->output_length())
|
|
throw Encoding_Error("EMSA3::encoding_of: Bad input length");
|
|
|
|
return emsa3_encoding(msg, output_bits,
|
|
&hash_id[0], hash_id.size());
|
|
}
|
|
|
|
/*
|
|
* Default signature decoding
|
|
*/
|
|
bool EMSA3::verify(const MemoryRegion<byte>& coded,
|
|
const MemoryRegion<byte>& raw,
|
|
size_t key_bits)
|
|
{
|
|
if(raw.size() != hash->output_length())
|
|
return false;
|
|
|
|
try
|
|
{
|
|
return (coded == emsa3_encoding(raw, key_bits,
|
|
&hash_id[0], hash_id.size()));
|
|
}
|
|
catch(...)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* EMSA3 Constructor
|
|
*/
|
|
EMSA3::EMSA3(HashFunction* hash_in) : hash(hash_in)
|
|
{
|
|
hash_id = pkcs_hash_id(hash->name());
|
|
}
|
|
|
|
/*
|
|
* EMSA3 Destructor
|
|
*/
|
|
EMSA3::~EMSA3()
|
|
{
|
|
delete hash;
|
|
}
|
|
|
|
/*
|
|
* EMSA3_Raw Update Operation
|
|
*/
|
|
void EMSA3_Raw::update(const byte input[], size_t length)
|
|
{
|
|
message += std::make_pair(input, length);
|
|
}
|
|
|
|
/*
|
|
* Return the raw (unencoded) data
|
|
*/
|
|
SecureVector<byte> EMSA3_Raw::raw_data()
|
|
{
|
|
SecureVector<byte> ret;
|
|
std::swap(ret, message);
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* EMSA3_Raw Encode Operation
|
|
*/
|
|
SecureVector<byte> EMSA3_Raw::encoding_of(const MemoryRegion<byte>& msg,
|
|
size_t output_bits,
|
|
RandomNumberGenerator&)
|
|
{
|
|
return emsa3_encoding(msg, output_bits, 0, 0);
|
|
}
|
|
|
|
/*
|
|
* Default signature decoding
|
|
*/
|
|
bool EMSA3_Raw::verify(const MemoryRegion<byte>& coded,
|
|
const MemoryRegion<byte>& raw,
|
|
size_t key_bits)
|
|
{
|
|
try
|
|
{
|
|
return (coded == emsa3_encoding(raw, key_bits, 0, 0));
|
|
}
|
|
catch(...)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
}
|
|
/*
|
|
* EMSA4
|
|
* (C) 1999-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* EMSA4 Update Operation
|
|
*/
|
|
void EMSA4::update(const byte input[], size_t length)
|
|
{
|
|
hash->update(input, length);
|
|
}
|
|
|
|
/*
|
|
* Return the raw (unencoded) data
|
|
*/
|
|
SecureVector<byte> EMSA4::raw_data()
|
|
{
|
|
return hash->final();
|
|
}
|
|
|
|
/*
|
|
* EMSA4 Encode Operation
|
|
*/
|
|
SecureVector<byte> EMSA4::encoding_of(const MemoryRegion<byte>& msg,
|
|
size_t output_bits,
|
|
RandomNumberGenerator& rng)
|
|
{
|
|
const size_t HASH_SIZE = hash->output_length();
|
|
|
|
if(msg.size() != HASH_SIZE)
|
|
throw Encoding_Error("EMSA4::encoding_of: Bad input length");
|
|
if(output_bits < 8*HASH_SIZE + 8*SALT_SIZE + 9)
|
|
throw Encoding_Error("EMSA4::encoding_of: Output length is too small");
|
|
|
|
const size_t output_length = (output_bits + 7) / 8;
|
|
|
|
SecureVector<byte> salt = rng.random_vec(SALT_SIZE);
|
|
|
|
for(size_t j = 0; j != 8; ++j)
|
|
hash->update(0);
|
|
hash->update(msg);
|
|
hash->update(salt, SALT_SIZE);
|
|
SecureVector<byte> H = hash->final();
|
|
|
|
SecureVector<byte> EM(output_length);
|
|
|
|
EM[output_length - HASH_SIZE - SALT_SIZE - 2] = 0x01;
|
|
EM.copy(output_length - 1 - HASH_SIZE - SALT_SIZE, salt, SALT_SIZE);
|
|
mgf->mask(H, HASH_SIZE, EM, output_length - HASH_SIZE - 1);
|
|
EM[0] &= 0xFF >> (8 * ((output_bits + 7) / 8) - output_bits);
|
|
EM.copy(output_length - 1 - HASH_SIZE, H, HASH_SIZE);
|
|
EM[output_length-1] = 0xBC;
|
|
|
|
return EM;
|
|
}
|
|
|
|
/*
|
|
* EMSA4 Decode/Verify Operation
|
|
*/
|
|
bool EMSA4::verify(const MemoryRegion<byte>& const_coded,
|
|
const MemoryRegion<byte>& raw, size_t key_bits)
|
|
{
|
|
const size_t HASH_SIZE = hash->output_length();
|
|
const size_t KEY_BYTES = (key_bits + 7) / 8;
|
|
|
|
if(key_bits < 8*HASH_SIZE + 9)
|
|
return false;
|
|
|
|
if(raw.size() != HASH_SIZE)
|
|
return false;
|
|
|
|
if(const_coded.size() > KEY_BYTES || const_coded.size() <= 1)
|
|
return false;
|
|
|
|
if(const_coded[const_coded.size()-1] != 0xBC)
|
|
return false;
|
|
|
|
SecureVector<byte> coded = const_coded;
|
|
if(coded.size() < KEY_BYTES)
|
|
{
|
|
SecureVector<byte> temp(KEY_BYTES);
|
|
temp.copy(KEY_BYTES - coded.size(), coded, coded.size());
|
|
coded = temp;
|
|
}
|
|
|
|
const size_t TOP_BITS = 8 * ((key_bits + 7) / 8) - key_bits;
|
|
if(TOP_BITS > 8 - high_bit(coded[0]))
|
|
return false;
|
|
|
|
SecureVector<byte> DB(&coded[0], coded.size() - HASH_SIZE - 1);
|
|
SecureVector<byte> H(&coded[coded.size() - HASH_SIZE - 1], HASH_SIZE);
|
|
|
|
mgf->mask(H, H.size(), DB, coded.size() - H.size() - 1);
|
|
DB[0] &= 0xFF >> TOP_BITS;
|
|
|
|
size_t salt_offset = 0;
|
|
for(size_t j = 0; j != DB.size(); ++j)
|
|
{
|
|
if(DB[j] == 0x01)
|
|
{ salt_offset = j + 1; break; }
|
|
if(DB[j])
|
|
return false;
|
|
}
|
|
if(salt_offset == 0)
|
|
return false;
|
|
|
|
SecureVector<byte> salt(&DB[salt_offset], DB.size() - salt_offset);
|
|
|
|
for(size_t j = 0; j != 8; ++j)
|
|
hash->update(0);
|
|
hash->update(raw);
|
|
hash->update(salt);
|
|
SecureVector<byte> H2 = hash->final();
|
|
|
|
return (H == H2);
|
|
}
|
|
|
|
/*
|
|
* EMSA4 Constructor
|
|
*/
|
|
EMSA4::EMSA4(HashFunction* h) :
|
|
SALT_SIZE(h->output_length()), hash(h)
|
|
{
|
|
mgf = new MGF1(hash->clone());
|
|
}
|
|
|
|
/*
|
|
* EMSA4 Constructor
|
|
*/
|
|
EMSA4::EMSA4(HashFunction* h, size_t salt_size) :
|
|
SALT_SIZE(salt_size), hash(h)
|
|
{
|
|
mgf = new MGF1(hash->clone());
|
|
}
|
|
|
|
}
|
|
/*
|
|
* EMSA-Raw
|
|
* (C) 1999-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* EMSA-Raw Encode Operation
|
|
*/
|
|
void EMSA_Raw::update(const byte input[], size_t length)
|
|
{
|
|
message += std::make_pair(input, length);
|
|
}
|
|
|
|
/*
|
|
* Return the raw (unencoded) data
|
|
*/
|
|
SecureVector<byte> EMSA_Raw::raw_data()
|
|
{
|
|
SecureVector<byte> output;
|
|
std::swap(message, output);
|
|
return output;
|
|
}
|
|
|
|
/*
|
|
* EMSA-Raw Encode Operation
|
|
*/
|
|
SecureVector<byte> EMSA_Raw::encoding_of(const MemoryRegion<byte>& msg,
|
|
size_t,
|
|
RandomNumberGenerator&)
|
|
{
|
|
return msg;
|
|
}
|
|
|
|
/*
|
|
* EMSA-Raw Verify Operation
|
|
*/
|
|
bool EMSA_Raw::verify(const MemoryRegion<byte>& coded,
|
|
const MemoryRegion<byte>& raw,
|
|
size_t)
|
|
{
|
|
if(coded.size() == raw.size())
|
|
return (coded == raw);
|
|
|
|
if(coded.size() > raw.size())
|
|
return false;
|
|
|
|
// handle zero padding differences
|
|
const size_t leading_zeros_expected = raw.size() - coded.size();
|
|
|
|
bool same_modulo_leading_zeros = true;
|
|
|
|
for(size_t i = 0; i != leading_zeros_expected; ++i)
|
|
if(raw[i])
|
|
same_modulo_leading_zeros = false;
|
|
|
|
if(!same_mem(&coded[0], &raw[leading_zeros_expected], coded.size()))
|
|
same_modulo_leading_zeros = false;
|
|
|
|
return same_modulo_leading_zeros;
|
|
}
|
|
|
|
}
|
|
/*
|
|
* Hash Function Identification
|
|
* (C) 1999-2008 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
namespace {
|
|
|
|
const byte MD2_PKCS_ID[] = {
|
|
0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86,
|
|
0xF7, 0x0D, 0x02, 0x02, 0x05, 0x00, 0x04, 0x10 };
|
|
|
|
const byte MD5_PKCS_ID[] = {
|
|
0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86,
|
|
0xF7, 0x0D, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 };
|
|
|
|
const byte RIPEMD_128_PKCS_ID[] = {
|
|
0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x24, 0x03, 0x02,
|
|
0x02, 0x05, 0x00, 0x04, 0x14 };
|
|
|
|
const byte RIPEMD_160_PKCS_ID[] = {
|
|
0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x24, 0x03, 0x02,
|
|
0x01, 0x05, 0x00, 0x04, 0x14 };
|
|
|
|
const byte SHA_160_PKCS_ID[] = {
|
|
0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02,
|
|
0x1A, 0x05, 0x00, 0x04, 0x14 };
|
|
|
|
const byte SHA_224_PKCS_ID[] = {
|
|
0x30, 0x2D, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
|
|
0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1C };
|
|
|
|
const byte SHA_256_PKCS_ID[] = {
|
|
0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
|
|
0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 };
|
|
|
|
const byte SHA_384_PKCS_ID[] = {
|
|
0x30, 0x41, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
|
|
0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30 };
|
|
|
|
const byte SHA_512_PKCS_ID[] = {
|
|
0x30, 0x51, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
|
|
0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40 };
|
|
|
|
const byte TIGER_PKCS_ID[] = {
|
|
0x30, 0x29, 0x30, 0x0D, 0x06, 0x09, 0x2B, 0x06, 0x01, 0x04,
|
|
0x01, 0xDA, 0x47, 0x0C, 0x02, 0x05, 0x00, 0x04, 0x18 };
|
|
|
|
}
|
|
|
|
/*
|
|
* HashID as specified by PKCS
|
|
*/
|
|
MemoryVector<byte> pkcs_hash_id(const std::string& name)
|
|
{
|
|
// Special case for SSL/TLS RSA signatures
|
|
if(name == "Parallel(MD5,SHA-160)")
|
|
return MemoryVector<byte>();
|
|
|
|
if(name == "MD2")
|
|
return MemoryVector<byte>(MD2_PKCS_ID, sizeof(MD2_PKCS_ID));
|
|
if(name == "MD5")
|
|
return MemoryVector<byte>(MD5_PKCS_ID, sizeof(MD5_PKCS_ID));
|
|
if(name == "RIPEMD-128")
|
|
return MemoryVector<byte>(RIPEMD_128_PKCS_ID, sizeof(RIPEMD_128_PKCS_ID));
|
|
if(name == "RIPEMD-160")
|
|
return MemoryVector<byte>(RIPEMD_160_PKCS_ID, sizeof(RIPEMD_160_PKCS_ID));
|
|
if(name == "SHA-160")
|
|
return MemoryVector<byte>(SHA_160_PKCS_ID, sizeof(SHA_160_PKCS_ID));
|
|
if(name == "SHA-224")
|
|
return MemoryVector<byte>(SHA_224_PKCS_ID, sizeof(SHA_224_PKCS_ID));
|
|
if(name == "SHA-256")
|
|
return MemoryVector<byte>(SHA_256_PKCS_ID, sizeof(SHA_256_PKCS_ID));
|
|
if(name == "SHA-384")
|
|
return MemoryVector<byte>(SHA_384_PKCS_ID, sizeof(SHA_384_PKCS_ID));
|
|
if(name == "SHA-512")
|
|
return MemoryVector<byte>(SHA_512_PKCS_ID, sizeof(SHA_512_PKCS_ID));
|
|
if(name == "Tiger(24,3)")
|
|
return MemoryVector<byte>(TIGER_PKCS_ID, sizeof(TIGER_PKCS_ID));
|
|
|
|
throw Invalid_Argument("No PKCS #1 identifier for " + name);
|
|
}
|
|
|
|
/*
|
|
* HashID as specified by IEEE 1363/X9.31
|
|
*/
|
|
byte ieee1363_hash_id(const std::string& name)
|
|
{
|
|
if(name == "SHA-160") return 0x33;
|
|
|
|
if(name == "SHA-224") return 0x38;
|
|
if(name == "SHA-256") return 0x34;
|
|
if(name == "SHA-384") return 0x36;
|
|
if(name == "SHA-512") return 0x35;
|
|
|
|
if(name == "RIPEMD-160") return 0x31;
|
|
if(name == "RIPEMD-128") return 0x32;
|
|
|
|
if(name == "Whirlpool") return 0x37;
|
|
|
|
return 0;
|
|
}
|
|
|
|
}
|
|
/*
|
|
* Blinding for public key operations
|
|
* (C) 1999-2010 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* Blinder Constructor
|
|
*/
|
|
Blinder::Blinder(const BigInt& e, const BigInt& d, const BigInt& n)
|
|
{
|
|
if(e < 1 || d < 1 || n < 1)
|
|
throw Invalid_Argument("Blinder: Arguments too small");
|
|
|
|
reducer = Modular_Reducer(n);
|
|
this->e = e;
|
|
this->d = d;
|
|
}
|
|
|
|
/*
|
|
* Blind a number
|
|
*/
|
|
BigInt Blinder::blind(const BigInt& i) const
|
|
{
|
|
if(!reducer.initialized())
|
|
return i;
|
|
|
|
e = reducer.square(e);
|
|
d = reducer.square(d);
|
|
return reducer.multiply(i, e);
|
|
}
|
|
|
|
/*
|
|
* Unblind a number
|
|
*/
|
|
BigInt Blinder::unblind(const BigInt& i) const
|
|
{
|
|
if(!reducer.initialized())
|
|
return i;
|
|
return reducer.multiply(i, d);
|
|
}
|
|
|
|
}
|
|
/*
|
|
* Diffie-Hellman
|
|
* (C) 1999-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* DH_PublicKey Constructor
|
|
*/
|
|
DH_PublicKey::DH_PublicKey(const DL_Group& grp, const BigInt& y1)
|
|
{
|
|
group = grp;
|
|
y = y1;
|
|
}
|
|
|
|
/*
|
|
* Return the public value for key agreement
|
|
*/
|
|
MemoryVector<byte> DH_PublicKey::public_value() const
|
|
{
|
|
return BigInt::encode_1363(y, group_p().bytes());
|
|
}
|
|
|
|
/*
|
|
* Create a DH private key
|
|
*/
|
|
DH_PrivateKey::DH_PrivateKey(RandomNumberGenerator& rng,
|
|
const DL_Group& grp,
|
|
const BigInt& x_arg)
|
|
{
|
|
group = grp;
|
|
x = x_arg;
|
|
|
|
if(x == 0)
|
|
{
|
|
const BigInt& p = group_p();
|
|
x.randomize(rng, 2 * dl_work_factor(p.bits()));
|
|
}
|
|
|
|
if(y == 0)
|
|
y = power_mod(group_g(), x, group_p());
|
|
|
|
if(x == 0)
|
|
gen_check(rng);
|
|
else
|
|
load_check(rng);
|
|
}
|
|
|
|
/*
|
|
* Load a DH private key
|
|
*/
|
|
DH_PrivateKey::DH_PrivateKey(const AlgorithmIdentifier& alg_id,
|
|
const MemoryRegion<byte>& key_bits,
|
|
RandomNumberGenerator& rng) :
|
|
DL_Scheme_PrivateKey(alg_id, key_bits, DL_Group::ANSI_X9_42)
|
|
{
|
|
if(y == 0)
|
|
y = power_mod(group_g(), x, group_p());
|
|
|
|
load_check(rng);
|
|
}
|
|
|
|
/*
|
|
* Return the public value for key agreement
|
|
*/
|
|
MemoryVector<byte> DH_PrivateKey::public_value() const
|
|
{
|
|
return DH_PublicKey::public_value();
|
|
}
|
|
|
|
DH_KA_Operation::DH_KA_Operation(const DH_PrivateKey& dh) :
|
|
p(dh.group_p()), powermod_x_p(dh.get_x(), p)
|
|
{
|
|
BigInt k(global_state().global_rng(), p.bits() - 1);
|
|
blinder = Blinder(k, powermod_x_p(inverse_mod(k, p)), p);
|
|
}
|
|
|
|
SecureVector<byte> DH_KA_Operation::agree(const byte w[], size_t w_len)
|
|
{
|
|
BigInt input = BigInt::decode(w, w_len);
|
|
|
|
BigInt r = blinder.unblind(powermod_x_p(blinder.blind(input)));
|
|
|
|
return BigInt::encode_1363(r, p.bytes());
|
|
}
|
|
|
|
}
|
|
/*
|
|
* DL Scheme
|
|
* (C) 1999-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
AlgorithmIdentifier DL_Scheme_PublicKey::algorithm_identifier() const
|
|
{
|
|
return AlgorithmIdentifier(get_oid(),
|
|
group.DER_encode(group_format()));
|
|
}
|
|
|
|
MemoryVector<byte> DL_Scheme_PublicKey::x509_subject_public_key() const
|
|
{
|
|
return DER_Encoder().encode(y).get_contents();
|
|
}
|
|
|
|
DL_Scheme_PublicKey::DL_Scheme_PublicKey(const AlgorithmIdentifier& alg_id,
|
|
const MemoryRegion<byte>& key_bits,
|
|
DL_Group::Format format)
|
|
{
|
|
DataSource_Memory source(alg_id.parameters);
|
|
group.BER_decode(source, format);
|
|
|
|
BER_Decoder(key_bits).decode(y);
|
|
}
|
|
|
|
MemoryVector<byte> DL_Scheme_PrivateKey::pkcs8_private_key() const
|
|
{
|
|
return DER_Encoder().encode(x).get_contents();
|
|
}
|
|
|
|
DL_Scheme_PrivateKey::DL_Scheme_PrivateKey(const AlgorithmIdentifier& alg_id,
|
|
const MemoryRegion<byte>& key_bits,
|
|
DL_Group::Format format)
|
|
{
|
|
DataSource_Memory source(alg_id.parameters);
|
|
group.BER_decode(source, format);
|
|
|
|
BER_Decoder(key_bits).decode(x);
|
|
}
|
|
|
|
/*
|
|
* Check Public DL Parameters
|
|
*/
|
|
bool DL_Scheme_PublicKey::check_key(RandomNumberGenerator& rng,
|
|
bool strong) const
|
|
{
|
|
if(y < 2 || y >= group_p())
|
|
return false;
|
|
if(!group.verify_group(rng, strong))
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* Check DL Scheme Private Parameters
|
|
*/
|
|
bool DL_Scheme_PrivateKey::check_key(RandomNumberGenerator& rng,
|
|
bool strong) const
|
|
{
|
|
const BigInt& p = group_p();
|
|
const BigInt& g = group_g();
|
|
|
|
if(y < 2 || y >= p || x < 2 || x >= p)
|
|
return false;
|
|
if(!group.verify_group(rng, strong))
|
|
return false;
|
|
|
|
if(!strong)
|
|
return true;
|
|
|
|
if(y != power_mod(g, x, p))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
}
|
|
/*
|
|
* Discrete Logarithm Parameters
|
|
* (C) 1999-2008 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* DL_Group Constructor
|
|
*/
|
|
DL_Group::DL_Group()
|
|
{
|
|
initialized = false;
|
|
}
|
|
|
|
/*
|
|
* DL_Group Constructor
|
|
*/
|
|
DL_Group::DL_Group(const std::string& type)
|
|
{
|
|
std::string grp_contents = global_state().get("dl", type);
|
|
|
|
if(grp_contents == "")
|
|
throw Invalid_Argument("DL_Group: Unknown group " + type);
|
|
|
|
DataSource_Memory pem(grp_contents);
|
|
PEM_decode(pem);
|
|
}
|
|
|
|
/*
|
|
* DL_Group Constructor
|
|
*/
|
|
DL_Group::DL_Group(RandomNumberGenerator& rng,
|
|
PrimeType type, size_t pbits, size_t qbits)
|
|
{
|
|
if(pbits < 512)
|
|
throw Invalid_Argument("DL_Group: prime size " + to_string(pbits) +
|
|
" is too small");
|
|
|
|
if(type == Strong)
|
|
{
|
|
p = random_safe_prime(rng, pbits);
|
|
q = (p - 1) / 2;
|
|
g = 2;
|
|
}
|
|
else if(type == Prime_Subgroup)
|
|
{
|
|
if(!qbits)
|
|
qbits = 2 * dl_work_factor(pbits);
|
|
|
|
q = random_prime(rng, qbits);
|
|
BigInt X;
|
|
while(p.bits() != pbits || !check_prime(p, rng))
|
|
{
|
|
X.randomize(rng, pbits);
|
|
p = X - (X % (2*q) - 1);
|
|
}
|
|
|
|
g = make_dsa_generator(p, q);
|
|
}
|
|
else if(type == DSA_Kosherizer)
|
|
{
|
|
qbits = qbits ? qbits : ((pbits <= 1024) ? 160 : 256);
|
|
|
|
generate_dsa_primes(rng,
|
|
global_state().algorithm_factory(),
|
|
p, q,
|
|
pbits, qbits);
|
|
|
|
g = make_dsa_generator(p, q);
|
|
}
|
|
|
|
initialized = true;
|
|
}
|
|
|
|
/*
|
|
* DL_Group Constructor
|
|
*/
|
|
DL_Group::DL_Group(RandomNumberGenerator& rng,
|
|
const MemoryRegion<byte>& seed, size_t pbits, size_t qbits)
|
|
{
|
|
if(!generate_dsa_primes(rng,
|
|
global_state().algorithm_factory(),
|
|
p, q, pbits, qbits, seed))
|
|
throw Invalid_Argument("DL_Group: The seed given does not "
|
|
"generate a DSA group");
|
|
|
|
g = make_dsa_generator(p, q);
|
|
|
|
initialized = true;
|
|
}
|
|
|
|
/*
|
|
* DL_Group Constructor
|
|
*/
|
|
DL_Group::DL_Group(const BigInt& p1, const BigInt& g1)
|
|
{
|
|
initialize(p1, 0, g1);
|
|
}
|
|
|
|
/*
|
|
* DL_Group Constructor
|
|
*/
|
|
DL_Group::DL_Group(const BigInt& p1, const BigInt& q1, const BigInt& g1)
|
|
{
|
|
initialize(p1, q1, g1);
|
|
}
|
|
|
|
/*
|
|
* DL_Group Initializer
|
|
*/
|
|
void DL_Group::initialize(const BigInt& p1, const BigInt& q1, const BigInt& g1)
|
|
{
|
|
if(p1 < 3)
|
|
throw Invalid_Argument("DL_Group: Prime invalid");
|
|
if(g1 < 2 || g1 >= p1)
|
|
throw Invalid_Argument("DL_Group: Generator invalid");
|
|
if(q1 < 0 || q1 >= p1)
|
|
throw Invalid_Argument("DL_Group: Subgroup invalid");
|
|
|
|
p = p1;
|
|
g = g1;
|
|
q = q1;
|
|
|
|
initialized = true;
|
|
}
|
|
|
|
/*
|
|
* Verify that the group has been set
|
|
*/
|
|
void DL_Group::init_check() const
|
|
{
|
|
if(!initialized)
|
|
throw Invalid_State("DLP group cannot be used uninitialized");
|
|
}
|
|
|
|
/*
|
|
* Verify the parameters
|
|
*/
|
|
bool DL_Group::verify_group(RandomNumberGenerator& rng,
|
|
bool strong) const
|
|
{
|
|
init_check();
|
|
|
|
if(g < 2 || p < 3 || q < 0)
|
|
return false;
|
|
if((q != 0) && ((p - 1) % q != 0))
|
|
return false;
|
|
|
|
if(!strong)
|
|
return true;
|
|
|
|
if(!check_prime(p, rng))
|
|
return false;
|
|
if((q > 0) && !check_prime(q, rng))
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* Return the prime
|
|
*/
|
|
const BigInt& DL_Group::get_p() const
|
|
{
|
|
init_check();
|
|
return p;
|
|
}
|
|
|
|
/*
|
|
* Return the generator
|
|
*/
|
|
const BigInt& DL_Group::get_g() const
|
|
{
|
|
init_check();
|
|
return g;
|
|
}
|
|
|
|
/*
|
|
* Return the subgroup
|
|
*/
|
|
const BigInt& DL_Group::get_q() const
|
|
{
|
|
init_check();
|
|
if(q == 0)
|
|
throw Invalid_State("DLP group has no q prime specified");
|
|
return q;
|
|
}
|
|
|
|
/*
|
|
* DER encode the parameters
|
|
*/
|
|
SecureVector<byte> DL_Group::DER_encode(Format format) const
|
|
{
|
|
init_check();
|
|
|
|
if((q == 0) && (format != PKCS_3))
|
|
throw Encoding_Error("The ANSI DL parameter formats require a subgroup");
|
|
|
|
if(format == ANSI_X9_57)
|
|
{
|
|
return DER_Encoder()
|
|
.start_cons(SEQUENCE)
|
|
.encode(p)
|
|
.encode(q)
|
|
.encode(g)
|
|
.end_cons()
|
|
.get_contents();
|
|
}
|
|
else if(format == ANSI_X9_42)
|
|
{
|
|
return DER_Encoder()
|
|
.start_cons(SEQUENCE)
|
|
.encode(p)
|
|
.encode(g)
|
|
.encode(q)
|
|
.end_cons()
|
|
.get_contents();
|
|
}
|
|
else if(format == PKCS_3)
|
|
{
|
|
return DER_Encoder()
|
|
.start_cons(SEQUENCE)
|
|
.encode(p)
|
|
.encode(g)
|
|
.end_cons()
|
|
.get_contents();
|
|
}
|
|
|
|
throw Invalid_Argument("Unknown DL_Group encoding " + to_string(format));
|
|
}
|
|
|
|
/*
|
|
* PEM encode the parameters
|
|
*/
|
|
std::string DL_Group::PEM_encode(Format format) const
|
|
{
|
|
SecureVector<byte> encoding = DER_encode(format);
|
|
if(format == PKCS_3)
|
|
return PEM_Code::encode(encoding, "DH PARAMETERS");
|
|
else if(format == ANSI_X9_57)
|
|
return PEM_Code::encode(encoding, "DSA PARAMETERS");
|
|
else if(format == ANSI_X9_42)
|
|
return PEM_Code::encode(encoding, "X942 DH PARAMETERS");
|
|
else
|
|
throw Invalid_Argument("Unknown DL_Group encoding " + to_string(format));
|
|
}
|
|
|
|
/*
|
|
* Decode BER encoded parameters
|
|
*/
|
|
void DL_Group::BER_decode(DataSource& source, Format format)
|
|
{
|
|
BigInt new_p, new_q, new_g;
|
|
|
|
BER_Decoder decoder(source);
|
|
BER_Decoder ber = decoder.start_cons(SEQUENCE);
|
|
|
|
if(format == ANSI_X9_57)
|
|
{
|
|
ber.decode(new_p)
|
|
.decode(new_q)
|
|
.decode(new_g)
|
|
.verify_end();
|
|
}
|
|
else if(format == ANSI_X9_42)
|
|
{
|
|
ber.decode(new_p)
|
|
.decode(new_g)
|
|
.decode(new_q)
|
|
.discard_remaining();
|
|
}
|
|
else if(format == PKCS_3)
|
|
{
|
|
ber.decode(new_p)
|
|
.decode(new_g)
|
|
.discard_remaining();
|
|
}
|
|
else
|
|
throw Invalid_Argument("Unknown DL_Group encoding " + to_string(format));
|
|
|
|
initialize(new_p, new_q, new_g);
|
|
}
|
|
|
|
/*
|
|
* Decode PEM encoded parameters
|
|
*/
|
|
void DL_Group::PEM_decode(DataSource& source)
|
|
{
|
|
std::string label;
|
|
DataSource_Memory ber(PEM_Code::decode(source, label));
|
|
|
|
if(label == "DH PARAMETERS")
|
|
BER_decode(ber, PKCS_3);
|
|
else if(label == "DSA PARAMETERS")
|
|
BER_decode(ber, ANSI_X9_57);
|
|
else if(label == "X942 DH PARAMETERS")
|
|
BER_decode(ber, ANSI_X9_42);
|
|
else
|
|
throw Decoding_Error("DL_Group: Invalid PEM label " + label);
|
|
}
|
|
|
|
/*
|
|
* Create generator of the q-sized subgroup (DSA style generator)
|
|
*/
|
|
BigInt DL_Group::make_dsa_generator(const BigInt& p, const BigInt& q)
|
|
{
|
|
BigInt g, e = (p - 1) / q;
|
|
|
|
BOTAN_ASSERT(e > 0, "q does not divide p, invalid group");
|
|
|
|
for(size_t i = 0; i != PRIME_TABLE_SIZE; ++i)
|
|
{
|
|
g = power_mod(PRIMES[i], e, p);
|
|
if(g > 1)
|
|
return g;
|
|
}
|
|
|
|
throw Internal_Error("DL_Group: Couldn't create a suitable generator");
|
|
}
|
|
|
|
}
|
|
/*
|
|
* DLIES
|
|
* (C) 1999-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* DLIES_Encryptor Constructor
|
|
*/
|
|
DLIES_Encryptor::DLIES_Encryptor(const PK_Key_Agreement_Key& key,
|
|
KDF* kdf_obj,
|
|
MessageAuthenticationCode* mac_obj,
|
|
size_t mac_kl) :
|
|
ka(key, "Raw"),
|
|
kdf(kdf_obj),
|
|
mac(mac_obj),
|
|
mac_keylen(mac_kl)
|
|
{
|
|
my_key = key.public_value();
|
|
}
|
|
|
|
DLIES_Encryptor::~DLIES_Encryptor()
|
|
{
|
|
delete kdf;
|
|
delete mac;
|
|
}
|
|
|
|
/*
|
|
* DLIES Encryption
|
|
*/
|
|
SecureVector<byte> DLIES_Encryptor::enc(const byte in[], size_t length,
|
|
RandomNumberGenerator&) const
|
|
{
|
|
if(length > maximum_input_size())
|
|
throw Invalid_Argument("DLIES: Plaintext too large");
|
|
if(other_key.empty())
|
|
throw Invalid_State("DLIES: The other key was never set");
|
|
|
|
SecureVector<byte> out(my_key.size() + length + mac->output_length());
|
|
out.copy(&my_key[0], my_key.size());
|
|
out.copy(my_key.size(), in, length);
|
|
|
|
SecureVector<byte> vz = my_key;
|
|
vz += ka.derive_key(0, other_key).bits_of();
|
|
|
|
const size_t K_LENGTH = length + mac_keylen;
|
|
OctetString K = kdf->derive_key(K_LENGTH, vz);
|
|
|
|
if(K.length() != K_LENGTH)
|
|
throw Encoding_Error("DLIES: KDF did not provide sufficient output");
|
|
byte* C = &out[my_key.size()];
|
|
|
|
xor_buf(C, K.begin() + mac_keylen, length);
|
|
mac->set_key(K.begin(), mac_keylen);
|
|
|
|
mac->update(C, length);
|
|
for(size_t j = 0; j != 8; ++j)
|
|
mac->update(0);
|
|
|
|
mac->final(C + length);
|
|
|
|
return out;
|
|
}
|
|
|
|
/*
|
|
* Set the other parties public key
|
|
*/
|
|
void DLIES_Encryptor::set_other_key(const MemoryRegion<byte>& ok)
|
|
{
|
|
other_key = ok;
|
|
}
|
|
|
|
/*
|
|
* Return the max size, in bytes, of a message
|
|
*/
|
|
size_t DLIES_Encryptor::maximum_input_size() const
|
|
{
|
|
return 32;
|
|
}
|
|
|
|
/*
|
|
* DLIES_Decryptor Constructor
|
|
*/
|
|
DLIES_Decryptor::DLIES_Decryptor(const PK_Key_Agreement_Key& key,
|
|
KDF* kdf_obj,
|
|
MessageAuthenticationCode* mac_obj,
|
|
size_t mac_kl) :
|
|
ka(key, "Raw"),
|
|
kdf(kdf_obj),
|
|
mac(mac_obj),
|
|
mac_keylen(mac_kl)
|
|
{
|
|
my_key = key.public_value();
|
|
}
|
|
|
|
DLIES_Decryptor::~DLIES_Decryptor()
|
|
{
|
|
delete kdf;
|
|
delete mac;
|
|
}
|
|
|
|
/*
|
|
* DLIES Decryption
|
|
*/
|
|
SecureVector<byte> DLIES_Decryptor::dec(const byte msg[], size_t length) const
|
|
{
|
|
if(length < my_key.size() + mac->output_length())
|
|
throw Decoding_Error("DLIES decryption: ciphertext is too short");
|
|
|
|
const size_t CIPHER_LEN = length - my_key.size() - mac->output_length();
|
|
|
|
SecureVector<byte> v(msg, my_key.size());
|
|
SecureVector<byte> C(msg + my_key.size(), CIPHER_LEN);
|
|
SecureVector<byte> T(msg + my_key.size() + CIPHER_LEN, mac->output_length());
|
|
|
|
SecureVector<byte> vz(msg, my_key.size());
|
|
vz += ka.derive_key(0, v).bits_of();
|
|
|
|
const size_t K_LENGTH = C.size() + mac_keylen;
|
|
OctetString K = kdf->derive_key(K_LENGTH, vz);
|
|
if(K.length() != K_LENGTH)
|
|
throw Encoding_Error("DLIES: KDF did not provide sufficient output");
|
|
|
|
mac->set_key(K.begin(), mac_keylen);
|
|
mac->update(C);
|
|
for(size_t j = 0; j != 8; ++j)
|
|
mac->update(0);
|
|
SecureVector<byte> T2 = mac->final();
|
|
if(T != T2)
|
|
throw Decoding_Error("DLIES: message authentication failed");
|
|
|
|
xor_buf(C, K.begin() + mac_keylen, C.size());
|
|
|
|
return C;
|
|
}
|
|
|
|
}
|
|
/*
|
|
* DSA
|
|
* (C) 1999-2010 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* DSA_PublicKey Constructor
|
|
*/
|
|
DSA_PublicKey::DSA_PublicKey(const DL_Group& grp, const BigInt& y1)
|
|
{
|
|
group = grp;
|
|
y = y1;
|
|
}
|
|
|
|
/*
|
|
* Create a DSA private key
|
|
*/
|
|
DSA_PrivateKey::DSA_PrivateKey(RandomNumberGenerator& rng,
|
|
const DL_Group& grp,
|
|
const BigInt& x_arg)
|
|
{
|
|
group = grp;
|
|
x = x_arg;
|
|
|
|
if(x == 0)
|
|
x = BigInt::random_integer(rng, 2, group_q() - 1);
|
|
|
|
y = power_mod(group_g(), x, group_p());
|
|
|
|
if(x_arg == 0)
|
|
gen_check(rng);
|
|
else
|
|
load_check(rng);
|
|
}
|
|
|
|
DSA_PrivateKey::DSA_PrivateKey(const AlgorithmIdentifier& alg_id,
|
|
const MemoryRegion<byte>& key_bits,
|
|
RandomNumberGenerator& rng) :
|
|
DL_Scheme_PrivateKey(alg_id, key_bits, DL_Group::ANSI_X9_57)
|
|
{
|
|
y = power_mod(group_g(), x, group_p());
|
|
|
|
load_check(rng);
|
|
}
|
|
|
|
/*
|
|
* Check Private DSA Parameters
|
|
*/
|
|
bool DSA_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const
|
|
{
|
|
if(!DL_Scheme_PrivateKey::check_key(rng, strong) || x >= group_q())
|
|
return false;
|
|
|
|
if(!strong)
|
|
return true;
|
|
|
|
return KeyPair::signature_consistency_check(rng, *this, "EMSA1(SHA-1)");
|
|
}
|
|
|
|
DSA_Signature_Operation::DSA_Signature_Operation(const DSA_PrivateKey& dsa) :
|
|
q(dsa.group_q()),
|
|
x(dsa.get_x()),
|
|
powermod_g_p(dsa.group_g(), dsa.group_p()),
|
|
mod_q(dsa.group_q())
|
|
{
|
|
}
|
|
|
|
SecureVector<byte>
|
|
DSA_Signature_Operation::sign(const byte msg[], size_t msg_len,
|
|
RandomNumberGenerator& rng)
|
|
{
|
|
rng.add_entropy(msg, msg_len);
|
|
|
|
BigInt i(msg, msg_len);
|
|
BigInt r = 0, s = 0;
|
|
|
|
while(r == 0 || s == 0)
|
|
{
|
|
BigInt k;
|
|
do
|
|
k.randomize(rng, q.bits());
|
|
while(k >= q);
|
|
|
|
r = mod_q.reduce(powermod_g_p(k));
|
|
s = mod_q.multiply(inverse_mod(k, q), mul_add(x, r, i));
|
|
}
|
|
|
|
SecureVector<byte> output(2*q.bytes());
|
|
r.binary_encode(&output[output.size() / 2 - r.bytes()]);
|
|
s.binary_encode(&output[output.size() - s.bytes()]);
|
|
return output;
|
|
}
|
|
|
|
DSA_Verification_Operation::DSA_Verification_Operation(const DSA_PublicKey& dsa) :
|
|
q(dsa.group_q()), y(dsa.get_y())
|
|
{
|
|
powermod_g_p = Fixed_Base_Power_Mod(dsa.group_g(), dsa.group_p());
|
|
powermod_y_p = Fixed_Base_Power_Mod(y, dsa.group_p());
|
|
mod_p = Modular_Reducer(dsa.group_p());
|
|
mod_q = Modular_Reducer(dsa.group_q());
|
|
}
|
|
|
|
bool DSA_Verification_Operation::verify(const byte msg[], size_t msg_len,
|
|
const byte sig[], size_t sig_len)
|
|
{
|
|
const BigInt& q = mod_q.get_modulus();
|
|
|
|
if(sig_len != 2*q.bytes() || msg_len > q.bytes())
|
|
return false;
|
|
|
|
BigInt r(sig, q.bytes());
|
|
BigInt s(sig + q.bytes(), q.bytes());
|
|
BigInt i(msg, msg_len);
|
|
|
|
if(r <= 0 || r >= q || s <= 0 || s >= q)
|
|
return false;
|
|
|
|
s = inverse_mod(s, q);
|
|
s = mod_p.multiply(powermod_g_p(mod_q.multiply(s, i)),
|
|
powermod_y_p(mod_q.multiply(s, r)));
|
|
|
|
return (mod_q.reduce(s) == r);
|
|
}
|
|
|
|
}
|
|
/*
|
|
* ECC Domain Parameters
|
|
*
|
|
* (C) 2007 Falko Strenzke, FlexSecure GmbH
|
|
* 2008 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
EC_Group::EC_Group(const OID& domain_oid)
|
|
{
|
|
std::string pem =
|
|
global_state().get("ec", OIDS::lookup(domain_oid));
|
|
|
|
if(pem == "")
|
|
throw Lookup_Error("No ECC domain data for " + domain_oid.as_string());
|
|
|
|
*this = EC_Group(pem);
|
|
oid = domain_oid.as_string();
|
|
}
|
|
|
|
EC_Group::EC_Group(const std::string& str)
|
|
{
|
|
if(str == "")
|
|
return; // no initialization / uninitialized
|
|
|
|
try
|
|
{
|
|
DataSource_Memory input(str);
|
|
|
|
SecureVector<byte> ber =
|
|
PEM_Code::decode_check_label(input, "EC PARAMETERS");
|
|
|
|
*this = EC_Group(ber);
|
|
}
|
|
catch(Decoding_Error) // hmm, not PEM?
|
|
{
|
|
*this = EC_Group(OIDS::lookup(str));
|
|
}
|
|
}
|
|
|
|
EC_Group::EC_Group(const MemoryRegion<byte>& ber_data)
|
|
{
|
|
BER_Decoder ber(ber_data);
|
|
BER_Object obj = ber.get_next_object();
|
|
|
|
if(obj.type_tag == NULL_TAG)
|
|
throw Decoding_Error("Cannot handle ImplicitCA ECDSA parameters");
|
|
else if(obj.type_tag == OBJECT_ID)
|
|
{
|
|
OID dom_par_oid;
|
|
BER_Decoder(ber_data).decode(dom_par_oid);
|
|
*this = EC_Group(dom_par_oid);
|
|
}
|
|
else if(obj.type_tag == SEQUENCE)
|
|
{
|
|
BigInt p, a, b;
|
|
SecureVector<byte> sv_base_point;
|
|
|
|
BER_Decoder(ber_data)
|
|
.start_cons(SEQUENCE)
|
|
.decode_and_check<size_t>(1, "Unknown ECC param version code")
|
|
.start_cons(SEQUENCE)
|
|
.decode_and_check(OID("1.2.840.10045.1.1"),
|
|
"Only prime ECC fields supported")
|
|
.decode(p)
|
|
.end_cons()
|
|
.start_cons(SEQUENCE)
|
|
.decode_octet_string_bigint(a)
|
|
.decode_octet_string_bigint(b)
|
|
.end_cons()
|
|
.decode(sv_base_point, OCTET_STRING)
|
|
.decode(order)
|
|
.decode(cofactor)
|
|
.end_cons()
|
|
.verify_end();
|
|
|
|
curve = CurveGFp(p, a, b);
|
|
base_point = OS2ECP(sv_base_point, curve);
|
|
}
|
|
else
|
|
throw Decoding_Error("Unexpected tag while decoding ECC domain params");
|
|
}
|
|
|
|
SecureVector<byte>
|
|
EC_Group::DER_encode(EC_Group_Encoding form) const
|
|
{
|
|
if(form == EC_DOMPAR_ENC_EXPLICIT)
|
|
{
|
|
const size_t ecpVers1 = 1;
|
|
OID curve_type("1.2.840.10045.1.1");
|
|
|
|
const size_t p_bytes = curve.get_p().bytes();
|
|
|
|
return DER_Encoder()
|
|
.start_cons(SEQUENCE)
|
|
.encode(ecpVers1)
|
|
.start_cons(SEQUENCE)
|
|
.encode(curve_type)
|
|
.encode(curve.get_p())
|
|
.end_cons()
|
|
.start_cons(SEQUENCE)
|
|
.encode(BigInt::encode_1363(curve.get_a(), p_bytes),
|
|
OCTET_STRING)
|
|
.encode(BigInt::encode_1363(curve.get_b(), p_bytes),
|
|
OCTET_STRING)
|
|
.end_cons()
|
|
.encode(EC2OSP(base_point, PointGFp::UNCOMPRESSED), OCTET_STRING)
|
|
.encode(order)
|
|
.encode(cofactor)
|
|
.end_cons()
|
|
.get_contents();
|
|
}
|
|
else if(form == EC_DOMPAR_ENC_OID)
|
|
return DER_Encoder().encode(get_oid()).get_contents();
|
|
else if(form == EC_DOMPAR_ENC_IMPLICITCA)
|
|
return DER_Encoder().encode_null().get_contents();
|
|
else
|
|
throw Internal_Error("EC_Group::DER_encode: Unknown encoding");
|
|
}
|
|
|
|
std::string EC_Group::PEM_encode() const
|
|
{
|
|
SecureVector<byte> der = DER_encode(EC_DOMPAR_ENC_EXPLICIT);
|
|
return PEM_Code::encode(der, "EC PARAMETERS");
|
|
}
|
|
|
|
}
|
|
/*
|
|
* ECC Key implemenation
|
|
* (C) 2007 Manuel Hartl, FlexSecure GmbH
|
|
* Falko Strenzke, FlexSecure GmbH
|
|
* 2008-2010 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
EC_PublicKey::EC_PublicKey(const EC_Group& dom_par,
|
|
const PointGFp& pub_point) :
|
|
domain_params(dom_par), public_key(pub_point),
|
|
domain_encoding(EC_DOMPAR_ENC_EXPLICIT)
|
|
{
|
|
if(domain().get_curve() != public_point().get_curve())
|
|
throw Invalid_Argument("EC_PublicKey: curve mismatch in constructor");
|
|
}
|
|
|
|
EC_PublicKey::EC_PublicKey(const AlgorithmIdentifier& alg_id,
|
|
const MemoryRegion<byte>& key_bits)
|
|
{
|
|
domain_params = EC_Group(alg_id.parameters);
|
|
domain_encoding = EC_DOMPAR_ENC_EXPLICIT;
|
|
|
|
public_key = OS2ECP(key_bits, domain().get_curve());
|
|
}
|
|
|
|
bool EC_PublicKey::check_key(RandomNumberGenerator&,
|
|
bool) const
|
|
{
|
|
return public_point().on_the_curve();
|
|
}
|
|
|
|
AlgorithmIdentifier EC_PublicKey::algorithm_identifier() const
|
|
{
|
|
return AlgorithmIdentifier(get_oid(), DER_domain());
|
|
}
|
|
|
|
MemoryVector<byte> EC_PublicKey::x509_subject_public_key() const
|
|
{
|
|
return EC2OSP(public_point(), PointGFp::COMPRESSED);
|
|
}
|
|
|
|
void EC_PublicKey::set_parameter_encoding(EC_Group_Encoding form)
|
|
{
|
|
if(form != EC_DOMPAR_ENC_EXPLICIT &&
|
|
form != EC_DOMPAR_ENC_IMPLICITCA &&
|
|
form != EC_DOMPAR_ENC_OID)
|
|
throw Invalid_Argument("Invalid encoding form for EC-key object specified");
|
|
|
|
if((form == EC_DOMPAR_ENC_OID) && (domain_params.get_oid() == ""))
|
|
throw Invalid_Argument("Invalid encoding form OID specified for "
|
|
"EC-key object whose corresponding domain "
|
|
"parameters are without oid");
|
|
|
|
domain_encoding = form;
|
|
}
|
|
|
|
const BigInt& EC_PrivateKey::private_value() const
|
|
{
|
|
if(private_key == 0)
|
|
throw Invalid_State("EC_PrivateKey::private_value - uninitialized");
|
|
|
|
return private_key;
|
|
}
|
|
|
|
/**
|
|
* EC_PrivateKey constructor
|
|
*/
|
|
EC_PrivateKey::EC_PrivateKey(RandomNumberGenerator& rng,
|
|
const EC_Group& ec_group,
|
|
const BigInt& x)
|
|
{
|
|
domain_params = ec_group;
|
|
domain_encoding = EC_DOMPAR_ENC_EXPLICIT;
|
|
|
|
if(x == 0)
|
|
private_key = BigInt::random_integer(rng, 1, domain().get_order());
|
|
else
|
|
private_key = x;
|
|
|
|
public_key = domain().get_base_point() * private_key;
|
|
|
|
BOTAN_ASSERT(public_key.on_the_curve(),
|
|
"ECC private key was not on the curve");
|
|
}
|
|
|
|
MemoryVector<byte> EC_PrivateKey::pkcs8_private_key() const
|
|
{
|
|
return DER_Encoder()
|
|
.start_cons(SEQUENCE)
|
|
.encode(static_cast<size_t>(1))
|
|
.encode(BigInt::encode_1363(private_key, private_key.bytes()),
|
|
OCTET_STRING)
|
|
.end_cons()
|
|
.get_contents();
|
|
}
|
|
|
|
EC_PrivateKey::EC_PrivateKey(const AlgorithmIdentifier& alg_id,
|
|
const MemoryRegion<byte>& key_bits)
|
|
{
|
|
domain_params = EC_Group(alg_id.parameters);
|
|
domain_encoding = EC_DOMPAR_ENC_EXPLICIT;
|
|
|
|
BER_Decoder(key_bits)
|
|
.start_cons(SEQUENCE)
|
|
.decode_and_check<size_t>(1, "Unknown version code for ECC key")
|
|
.decode_octet_string_bigint(private_key)
|
|
.verify_end()
|
|
.end_cons();
|
|
|
|
public_key = domain().get_base_point() * private_key;
|
|
|
|
BOTAN_ASSERT(public_key.on_the_curve(),
|
|
"Loaded ECC private key not on the curve");
|
|
}
|
|
|
|
}
|
|
/*
|
|
* ECDH implemenation
|
|
* (C) 2007 Manuel Hartl, FlexSecure GmbH
|
|
* 2007 Falko Strenzke, FlexSecure GmbH
|
|
* 2008-2010 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
ECDH_KA_Operation::ECDH_KA_Operation(const ECDH_PrivateKey& key) :
|
|
curve(key.domain().get_curve()),
|
|
cofactor(key.domain().get_cofactor())
|
|
{
|
|
l_times_priv = inverse_mod(cofactor, key.domain().get_order()) *
|
|
key.private_value();
|
|
}
|
|
|
|
SecureVector<byte> ECDH_KA_Operation::agree(const byte w[], size_t w_len)
|
|
{
|
|
PointGFp point = OS2ECP(w, w_len, curve);
|
|
|
|
PointGFp S = (cofactor * point) * l_times_priv;
|
|
|
|
BOTAN_ASSERT(S.on_the_curve(),
|
|
"ECDH agreed value not on the curve");
|
|
|
|
return BigInt::encode_1363(S.get_affine_x(),
|
|
curve.get_p().bytes());
|
|
}
|
|
|
|
}
|
|
/*
|
|
* ECDSA implemenation
|
|
* (C) 2007 Manuel Hartl, FlexSecure GmbH
|
|
* 2007 Falko Strenzke, FlexSecure GmbH
|
|
* 2008-2010 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
bool ECDSA_PrivateKey::check_key(RandomNumberGenerator& rng,
|
|
bool strong) const
|
|
{
|
|
if(!public_point().on_the_curve())
|
|
return false;
|
|
|
|
if(!strong)
|
|
return true;
|
|
|
|
return KeyPair::signature_consistency_check(rng, *this, "EMSA1(SHA-1)");
|
|
}
|
|
|
|
ECDSA_Signature_Operation::ECDSA_Signature_Operation(const ECDSA_PrivateKey& ecdsa) :
|
|
base_point(ecdsa.domain().get_base_point()),
|
|
order(ecdsa.domain().get_order()),
|
|
x(ecdsa.private_value()),
|
|
mod_order(order)
|
|
{
|
|
}
|
|
|
|
SecureVector<byte>
|
|
ECDSA_Signature_Operation::sign(const byte msg[], size_t msg_len,
|
|
RandomNumberGenerator& rng)
|
|
{
|
|
rng.add_entropy(msg, msg_len);
|
|
|
|
BigInt m(msg, msg_len);
|
|
|
|
BigInt r = 0, s = 0;
|
|
|
|
while(r == 0 || s == 0)
|
|
{
|
|
// This contortion is necessary for the tests
|
|
BigInt k;
|
|
k.randomize(rng, order.bits());
|
|
|
|
while(k >= order)
|
|
k.randomize(rng, order.bits() - 1);
|
|
|
|
PointGFp k_times_P = base_point * k;
|
|
r = mod_order.reduce(k_times_P.get_affine_x());
|
|
s = mod_order.multiply(inverse_mod(k, order), mul_add(x, r, m));
|
|
}
|
|
|
|
SecureVector<byte> output(2*order.bytes());
|
|
r.binary_encode(&output[output.size() / 2 - r.bytes()]);
|
|
s.binary_encode(&output[output.size() - s.bytes()]);
|
|
return output;
|
|
}
|
|
|
|
ECDSA_Verification_Operation::ECDSA_Verification_Operation(const ECDSA_PublicKey& ecdsa) :
|
|
base_point(ecdsa.domain().get_base_point()),
|
|
public_point(ecdsa.public_point()),
|
|
order(ecdsa.domain().get_order())
|
|
{
|
|
}
|
|
|
|
bool ECDSA_Verification_Operation::verify(const byte msg[], size_t msg_len,
|
|
const byte sig[], size_t sig_len)
|
|
{
|
|
if(sig_len != order.bytes()*2)
|
|
return false;
|
|
|
|
BigInt e(msg, msg_len);
|
|
|
|
BigInt r(sig, sig_len / 2);
|
|
BigInt s(sig + sig_len / 2, sig_len / 2);
|
|
|
|
if(r <= 0 || r >= order || s <= 0 || s >= order)
|
|
return false;
|
|
|
|
BigInt w = inverse_mod(s, order);
|
|
|
|
PointGFp R = w * multi_exponentiate(base_point, e,
|
|
public_point, r);
|
|
|
|
if(R.is_zero())
|
|
return false;
|
|
|
|
return (R.get_affine_x() % order == r);
|
|
}
|
|
|
|
}
|
|
/*
|
|
* ElGamal
|
|
* (C) 1999-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* ElGamal_PublicKey Constructor
|
|
*/
|
|
ElGamal_PublicKey::ElGamal_PublicKey(const DL_Group& grp, const BigInt& y1)
|
|
{
|
|
group = grp;
|
|
y = y1;
|
|
}
|
|
|
|
/*
|
|
* ElGamal_PrivateKey Constructor
|
|
*/
|
|
ElGamal_PrivateKey::ElGamal_PrivateKey(RandomNumberGenerator& rng,
|
|
const DL_Group& grp,
|
|
const BigInt& x_arg)
|
|
{
|
|
group = grp;
|
|
x = x_arg;
|
|
|
|
if(x == 0)
|
|
x.randomize(rng, 2 * dl_work_factor(group_p().bits()));
|
|
|
|
y = power_mod(group_g(), x, group_p());
|
|
|
|
if(x_arg == 0)
|
|
gen_check(rng);
|
|
else
|
|
load_check(rng);
|
|
}
|
|
|
|
ElGamal_PrivateKey::ElGamal_PrivateKey(const AlgorithmIdentifier& alg_id,
|
|
const MemoryRegion<byte>& key_bits,
|
|
RandomNumberGenerator& rng) :
|
|
DL_Scheme_PrivateKey(alg_id, key_bits, DL_Group::ANSI_X9_42)
|
|
{
|
|
y = power_mod(group_g(), x, group_p());
|
|
load_check(rng);
|
|
}
|
|
|
|
/*
|
|
* Check Private ElGamal Parameters
|
|
*/
|
|
bool ElGamal_PrivateKey::check_key(RandomNumberGenerator& rng,
|
|
bool strong) const
|
|
{
|
|
if(!DL_Scheme_PrivateKey::check_key(rng, strong))
|
|
return false;
|
|
|
|
if(!strong)
|
|
return true;
|
|
|
|
return KeyPair::encryption_consistency_check(rng, *this, "EME1(SHA-1)");
|
|
}
|
|
|
|
ElGamal_Encryption_Operation::ElGamal_Encryption_Operation(const ElGamal_PublicKey& key)
|
|
{
|
|
const BigInt& p = key.group_p();
|
|
|
|
powermod_g_p = Fixed_Base_Power_Mod(key.group_g(), p);
|
|
powermod_y_p = Fixed_Base_Power_Mod(key.get_y(), p);
|
|
mod_p = Modular_Reducer(p);
|
|
}
|
|
|
|
SecureVector<byte>
|
|
ElGamal_Encryption_Operation::encrypt(const byte msg[], size_t msg_len,
|
|
RandomNumberGenerator& rng)
|
|
{
|
|
const BigInt& p = mod_p.get_modulus();
|
|
|
|
BigInt m(msg, msg_len);
|
|
|
|
if(m >= p)
|
|
throw Invalid_Argument("ElGamal encryption: Input is too large");
|
|
|
|
BigInt k(rng, 2 * dl_work_factor(p.bits()));
|
|
|
|
BigInt a = powermod_g_p(k);
|
|
BigInt b = mod_p.multiply(m, powermod_y_p(k));
|
|
|
|
SecureVector<byte> output(2*p.bytes());
|
|
a.binary_encode(&output[p.bytes() - a.bytes()]);
|
|
b.binary_encode(&output[output.size() / 2 + (p.bytes() - b.bytes())]);
|
|
return output;
|
|
}
|
|
|
|
ElGamal_Decryption_Operation::ElGamal_Decryption_Operation(const ElGamal_PrivateKey& key)
|
|
{
|
|
const BigInt& p = key.group_p();
|
|
|
|
powermod_x_p = Fixed_Exponent_Power_Mod(key.get_x(), p);
|
|
mod_p = Modular_Reducer(p);
|
|
|
|
BigInt k(global_state().global_rng(), p.bits() - 1);
|
|
blinder = Blinder(k, powermod_x_p(k), p);
|
|
}
|
|
|
|
SecureVector<byte>
|
|
ElGamal_Decryption_Operation::decrypt(const byte msg[], size_t msg_len)
|
|
{
|
|
const BigInt& p = mod_p.get_modulus();
|
|
|
|
const size_t p_bytes = p.bytes();
|
|
|
|
if(msg_len != 2 * p_bytes)
|
|
throw Invalid_Argument("ElGamal decryption: Invalid message");
|
|
|
|
BigInt a(msg, p_bytes);
|
|
BigInt b(msg + p_bytes, p_bytes);
|
|
|
|
if(a >= p || b >= p)
|
|
throw Invalid_Argument("ElGamal decryption: Invalid message");
|
|
|
|
a = blinder.blind(a);
|
|
|
|
BigInt r = mod_p.multiply(b, inverse_mod(powermod_x_p(a), p));
|
|
|
|
return BigInt::encode(blinder.unblind(r));
|
|
}
|
|
|
|
}
|
|
/*
|
|
* GOST 34.10-2001 implemenation
|
|
* (C) 2007 Falko Strenzke, FlexSecure GmbH
|
|
* Manuel Hartl, FlexSecure GmbH
|
|
* (C) 2008-2010 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
MemoryVector<byte> GOST_3410_PublicKey::x509_subject_public_key() const
|
|
{
|
|
// Trust CryptoPro to come up with something obnoxious
|
|
const BigInt x = public_point().get_affine_x();
|
|
const BigInt y = public_point().get_affine_y();
|
|
|
|
size_t part_size = std::max(x.bytes(), y.bytes());
|
|
|
|
MemoryVector<byte> bits(2*part_size);
|
|
|
|
x.binary_encode(&bits[part_size - x.bytes()]);
|
|
y.binary_encode(&bits[2*part_size - y.bytes()]);
|
|
|
|
// Keys are stored in little endian format (WTF)
|
|
for(size_t i = 0; i != part_size / 2; ++i)
|
|
{
|
|
std::swap(bits[i], bits[part_size-1-i]);
|
|
std::swap(bits[part_size+i], bits[2*part_size-1-i]);
|
|
}
|
|
|
|
return DER_Encoder().encode(bits, OCTET_STRING).get_contents();
|
|
}
|
|
|
|
AlgorithmIdentifier GOST_3410_PublicKey::algorithm_identifier() const
|
|
{
|
|
MemoryVector<byte> params =
|
|
DER_Encoder().start_cons(SEQUENCE)
|
|
.encode(OID(domain().get_oid()))
|
|
.end_cons()
|
|
.get_contents();
|
|
|
|
return AlgorithmIdentifier(get_oid(), params);
|
|
}
|
|
|
|
GOST_3410_PublicKey::GOST_3410_PublicKey(const AlgorithmIdentifier& alg_id,
|
|
const MemoryRegion<byte>& key_bits)
|
|
{
|
|
OID ecc_param_id;
|
|
|
|
// Also includes hash and cipher OIDs... brilliant design guys
|
|
BER_Decoder(alg_id.parameters).start_cons(SEQUENCE).decode(ecc_param_id);
|
|
|
|
domain_params = EC_Group(ecc_param_id);
|
|
|
|
SecureVector<byte> bits;
|
|
BER_Decoder(key_bits).decode(bits, OCTET_STRING);
|
|
|
|
const size_t part_size = bits.size() / 2;
|
|
|
|
// Keys are stored in little endian format (WTF)
|
|
for(size_t i = 0; i != part_size / 2; ++i)
|
|
{
|
|
std::swap(bits[i], bits[part_size-1-i]);
|
|
std::swap(bits[part_size+i], bits[2*part_size-1-i]);
|
|
}
|
|
|
|
BigInt x(&bits[0], part_size);
|
|
BigInt y(&bits[part_size], part_size);
|
|
|
|
public_key = PointGFp(domain().get_curve(), x, y);
|
|
|
|
BOTAN_ASSERT(public_key.on_the_curve(),
|
|
"Loaded GOST 34.10 public key not on the curve");
|
|
}
|
|
|
|
namespace {
|
|
|
|
BigInt decode_le(const byte msg[], size_t msg_len)
|
|
{
|
|
SecureVector<byte> msg_le(msg, msg_len);
|
|
|
|
for(size_t i = 0; i != msg_le.size() / 2; ++i)
|
|
std::swap(msg_le[i], msg_le[msg_le.size()-1-i]);
|
|
|
|
return BigInt(&msg_le[0], msg_le.size());
|
|
}
|
|
|
|
}
|
|
|
|
GOST_3410_Signature_Operation::GOST_3410_Signature_Operation(
|
|
const GOST_3410_PrivateKey& gost_3410) :
|
|
|
|
base_point(gost_3410.domain().get_base_point()),
|
|
order(gost_3410.domain().get_order()),
|
|
x(gost_3410.private_value())
|
|
{
|
|
}
|
|
|
|
SecureVector<byte>
|
|
GOST_3410_Signature_Operation::sign(const byte msg[], size_t msg_len,
|
|
RandomNumberGenerator& rng)
|
|
{
|
|
BigInt k;
|
|
do
|
|
k.randomize(rng, order.bits()-1);
|
|
while(k >= order);
|
|
|
|
BigInt e = decode_le(msg, msg_len);
|
|
|
|
e %= order;
|
|
if(e == 0)
|
|
e = 1;
|
|
|
|
PointGFp k_times_P = base_point * k;
|
|
|
|
BOTAN_ASSERT(k_times_P.on_the_curve(),
|
|
"GOST 34.10 k*g not on the curve");
|
|
|
|
BigInt r = k_times_P.get_affine_x() % order;
|
|
|
|
BigInt s = (r*x + k*e) % order;
|
|
|
|
if(r == 0 || s == 0)
|
|
throw Invalid_State("GOST 34.10: r == 0 || s == 0");
|
|
|
|
SecureVector<byte> output(2*order.bytes());
|
|
s.binary_encode(&output[output.size() / 2 - s.bytes()]);
|
|
r.binary_encode(&output[output.size() - r.bytes()]);
|
|
return output;
|
|
}
|
|
|
|
GOST_3410_Verification_Operation::GOST_3410_Verification_Operation(const GOST_3410_PublicKey& gost) :
|
|
base_point(gost.domain().get_base_point()),
|
|
public_point(gost.public_point()),
|
|
order(gost.domain().get_order())
|
|
{
|
|
}
|
|
|
|
bool GOST_3410_Verification_Operation::verify(const byte msg[], size_t msg_len,
|
|
const byte sig[], size_t sig_len)
|
|
{
|
|
if(sig_len != order.bytes()*2)
|
|
return false;
|
|
|
|
BigInt e = decode_le(msg, msg_len);
|
|
|
|
BigInt s(sig, sig_len / 2);
|
|
BigInt r(sig + sig_len / 2, sig_len / 2);
|
|
|
|
if(r <= 0 || r >= order || s <= 0 || s >= order)
|
|
return false;
|
|
|
|
e %= order;
|
|
if(e == 0)
|
|
e = 1;
|
|
|
|
BigInt v = inverse_mod(e, order);
|
|
|
|
BigInt z1 = (s*v) % order;
|
|
BigInt z2 = (-r*v) % order;
|
|
|
|
PointGFp R = multi_exponentiate(base_point, z1,
|
|
public_point, z2);
|
|
|
|
if(R.is_zero())
|
|
return false;
|
|
|
|
return (R.get_affine_x() == r);
|
|
}
|
|
|
|
}
|
|
/*
|
|
* IF Scheme
|
|
* (C) 1999-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
AlgorithmIdentifier IF_Scheme_PublicKey::algorithm_identifier() const
|
|
{
|
|
return AlgorithmIdentifier(get_oid(),
|
|
AlgorithmIdentifier::USE_NULL_PARAM);
|
|
}
|
|
|
|
MemoryVector<byte> IF_Scheme_PublicKey::x509_subject_public_key() const
|
|
{
|
|
return DER_Encoder()
|
|
.start_cons(SEQUENCE)
|
|
.encode(n)
|
|
.encode(e)
|
|
.end_cons()
|
|
.get_contents();
|
|
}
|
|
|
|
IF_Scheme_PublicKey::IF_Scheme_PublicKey(const AlgorithmIdentifier&,
|
|
const MemoryRegion<byte>& key_bits)
|
|
{
|
|
BER_Decoder(key_bits)
|
|
.start_cons(SEQUENCE)
|
|
.decode(n)
|
|
.decode(e)
|
|
.verify_end()
|
|
.end_cons();
|
|
}
|
|
|
|
/*
|
|
* Check IF Scheme Public Parameters
|
|
*/
|
|
bool IF_Scheme_PublicKey::check_key(RandomNumberGenerator&, bool) const
|
|
{
|
|
if(n < 35 || n.is_even() || e < 2)
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
MemoryVector<byte> IF_Scheme_PrivateKey::pkcs8_private_key() const
|
|
{
|
|
return DER_Encoder()
|
|
.start_cons(SEQUENCE)
|
|
.encode(static_cast<size_t>(0))
|
|
.encode(n)
|
|
.encode(e)
|
|
.encode(d)
|
|
.encode(p)
|
|
.encode(q)
|
|
.encode(d1)
|
|
.encode(d2)
|
|
.encode(c)
|
|
.end_cons()
|
|
.get_contents();
|
|
}
|
|
|
|
IF_Scheme_PrivateKey::IF_Scheme_PrivateKey(RandomNumberGenerator& rng,
|
|
const AlgorithmIdentifier&,
|
|
const MemoryRegion<byte>& key_bits)
|
|
{
|
|
BER_Decoder(key_bits)
|
|
.start_cons(SEQUENCE)
|
|
.decode_and_check<size_t>(0, "Unknown PKCS #1 key format version")
|
|
.decode(n)
|
|
.decode(e)
|
|
.decode(d)
|
|
.decode(p)
|
|
.decode(q)
|
|
.decode(d1)
|
|
.decode(d2)
|
|
.decode(c)
|
|
.end_cons();
|
|
|
|
load_check(rng);
|
|
}
|
|
|
|
IF_Scheme_PrivateKey::IF_Scheme_PrivateKey(RandomNumberGenerator& rng,
|
|
const BigInt& prime1,
|
|
const BigInt& prime2,
|
|
const BigInt& exp,
|
|
const BigInt& d_exp,
|
|
const BigInt& mod)
|
|
{
|
|
p = prime1;
|
|
q = prime2;
|
|
e = exp;
|
|
d = d_exp;
|
|
n = mod.is_nonzero() ? mod : p * q;
|
|
|
|
if(d == 0)
|
|
{
|
|
BigInt inv_for_d = lcm(p - 1, q - 1);
|
|
if(e.is_even())
|
|
inv_for_d >>= 1;
|
|
|
|
d = inverse_mod(e, inv_for_d);
|
|
}
|
|
|
|
d1 = d % (p - 1);
|
|
d2 = d % (q - 1);
|
|
c = inverse_mod(q, p);
|
|
|
|
load_check(rng);
|
|
}
|
|
|
|
/*
|
|
* Check IF Scheme Private Parameters
|
|
*/
|
|
bool IF_Scheme_PrivateKey::check_key(RandomNumberGenerator& rng,
|
|
bool strong) const
|
|
{
|
|
if(n < 35 || n.is_even() || e < 2 || d < 2 || p < 3 || q < 3 || p*q != n)
|
|
return false;
|
|
|
|
if(!strong)
|
|
return true;
|
|
|
|
if(d1 != d % (p - 1) || d2 != d % (q - 1) || c != inverse_mod(q, p))
|
|
return false;
|
|
if(!check_prime(p, rng) || !check_prime(q, rng))
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
}
|
|
/*
|
|
* Keypair Checks
|
|
* (C) 1999-2010 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
namespace KeyPair {
|
|
|
|
/*
|
|
* Check an encryption key pair for consistency
|
|
*/
|
|
bool encryption_consistency_check(RandomNumberGenerator& rng,
|
|
const Private_Key& key,
|
|
const std::string& padding)
|
|
{
|
|
PK_Encryptor_EME encryptor(key, padding);
|
|
PK_Decryptor_EME decryptor(key, padding);
|
|
|
|
/*
|
|
Weird corner case, if the key is too small to encrypt anything at
|
|
all. This can happen with very small RSA keys with PSS
|
|
*/
|
|
if(encryptor.maximum_input_size() == 0)
|
|
return true;
|
|
|
|
SecureVector<byte> plaintext =
|
|
rng.random_vec(encryptor.maximum_input_size() - 1);
|
|
|
|
SecureVector<byte> ciphertext = encryptor.encrypt(plaintext, rng);
|
|
if(ciphertext == plaintext)
|
|
return false;
|
|
|
|
SecureVector<byte> decrypted = decryptor.decrypt(ciphertext);
|
|
|
|
return (plaintext == decrypted);
|
|
}
|
|
|
|
/*
|
|
* Check a signature key pair for consistency
|
|
*/
|
|
bool signature_consistency_check(RandomNumberGenerator& rng,
|
|
const Private_Key& key,
|
|
const std::string& padding)
|
|
{
|
|
PK_Signer signer(key, padding);
|
|
PK_Verifier verifier(key, padding);
|
|
|
|
SecureVector<byte> message = rng.random_vec(16);
|
|
|
|
SecureVector<byte> signature;
|
|
|
|
try
|
|
{
|
|
signature = signer.sign_message(message, rng);
|
|
}
|
|
catch(Encoding_Error)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if(!verifier.verify_message(message, signature))
|
|
return false;
|
|
|
|
// Now try to check a corrupt signature, ensure it does not succeed
|
|
++message[0];
|
|
|
|
if(verifier.verify_message(message, signature))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
/*
|
|
* Nyberg-Rueppel
|
|
* (C) 1999-2010 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
NR_PublicKey::NR_PublicKey(const AlgorithmIdentifier& alg_id,
|
|
const MemoryRegion<byte>& key_bits) :
|
|
DL_Scheme_PublicKey(alg_id, key_bits, DL_Group::ANSI_X9_57)
|
|
{
|
|
}
|
|
|
|
/*
|
|
* NR_PublicKey Constructor
|
|
*/
|
|
NR_PublicKey::NR_PublicKey(const DL_Group& grp, const BigInt& y1)
|
|
{
|
|
group = grp;
|
|
y = y1;
|
|
}
|
|
|
|
/*
|
|
* Create a NR private key
|
|
*/
|
|
NR_PrivateKey::NR_PrivateKey(RandomNumberGenerator& rng,
|
|
const DL_Group& grp,
|
|
const BigInt& x_arg)
|
|
{
|
|
group = grp;
|
|
x = x_arg;
|
|
|
|
if(x == 0)
|
|
x = BigInt::random_integer(rng, 2, group_q() - 1);
|
|
|
|
y = power_mod(group_g(), x, group_p());
|
|
|
|
if(x_arg == 0)
|
|
gen_check(rng);
|
|
else
|
|
load_check(rng);
|
|
}
|
|
|
|
NR_PrivateKey::NR_PrivateKey(const AlgorithmIdentifier& alg_id,
|
|
const MemoryRegion<byte>& key_bits,
|
|
RandomNumberGenerator& rng) :
|
|
DL_Scheme_PrivateKey(alg_id, key_bits, DL_Group::ANSI_X9_57)
|
|
{
|
|
y = power_mod(group_g(), x, group_p());
|
|
|
|
load_check(rng);
|
|
}
|
|
|
|
/*
|
|
* Check Private Nyberg-Rueppel Parameters
|
|
*/
|
|
bool NR_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const
|
|
{
|
|
if(!DL_Scheme_PrivateKey::check_key(rng, strong) || x >= group_q())
|
|
return false;
|
|
|
|
if(!strong)
|
|
return true;
|
|
|
|
return KeyPair::signature_consistency_check(rng, *this, "EMSA1(SHA-1)");
|
|
}
|
|
|
|
NR_Signature_Operation::NR_Signature_Operation(const NR_PrivateKey& nr) :
|
|
q(nr.group_q()),
|
|
x(nr.get_x()),
|
|
powermod_g_p(nr.group_g(), nr.group_p()),
|
|
mod_q(nr.group_q())
|
|
{
|
|
}
|
|
|
|
SecureVector<byte>
|
|
NR_Signature_Operation::sign(const byte msg[], size_t msg_len,
|
|
RandomNumberGenerator& rng)
|
|
{
|
|
rng.add_entropy(msg, msg_len);
|
|
|
|
BigInt f(msg, msg_len);
|
|
|
|
if(f >= q)
|
|
throw Invalid_Argument("NR_Signature_Operation: Input is out of range");
|
|
|
|
BigInt c, d;
|
|
|
|
while(c == 0)
|
|
{
|
|
BigInt k;
|
|
do
|
|
k.randomize(rng, q.bits());
|
|
while(k >= q);
|
|
|
|
c = mod_q.reduce(powermod_g_p(k) + f);
|
|
d = mod_q.reduce(k - x * c);
|
|
}
|
|
|
|
SecureVector<byte> output(2*q.bytes());
|
|
c.binary_encode(&output[output.size() / 2 - c.bytes()]);
|
|
d.binary_encode(&output[output.size() - d.bytes()]);
|
|
return output;
|
|
}
|
|
|
|
NR_Verification_Operation::NR_Verification_Operation(const NR_PublicKey& nr) :
|
|
q(nr.group_q()), y(nr.get_y())
|
|
{
|
|
powermod_g_p = Fixed_Base_Power_Mod(nr.group_g(), nr.group_p());
|
|
powermod_y_p = Fixed_Base_Power_Mod(y, nr.group_p());
|
|
mod_p = Modular_Reducer(nr.group_p());
|
|
mod_q = Modular_Reducer(nr.group_q());
|
|
}
|
|
|
|
SecureVector<byte>
|
|
NR_Verification_Operation::verify_mr(const byte msg[], size_t msg_len)
|
|
{
|
|
const BigInt& q = mod_q.get_modulus();
|
|
|
|
if(msg_len != 2*q.bytes())
|
|
throw Invalid_Argument("NR verification: Invalid signature");
|
|
|
|
BigInt c(msg, q.bytes());
|
|
BigInt d(msg + q.bytes(), q.bytes());
|
|
|
|
if(c.is_zero() || c >= q || d >= q)
|
|
throw Invalid_Argument("NR verification: Invalid signature");
|
|
|
|
BigInt i = mod_p.multiply(powermod_g_p(d), powermod_y_p(c));
|
|
return BigInt::encode(mod_q.reduce(c - i));
|
|
}
|
|
|
|
}
|
|
/*
|
|
* PK Key
|
|
* (C) 1999-2010 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
#if defined(BOTAN_HAS_RSA)
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_DSA)
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_ECDSA)
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_GOST_34_10_2001)
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_RW)
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_ELGAMAL)
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_ECDH)
|
|
#endif
|
|
|
|
namespace Botan {
|
|
|
|
Public_Key* make_public_key(const AlgorithmIdentifier& alg_id,
|
|
const MemoryRegion<byte>& key_bits)
|
|
{
|
|
const std::string alg_name = OIDS::lookup(alg_id.oid);
|
|
if(alg_name == "")
|
|
throw Decoding_Error("Unknown algorithm OID: " + alg_id.oid.as_string());
|
|
|
|
#if defined(BOTAN_HAS_RSA)
|
|
if(alg_name == "RSA")
|
|
return new RSA_PublicKey(alg_id, key_bits);
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_RW)
|
|
if(alg_name == "RW")
|
|
return new RW_PublicKey(alg_id, key_bits);
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_DSA)
|
|
if(alg_name == "DSA")
|
|
return new DSA_PublicKey(alg_id, key_bits);
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
|
|
if(alg_name == "DH")
|
|
return new DH_PublicKey(alg_id, key_bits);
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
|
|
if(alg_name == "NR")
|
|
return new NR_PublicKey(alg_id, key_bits);
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_ELGAMAL)
|
|
if(alg_name == "ElGamal")
|
|
return new ElGamal_PublicKey(alg_id, key_bits);
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_ECDSA)
|
|
if(alg_name == "ECDSA")
|
|
return new ECDSA_PublicKey(alg_id, key_bits);
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_GOST_34_10_2001)
|
|
if(alg_name == "GOST-34.10")
|
|
return new GOST_3410_PublicKey(alg_id, key_bits);
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_ECDH)
|
|
if(alg_name == "ECDH")
|
|
return new ECDH_PublicKey(alg_id, key_bits);
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
Private_Key* make_private_key(const AlgorithmIdentifier& alg_id,
|
|
const MemoryRegion<byte>& key_bits,
|
|
RandomNumberGenerator& rng)
|
|
{
|
|
const std::string alg_name = OIDS::lookup(alg_id.oid);
|
|
if(alg_name == "")
|
|
throw Decoding_Error("Unknown algorithm OID: " + alg_id.oid.as_string());
|
|
|
|
#if defined(BOTAN_HAS_RSA)
|
|
if(alg_name == "RSA")
|
|
return new RSA_PrivateKey(alg_id, key_bits, rng);
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_RW)
|
|
if(alg_name == "RW")
|
|
return new RW_PrivateKey(alg_id, key_bits, rng);
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_DSA)
|
|
if(alg_name == "DSA")
|
|
return new DSA_PrivateKey(alg_id, key_bits, rng);
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
|
|
if(alg_name == "DH")
|
|
return new DH_PrivateKey(alg_id, key_bits, rng);
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
|
|
if(alg_name == "NR")
|
|
return new NR_PrivateKey(alg_id, key_bits, rng);
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_ELGAMAL)
|
|
if(alg_name == "ElGamal")
|
|
return new ElGamal_PrivateKey(alg_id, key_bits, rng);
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_ECDSA)
|
|
if(alg_name == "ECDSA")
|
|
return new ECDSA_PrivateKey(alg_id, key_bits);
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_GOST_34_10_2001)
|
|
if(alg_name == "GOST-34.10")
|
|
return new GOST_3410_PrivateKey(alg_id, key_bits);
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_ECDH)
|
|
if(alg_name == "ECDH")
|
|
return new ECDH_PrivateKey(alg_id, key_bits);
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
}
|
|
/*
|
|
* PK Key Types
|
|
* (C) 1999-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* Default OID access
|
|
*/
|
|
OID Public_Key::get_oid() const
|
|
{
|
|
try {
|
|
return OIDS::lookup(algo_name());
|
|
}
|
|
catch(Lookup_Error)
|
|
{
|
|
throw Lookup_Error("PK algo " + algo_name() + " has no defined OIDs");
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Run checks on a loaded public key
|
|
*/
|
|
void Public_Key::load_check(RandomNumberGenerator& rng) const
|
|
{
|
|
if(!check_key(rng, BOTAN_PUBLIC_KEY_STRONG_CHECKS_ON_LOAD))
|
|
throw Invalid_Argument(algo_name() + ": Invalid public key");
|
|
}
|
|
|
|
/*
|
|
* Run checks on a loaded private key
|
|
*/
|
|
void Private_Key::load_check(RandomNumberGenerator& rng) const
|
|
{
|
|
if(!check_key(rng, BOTAN_PRIVATE_KEY_STRONG_CHECKS_ON_LOAD))
|
|
throw Invalid_Argument(algo_name() + ": Invalid private key");
|
|
}
|
|
|
|
/*
|
|
* Run checks on a generated private key
|
|
*/
|
|
void Private_Key::gen_check(RandomNumberGenerator& rng) const
|
|
{
|
|
if(!check_key(rng, BOTAN_PRIVATE_KEY_STRONG_CHECKS_ON_GENERATE))
|
|
throw Self_Test_Failure(algo_name() + " private key generation failed");
|
|
}
|
|
|
|
}
|
|
/*
|
|
* PKCS #8
|
|
* (C) 1999-2010 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
#include <memory>
|
|
|
|
namespace Botan {
|
|
|
|
namespace PKCS8 {
|
|
|
|
namespace {
|
|
|
|
/*
|
|
* Get info from an EncryptedPrivateKeyInfo
|
|
*/
|
|
SecureVector<byte> PKCS8_extract(DataSource& source,
|
|
AlgorithmIdentifier& pbe_alg_id)
|
|
{
|
|
SecureVector<byte> key_data;
|
|
|
|
BER_Decoder(source)
|
|
.start_cons(SEQUENCE)
|
|
.decode(pbe_alg_id)
|
|
.decode(key_data, OCTET_STRING)
|
|
.verify_end();
|
|
|
|
return key_data;
|
|
}
|
|
|
|
/*
|
|
* PEM decode and/or decrypt a private key
|
|
*/
|
|
SecureVector<byte> PKCS8_decode(DataSource& source, const User_Interface& ui,
|
|
AlgorithmIdentifier& pk_alg_id)
|
|
{
|
|
AlgorithmIdentifier pbe_alg_id;
|
|
SecureVector<byte> key_data, key;
|
|
bool is_encrypted = true;
|
|
|
|
try {
|
|
if(ASN1::maybe_BER(source) && !PEM_Code::matches(source))
|
|
key_data = PKCS8_extract(source, pbe_alg_id);
|
|
else
|
|
{
|
|
std::string label;
|
|
key_data = PEM_Code::decode(source, label);
|
|
if(label == "PRIVATE KEY")
|
|
is_encrypted = false;
|
|
else if(label == "ENCRYPTED PRIVATE KEY")
|
|
{
|
|
DataSource_Memory key_source(key_data);
|
|
key_data = PKCS8_extract(key_source, pbe_alg_id);
|
|
}
|
|
else
|
|
throw PKCS8_Exception("Unknown PEM label " + label);
|
|
}
|
|
|
|
if(key_data.empty())
|
|
throw PKCS8_Exception("No key data found");
|
|
}
|
|
catch(Decoding_Error)
|
|
{
|
|
throw Decoding_Error("PKCS #8 private key decoding failed");
|
|
}
|
|
|
|
if(!is_encrypted)
|
|
key = key_data;
|
|
|
|
const size_t MAX_TRIES = 3;
|
|
|
|
size_t tries = 0;
|
|
while(true)
|
|
{
|
|
try {
|
|
if(MAX_TRIES && tries >= MAX_TRIES)
|
|
break;
|
|
|
|
if(is_encrypted)
|
|
{
|
|
DataSource_Memory params(pbe_alg_id.parameters);
|
|
std::unique_ptr<PBE> pbe(get_pbe(pbe_alg_id.oid, params));
|
|
|
|
User_Interface::UI_Result result = User_Interface::OK;
|
|
const std::string passphrase =
|
|
ui.get_passphrase("PKCS #8 private key", source.id(), result);
|
|
|
|
if(result == User_Interface::CANCEL_ACTION)
|
|
break;
|
|
|
|
pbe->set_key(passphrase);
|
|
Pipe decryptor(pbe.release());
|
|
|
|
decryptor.process_msg(key_data);
|
|
key = decryptor.read_all();
|
|
}
|
|
|
|
BER_Decoder(key)
|
|
.start_cons(SEQUENCE)
|
|
.decode_and_check<size_t>(0, "Unknown PKCS #8 version number")
|
|
.decode(pk_alg_id)
|
|
.decode(key, OCTET_STRING)
|
|
.discard_remaining()
|
|
.end_cons();
|
|
|
|
break;
|
|
}
|
|
catch(Decoding_Error)
|
|
{
|
|
++tries;
|
|
}
|
|
}
|
|
|
|
if(key.empty())
|
|
throw Decoding_Error("PKCS #8 private key decoding failed");
|
|
return key;
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
* BER encode a PKCS #8 private key, unencrypted
|
|
*/
|
|
SecureVector<byte> BER_encode(const Private_Key& key)
|
|
{
|
|
const size_t PKCS8_VERSION = 0;
|
|
|
|
return DER_Encoder()
|
|
.start_cons(SEQUENCE)
|
|
.encode(PKCS8_VERSION)
|
|
.encode(key.pkcs8_algorithm_identifier())
|
|
.encode(key.pkcs8_private_key(), OCTET_STRING)
|
|
.end_cons()
|
|
.get_contents();
|
|
}
|
|
|
|
/*
|
|
* PEM encode a PKCS #8 private key, unencrypted
|
|
*/
|
|
std::string PEM_encode(const Private_Key& key)
|
|
{
|
|
return PEM_Code::encode(PKCS8::BER_encode(key), "PRIVATE KEY");
|
|
}
|
|
|
|
/*
|
|
* BER encode a PKCS #8 private key, encrypted
|
|
*/
|
|
SecureVector<byte> BER_encode(const Private_Key& key,
|
|
RandomNumberGenerator& rng,
|
|
const std::string& pass,
|
|
const std::string& pbe_algo)
|
|
{
|
|
const std::string DEFAULT_PBE = "PBE-PKCS5v20(SHA-1,AES-256/CBC)";
|
|
|
|
std::unique_ptr<PBE> pbe(get_pbe(((pbe_algo != "") ? pbe_algo : DEFAULT_PBE)));
|
|
|
|
pbe->new_params(rng);
|
|
pbe->set_key(pass);
|
|
|
|
AlgorithmIdentifier pbe_algid(pbe->get_oid(), pbe->encode_params());
|
|
|
|
Pipe key_encrytor(pbe.release());
|
|
key_encrytor.process_msg(PKCS8::BER_encode(key));
|
|
|
|
return DER_Encoder()
|
|
.start_cons(SEQUENCE)
|
|
.encode(pbe_algid)
|
|
.encode(key_encrytor.read_all(), OCTET_STRING)
|
|
.end_cons()
|
|
.get_contents();
|
|
}
|
|
|
|
/*
|
|
* PEM encode a PKCS #8 private key, encrypted
|
|
*/
|
|
std::string PEM_encode(const Private_Key& key,
|
|
RandomNumberGenerator& rng,
|
|
const std::string& pass,
|
|
const std::string& pbe_algo)
|
|
{
|
|
if(pass == "")
|
|
return PEM_encode(key);
|
|
|
|
return PEM_Code::encode(PKCS8::BER_encode(key, rng, pass, pbe_algo),
|
|
"ENCRYPTED PRIVATE KEY");
|
|
}
|
|
|
|
/*
|
|
* Extract a private key and return it
|
|
*/
|
|
Private_Key* load_key(DataSource& source,
|
|
RandomNumberGenerator& rng,
|
|
const User_Interface& ui)
|
|
{
|
|
AlgorithmIdentifier alg_id;
|
|
SecureVector<byte> pkcs8_key = PKCS8_decode(source, ui, alg_id);
|
|
|
|
const std::string alg_name = OIDS::lookup(alg_id.oid);
|
|
if(alg_name == "" || alg_name == alg_id.oid.as_string())
|
|
throw PKCS8_Exception("Unknown algorithm OID: " +
|
|
alg_id.oid.as_string());
|
|
|
|
return make_private_key(alg_id, pkcs8_key, rng);
|
|
}
|
|
|
|
/*
|
|
* Extract a private key and return it
|
|
*/
|
|
Private_Key* load_key(const std::string& fsname,
|
|
RandomNumberGenerator& rng,
|
|
const User_Interface& ui)
|
|
{
|
|
DataSource_Stream source(fsname, true);
|
|
return PKCS8::load_key(source, rng, ui);
|
|
}
|
|
|
|
/*
|
|
* Extract a private key and return it
|
|
*/
|
|
Private_Key* load_key(DataSource& source,
|
|
RandomNumberGenerator& rng,
|
|
const std::string& pass)
|
|
{
|
|
return PKCS8::load_key(source, rng, User_Interface(pass));
|
|
}
|
|
|
|
/*
|
|
* Extract a private key and return it
|
|
*/
|
|
Private_Key* load_key(const std::string& fsname,
|
|
RandomNumberGenerator& rng,
|
|
const std::string& pass)
|
|
{
|
|
return PKCS8::load_key(fsname, rng, User_Interface(pass));
|
|
}
|
|
|
|
/*
|
|
* Make a copy of this private key
|
|
*/
|
|
Private_Key* copy_key(const Private_Key& key,
|
|
RandomNumberGenerator& rng)
|
|
{
|
|
DataSource_Memory source(PEM_encode(key));
|
|
return PKCS8::load_key(source, rng);
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
/*
|
|
* Public Key Base
|
|
* (C) 1999-2010 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
#include <memory>
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* PK_Encryptor_EME Constructor
|
|
*/
|
|
PK_Encryptor_EME::PK_Encryptor_EME(const Public_Key& key,
|
|
const std::string& eme_name)
|
|
{
|
|
Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory());
|
|
|
|
op = 0;
|
|
|
|
while(const Engine* engine = i.next())
|
|
{
|
|
op = engine->get_encryption_op(key);
|
|
if(op)
|
|
break;
|
|
}
|
|
|
|
if(!op)
|
|
throw Lookup_Error("PK_Encryptor_EME: No working engine for " +
|
|
key.algo_name());
|
|
|
|
eme = (eme_name == "Raw") ? 0 : get_eme(eme_name);
|
|
}
|
|
|
|
/*
|
|
* Encrypt a message
|
|
*/
|
|
SecureVector<byte>
|
|
PK_Encryptor_EME::enc(const byte in[],
|
|
size_t length,
|
|
RandomNumberGenerator& rng) const
|
|
{
|
|
if(eme)
|
|
{
|
|
SecureVector<byte> encoded =
|
|
eme->encode(in, length, op->max_input_bits(), rng);
|
|
|
|
if(8*(encoded.size() - 1) + high_bit(encoded[0]) > op->max_input_bits())
|
|
throw Invalid_Argument("PK_Encryptor_EME: Input is too large");
|
|
|
|
return op->encrypt(&encoded[0], encoded.size(), rng);
|
|
}
|
|
else
|
|
{
|
|
if(8*(length - 1) + high_bit(in[0]) > op->max_input_bits())
|
|
throw Invalid_Argument("PK_Encryptor_EME: Input is too large");
|
|
|
|
return op->encrypt(&in[0], length, rng);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Return the max size, in bytes, of a message
|
|
*/
|
|
size_t PK_Encryptor_EME::maximum_input_size() const
|
|
{
|
|
if(!eme)
|
|
return (op->max_input_bits() / 8);
|
|
else
|
|
return eme->maximum_input_size(op->max_input_bits());
|
|
}
|
|
|
|
/*
|
|
* PK_Decryptor_EME Constructor
|
|
*/
|
|
PK_Decryptor_EME::PK_Decryptor_EME(const Private_Key& key,
|
|
const std::string& eme_name)
|
|
{
|
|
Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory());
|
|
|
|
op = 0;
|
|
|
|
while(const Engine* engine = i.next())
|
|
{
|
|
op = engine->get_decryption_op(key);
|
|
if(op)
|
|
break;
|
|
}
|
|
|
|
if(!op)
|
|
throw Lookup_Error("PK_Decryptor_EME: No working engine for " +
|
|
key.algo_name());
|
|
|
|
eme = (eme_name == "Raw") ? 0 : get_eme(eme_name);
|
|
}
|
|
|
|
/*
|
|
* Decrypt a message
|
|
*/
|
|
SecureVector<byte> PK_Decryptor_EME::dec(const byte msg[],
|
|
size_t length) const
|
|
{
|
|
try {
|
|
SecureVector<byte> decrypted = op->decrypt(msg, length);
|
|
if(eme)
|
|
return eme->decode(decrypted, op->max_input_bits());
|
|
else
|
|
return decrypted;
|
|
}
|
|
catch(Invalid_Argument)
|
|
{
|
|
throw Decoding_Error("PK_Decryptor_EME: Input is invalid");
|
|
}
|
|
}
|
|
|
|
/*
|
|
* PK_Signer Constructor
|
|
*/
|
|
PK_Signer::PK_Signer(const Private_Key& key,
|
|
const std::string& emsa_name,
|
|
Signature_Format format,
|
|
Fault_Protection prot)
|
|
{
|
|
Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory());
|
|
|
|
op = 0;
|
|
verify_op = 0;
|
|
|
|
while(const Engine* engine = i.next())
|
|
{
|
|
if(!op)
|
|
op = engine->get_signature_op(key);
|
|
|
|
if(!verify_op && prot == ENABLE_FAULT_PROTECTION)
|
|
verify_op = engine->get_verify_op(key);
|
|
|
|
if(op && (verify_op || prot == DISABLE_FAULT_PROTECTION))
|
|
break;
|
|
}
|
|
|
|
if(!op || (!verify_op && prot == ENABLE_FAULT_PROTECTION))
|
|
throw Lookup_Error("PK_Signer: No working engine for " +
|
|
key.algo_name());
|
|
|
|
emsa = get_emsa(emsa_name);
|
|
sig_format = format;
|
|
}
|
|
|
|
/*
|
|
* Sign a message
|
|
*/
|
|
SecureVector<byte> PK_Signer::sign_message(const byte msg[], size_t length,
|
|
RandomNumberGenerator& rng)
|
|
{
|
|
update(msg, length);
|
|
return signature(rng);
|
|
}
|
|
|
|
/*
|
|
* Add more to the message to be signed
|
|
*/
|
|
void PK_Signer::update(const byte in[], size_t length)
|
|
{
|
|
emsa->update(in, length);
|
|
}
|
|
|
|
/*
|
|
* Check the signature we just created, to help prevent fault attacks
|
|
*/
|
|
bool PK_Signer::self_test_signature(const MemoryRegion<byte>& msg,
|
|
const MemoryRegion<byte>& sig) const
|
|
{
|
|
if(!verify_op)
|
|
return true; // checking disabled, assume ok
|
|
|
|
if(verify_op->with_recovery())
|
|
{
|
|
SecureVector<byte> recovered =
|
|
verify_op->verify_mr(&sig[0], sig.size());
|
|
|
|
if(msg.size() > recovered.size())
|
|
{
|
|
size_t extra_0s = msg.size() - recovered.size();
|
|
|
|
for(size_t i = 0; i != extra_0s; ++i)
|
|
if(msg[i] != 0)
|
|
return false;
|
|
|
|
return same_mem(&msg[extra_0s], &recovered[0], recovered.size());
|
|
}
|
|
|
|
return (recovered == msg);
|
|
}
|
|
else
|
|
return verify_op->verify(&msg[0], msg.size(),
|
|
&sig[0], sig.size());
|
|
}
|
|
|
|
/*
|
|
* Create a signature
|
|
*/
|
|
SecureVector<byte> PK_Signer::signature(RandomNumberGenerator& rng)
|
|
{
|
|
SecureVector<byte> encoded = emsa->encoding_of(emsa->raw_data(),
|
|
op->max_input_bits(),
|
|
rng);
|
|
|
|
SecureVector<byte> plain_sig = op->sign(&encoded[0], encoded.size(), rng);
|
|
|
|
BOTAN_ASSERT(self_test_signature(encoded, plain_sig),
|
|
"PK_Signer consistency check failed");
|
|
|
|
if(op->message_parts() == 1 || sig_format == IEEE_1363)
|
|
return plain_sig;
|
|
|
|
if(sig_format == DER_SEQUENCE)
|
|
{
|
|
if(plain_sig.size() % op->message_parts())
|
|
throw Encoding_Error("PK_Signer: strange signature size found");
|
|
const size_t SIZE_OF_PART = plain_sig.size() / op->message_parts();
|
|
|
|
std::vector<BigInt> sig_parts(op->message_parts());
|
|
for(size_t j = 0; j != sig_parts.size(); ++j)
|
|
sig_parts[j].binary_decode(&plain_sig[SIZE_OF_PART*j], SIZE_OF_PART);
|
|
|
|
return DER_Encoder()
|
|
.start_cons(SEQUENCE)
|
|
.encode_list(sig_parts)
|
|
.end_cons()
|
|
.get_contents();
|
|
}
|
|
else
|
|
throw Encoding_Error("PK_Signer: Unknown signature format " +
|
|
to_string(sig_format));
|
|
}
|
|
|
|
/*
|
|
* PK_Verifier Constructor
|
|
*/
|
|
PK_Verifier::PK_Verifier(const Public_Key& key,
|
|
const std::string& emsa_name,
|
|
Signature_Format format)
|
|
{
|
|
Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory());
|
|
|
|
op = 0;
|
|
|
|
while(const Engine* engine = i.next())
|
|
{
|
|
op = engine->get_verify_op(key);
|
|
if(op)
|
|
break;
|
|
}
|
|
|
|
if(!op)
|
|
throw Lookup_Error("PK_Verifier: No working engine for " +
|
|
key.algo_name());
|
|
|
|
emsa = get_emsa(emsa_name);
|
|
sig_format = format;
|
|
}
|
|
|
|
/*
|
|
* Set the signature format
|
|
*/
|
|
void PK_Verifier::set_input_format(Signature_Format format)
|
|
{
|
|
if(op->message_parts() == 1 && format != IEEE_1363)
|
|
throw Invalid_State("PK_Verifier: This algorithm always uses IEEE 1363");
|
|
sig_format = format;
|
|
}
|
|
|
|
/*
|
|
* Verify a message
|
|
*/
|
|
bool PK_Verifier::verify_message(const byte msg[], size_t msg_length,
|
|
const byte sig[], size_t sig_length)
|
|
{
|
|
update(msg, msg_length);
|
|
return check_signature(sig, sig_length);
|
|
}
|
|
|
|
/*
|
|
* Append to the message
|
|
*/
|
|
void PK_Verifier::update(const byte in[], size_t length)
|
|
{
|
|
emsa->update(in, length);
|
|
}
|
|
|
|
/*
|
|
* Check a signature
|
|
*/
|
|
bool PK_Verifier::check_signature(const byte sig[], size_t length)
|
|
{
|
|
try {
|
|
if(sig_format == IEEE_1363)
|
|
return validate_signature(emsa->raw_data(), sig, length);
|
|
else if(sig_format == DER_SEQUENCE)
|
|
{
|
|
BER_Decoder decoder(sig, length);
|
|
BER_Decoder ber_sig = decoder.start_cons(SEQUENCE);
|
|
|
|
size_t count = 0;
|
|
SecureVector<byte> real_sig;
|
|
while(ber_sig.more_items())
|
|
{
|
|
BigInt sig_part;
|
|
ber_sig.decode(sig_part);
|
|
real_sig += BigInt::encode_1363(sig_part, op->message_part_size());
|
|
++count;
|
|
}
|
|
|
|
if(count != op->message_parts())
|
|
throw Decoding_Error("PK_Verifier: signature size invalid");
|
|
|
|
return validate_signature(emsa->raw_data(),
|
|
&real_sig[0], real_sig.size());
|
|
}
|
|
else
|
|
throw Decoding_Error("PK_Verifier: Unknown signature format " +
|
|
to_string(sig_format));
|
|
}
|
|
catch(Invalid_Argument) { return false; }
|
|
}
|
|
|
|
/*
|
|
* Verify a signature
|
|
*/
|
|
bool PK_Verifier::validate_signature(const MemoryRegion<byte>& msg,
|
|
const byte sig[], size_t sig_len)
|
|
{
|
|
if(op->with_recovery())
|
|
{
|
|
SecureVector<byte> output_of_key = op->verify_mr(sig, sig_len);
|
|
return emsa->verify(output_of_key, msg, op->max_input_bits());
|
|
}
|
|
else
|
|
{
|
|
Null_RNG rng;
|
|
|
|
SecureVector<byte> encoded =
|
|
emsa->encoding_of(msg, op->max_input_bits(), rng);
|
|
|
|
return op->verify(&encoded[0], encoded.size(), sig, sig_len);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* PK_Key_Agreement Constructor
|
|
*/
|
|
PK_Key_Agreement::PK_Key_Agreement(const PK_Key_Agreement_Key& key,
|
|
const std::string& kdf_name)
|
|
{
|
|
Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory());
|
|
|
|
op = 0;
|
|
|
|
while(const Engine* engine = i.next())
|
|
{
|
|
op = engine->get_key_agreement_op(key);
|
|
if(op)
|
|
break;
|
|
}
|
|
|
|
if(!op)
|
|
throw Lookup_Error("PK_Key_Agreement: No working engine for " +
|
|
key.algo_name());
|
|
|
|
kdf = (kdf_name == "Raw") ? 0 : get_kdf(kdf_name);
|
|
}
|
|
|
|
SymmetricKey PK_Key_Agreement::derive_key(size_t key_len, const byte in[],
|
|
size_t in_len, const byte params[],
|
|
size_t params_len) const
|
|
{
|
|
SecureVector<byte> z = op->agree(in, in_len);
|
|
|
|
if(!kdf)
|
|
return z;
|
|
|
|
return kdf->derive_key(key_len, z, params, params_len);
|
|
}
|
|
|
|
}
|
|
/*
|
|
* KeyUsage
|
|
* (C) 1999-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
namespace BER {
|
|
|
|
/*
|
|
* Decode a BER encoded KeyUsage
|
|
*/
|
|
void decode(BER_Decoder& source, Key_Constraints& key_usage)
|
|
{
|
|
BER_Object obj = source.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");
|
|
|
|
const byte mask = (0xFF << obj.value[0]);
|
|
obj.value[obj.value.size()-1] &= mask;
|
|
|
|
u16bit usage = 0;
|
|
for(size_t j = 1; j != obj.value.size(); ++j)
|
|
usage = (obj.value[j] << 8) | usage;
|
|
|
|
key_usage = Key_Constraints(usage);
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
/*
|
|
* RSA
|
|
* (C) 1999-2010 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* Create a RSA private key
|
|
*/
|
|
RSA_PrivateKey::RSA_PrivateKey(RandomNumberGenerator& rng,
|
|
size_t bits, size_t exp)
|
|
{
|
|
if(bits < 512)
|
|
throw Invalid_Argument(algo_name() + ": Can't make a key that is only " +
|
|
to_string(bits) + " bits long");
|
|
if(exp < 3 || exp % 2 == 0)
|
|
throw Invalid_Argument(algo_name() + ": Invalid encryption exponent");
|
|
|
|
e = exp;
|
|
|
|
do
|
|
{
|
|
p = random_prime(rng, (bits + 1) / 2, e);
|
|
q = random_prime(rng, bits - p.bits(), e);
|
|
n = p * q;
|
|
} while(n.bits() != bits);
|
|
|
|
d = inverse_mod(e, lcm(p - 1, q - 1));
|
|
d1 = d % (p - 1);
|
|
d2 = d % (q - 1);
|
|
c = inverse_mod(q, p);
|
|
|
|
gen_check(rng);
|
|
}
|
|
|
|
/*
|
|
* Check Private RSA Parameters
|
|
*/
|
|
bool RSA_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const
|
|
{
|
|
if(!IF_Scheme_PrivateKey::check_key(rng, strong))
|
|
return false;
|
|
|
|
if(!strong)
|
|
return true;
|
|
|
|
if((e * d) % lcm(p - 1, q - 1) != 1)
|
|
return false;
|
|
|
|
return KeyPair::signature_consistency_check(rng, *this, "EMSA4(SHA-1)");
|
|
}
|
|
|
|
RSA_Private_Operation::RSA_Private_Operation(const RSA_PrivateKey& rsa) :
|
|
n(rsa.get_n()),
|
|
q(rsa.get_q()),
|
|
c(rsa.get_c()),
|
|
powermod_e_n(rsa.get_e(), rsa.get_n()),
|
|
powermod_d1_p(rsa.get_d1(), rsa.get_p()),
|
|
powermod_d2_q(rsa.get_d2(), rsa.get_q()),
|
|
mod_p(rsa.get_p())
|
|
{
|
|
BigInt k(global_state().global_rng(), n.bits() - 1);
|
|
blinder = Blinder(powermod_e_n(k), inverse_mod(k, n), n);
|
|
}
|
|
|
|
BigInt RSA_Private_Operation::private_op(const BigInt& m) const
|
|
{
|
|
if(m >= n)
|
|
throw Invalid_Argument("RSA private op - input is too large");
|
|
|
|
BigInt j1 = powermod_d1_p(m);
|
|
BigInt j2 = powermod_d2_q(m);
|
|
|
|
j1 = mod_p.reduce(sub_mul(j1, j2, c));
|
|
|
|
return mul_add(j1, q, j2);
|
|
}
|
|
|
|
SecureVector<byte>
|
|
RSA_Private_Operation::sign(const byte msg[], size_t msg_len,
|
|
RandomNumberGenerator&)
|
|
{
|
|
/* We don't check signatures against powermod_e_n here because
|
|
PK_Signer checks verification consistency for all signature
|
|
algorithms.
|
|
*/
|
|
|
|
BigInt m(msg, msg_len);
|
|
BigInt x = blinder.unblind(private_op(blinder.blind(m)));
|
|
return BigInt::encode_1363(x, n.bytes());
|
|
}
|
|
|
|
/*
|
|
* RSA Decryption Operation
|
|
*/
|
|
SecureVector<byte>
|
|
RSA_Private_Operation::decrypt(const byte msg[], size_t msg_len)
|
|
{
|
|
BigInt m(msg, msg_len);
|
|
BigInt x = blinder.unblind(private_op(blinder.blind(m)));
|
|
|
|
BOTAN_ASSERT(m == powermod_e_n(x),
|
|
"RSA private op failed consistency check");
|
|
|
|
return BigInt::encode(x);
|
|
}
|
|
|
|
}
|
|
/*
|
|
* Rabin-Williams
|
|
* (C) 1999-2008 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
#include <algorithm>
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* Create a Rabin-Williams private key
|
|
*/
|
|
RW_PrivateKey::RW_PrivateKey(RandomNumberGenerator& rng,
|
|
size_t bits, size_t exp)
|
|
{
|
|
if(bits < 512)
|
|
throw Invalid_Argument(algo_name() + ": Can't make a key that is only " +
|
|
to_string(bits) + " bits long");
|
|
if(exp < 2 || exp % 2 == 1)
|
|
throw Invalid_Argument(algo_name() + ": Invalid encryption exponent");
|
|
|
|
e = exp;
|
|
|
|
do
|
|
{
|
|
p = random_prime(rng, (bits + 1) / 2, e / 2, 3, 4);
|
|
q = random_prime(rng, bits - p.bits(), e / 2, ((p % 8 == 3) ? 7 : 3), 8);
|
|
n = p * q;
|
|
} while(n.bits() != bits);
|
|
|
|
d = inverse_mod(e, lcm(p - 1, q - 1) >> 1);
|
|
d1 = d % (p - 1);
|
|
d2 = d % (q - 1);
|
|
c = inverse_mod(q, p);
|
|
|
|
gen_check(rng);
|
|
}
|
|
|
|
/*
|
|
* Check Private Rabin-Williams Parameters
|
|
*/
|
|
bool RW_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const
|
|
{
|
|
if(!IF_Scheme_PrivateKey::check_key(rng, strong))
|
|
return false;
|
|
|
|
if(!strong)
|
|
return true;
|
|
|
|
if((e * d) % (lcm(p - 1, q - 1) / 2) != 1)
|
|
return false;
|
|
|
|
return KeyPair::signature_consistency_check(rng, *this, "EMSA2(SHA-1)");
|
|
}
|
|
|
|
RW_Signature_Operation::RW_Signature_Operation(const RW_PrivateKey& rw) :
|
|
n(rw.get_n()),
|
|
e(rw.get_e()),
|
|
q(rw.get_q()),
|
|
c(rw.get_c()),
|
|
powermod_d1_p(rw.get_d1(), rw.get_p()),
|
|
powermod_d2_q(rw.get_d2(), rw.get_q()),
|
|
mod_p(rw.get_p())
|
|
{
|
|
}
|
|
|
|
SecureVector<byte>
|
|
RW_Signature_Operation::sign(const byte msg[], size_t msg_len,
|
|
RandomNumberGenerator& rng)
|
|
{
|
|
if(!blinder.initialized())
|
|
{
|
|
BigInt k(rng, n.bits() / 2);
|
|
blinder = Blinder(power_mod(k, e, n), inverse_mod(k, n), n);
|
|
}
|
|
|
|
BigInt i(msg, msg_len);
|
|
|
|
if(i >= n || i % 16 != 12)
|
|
throw Invalid_Argument("Rabin-Williams: invalid input");
|
|
|
|
if(jacobi(i, n) != 1)
|
|
i >>= 1;
|
|
|
|
i = blinder.blind(i);
|
|
|
|
BigInt j1 = powermod_d1_p(i);
|
|
BigInt j2 = powermod_d2_q(i);
|
|
j1 = mod_p.reduce(sub_mul(j1, j2, c));
|
|
|
|
BigInt r = blinder.unblind(mul_add(j1, q, j2));
|
|
|
|
r = std::min(r, n - r);
|
|
|
|
return BigInt::encode_1363(r, n.bytes());
|
|
}
|
|
|
|
SecureVector<byte>
|
|
RW_Verification_Operation::verify_mr(const byte msg[], size_t msg_len)
|
|
{
|
|
BigInt m(msg, msg_len);
|
|
|
|
if((m > (n >> 1)) || m.is_negative())
|
|
throw Invalid_Argument("RW signature verification: m > n / 2 || m < 0");
|
|
|
|
BigInt r = powermod_e_n(m);
|
|
if(r % 16 == 12)
|
|
return BigInt::encode(r);
|
|
if(r % 8 == 6)
|
|
return BigInt::encode(2*r);
|
|
|
|
r = n - r;
|
|
if(r % 16 == 12)
|
|
return BigInt::encode(r);
|
|
if(r % 8 == 6)
|
|
return BigInt::encode(2*r);
|
|
|
|
throw Invalid_Argument("RW signature verification: Invalid signature");
|
|
}
|
|
|
|
}
|
|
/*
|
|
* Public Key Work Factor Functions
|
|
* (C) 1999-2007,2012 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
#include <algorithm>
|
|
#include <cmath>
|
|
|
|
namespace Botan {
|
|
|
|
size_t dl_work_factor(size_t bits)
|
|
{
|
|
/*
|
|
Based on GNFS work factors. Constant is 1.43 times the asymptotic
|
|
value; I'm not sure but I believe that came from a paper on 'real
|
|
world' runtimes, but I don't remember where now.
|
|
|
|
Sample return values:
|
|
|512| -> 64
|
|
|1024| -> 86
|
|
|1536| -> 102
|
|
|2048| -> 116
|
|
|3072| -> 138
|
|
|4096| -> 155
|
|
|8192| -> 206
|
|
|
|
For DL algos, we use an exponent of twice the size of the result;
|
|
the assumption is that an arbitrary discrete log on a group of size
|
|
bits would take about 2^n effort, and thus using an exponent of
|
|
size 2^(2*n) implies that all available attacks are about as easy
|
|
(as e.g Pollard's kangaroo algorithm can compute the DL in sqrt(x)
|
|
operations) while minimizing the exponent size for performance
|
|
reasons.
|
|
*/
|
|
|
|
const size_t MIN_WORKFACTOR = 64;
|
|
|
|
// approximates natural logarithm of p
|
|
const double log_p = bits / 1.4426;
|
|
|
|
const double strength =
|
|
2.76 * std::pow(log_p, 1.0/3.0) * std::pow(std::log(log_p), 2.0/3.0);
|
|
|
|
return std::max(static_cast<size_t>(strength), MIN_WORKFACTOR);
|
|
}
|
|
|
|
}
|
|
/*
|
|
* X.509 Public Key
|
|
* (C) 1999-2010 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
#include <memory>
|
|
|
|
namespace Botan {
|
|
|
|
namespace X509 {
|
|
|
|
MemoryVector<byte> BER_encode(const Public_Key& key)
|
|
{
|
|
return DER_Encoder()
|
|
.start_cons(SEQUENCE)
|
|
.encode(key.algorithm_identifier())
|
|
.encode(key.x509_subject_public_key(), BIT_STRING)
|
|
.end_cons()
|
|
.get_contents();
|
|
}
|
|
|
|
/*
|
|
* PEM encode a X.509 public key
|
|
*/
|
|
std::string PEM_encode(const Public_Key& key)
|
|
{
|
|
return PEM_Code::encode(X509::BER_encode(key),
|
|
"PUBLIC KEY");
|
|
}
|
|
|
|
/*
|
|
* Extract a public key and return it
|
|
*/
|
|
Public_Key* load_key(DataSource& source)
|
|
{
|
|
try {
|
|
AlgorithmIdentifier alg_id;
|
|
MemoryVector<byte> key_bits;
|
|
|
|
if(ASN1::maybe_BER(source) && !PEM_Code::matches(source))
|
|
{
|
|
BER_Decoder(source)
|
|
.start_cons(SEQUENCE)
|
|
.decode(alg_id)
|
|
.decode(key_bits, BIT_STRING)
|
|
.verify_end()
|
|
.end_cons();
|
|
}
|
|
else
|
|
{
|
|
DataSource_Memory ber(
|
|
PEM_Code::decode_check_label(source, "PUBLIC KEY")
|
|
);
|
|
|
|
BER_Decoder(ber)
|
|
.start_cons(SEQUENCE)
|
|
.decode(alg_id)
|
|
.decode(key_bits, BIT_STRING)
|
|
.verify_end()
|
|
.end_cons();
|
|
}
|
|
|
|
if(key_bits.empty())
|
|
throw Decoding_Error("X.509 public key decoding failed");
|
|
|
|
return make_public_key(alg_id, key_bits);
|
|
}
|
|
catch(Decoding_Error)
|
|
{
|
|
throw Decoding_Error("X.509 public key decoding failed");
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Extract a public key and return it
|
|
*/
|
|
Public_Key* load_key(const std::string& fsname)
|
|
{
|
|
DataSource_Stream source(fsname, true);
|
|
return X509::load_key(source);
|
|
}
|
|
|
|
/*
|
|
* Extract a public key and return it
|
|
*/
|
|
Public_Key* load_key(const MemoryRegion<byte>& mem)
|
|
{
|
|
DataSource_Memory source(mem);
|
|
return X509::load_key(source);
|
|
}
|
|
|
|
/*
|
|
* Make a copy of this public key
|
|
*/
|
|
Public_Key* copy_key(const Public_Key& key)
|
|
{
|
|
DataSource_Memory source(PEM_encode(key));
|
|
return X509::load_key(source);
|
|
}
|
|
|
|
/*
|
|
* Find the allowable key constraints
|
|
*/
|
|
Key_Constraints find_constraints(const Public_Key& pub_key,
|
|
Key_Constraints limits)
|
|
{
|
|
const std::string name = pub_key.algo_name();
|
|
|
|
size_t constraints = 0;
|
|
|
|
if(name == "DH" || name == "ECDH")
|
|
constraints |= KEY_AGREEMENT;
|
|
|
|
if(name == "RSA" || name == "ElGamal")
|
|
constraints |= KEY_ENCIPHERMENT | DATA_ENCIPHERMENT;
|
|
|
|
if(name == "RSA" || name == "RW" || name == "NR" ||
|
|
name == "DSA" || name == "ECDSA")
|
|
constraints |= DIGITAL_SIGNATURE | NON_REPUDIATION;
|
|
|
|
if(limits)
|
|
constraints &= limits;
|
|
|
|
return Key_Constraints(constraints);
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
/*
|
|
* HMAC_RNG
|
|
* (C) 2008-2009 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
#include <algorithm>
|
|
|
|
namespace Botan {
|
|
|
|
namespace {
|
|
|
|
void hmac_prf(MessageAuthenticationCode* prf,
|
|
MemoryRegion<byte>& K,
|
|
u32bit& counter,
|
|
const std::string& label)
|
|
{
|
|
prf->update(K);
|
|
prf->update(label);
|
|
prf->update_be(counter);
|
|
prf->final(&K[0]);
|
|
|
|
++counter;
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
* Generate a buffer of random bytes
|
|
*/
|
|
void HMAC_RNG::randomize(byte out[], size_t length)
|
|
{
|
|
if(!is_seeded())
|
|
throw PRNG_Unseeded(name());
|
|
|
|
/*
|
|
HMAC KDF as described in E-t-E, using a CTXinfo of "rng"
|
|
*/
|
|
while(length)
|
|
{
|
|
hmac_prf(prf, K, counter, "rng");
|
|
|
|
const size_t copied = std::min<size_t>(K.size(), length);
|
|
|
|
copy_mem(out, &K[0], copied);
|
|
out += copied;
|
|
length -= copied;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Poll for entropy and reset the internal keys
|
|
*/
|
|
void HMAC_RNG::reseed(size_t poll_bits)
|
|
{
|
|
/*
|
|
Using the terminology of E-t-E, XTR is the MAC function (normally
|
|
HMAC) seeded with XTS (below) and we form SKM, the key material, by
|
|
fast polling each source, and then slow polling as many as we think
|
|
we need (in the following loop), and feeding all of the poll
|
|
results, along with any optional user input, along with, finally,
|
|
feedback of the current PRK value, into the extractor function.
|
|
*/
|
|
|
|
Entropy_Accumulator_BufferedComputation accum(*extractor, poll_bits);
|
|
|
|
if(!entropy_sources.empty())
|
|
{
|
|
size_t poll_attempt = 0;
|
|
|
|
while(!accum.polling_goal_achieved() && poll_attempt < poll_bits)
|
|
{
|
|
const size_t src_idx = poll_attempt % entropy_sources.size();
|
|
entropy_sources[src_idx]->poll(accum);
|
|
++poll_attempt;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* It is necessary to feed forward poll data. Otherwise, a good poll
|
|
* (collecting a large amount of conditional entropy) followed by a
|
|
* bad one (collecting little) would be unsafe. Do this by
|
|
* generating new PRF outputs using the previous key and feeding
|
|
* them into the extractor function.
|
|
*
|
|
* Cycle the RNG once (CTXinfo="rng"), then generate a new PRF
|
|
* output using the CTXinfo "reseed". Provide these values as input
|
|
* to the extractor function.
|
|
*/
|
|
hmac_prf(prf, K, counter, "rng");
|
|
extractor->update(K); // K is the CTXinfo=rng PRF output
|
|
|
|
hmac_prf(prf, K, counter, "reseed");
|
|
extractor->update(K); // K is the CTXinfo=reseed PRF output
|
|
|
|
/* Now derive the new PRK using everything that has been fed into
|
|
the extractor, and set the PRF key to that */
|
|
prf->set_key(extractor->final());
|
|
|
|
// Now generate a new PRF output to use as the XTS extractor salt
|
|
hmac_prf(prf, K, counter, "xts");
|
|
extractor->set_key(K);
|
|
|
|
// Reset state
|
|
zeroise(K);
|
|
counter = 0;
|
|
user_input_len = 0;
|
|
|
|
/*
|
|
Consider ourselves seeded once we've collected an estimated 128 bits of
|
|
entropy in a single poll.
|
|
*/
|
|
if(seeded == false && accum.bits_collected() >= 128)
|
|
seeded = true;
|
|
}
|
|
|
|
/*
|
|
* Add user-supplied entropy to the extractor input
|
|
*/
|
|
void HMAC_RNG::add_entropy(const byte input[], size_t length)
|
|
{
|
|
const size_t USER_ENTROPY_WATERSHED = 64;
|
|
|
|
extractor->update(input, length);
|
|
user_input_len += length;
|
|
|
|
/*
|
|
* After we've accumulated at least USER_ENTROPY_WATERSHED bytes of
|
|
* user input, reseed. This input will automatically have been
|
|
* included if reseed was called already, as it's just included in
|
|
* the extractor input.
|
|
*/
|
|
if(user_input_len >= USER_ENTROPY_WATERSHED)
|
|
reseed(0);
|
|
}
|
|
|
|
/*
|
|
* Add another entropy source to the list
|
|
*/
|
|
void HMAC_RNG::add_entropy_source(EntropySource* src)
|
|
{
|
|
entropy_sources.push_back(src);
|
|
}
|
|
|
|
/*
|
|
* Clear memory of sensitive data
|
|
*/
|
|
void HMAC_RNG::clear()
|
|
{
|
|
extractor->clear();
|
|
prf->clear();
|
|
zeroise(K);
|
|
counter = 0;
|
|
user_input_len = 0;
|
|
seeded = false;
|
|
}
|
|
|
|
/*
|
|
* Return the name of this type
|
|
*/
|
|
std::string HMAC_RNG::name() const
|
|
{
|
|
return "HMAC_RNG(" + extractor->name() + "," + prf->name() + ")";
|
|
}
|
|
|
|
/*
|
|
* HMAC_RNG Constructor
|
|
*/
|
|
HMAC_RNG::HMAC_RNG(MessageAuthenticationCode* extractor_mac,
|
|
MessageAuthenticationCode* prf_mac) :
|
|
extractor(extractor_mac), prf(prf_mac)
|
|
{
|
|
if(!prf->valid_keylength(extractor->output_length()) ||
|
|
!extractor->valid_keylength(prf->output_length()))
|
|
throw Invalid_Argument("HMAC_RNG: Bad algo combination " +
|
|
extractor->name() + " and " +
|
|
prf->name());
|
|
|
|
// First PRF inputs are all zero, as specified in section 2
|
|
K.resize(prf->output_length());
|
|
|
|
counter = 0;
|
|
user_input_len = 0;
|
|
seeded = false;
|
|
|
|
/*
|
|
Normally we want to feedback PRF output into the input to the
|
|
extractor function to ensure a single bad poll does not damage the
|
|
RNG, but obviously that is meaningless to do on the first poll.
|
|
|
|
We will want to use the PRF before we set the first key (in
|
|
reseed), and it is a pain to keep track if it is set or
|
|
not. Since the first time it doesn't matter anyway, just set the
|
|
PRF key to constant zero: randomize() will not produce output
|
|
unless is_seeded() returns true, and that will only be the case if
|
|
the estimated entropy counter is high enough. That variable is only
|
|
set when a reseeding is performed.
|
|
*/
|
|
MemoryVector<byte> prf_key(extractor->output_length());
|
|
prf->set_key(prf_key);
|
|
|
|
/*
|
|
Use PRF("Botan HMAC_RNG XTS") as the intitial XTS key.
|
|
|
|
This will be used during the first extraction sequence; XTS values
|
|
after this one are generated using the PRF.
|
|
|
|
If I understand the E-t-E paper correctly (specifically Section 4),
|
|
using this fixed extractor key is safe to do.
|
|
*/
|
|
extractor->set_key(prf->process("Botan HMAC_RNG XTS"));
|
|
}
|
|
|
|
/*
|
|
* HMAC_RNG Destructor
|
|
*/
|
|
HMAC_RNG::~HMAC_RNG()
|
|
{
|
|
delete extractor;
|
|
delete prf;
|
|
|
|
std::for_each(entropy_sources.begin(), entropy_sources.end(),
|
|
del_fun<EntropySource>());
|
|
|
|
counter = 0;
|
|
}
|
|
|
|
}
|
|
/*
|
|
* Randpool
|
|
* (C) 1999-2009 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
#include <algorithm>
|
|
|
|
namespace Botan {
|
|
|
|
namespace {
|
|
|
|
/*
|
|
* PRF based on a MAC
|
|
*/
|
|
enum RANDPOOL_PRF_TAG {
|
|
CIPHER_KEY = 0,
|
|
MAC_KEY = 1,
|
|
GEN_OUTPUT = 2
|
|
};
|
|
|
|
}
|
|
|
|
/*
|
|
* Generate a buffer of random bytes
|
|
*/
|
|
void Randpool::randomize(byte out[], size_t length)
|
|
{
|
|
if(!is_seeded())
|
|
throw PRNG_Unseeded(name());
|
|
|
|
update_buffer();
|
|
while(length)
|
|
{
|
|
const size_t copied = std::min<size_t>(length, buffer.size());
|
|
copy_mem(out, &buffer[0], copied);
|
|
out += copied;
|
|
length -= copied;
|
|
update_buffer();
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Refill the output buffer
|
|
*/
|
|
void Randpool::update_buffer()
|
|
{
|
|
for(size_t i = 0; i != counter.size(); ++i)
|
|
if(++counter[i])
|
|
break;
|
|
|
|
mac->update(static_cast<byte>(GEN_OUTPUT));
|
|
mac->update(counter);
|
|
SecureVector<byte> mac_val = mac->final();
|
|
|
|
for(size_t i = 0; i != mac_val.size(); ++i)
|
|
buffer[i % buffer.size()] ^= mac_val[i];
|
|
cipher->encrypt(buffer);
|
|
|
|
if(counter[0] % ITERATIONS_BEFORE_RESEED == 0)
|
|
mix_pool();
|
|
}
|
|
|
|
/*
|
|
* Mix the entropy pool
|
|
*/
|
|
void Randpool::mix_pool()
|
|
{
|
|
const size_t BLOCK_SIZE = cipher->block_size();
|
|
|
|
mac->update(static_cast<byte>(MAC_KEY));
|
|
mac->update(pool);
|
|
mac->set_key(mac->final());
|
|
|
|
mac->update(static_cast<byte>(CIPHER_KEY));
|
|
mac->update(pool);
|
|
cipher->set_key(mac->final());
|
|
|
|
xor_buf(pool, buffer, BLOCK_SIZE);
|
|
cipher->encrypt(pool);
|
|
for(size_t i = 1; i != POOL_BLOCKS; ++i)
|
|
{
|
|
const byte* previous_block = &pool[BLOCK_SIZE*(i-1)];
|
|
byte* this_block = &pool[BLOCK_SIZE*i];
|
|
xor_buf(this_block, previous_block, BLOCK_SIZE);
|
|
cipher->encrypt(this_block);
|
|
}
|
|
|
|
update_buffer();
|
|
}
|
|
|
|
/*
|
|
* Reseed the internal state
|
|
*/
|
|
void Randpool::reseed(size_t poll_bits)
|
|
{
|
|
Entropy_Accumulator_BufferedComputation accum(*mac, poll_bits);
|
|
|
|
if(!entropy_sources.empty())
|
|
{
|
|
size_t poll_attempt = 0;
|
|
|
|
while(!accum.polling_goal_achieved() && poll_attempt < poll_bits)
|
|
{
|
|
entropy_sources[poll_attempt % entropy_sources.size()]->poll(accum);
|
|
++poll_attempt;
|
|
}
|
|
}
|
|
|
|
SecureVector<byte> mac_val = mac->final();
|
|
|
|
xor_buf(pool, mac_val, mac_val.size());
|
|
mix_pool();
|
|
|
|
if(accum.bits_collected() >= poll_bits)
|
|
seeded = true;
|
|
}
|
|
|
|
/*
|
|
* Add user-supplied entropy
|
|
*/
|
|
void Randpool::add_entropy(const byte input[], size_t length)
|
|
{
|
|
SecureVector<byte> mac_val = mac->process(input, length);
|
|
xor_buf(pool, mac_val, mac_val.size());
|
|
mix_pool();
|
|
|
|
if(length)
|
|
seeded = true;
|
|
}
|
|
|
|
/*
|
|
* Add another entropy source to the list
|
|
*/
|
|
void Randpool::add_entropy_source(EntropySource* src)
|
|
{
|
|
entropy_sources.push_back(src);
|
|
}
|
|
|
|
/*
|
|
* Clear memory of sensitive data
|
|
*/
|
|
void Randpool::clear()
|
|
{
|
|
cipher->clear();
|
|
mac->clear();
|
|
zeroise(pool);
|
|
zeroise(buffer);
|
|
zeroise(counter);
|
|
seeded = false;
|
|
}
|
|
|
|
/*
|
|
* Return the name of this type
|
|
*/
|
|
std::string Randpool::name() const
|
|
{
|
|
return "Randpool(" + cipher->name() + "," + mac->name() + ")";
|
|
}
|
|
|
|
/*
|
|
* Randpool Constructor
|
|
*/
|
|
Randpool::Randpool(BlockCipher* cipher_in,
|
|
MessageAuthenticationCode* mac_in,
|
|
size_t pool_blocks,
|
|
size_t iter_before_reseed) :
|
|
ITERATIONS_BEFORE_RESEED(iter_before_reseed),
|
|
POOL_BLOCKS(pool_blocks),
|
|
cipher(cipher_in),
|
|
mac(mac_in)
|
|
{
|
|
const size_t BLOCK_SIZE = cipher->block_size();
|
|
const size_t OUTPUT_LENGTH = mac->output_length();
|
|
|
|
if(OUTPUT_LENGTH < BLOCK_SIZE ||
|
|
!cipher->valid_keylength(OUTPUT_LENGTH) ||
|
|
!mac->valid_keylength(OUTPUT_LENGTH))
|
|
{
|
|
const std::string cipherName = cipher->name();
|
|
const std::string macName = mac->name();
|
|
delete cipher;
|
|
delete mac;
|
|
throw Internal_Error("Randpool: Invalid algorithm combination " +
|
|
cipherName + "/" + macName);
|
|
}
|
|
|
|
buffer.resize(BLOCK_SIZE);
|
|
pool.resize(POOL_BLOCKS * BLOCK_SIZE);
|
|
counter.resize(12);
|
|
seeded = false;
|
|
}
|
|
|
|
/*
|
|
* Randpool Destructor
|
|
*/
|
|
Randpool::~Randpool()
|
|
{
|
|
delete cipher;
|
|
delete mac;
|
|
|
|
std::for_each(entropy_sources.begin(), entropy_sources.end(),
|
|
del_fun<EntropySource>());
|
|
}
|
|
|
|
}
|
|
/*
|
|
* Random Number Generator Base
|
|
* (C) 1999-2008 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
#if defined(BOTAN_HAS_AUTO_SEEDING_RNG)
|
|
#endif
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* Get a single random byte
|
|
*/
|
|
byte RandomNumberGenerator::next_byte()
|
|
{
|
|
byte out;
|
|
this->randomize(&out, 1);
|
|
return out;
|
|
}
|
|
|
|
/*
|
|
* Create and seed a new RNG object
|
|
*/
|
|
RandomNumberGenerator* RandomNumberGenerator::make_rng()
|
|
{
|
|
#if defined(BOTAN_HAS_AUTO_SEEDING_RNG)
|
|
return new AutoSeeded_RNG;
|
|
#endif
|
|
|
|
throw Algorithm_Not_Found("RandomNumberGenerator::make_rng - no RNG found");
|
|
}
|
|
|
|
}
|
|
/*
|
|
* ANSI X9.31 RNG
|
|
* (C) 1999-2009 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
#include <algorithm>
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* Generate a buffer of random bytes
|
|
*/
|
|
void ANSI_X931_RNG::randomize(byte out[], size_t length)
|
|
{
|
|
if(!is_seeded())
|
|
throw PRNG_Unseeded(name());
|
|
|
|
while(length)
|
|
{
|
|
if(position == R.size())
|
|
update_buffer();
|
|
|
|
const size_t copied = std::min<size_t>(length, R.size() - position);
|
|
|
|
copy_mem(out, &R[position], copied);
|
|
out += copied;
|
|
length -= copied;
|
|
position += copied;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Refill the internal state
|
|
*/
|
|
void ANSI_X931_RNG::update_buffer()
|
|
{
|
|
const size_t BLOCK_SIZE = cipher->block_size();
|
|
|
|
SecureVector<byte> DT = prng->random_vec(BLOCK_SIZE);
|
|
cipher->encrypt(DT);
|
|
|
|
xor_buf(&R[0], &V[0], &DT[0], BLOCK_SIZE);
|
|
cipher->encrypt(R);
|
|
|
|
xor_buf(&V[0], &R[0], &DT[0], BLOCK_SIZE);
|
|
cipher->encrypt(V);
|
|
|
|
position = 0;
|
|
}
|
|
|
|
/*
|
|
* Reset V and the cipher key with new values
|
|
*/
|
|
void ANSI_X931_RNG::rekey()
|
|
{
|
|
const size_t BLOCK_SIZE = cipher->block_size();
|
|
|
|
if(prng->is_seeded())
|
|
{
|
|
cipher->set_key(prng->random_vec(cipher->maximum_keylength()));
|
|
|
|
if(V.size() != BLOCK_SIZE)
|
|
V.resize(BLOCK_SIZE);
|
|
prng->randomize(&V[0], V.size());
|
|
|
|
update_buffer();
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Reseed the internal state
|
|
*/
|
|
void ANSI_X931_RNG::reseed(size_t poll_bits)
|
|
{
|
|
prng->reseed(poll_bits);
|
|
rekey();
|
|
}
|
|
|
|
/*
|
|
* Add a entropy source to the underlying PRNG
|
|
*/
|
|
void ANSI_X931_RNG::add_entropy_source(EntropySource* src)
|
|
{
|
|
prng->add_entropy_source(src);
|
|
}
|
|
|
|
/*
|
|
* Add some entropy to the underlying PRNG
|
|
*/
|
|
void ANSI_X931_RNG::add_entropy(const byte input[], size_t length)
|
|
{
|
|
prng->add_entropy(input, length);
|
|
rekey();
|
|
}
|
|
|
|
/*
|
|
* Check if the PRNG is seeded
|
|
*/
|
|
bool ANSI_X931_RNG::is_seeded() const
|
|
{
|
|
return (V.size() > 0);
|
|
}
|
|
|
|
/*
|
|
* Clear memory of sensitive data
|
|
*/
|
|
void ANSI_X931_RNG::clear()
|
|
{
|
|
cipher->clear();
|
|
prng->clear();
|
|
zeroise(R);
|
|
V.clear();
|
|
|
|
position = 0;
|
|
}
|
|
|
|
/*
|
|
* Return the name of this type
|
|
*/
|
|
std::string ANSI_X931_RNG::name() const
|
|
{
|
|
return "X9.31(" + cipher->name() + ")";
|
|
}
|
|
|
|
/*
|
|
* ANSI X931 RNG Constructor
|
|
*/
|
|
ANSI_X931_RNG::ANSI_X931_RNG(BlockCipher* cipher_in,
|
|
RandomNumberGenerator* prng_in)
|
|
{
|
|
if(!prng_in || !cipher_in)
|
|
throw Invalid_Argument("ANSI_X931_RNG constructor: NULL arguments");
|
|
|
|
cipher = cipher_in;
|
|
prng = prng_in;
|
|
|
|
R.resize(cipher->block_size());
|
|
position = 0;
|
|
}
|
|
|
|
/*
|
|
* ANSI X931 RNG Destructor
|
|
*/
|
|
ANSI_X931_RNG::~ANSI_X931_RNG()
|
|
{
|
|
delete cipher;
|
|
delete prng;
|
|
}
|
|
|
|
}
|
|
/*
|
|
* Startup Self Tests
|
|
* (C) 1999-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
namespace {
|
|
|
|
/*
|
|
* Perform a Known Answer Test
|
|
*/
|
|
bool test_filter_kat(Filter* filter,
|
|
const std::string& input,
|
|
const std::string& expected_output)
|
|
{
|
|
Pipe pipe(new Hex_Decoder, filter, new Hex_Encoder);
|
|
pipe.process_msg(input);
|
|
|
|
const std::string output = pipe.read_all_as_string();
|
|
|
|
return (output == expected_output);
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
* Run a set of KATs
|
|
*/
|
|
std::map<std::string, bool>
|
|
algorithm_kat(const SCAN_Name& algo_name,
|
|
const std::map<std::string, std::string>& vars,
|
|
Algorithm_Factory& af)
|
|
{
|
|
const std::string& algo = algo_name.algo_name_and_args();
|
|
|
|
std::vector<std::string> providers = af.providers_of(algo);
|
|
std::map<std::string, bool> all_results;
|
|
|
|
if(providers.empty()) // no providers, nothing to do
|
|
return all_results;
|
|
|
|
const std::string input = search_map(vars, std::string("input"));
|
|
const std::string output = search_map(vars, std::string("output"));
|
|
|
|
SymmetricKey key(search_map(vars, std::string("key")));
|
|
InitializationVector iv(search_map(vars, std::string("iv")));
|
|
|
|
for(size_t i = 0; i != providers.size(); ++i)
|
|
{
|
|
const std::string provider = providers[i];
|
|
|
|
if(const HashFunction* proto =
|
|
af.prototype_hash_function(algo, provider))
|
|
{
|
|
Filter* filt = new Hash_Filter(proto->clone());
|
|
all_results[provider] = test_filter_kat(filt, input, output);
|
|
}
|
|
else if(const MessageAuthenticationCode* proto =
|
|
af.prototype_mac(algo, provider))
|
|
{
|
|
Keyed_Filter* filt = new MAC_Filter(proto->clone(), key);
|
|
all_results[provider] = test_filter_kat(filt, input, output);
|
|
}
|
|
else if(const StreamCipher* proto =
|
|
af.prototype_stream_cipher(algo, provider))
|
|
{
|
|
Keyed_Filter* filt = new StreamCipher_Filter(proto->clone());
|
|
filt->set_key(key);
|
|
filt->set_iv(iv);
|
|
|
|
all_results[provider] = test_filter_kat(filt, input, output);
|
|
}
|
|
else if(const BlockCipher* proto =
|
|
af.prototype_block_cipher(algo, provider))
|
|
{
|
|
Keyed_Filter* enc = get_cipher_mode(proto, ENCRYPTION,
|
|
algo_name.cipher_mode(),
|
|
algo_name.cipher_mode_pad());
|
|
|
|
Keyed_Filter* dec = get_cipher_mode(proto, DECRYPTION,
|
|
algo_name.cipher_mode(),
|
|
algo_name.cipher_mode_pad());
|
|
|
|
if(!enc || !dec)
|
|
{
|
|
delete enc;
|
|
delete dec;
|
|
continue;
|
|
}
|
|
|
|
enc->set_key(key);
|
|
|
|
if(enc->valid_iv_length(iv.length()))
|
|
enc->set_iv(iv);
|
|
else if(!enc->valid_iv_length(0))
|
|
throw Invalid_IV_Length(algo, iv.length());
|
|
|
|
dec->set_key(key);
|
|
|
|
if(dec->valid_iv_length(iv.length()))
|
|
dec->set_iv(iv);
|
|
else if(!dec->valid_iv_length(0))
|
|
throw Invalid_IV_Length(algo, iv.length());
|
|
|
|
bool enc_ok = test_filter_kat(enc, input, output);
|
|
bool dec_ok = test_filter_kat(dec, output, input);
|
|
|
|
all_results[provider] = enc_ok && dec_ok;
|
|
}
|
|
}
|
|
|
|
return all_results;
|
|
}
|
|
|
|
namespace {
|
|
|
|
void verify_results(const std::string& algo,
|
|
const std::map<std::string, bool>& results)
|
|
{
|
|
for(std::map<std::string, bool>::const_iterator i = results.begin();
|
|
i != results.end(); ++i)
|
|
{
|
|
if(!i->second)
|
|
throw Self_Test_Failure(algo + " self-test failed, provider "+
|
|
i->first);
|
|
}
|
|
}
|
|
|
|
void hash_test(Algorithm_Factory& af,
|
|
const std::string& name,
|
|
const std::string& in,
|
|
const std::string& out)
|
|
{
|
|
std::map<std::string, std::string> vars;
|
|
vars["input"] = in;
|
|
vars["output"] = out;
|
|
|
|
verify_results(name, algorithm_kat(name, vars, af));
|
|
}
|
|
|
|
void mac_test(Algorithm_Factory& af,
|
|
const std::string& name,
|
|
const std::string& in,
|
|
const std::string& out,
|
|
const std::string& key)
|
|
{
|
|
std::map<std::string, std::string> vars;
|
|
vars["input"] = in;
|
|
vars["output"] = out;
|
|
vars["key"] = key;
|
|
|
|
verify_results(name, algorithm_kat(name, vars, af));
|
|
}
|
|
|
|
/*
|
|
* Perform a KAT for a cipher
|
|
*/
|
|
void cipher_kat(Algorithm_Factory& af,
|
|
const std::string& algo,
|
|
const std::string& key_str,
|
|
const std::string& iv_str,
|
|
const std::string& in,
|
|
const std::string& ecb_out,
|
|
const std::string& cbc_out,
|
|
const std::string& cfb_out,
|
|
const std::string& ofb_out,
|
|
const std::string& ctr_out)
|
|
{
|
|
SymmetricKey key(key_str);
|
|
InitializationVector iv(iv_str);
|
|
|
|
std::map<std::string, std::string> vars;
|
|
vars["key"] = key_str;
|
|
vars["iv"] = iv_str;
|
|
vars["input"] = in;
|
|
|
|
std::map<std::string, bool> results;
|
|
|
|
vars["output"] = ecb_out;
|
|
verify_results(algo + "/ECB", algorithm_kat(algo + "/ECB", vars, af));
|
|
|
|
vars["output"] = cbc_out;
|
|
verify_results(algo + "/CBC",
|
|
algorithm_kat(algo + "/CBC/NoPadding", vars, af));
|
|
|
|
vars["output"] = cfb_out;
|
|
verify_results(algo + "/CFB", algorithm_kat(algo + "/CFB", vars, af));
|
|
|
|
vars["output"] = ofb_out;
|
|
verify_results(algo + "/OFB", algorithm_kat(algo + "/OFB", vars, af));
|
|
|
|
vars["output"] = ctr_out;
|
|
verify_results(algo + "/CTR", algorithm_kat(algo + "/CTR-BE", vars, af));
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
* Perform Self Tests
|
|
*/
|
|
bool passes_self_tests(Algorithm_Factory& af)
|
|
{
|
|
try
|
|
{
|
|
confirm_startup_self_tests(af);
|
|
}
|
|
catch(Self_Test_Failure)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* Perform Self Tests
|
|
*/
|
|
void confirm_startup_self_tests(Algorithm_Factory& af)
|
|
{
|
|
cipher_kat(af, "DES",
|
|
"0123456789ABCDEF", "1234567890ABCDEF",
|
|
"4E6F77206973207468652074696D6520666F7220616C6C20",
|
|
"3FA40E8A984D48156A271787AB8883F9893D51EC4B563B53",
|
|
"E5C7CDDE872BF27C43E934008C389C0F683788499A7C05F6",
|
|
"F3096249C7F46E51A69E839B1A92F78403467133898EA622",
|
|
"F3096249C7F46E5135F24A242EEB3D3F3D6D5BE3255AF8C3",
|
|
"F3096249C7F46E51163A8CA0FFC94C27FA2F80F480B86F75");
|
|
|
|
cipher_kat(af, "TripleDES",
|
|
"385D7189A5C3D485E1370AA5D408082B5CCCCB5E19F2D90E",
|
|
"C141B5FCCD28DC8A",
|
|
"6E1BD7C6120947A464A6AAB293A0F89A563D8D40D3461B68",
|
|
"64EAAD4ACBB9CEAD6C7615E7C7E4792FE587D91F20C7D2F4",
|
|
"6235A461AFD312973E3B4F7AA7D23E34E03371F8E8C376C9",
|
|
"E26BA806A59B0330DE40CA38E77A3E494BE2B212F6DD624B",
|
|
"E26BA806A59B03307DE2BCC25A08BA40A8BA335F5D604C62",
|
|
"E26BA806A59B03303C62C2EFF32D3ACDD5D5F35EBCC53371");
|
|
|
|
cipher_kat(af, "AES-128",
|
|
"2B7E151628AED2A6ABF7158809CF4F3C",
|
|
"000102030405060708090A0B0C0D0E0F",
|
|
"6BC1BEE22E409F96E93D7E117393172A"
|
|
"AE2D8A571E03AC9C9EB76FAC45AF8E51",
|
|
"3AD77BB40D7A3660A89ECAF32466EF97"
|
|
"F5D3D58503B9699DE785895A96FDBAAF",
|
|
"7649ABAC8119B246CEE98E9B12E9197D"
|
|
"5086CB9B507219EE95DB113A917678B2",
|
|
"3B3FD92EB72DAD20333449F8E83CFB4A"
|
|
"C8A64537A0B3A93FCDE3CDAD9F1CE58B",
|
|
"3B3FD92EB72DAD20333449F8E83CFB4A"
|
|
"7789508D16918F03F53C52DAC54ED825",
|
|
"3B3FD92EB72DAD20333449F8E83CFB4A"
|
|
"010C041999E03F36448624483E582D0E");
|
|
|
|
hash_test(af, "SHA-1",
|
|
"", "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709");
|
|
|
|
hash_test(af, "SHA-1",
|
|
"616263", "A9993E364706816ABA3E25717850C26C9CD0D89D");
|
|
|
|
hash_test(af, "SHA-1",
|
|
"6162636462636465636465666465666765666768666768696768696A"
|
|
"68696A6B696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F7071",
|
|
"84983E441C3BD26EBAAE4AA1F95129E5E54670F1");
|
|
|
|
mac_test(af, "HMAC(SHA-1)",
|
|
"4869205468657265",
|
|
"B617318655057264E28BC0B6FB378C8EF146BE00",
|
|
"0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B");
|
|
|
|
hash_test(af, "SHA-256",
|
|
"",
|
|
"E3B0C44298FC1C149AFBF4C8996FB924"
|
|
"27AE41E4649B934CA495991B7852B855");
|
|
|
|
hash_test(af, "SHA-256",
|
|
"616263",
|
|
"BA7816BF8F01CFEA414140DE5DAE2223"
|
|
"B00361A396177A9CB410FF61F20015AD");
|
|
|
|
hash_test(af, "SHA-256",
|
|
"6162636462636465636465666465666765666768666768696768696A"
|
|
"68696A6B696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F7071",
|
|
"248D6A61D20638B8E5C026930C3E6039"
|
|
"A33CE45964FF2167F6ECEDD419DB06C1");
|
|
|
|
mac_test(af, "HMAC(SHA-256)",
|
|
"4869205468657265",
|
|
"198A607EB44BFBC69903A0F1CF2BBDC5"
|
|
"BA0AA3F3D9AE3C1C7A3B1696A0B68CF7",
|
|
"0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B"
|
|
"0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B");
|
|
}
|
|
|
|
}
|
|
/*
|
|
* ARC4
|
|
* (C) 1999-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* Combine cipher stream with message
|
|
*/
|
|
void ARC4::cipher(const byte in[], byte out[], size_t length)
|
|
{
|
|
while(length >= buffer.size() - position)
|
|
{
|
|
xor_buf(out, in, &buffer[position], buffer.size() - position);
|
|
length -= (buffer.size() - position);
|
|
in += (buffer.size() - position);
|
|
out += (buffer.size() - position);
|
|
generate();
|
|
}
|
|
xor_buf(out, in, &buffer[position], length);
|
|
position += length;
|
|
}
|
|
|
|
/*
|
|
* Generate cipher stream
|
|
*/
|
|
void ARC4::generate()
|
|
{
|
|
byte SX, SY;
|
|
for(size_t i = 0; i != buffer.size(); i += 4)
|
|
{
|
|
SX = state[X+1]; Y = (Y + SX) % 256; SY = state[Y];
|
|
state[X+1] = SY; state[Y] = SX;
|
|
buffer[i] = state[(SX + SY) % 256];
|
|
|
|
SX = state[X+2]; Y = (Y + SX) % 256; SY = state[Y];
|
|
state[X+2] = SY; state[Y] = SX;
|
|
buffer[i+1] = state[(SX + SY) % 256];
|
|
|
|
SX = state[X+3]; Y = (Y + SX) % 256; SY = state[Y];
|
|
state[X+3] = SY; state[Y] = SX;
|
|
buffer[i+2] = state[(SX + SY) % 256];
|
|
|
|
X = (X + 4) % 256;
|
|
SX = state[X]; Y = (Y + SX) % 256; SY = state[Y];
|
|
state[X] = SY; state[Y] = SX;
|
|
buffer[i+3] = state[(SX + SY) % 256];
|
|
}
|
|
position = 0;
|
|
}
|
|
|
|
/*
|
|
* ARC4 Key Schedule
|
|
*/
|
|
void ARC4::key_schedule(const byte key[], size_t length)
|
|
{
|
|
clear();
|
|
|
|
for(size_t i = 0; i != 256; ++i)
|
|
state[i] = static_cast<byte>(i);
|
|
|
|
for(size_t i = 0, state_index = 0; i != 256; ++i)
|
|
{
|
|
state_index = (state_index + key[i % length] + state[i]) % 256;
|
|
std::swap(state[i], state[state_index]);
|
|
}
|
|
|
|
for(size_t i = 0; i <= SKIP; i += buffer.size())
|
|
generate();
|
|
|
|
position += (SKIP % buffer.size());
|
|
}
|
|
|
|
/*
|
|
* Return the name of this type
|
|
*/
|
|
std::string ARC4::name() const
|
|
{
|
|
if(SKIP == 0) return "ARC4";
|
|
if(SKIP == 256) return "MARK-4";
|
|
else return "RC4_skip(" + to_string(SKIP) + ")";
|
|
}
|
|
|
|
/*
|
|
* Clear memory of sensitive data
|
|
*/
|
|
void ARC4::clear()
|
|
{
|
|
zeroise(state);
|
|
zeroise(buffer);
|
|
position = X = Y = 0;
|
|
}
|
|
|
|
/*
|
|
* ARC4 Constructor
|
|
*/
|
|
ARC4::ARC4(size_t s) : SKIP(s),
|
|
state(256),
|
|
buffer(DEFAULT_BUFFERSIZE)
|
|
{
|
|
clear();
|
|
}
|
|
|
|
}
|
|
/*
|
|
* Counter mode
|
|
* (C) 1999-2011 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* CTR-BE Constructor
|
|
*/
|
|
|
|
CTR_BE::CTR_BE(BlockCipher* ciph) :
|
|
permutation(ciph),
|
|
counter(256 * permutation->block_size()),
|
|
buffer(counter.size()),
|
|
position(0)
|
|
{
|
|
}
|
|
|
|
/*
|
|
* CTR_BE Destructor
|
|
*/
|
|
CTR_BE::~CTR_BE()
|
|
{
|
|
delete permutation;
|
|
}
|
|
|
|
/*
|
|
* Zeroize
|
|
*/
|
|
void CTR_BE::clear()
|
|
{
|
|
permutation->clear();
|
|
zeroise(buffer);
|
|
zeroise(counter);
|
|
position = 0;
|
|
}
|
|
|
|
/*
|
|
* Set the key
|
|
*/
|
|
void CTR_BE::key_schedule(const byte key[], size_t key_len)
|
|
{
|
|
permutation->set_key(key, key_len);
|
|
|
|
// Set a default all-zeros IV
|
|
set_iv(0, 0);
|
|
}
|
|
|
|
/*
|
|
* Return the name of this type
|
|
*/
|
|
std::string CTR_BE::name() const
|
|
{
|
|
return ("CTR-BE(" + permutation->name() + ")");
|
|
}
|
|
|
|
/*
|
|
* CTR-BE Encryption/Decryption
|
|
*/
|
|
void CTR_BE::cipher(const byte in[], byte out[], size_t length)
|
|
{
|
|
while(length >= buffer.size() - position)
|
|
{
|
|
xor_buf(out, in, &buffer[position], buffer.size() - position);
|
|
length -= (buffer.size() - position);
|
|
in += (buffer.size() - position);
|
|
out += (buffer.size() - position);
|
|
increment_counter();
|
|
}
|
|
xor_buf(out, in, &buffer[position], length);
|
|
position += length;
|
|
}
|
|
|
|
/*
|
|
* Set CTR-BE IV
|
|
*/
|
|
void CTR_BE::set_iv(const byte iv[], size_t iv_len)
|
|
{
|
|
if(!valid_iv_length(iv_len))
|
|
throw Invalid_IV_Length(name(), iv_len);
|
|
|
|
const size_t bs = permutation->block_size();
|
|
|
|
zeroise(counter);
|
|
|
|
counter.copy(0, iv, iv_len);
|
|
|
|
/*
|
|
* Set counter blocks to IV, IV + 1, ... IV + 255
|
|
*/
|
|
for(size_t i = 1; i != 256; ++i)
|
|
{
|
|
counter.copy(i*bs, &counter[(i-1)*bs], bs);
|
|
|
|
for(size_t j = 0; j != bs; ++j)
|
|
if(++counter[i*bs + (bs - 1 - j)])
|
|
break;
|
|
}
|
|
|
|
permutation->encrypt_n(&counter[0], &buffer[0], 256);
|
|
position = 0;
|
|
}
|
|
|
|
/*
|
|
* Increment the counter and update the buffer
|
|
*/
|
|
void CTR_BE::increment_counter()
|
|
{
|
|
const size_t bs = permutation->block_size();
|
|
|
|
/*
|
|
* Each counter value always needs to be incremented by 256,
|
|
* so we don't touch the lowest byte and instead treat it as
|
|
* an increment of one starting with the next byte.
|
|
*/
|
|
for(size_t i = 0; i != 256; ++i)
|
|
{
|
|
for(size_t j = 1; j != bs; ++j)
|
|
if(++counter[i*bs + (bs - 1 - j)])
|
|
break;
|
|
}
|
|
|
|
permutation->encrypt_n(&counter[0], &buffer[0], 256);
|
|
|
|
position = 0;
|
|
}
|
|
|
|
}
|
|
/*
|
|
* OFB Mode
|
|
* (C) 1999-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
#include <algorithm>
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* OFB Constructor
|
|
*/
|
|
OFB::OFB(BlockCipher* ciph) : permutation(ciph)
|
|
{
|
|
position = 0;
|
|
buffer.resize(permutation->block_size());
|
|
}
|
|
|
|
/*
|
|
* OFB Destructor
|
|
*/
|
|
OFB::~OFB()
|
|
{
|
|
delete permutation;
|
|
}
|
|
|
|
/*
|
|
* Zeroize
|
|
*/
|
|
void OFB::clear()
|
|
{
|
|
permutation->clear();
|
|
zeroise(buffer);
|
|
position = 0;
|
|
}
|
|
|
|
/*
|
|
* Set the key
|
|
*/
|
|
void OFB::key_schedule(const byte key[], size_t key_len)
|
|
{
|
|
permutation->set_key(key, key_len);
|
|
|
|
// Set a default all-zeros IV
|
|
set_iv(0, 0);
|
|
}
|
|
|
|
/*
|
|
* Return the name of this type
|
|
*/
|
|
std::string OFB::name() const
|
|
{
|
|
return ("OFB(" + permutation->name() + ")");
|
|
}
|
|
|
|
/*
|
|
* CTR-BE Encryption/Decryption
|
|
*/
|
|
void OFB::cipher(const byte in[], byte out[], size_t length)
|
|
{
|
|
while(length >= buffer.size() - position)
|
|
{
|
|
xor_buf(out, in, &buffer[position], buffer.size() - position);
|
|
length -= (buffer.size() - position);
|
|
in += (buffer.size() - position);
|
|
out += (buffer.size() - position);
|
|
permutation->encrypt(buffer);
|
|
position = 0;
|
|
}
|
|
xor_buf(out, in, &buffer[position], length);
|
|
position += length;
|
|
}
|
|
|
|
/*
|
|
* Set CTR-BE IV
|
|
*/
|
|
void OFB::set_iv(const byte iv[], size_t iv_len)
|
|
{
|
|
if(!valid_iv_length(iv_len))
|
|
throw Invalid_IV_Length(name(), iv_len);
|
|
|
|
zeroise(buffer);
|
|
buffer.copy(0, iv, iv_len);
|
|
|
|
permutation->encrypt(buffer);
|
|
position = 0;
|
|
}
|
|
|
|
}
|
|
/*
|
|
* Salsa20 / XSalsa20
|
|
* (C) 1999-2010 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
namespace {
|
|
|
|
#define SALSA20_QUARTER_ROUND(x1, x2, x3, x4) \
|
|
do { \
|
|
x2 ^= rotate_left(x1 + x4, 7); \
|
|
x3 ^= rotate_left(x2 + x1, 9); \
|
|
x4 ^= rotate_left(x3 + x2, 13); \
|
|
x1 ^= rotate_left(x4 + x3, 18); \
|
|
} while(0)
|
|
|
|
/*
|
|
* Generate HSalsa20 cipher stream (for XSalsa20 IV setup)
|
|
*/
|
|
void hsalsa20(u32bit output[8], const u32bit input[16])
|
|
{
|
|
u32bit x00 = input[ 0], x01 = input[ 1], x02 = input[ 2], x03 = input[ 3],
|
|
x04 = input[ 4], x05 = input[ 5], x06 = input[ 6], x07 = input[ 7],
|
|
x08 = input[ 8], x09 = input[ 9], x10 = input[10], x11 = input[11],
|
|
x12 = input[12], x13 = input[13], x14 = input[14], x15 = input[15];
|
|
|
|
for(size_t i = 0; i != 10; ++i)
|
|
{
|
|
SALSA20_QUARTER_ROUND(x00, x04, x08, x12);
|
|
SALSA20_QUARTER_ROUND(x05, x09, x13, x01);
|
|
SALSA20_QUARTER_ROUND(x10, x14, x02, x06);
|
|
SALSA20_QUARTER_ROUND(x15, x03, x07, x11);
|
|
|
|
SALSA20_QUARTER_ROUND(x00, x01, x02, x03);
|
|
SALSA20_QUARTER_ROUND(x05, x06, x07, x04);
|
|
SALSA20_QUARTER_ROUND(x10, x11, x08, x09);
|
|
SALSA20_QUARTER_ROUND(x15, x12, x13, x14);
|
|
}
|
|
|
|
output[0] = x00;
|
|
output[1] = x05;
|
|
output[2] = x10;
|
|
output[3] = x15;
|
|
output[4] = x06;
|
|
output[5] = x07;
|
|
output[6] = x08;
|
|
output[7] = x09;
|
|
}
|
|
|
|
/*
|
|
* Generate Salsa20 cipher stream
|
|
*/
|
|
void salsa20(byte output[64], const u32bit input[16])
|
|
{
|
|
u32bit x00 = input[ 0], x01 = input[ 1], x02 = input[ 2], x03 = input[ 3],
|
|
x04 = input[ 4], x05 = input[ 5], x06 = input[ 6], x07 = input[ 7],
|
|
x08 = input[ 8], x09 = input[ 9], x10 = input[10], x11 = input[11],
|
|
x12 = input[12], x13 = input[13], x14 = input[14], x15 = input[15];
|
|
|
|
for(size_t i = 0; i != 10; ++i)
|
|
{
|
|
SALSA20_QUARTER_ROUND(x00, x04, x08, x12);
|
|
SALSA20_QUARTER_ROUND(x05, x09, x13, x01);
|
|
SALSA20_QUARTER_ROUND(x10, x14, x02, x06);
|
|
SALSA20_QUARTER_ROUND(x15, x03, x07, x11);
|
|
|
|
SALSA20_QUARTER_ROUND(x00, x01, x02, x03);
|
|
SALSA20_QUARTER_ROUND(x05, x06, x07, x04);
|
|
SALSA20_QUARTER_ROUND(x10, x11, x08, x09);
|
|
SALSA20_QUARTER_ROUND(x15, x12, x13, x14);
|
|
}
|
|
|
|
store_le(x00 + input[ 0], output + 4 * 0);
|
|
store_le(x01 + input[ 1], output + 4 * 1);
|
|
store_le(x02 + input[ 2], output + 4 * 2);
|
|
store_le(x03 + input[ 3], output + 4 * 3);
|
|
store_le(x04 + input[ 4], output + 4 * 4);
|
|
store_le(x05 + input[ 5], output + 4 * 5);
|
|
store_le(x06 + input[ 6], output + 4 * 6);
|
|
store_le(x07 + input[ 7], output + 4 * 7);
|
|
store_le(x08 + input[ 8], output + 4 * 8);
|
|
store_le(x09 + input[ 9], output + 4 * 9);
|
|
store_le(x10 + input[10], output + 4 * 10);
|
|
store_le(x11 + input[11], output + 4 * 11);
|
|
store_le(x12 + input[12], output + 4 * 12);
|
|
store_le(x13 + input[13], output + 4 * 13);
|
|
store_le(x14 + input[14], output + 4 * 14);
|
|
store_le(x15 + input[15], output + 4 * 15);
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
* Combine cipher stream with message
|
|
*/
|
|
void Salsa20::cipher(const byte in[], byte out[], size_t length)
|
|
{
|
|
while(length >= buffer.size() - position)
|
|
{
|
|
xor_buf(out, in, &buffer[position], buffer.size() - position);
|
|
length -= (buffer.size() - position);
|
|
in += (buffer.size() - position);
|
|
out += (buffer.size() - position);
|
|
salsa20(&buffer[0], &state[0]);
|
|
|
|
++state[8];
|
|
if(!state[8]) // if overflow in state[8]
|
|
++state[9]; // carry to state[9]
|
|
|
|
position = 0;
|
|
}
|
|
|
|
xor_buf(out, in, &buffer[position], length);
|
|
|
|
position += length;
|
|
}
|
|
|
|
/*
|
|
* Salsa20 Key Schedule
|
|
*/
|
|
void Salsa20::key_schedule(const byte key[], size_t length)
|
|
{
|
|
static const u32bit TAU[] =
|
|
{ 0x61707865, 0x3120646e, 0x79622d36, 0x6b206574 };
|
|
|
|
static const u32bit SIGMA[] =
|
|
{ 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574 };
|
|
|
|
clear();
|
|
|
|
if(length == 16)
|
|
{
|
|
state[0] = TAU[0];
|
|
state[1] = load_le<u32bit>(key, 0);
|
|
state[2] = load_le<u32bit>(key, 1);
|
|
state[3] = load_le<u32bit>(key, 2);
|
|
state[4] = load_le<u32bit>(key, 3);
|
|
state[5] = TAU[1];
|
|
state[10] = TAU[2];
|
|
state[11] = load_le<u32bit>(key, 0);
|
|
state[12] = load_le<u32bit>(key, 1);
|
|
state[13] = load_le<u32bit>(key, 2);
|
|
state[14] = load_le<u32bit>(key, 3);
|
|
state[15] = TAU[3];
|
|
}
|
|
else if(length == 32)
|
|
{
|
|
state[0] = SIGMA[0];
|
|
state[1] = load_le<u32bit>(key, 0);
|
|
state[2] = load_le<u32bit>(key, 1);
|
|
state[3] = load_le<u32bit>(key, 2);
|
|
state[4] = load_le<u32bit>(key, 3);
|
|
state[5] = SIGMA[1];
|
|
state[10] = SIGMA[2];
|
|
state[11] = load_le<u32bit>(key, 4);
|
|
state[12] = load_le<u32bit>(key, 5);
|
|
state[13] = load_le<u32bit>(key, 6);
|
|
state[14] = load_le<u32bit>(key, 7);
|
|
state[15] = SIGMA[3];
|
|
}
|
|
|
|
const byte ZERO[8] = { 0 };
|
|
set_iv(ZERO, sizeof(ZERO));
|
|
}
|
|
|
|
/*
|
|
* Return the name of this type
|
|
*/
|
|
void Salsa20::set_iv(const byte iv[], size_t length)
|
|
{
|
|
if(!valid_iv_length(length))
|
|
throw Invalid_IV_Length(name(), length);
|
|
|
|
if(length == 8)
|
|
{
|
|
// Salsa20
|
|
state[6] = load_le<u32bit>(iv, 0);
|
|
state[7] = load_le<u32bit>(iv, 1);
|
|
}
|
|
else
|
|
{
|
|
// XSalsa20
|
|
state[6] = load_le<u32bit>(iv, 0);
|
|
state[7] = load_le<u32bit>(iv, 1);
|
|
state[8] = load_le<u32bit>(iv, 2);
|
|
state[9] = load_le<u32bit>(iv, 3);
|
|
|
|
SecureVector<u32bit> hsalsa(8);
|
|
hsalsa20(&hsalsa[0], &state[0]);
|
|
|
|
state[ 1] = hsalsa[0];
|
|
state[ 2] = hsalsa[1];
|
|
state[ 3] = hsalsa[2];
|
|
state[ 4] = hsalsa[3];
|
|
state[ 6] = load_le<u32bit>(iv, 4);
|
|
state[ 7] = load_le<u32bit>(iv, 5);
|
|
state[11] = hsalsa[4];
|
|
state[12] = hsalsa[5];
|
|
state[13] = hsalsa[6];
|
|
state[14] = hsalsa[7];
|
|
}
|
|
|
|
state[8] = 0;
|
|
state[9] = 0;
|
|
|
|
salsa20(&buffer[0], &state[0]);
|
|
++state[8];
|
|
if(!state[8]) // if overflow in state[8]
|
|
++state[9]; // carry to state[9]
|
|
|
|
position = 0;
|
|
}
|
|
|
|
/*
|
|
* Return the name of this type
|
|
*/
|
|
std::string Salsa20::name() const
|
|
{
|
|
return "Salsa20";
|
|
}
|
|
|
|
/*
|
|
* Clear memory of sensitive data
|
|
*/
|
|
void Salsa20::clear()
|
|
{
|
|
zeroise(state);
|
|
zeroise(buffer);
|
|
position = 0;
|
|
}
|
|
|
|
}
|
|
/*
|
|
* Stream Cipher
|
|
* (C) 1999-2010 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
void StreamCipher::set_iv(const byte[], size_t iv_len)
|
|
{
|
|
if(iv_len)
|
|
throw Invalid_Argument("The stream cipher " + name() +
|
|
" does not support resyncronization");
|
|
}
|
|
|
|
bool StreamCipher::valid_iv_length(size_t iv_len) const
|
|
{
|
|
return (iv_len == 0);
|
|
}
|
|
|
|
}
|
|
/*
|
|
* Tables for Turing
|
|
* (C) 1999-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
const byte Turing::SBOX[256] = {
|
|
0x61, 0x51, 0xEB, 0x19, 0xB9, 0x5D, 0x60, 0x38, 0x7C, 0xB2, 0x06, 0x12,
|
|
0xC4, 0x5B, 0x16, 0x3B, 0x2B, 0x18, 0x83, 0xB0, 0x7F, 0x75, 0xFA, 0xA0,
|
|
0xE9, 0xDD, 0x6D, 0x7A, 0x6B, 0x68, 0x2D, 0x49, 0xB5, 0x1C, 0x90, 0xF7,
|
|
0xED, 0x9F, 0xE8, 0xCE, 0xAE, 0x77, 0xC2, 0x13, 0xFD, 0xCD, 0x3E, 0xCF,
|
|
0x37, 0x6A, 0xD4, 0xDB, 0x8E, 0x65, 0x1F, 0x1A, 0x87, 0xCB, 0x40, 0x15,
|
|
0x88, 0x0D, 0x35, 0xB3, 0x11, 0x0F, 0xD0, 0x30, 0x48, 0xF9, 0xA8, 0xAC,
|
|
0x85, 0x27, 0x0E, 0x8A, 0xE0, 0x50, 0x64, 0xA7, 0xCC, 0xE4, 0xF1, 0x98,
|
|
0xFF, 0xA1, 0x04, 0xDA, 0xD5, 0xBC, 0x1B, 0xBB, 0xD1, 0xFE, 0x31, 0xCA,
|
|
0xBA, 0xD9, 0x2E, 0xF3, 0x1D, 0x47, 0x4A, 0x3D, 0x71, 0x4C, 0xAB, 0x7D,
|
|
0x8D, 0xC7, 0x59, 0xB8, 0xC1, 0x96, 0x1E, 0xFC, 0x44, 0xC8, 0x7B, 0xDC,
|
|
0x5C, 0x78, 0x2A, 0x9D, 0xA5, 0xF0, 0x73, 0x22, 0x89, 0x05, 0xF4, 0x07,
|
|
0x21, 0x52, 0xA6, 0x28, 0x9A, 0x92, 0x69, 0x8F, 0xC5, 0xC3, 0xF5, 0xE1,
|
|
0xDE, 0xEC, 0x09, 0xF2, 0xD3, 0xAF, 0x34, 0x23, 0xAA, 0xDF, 0x7E, 0x82,
|
|
0x29, 0xC0, 0x24, 0x14, 0x03, 0x32, 0x4E, 0x39, 0x6F, 0xC6, 0xB1, 0x9B,
|
|
0xEA, 0x72, 0x79, 0x41, 0xD8, 0x26, 0x6C, 0x5E, 0x2C, 0xB4, 0xA2, 0x53,
|
|
0x57, 0xE2, 0x9C, 0x86, 0x54, 0x95, 0xB6, 0x80, 0x8C, 0x36, 0x67, 0xBD,
|
|
0x08, 0x93, 0x2F, 0x99, 0x5A, 0xF8, 0x3A, 0xD7, 0x56, 0x84, 0xD2, 0x01,
|
|
0xF6, 0x66, 0x4D, 0x55, 0x8B, 0x0C, 0x0B, 0x46, 0xB7, 0x3C, 0x45, 0x91,
|
|
0xA4, 0xE3, 0x70, 0xD6, 0xFB, 0xE6, 0x10, 0xA9, 0xC9, 0x00, 0x9E, 0xE7,
|
|
0x4F, 0x76, 0x25, 0x3F, 0x5F, 0xA3, 0x33, 0x20, 0x02, 0xEF, 0x62, 0x74,
|
|
0xEE, 0x17, 0x81, 0x42, 0x58, 0x0A, 0x4B, 0x63, 0xE5, 0xBE, 0x6E, 0xAD,
|
|
0xBF, 0x43, 0x94, 0x97 };
|
|
|
|
const u32bit Turing::Q_BOX[256] = {
|
|
0x1FAA1887, 0x4E5E435C, 0x9165C042, 0x250E6EF4, 0x5957EE20, 0xD484FED3,
|
|
0xA666C502, 0x7E54E8AE, 0xD12EE9D9, 0xFC1F38D4, 0x49829B5D, 0x1B5CDF3C,
|
|
0x74864249, 0xDA2E3963, 0x28F4429F, 0xC8432C35, 0x4AF40325, 0x9FC0DD70,
|
|
0xD8973DED, 0x1A02DC5E, 0xCD175B42, 0xF10012BF, 0x6694D78C, 0xACAAB26B,
|
|
0x4EC11B9A, 0x3F168146, 0xC0EA8EC5, 0xB38AC28F, 0x1FED5C0F, 0xAAB4101C,
|
|
0xEA2DB082, 0x470929E1, 0xE71843DE, 0x508299FC, 0xE72FBC4B, 0x2E3915DD,
|
|
0x9FA803FA, 0x9546B2DE, 0x3C233342, 0x0FCEE7C3, 0x24D607EF, 0x8F97EBAB,
|
|
0xF37F859B, 0xCD1F2E2F, 0xC25B71DA, 0x75E2269A, 0x1E39C3D1, 0xEDA56B36,
|
|
0xF8C9DEF2, 0x46C9FC5F, 0x1827B3A3, 0x70A56DDF, 0x0D25B510, 0x000F85A7,
|
|
0xB2E82E71, 0x68CB8816, 0x8F951E2A, 0x72F5F6AF, 0xE4CBC2B3, 0xD34FF55D,
|
|
0x2E6B6214, 0x220B83E3, 0xD39EA6F5, 0x6FE041AF, 0x6B2F1F17, 0xAD3B99EE,
|
|
0x16A65EC0, 0x757016C6, 0xBA7709A4, 0xB0326E01, 0xF4B280D9, 0x4BFB1418,
|
|
0xD6AFF227, 0xFD548203, 0xF56B9D96, 0x6717A8C0, 0x00D5BF6E, 0x10EE7888,
|
|
0xEDFCFE64, 0x1BA193CD, 0x4B0D0184, 0x89AE4930, 0x1C014F36, 0x82A87088,
|
|
0x5EAD6C2A, 0xEF22C678, 0x31204DE7, 0xC9C2E759, 0xD200248E, 0x303B446B,
|
|
0xB00D9FC2, 0x9914A895, 0x906CC3A1, 0x54FEF170, 0x34C19155, 0xE27B8A66,
|
|
0x131B5E69, 0xC3A8623E, 0x27BDFA35, 0x97F068CC, 0xCA3A6ACD, 0x4B55E936,
|
|
0x86602DB9, 0x51DF13C1, 0x390BB16D, 0x5A80B83C, 0x22B23763, 0x39D8A911,
|
|
0x2CB6BC13, 0xBF5579D7, 0x6C5C2FA8, 0xA8F4196E, 0xBCDB5476, 0x6864A866,
|
|
0x416E16AD, 0x897FC515, 0x956FEB3C, 0xF6C8A306, 0x216799D9, 0x171A9133,
|
|
0x6C2466DD, 0x75EB5DCD, 0xDF118F50, 0xE4AFB226, 0x26B9CEF3, 0xADB36189,
|
|
0x8A7A19B1, 0xE2C73084, 0xF77DED5C, 0x8B8BC58F, 0x06DDE421, 0xB41E47FB,
|
|
0xB1CC715E, 0x68C0FF99, 0x5D122F0F, 0xA4D25184, 0x097A5E6C, 0x0CBF18BC,
|
|
0xC2D7C6E0, 0x8BB7E420, 0xA11F523F, 0x35D9B8A2, 0x03DA1A6B, 0x06888C02,
|
|
0x7DD1E354, 0x6BBA7D79, 0x32CC7753, 0xE52D9655, 0xA9829DA1, 0x301590A7,
|
|
0x9BC1C149, 0x13537F1C, 0xD3779B69, 0x2D71F2B7, 0x183C58FA, 0xACDC4418,
|
|
0x8D8C8C76, 0x2620D9F0, 0x71A80D4D, 0x7A74C473, 0x449410E9, 0xA20E4211,
|
|
0xF9C8082B, 0x0A6B334A, 0xB5F68ED2, 0x8243CC1B, 0x453C0FF3, 0x9BE564A0,
|
|
0x4FF55A4F, 0x8740F8E7, 0xCCA7F15F, 0xE300FE21, 0x786D37D6, 0xDFD506F1,
|
|
0x8EE00973, 0x17BBDE36, 0x7A670FA8, 0x5C31AB9E, 0xD4DAB618, 0xCC1F52F5,
|
|
0xE358EB4F, 0x19B9E343, 0x3A8D77DD, 0xCDB93DA6, 0x140FD52D, 0x395412F8,
|
|
0x2BA63360, 0x37E53AD0, 0x80700F1C, 0x7624ED0B, 0x703DC1EC, 0xB7366795,
|
|
0xD6549D15, 0x66CE46D7, 0xD17ABE76, 0xA448E0A0, 0x28F07C02, 0xC31249B7,
|
|
0x6E9ED6BA, 0xEAA47F78, 0xBBCFFFBD, 0xC507CA84, 0xE965F4DA, 0x8E9F35DA,
|
|
0x6AD2AA44, 0x577452AC, 0xB5D674A7, 0x5461A46A, 0x6763152A, 0x9C12B7AA,
|
|
0x12615927, 0x7B4FB118, 0xC351758D, 0x7E81687B, 0x5F52F0B3, 0x2D4254ED,
|
|
0xD4C77271, 0x0431ACAB, 0xBEF94AEC, 0xFEE994CD, 0x9C4D9E81, 0xED623730,
|
|
0xCF8A21E8, 0x51917F0B, 0xA7A9B5D6, 0xB297ADF8, 0xEED30431, 0x68CAC921,
|
|
0xF1B35D46, 0x7A430A36, 0x51194022, 0x9ABCA65E, 0x85EC70BA, 0x39AEA8CC,
|
|
0x737BAE8B, 0x582924D5, 0x03098A5A, 0x92396B81, 0x18DE2522, 0x745C1CB8,
|
|
0xA1B8FE1D, 0x5DB3C697, 0x29164F83, 0x97C16376, 0x8419224C, 0x21203B35,
|
|
0x833AC0FE, 0xD966A19A, 0xAAF0B24F, 0x40FDA998, 0xE7D52D71, 0x390896A8,
|
|
0xCEE6053F, 0xD0B0D300, 0xFF99CBCC, 0x065E3D40 };
|
|
|
|
}
|
|
/*
|
|
* Turing
|
|
* (C) 1999-2008 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
namespace {
|
|
|
|
/*
|
|
* Perform an N-way PHT
|
|
*/
|
|
inline void PHT(MemoryRegion<u32bit>& B)
|
|
{
|
|
u32bit sum = 0;
|
|
for(size_t i = 0; i < B.size() - 1; ++i)
|
|
sum += B[i];
|
|
|
|
B[B.size()-1] += sum;
|
|
|
|
sum = B[B.size()-1];
|
|
for(size_t i = 0; i < B.size() - 1; ++i)
|
|
B[i] += sum;
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
* Combine cipher stream with message
|
|
*/
|
|
void Turing::cipher(const byte in[], byte out[], size_t length)
|
|
{
|
|
while(length >= buffer.size() - position)
|
|
{
|
|
xor_buf(out, in, &buffer[position], buffer.size() - position);
|
|
length -= (buffer.size() - position);
|
|
in += (buffer.size() - position);
|
|
out += (buffer.size() - position);
|
|
generate();
|
|
}
|
|
xor_buf(out, in, &buffer[position], length);
|
|
position += length;
|
|
}
|
|
|
|
/*
|
|
* Generate cipher stream
|
|
*/
|
|
void Turing::generate()
|
|
{
|
|
// Table for Turing's polynomial multiplication
|
|
static const u32bit MULT_TAB[256] = {
|
|
0x00000000, 0xD02B4367, 0xED5686CE, 0x3D7DC5A9, 0x97AC41D1, 0x478702B6,
|
|
0x7AFAC71F, 0xAAD18478, 0x631582EF, 0xB33EC188, 0x8E430421, 0x5E684746,
|
|
0xF4B9C33E, 0x24928059, 0x19EF45F0, 0xC9C40697, 0xC62A4993, 0x16010AF4,
|
|
0x2B7CCF5D, 0xFB578C3A, 0x51860842, 0x81AD4B25, 0xBCD08E8C, 0x6CFBCDEB,
|
|
0xA53FCB7C, 0x7514881B, 0x48694DB2, 0x98420ED5, 0x32938AAD, 0xE2B8C9CA,
|
|
0xDFC50C63, 0x0FEE4F04, 0xC154926B, 0x117FD10C, 0x2C0214A5, 0xFC2957C2,
|
|
0x56F8D3BA, 0x86D390DD, 0xBBAE5574, 0x6B851613, 0xA2411084, 0x726A53E3,
|
|
0x4F17964A, 0x9F3CD52D, 0x35ED5155, 0xE5C61232, 0xD8BBD79B, 0x089094FC,
|
|
0x077EDBF8, 0xD755989F, 0xEA285D36, 0x3A031E51, 0x90D29A29, 0x40F9D94E,
|
|
0x7D841CE7, 0xADAF5F80, 0x646B5917, 0xB4401A70, 0x893DDFD9, 0x59169CBE,
|
|
0xF3C718C6, 0x23EC5BA1, 0x1E919E08, 0xCEBADD6F, 0xCFA869D6, 0x1F832AB1,
|
|
0x22FEEF18, 0xF2D5AC7F, 0x58042807, 0x882F6B60, 0xB552AEC9, 0x6579EDAE,
|
|
0xACBDEB39, 0x7C96A85E, 0x41EB6DF7, 0x91C02E90, 0x3B11AAE8, 0xEB3AE98F,
|
|
0xD6472C26, 0x066C6F41, 0x09822045, 0xD9A96322, 0xE4D4A68B, 0x34FFE5EC,
|
|
0x9E2E6194, 0x4E0522F3, 0x7378E75A, 0xA353A43D, 0x6A97A2AA, 0xBABCE1CD,
|
|
0x87C12464, 0x57EA6703, 0xFD3BE37B, 0x2D10A01C, 0x106D65B5, 0xC04626D2,
|
|
0x0EFCFBBD, 0xDED7B8DA, 0xE3AA7D73, 0x33813E14, 0x9950BA6C, 0x497BF90B,
|
|
0x74063CA2, 0xA42D7FC5, 0x6DE97952, 0xBDC23A35, 0x80BFFF9C, 0x5094BCFB,
|
|
0xFA453883, 0x2A6E7BE4, 0x1713BE4D, 0xC738FD2A, 0xC8D6B22E, 0x18FDF149,
|
|
0x258034E0, 0xF5AB7787, 0x5F7AF3FF, 0x8F51B098, 0xB22C7531, 0x62073656,
|
|
0xABC330C1, 0x7BE873A6, 0x4695B60F, 0x96BEF568, 0x3C6F7110, 0xEC443277,
|
|
0xD139F7DE, 0x0112B4B9, 0xD31DD2E1, 0x03369186, 0x3E4B542F, 0xEE601748,
|
|
0x44B19330, 0x949AD057, 0xA9E715FE, 0x79CC5699, 0xB008500E, 0x60231369,
|
|
0x5D5ED6C0, 0x8D7595A7, 0x27A411DF, 0xF78F52B8, 0xCAF29711, 0x1AD9D476,
|
|
0x15379B72, 0xC51CD815, 0xF8611DBC, 0x284A5EDB, 0x829BDAA3, 0x52B099C4,
|
|
0x6FCD5C6D, 0xBFE61F0A, 0x7622199D, 0xA6095AFA, 0x9B749F53, 0x4B5FDC34,
|
|
0xE18E584C, 0x31A51B2B, 0x0CD8DE82, 0xDCF39DE5, 0x1249408A, 0xC26203ED,
|
|
0xFF1FC644, 0x2F348523, 0x85E5015B, 0x55CE423C, 0x68B38795, 0xB898C4F2,
|
|
0x715CC265, 0xA1778102, 0x9C0A44AB, 0x4C2107CC, 0xE6F083B4, 0x36DBC0D3,
|
|
0x0BA6057A, 0xDB8D461D, 0xD4630919, 0x04484A7E, 0x39358FD7, 0xE91ECCB0,
|
|
0x43CF48C8, 0x93E40BAF, 0xAE99CE06, 0x7EB28D61, 0xB7768BF6, 0x675DC891,
|
|
0x5A200D38, 0x8A0B4E5F, 0x20DACA27, 0xF0F18940, 0xCD8C4CE9, 0x1DA70F8E,
|
|
0x1CB5BB37, 0xCC9EF850, 0xF1E33DF9, 0x21C87E9E, 0x8B19FAE6, 0x5B32B981,
|
|
0x664F7C28, 0xB6643F4F, 0x7FA039D8, 0xAF8B7ABF, 0x92F6BF16, 0x42DDFC71,
|
|
0xE80C7809, 0x38273B6E, 0x055AFEC7, 0xD571BDA0, 0xDA9FF2A4, 0x0AB4B1C3,
|
|
0x37C9746A, 0xE7E2370D, 0x4D33B375, 0x9D18F012, 0xA06535BB, 0x704E76DC,
|
|
0xB98A704B, 0x69A1332C, 0x54DCF685, 0x84F7B5E2, 0x2E26319A, 0xFE0D72FD,
|
|
0xC370B754, 0x135BF433, 0xDDE1295C, 0x0DCA6A3B, 0x30B7AF92, 0xE09CECF5,
|
|
0x4A4D688D, 0x9A662BEA, 0xA71BEE43, 0x7730AD24, 0xBEF4ABB3, 0x6EDFE8D4,
|
|
0x53A22D7D, 0x83896E1A, 0x2958EA62, 0xF973A905, 0xC40E6CAC, 0x14252FCB,
|
|
0x1BCB60CF, 0xCBE023A8, 0xF69DE601, 0x26B6A566, 0x8C67211E, 0x5C4C6279,
|
|
0x6131A7D0, 0xB11AE4B7, 0x78DEE220, 0xA8F5A147, 0x958864EE, 0x45A32789,
|
|
0xEF72A3F1, 0x3F59E096, 0x0224253F, 0xD20F6658 };
|
|
|
|
/*
|
|
I tried an implementation without precomputed LFSR offsets, since
|
|
I thought that might allow (especially on x86-64) the use of leal to
|
|
compute all the offsets.. However on my Core2 with GCC 4.3 it
|
|
turned out significantly slower (238 Mib/s, versus 300 Mib/s
|
|
with precomputed offsets)
|
|
|
|
I also tried using byte vs u32bit for the offset variable (since
|
|
x86 memory addressing modes can be odd), but it made things even
|
|
slower (186 Mib/s)
|
|
*/
|
|
static const byte OFFSETS[221] = {
|
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 14, 15, 16,
|
|
5, 6, 7, 8, 9, 10, 11, 12, 13, 0, 2, 3, 4,
|
|
10, 11, 12, 13, 14, 15, 16, 0, 1, 5, 7, 8, 9,
|
|
15, 16, 0, 1, 2, 3, 4, 5, 6, 10, 12, 13, 14,
|
|
3, 4, 5, 6, 7, 8, 9, 10, 11, 15, 0, 1, 2,
|
|
8, 9, 10, 11, 12, 13, 14, 15, 16, 3, 5, 6, 7,
|
|
13, 14, 15, 16, 0, 1, 2, 3, 4, 8, 10, 11, 12,
|
|
1, 2, 3, 4, 5, 6, 7, 8, 9, 13, 15, 16, 0,
|
|
6, 7, 8, 9, 10, 11, 12, 13, 14, 1, 3, 4, 5,
|
|
11, 12, 13, 14, 15, 16, 0, 1, 2, 6, 8, 9, 10,
|
|
16, 0, 1, 2, 3, 4, 5, 6, 7, 11, 13, 14, 15,
|
|
4, 5, 6, 7, 8, 9, 10, 11, 12, 16, 1, 2, 3,
|
|
9, 10, 11, 12, 13, 14, 15, 16, 0, 4, 6, 7, 8,
|
|
14, 15, 16, 0, 1, 2, 3, 4, 5, 9, 11, 12, 13,
|
|
2, 3, 4, 5, 6, 7, 8, 9, 10, 14, 16, 0, 1,
|
|
7, 8, 9, 10, 11, 12, 13, 14, 15, 2, 4, 5, 6,
|
|
12, 13, 14, 15, 16, 0, 1, 2, 3, 7, 9, 10, 11 };
|
|
|
|
for(size_t i = 0; i != 17; ++i)
|
|
{
|
|
const byte* R_off = OFFSETS + 13*i;
|
|
|
|
u32bit R0 = R[R_off[0]];
|
|
u32bit R1 = R[R_off[1]];
|
|
u32bit R2 = R[R_off[2]];
|
|
u32bit R3 = R[R_off[3]];
|
|
u32bit R4 = R[R_off[4]];
|
|
|
|
const u32bit R5 = R[R_off[5]];
|
|
const u32bit R6 = R[R_off[6]];
|
|
const u32bit R7 = R[R_off[7]];
|
|
const u32bit R8 = R[R_off[8]];
|
|
const u32bit R9 = R[R_off[9]];
|
|
const u32bit R10 = R[R_off[10]];
|
|
const u32bit R11 = R[R_off[11]];
|
|
const u32bit R12 = R[R_off[12]];
|
|
|
|
R[R_off[0]] = R0 = ((R0 << 8) ^ MULT_TAB[(R0 >> 24) & 0xFF]) ^ R11 ^ R4;
|
|
|
|
u32bit A = R0;
|
|
u32bit B = R10;
|
|
u32bit C = R7;
|
|
u32bit D = R2;
|
|
u32bit E = R1;
|
|
|
|
E += A + B + C + D;
|
|
|
|
A += E;
|
|
B += E;
|
|
C += E;
|
|
D += E;
|
|
|
|
A = S0[get_byte(0, A)] ^ S1[get_byte(1, A)] ^
|
|
S2[get_byte(2, A)] ^ S3[get_byte(3, A)];
|
|
B = S0[get_byte(1, B)] ^ S1[get_byte(2, B)] ^
|
|
S2[get_byte(3, B)] ^ S3[get_byte(0, B)];
|
|
C = S0[get_byte(2, C)] ^ S1[get_byte(3, C)] ^
|
|
S2[get_byte(0, C)] ^ S3[get_byte(1, C)];
|
|
D = S0[get_byte(3, D)] ^ S1[get_byte(0, D)] ^
|
|
S2[get_byte(1, D)] ^ S3[get_byte(2, D)];
|
|
E = S0[get_byte(0, E)] ^ S1[get_byte(1, E)] ^
|
|
S2[get_byte(2, E)] ^ S3[get_byte(3, E)];
|
|
|
|
E += A + B + C + D;
|
|
|
|
A += E;
|
|
B += E;
|
|
C += E;
|
|
D += E;
|
|
|
|
R[R_off[1]] = R1 = ((R1 << 8) ^ MULT_TAB[(R1 >> 24) & 0xFF]) ^ R12 ^ R5;
|
|
R[R_off[2]] = R2 = ((R2 << 8) ^ MULT_TAB[(R2 >> 24) & 0xFF]) ^ R0 ^ R6;
|
|
R[R_off[3]] = ((R3 << 8) ^ MULT_TAB[(R3 >> 24) & 0xFF]) ^ R1 ^ R7;
|
|
|
|
E += R4;
|
|
|
|
R[R_off[4]] = ((R4 << 8) ^ MULT_TAB[(R4 >> 24) & 0xFF]) ^ R2 ^ R8;
|
|
|
|
A += R1;
|
|
B += R12;
|
|
C += R9;
|
|
D += R5;
|
|
|
|
store_be(A, &buffer[20*i + 0]);
|
|
store_be(B, &buffer[20*i + 4]);
|
|
store_be(C, &buffer[20*i + 8]);
|
|
store_be(D, &buffer[20*i + 12]);
|
|
store_be(E, &buffer[20*i + 16]);
|
|
}
|
|
|
|
position = 0;
|
|
}
|
|
|
|
/*
|
|
* Turing's byte mixing step
|
|
*/
|
|
u32bit Turing::fixedS(u32bit W)
|
|
{
|
|
byte B = SBOX[get_byte(0, W)];
|
|
W ^= Q_BOX[B];
|
|
W &= 0x00FFFFFF;
|
|
W |= B << 24;
|
|
|
|
B = SBOX[get_byte(1, W)];
|
|
W ^= rotate_left(Q_BOX[B], 8);
|
|
W &= 0xFF00FFFF;
|
|
W |= B << 16;
|
|
|
|
B = SBOX[get_byte(2, W)];
|
|
W ^= rotate_left(Q_BOX[B], 16);
|
|
W &= 0xFFFF00FF;
|
|
W |= B << 8;
|
|
|
|
B = SBOX[get_byte(3, W)];
|
|
W ^= rotate_left(Q_BOX[B], 24);
|
|
W &= 0xFFFFFF00;
|
|
W |= B;
|
|
|
|
return W;
|
|
}
|
|
|
|
/*
|
|
* Turing Key Schedule
|
|
*/
|
|
void Turing::key_schedule(const byte key[], size_t length)
|
|
{
|
|
K.resize(length / 4);
|
|
for(size_t i = 0; i != length; ++i)
|
|
K[i/4] = (K[i/4] << 8) + key[i];
|
|
|
|
for(size_t i = 0; i != K.size(); ++i)
|
|
K[i] = fixedS(K[i]);
|
|
|
|
PHT(K);
|
|
|
|
for(u32bit i = 0; i != 256; ++i)
|
|
{
|
|
u32bit W0 = 0, C0 = i;
|
|
u32bit W1 = 0, C1 = i;
|
|
u32bit W2 = 0, C2 = i;
|
|
u32bit W3 = 0, C3 = i;
|
|
|
|
for(size_t j = 0; j < K.size(); ++j)
|
|
{
|
|
C0 = SBOX[get_byte(0, K[j]) ^ C0];
|
|
C1 = SBOX[get_byte(1, K[j]) ^ C1];
|
|
C2 = SBOX[get_byte(2, K[j]) ^ C2];
|
|
C3 = SBOX[get_byte(3, K[j]) ^ C3];
|
|
|
|
W0 ^= rotate_left(Q_BOX[C0], j);
|
|
W1 ^= rotate_left(Q_BOX[C1], j + 8);
|
|
W2 ^= rotate_left(Q_BOX[C2], j + 16);
|
|
W3 ^= rotate_left(Q_BOX[C3], j + 24);
|
|
}
|
|
|
|
S0[i] = (W0 & 0x00FFFFFF) | (C0 << 24);
|
|
S1[i] = (W1 & 0xFF00FFFF) | (C1 << 16);
|
|
S2[i] = (W2 & 0xFFFF00FF) | (C2 << 8);
|
|
S3[i] = (W3 & 0xFFFFFF00) | C3;
|
|
}
|
|
|
|
set_iv(0, 0);
|
|
}
|
|
|
|
/*
|
|
* Resynchronization
|
|
*/
|
|
void Turing::set_iv(const byte iv[], size_t length)
|
|
{
|
|
if(!valid_iv_length(length))
|
|
throw Invalid_IV_Length(name(), length);
|
|
|
|
SecureVector<u32bit> IV(length / 4);
|
|
for(size_t i = 0; i != length; ++i)
|
|
IV[i/4] = (IV[i/4] << 8) + iv[i];
|
|
|
|
for(size_t i = 0; i != IV.size(); ++i)
|
|
R[i] = IV[i] = fixedS(IV[i]);
|
|
|
|
for(size_t i = 0; i != K.size(); ++i)
|
|
R[i+IV.size()] = K[i];
|
|
|
|
R[K.size() + IV.size()] = (0x010203 << 8) | (K.size() << 4) | IV.size();
|
|
|
|
for(size_t i = K.size() + IV.size() + 1; i != 17; ++i)
|
|
{
|
|
const u32bit W = R[i-K.size()-IV.size()-1] + R[i-1];
|
|
R[i] = S0[get_byte(0, W)] ^ S1[get_byte(1, W)] ^
|
|
S2[get_byte(2, W)] ^ S3[get_byte(3, W)];
|
|
}
|
|
|
|
PHT(R);
|
|
|
|
generate();
|
|
}
|
|
|
|
/*
|
|
* Clear memory of sensitive data
|
|
*/
|
|
void Turing::clear()
|
|
{
|
|
zeroise(S0);
|
|
zeroise(S1);
|
|
zeroise(S2);
|
|
zeroise(S3);
|
|
|
|
zeroise(buffer);
|
|
position = 0;
|
|
}
|
|
|
|
}
|
|
/*
|
|
* WiderWake
|
|
* (C) 1999-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* Combine cipher stream with message
|
|
*/
|
|
void WiderWake_41_BE::cipher(const byte in[], byte out[], size_t length)
|
|
{
|
|
while(length >= buffer.size() - position)
|
|
{
|
|
xor_buf(out, in, &buffer[position], buffer.size() - position);
|
|
length -= (buffer.size() - position);
|
|
in += (buffer.size() - position);
|
|
out += (buffer.size() - position);
|
|
generate(buffer.size());
|
|
}
|
|
xor_buf(out, in, &buffer[position], length);
|
|
position += length;
|
|
}
|
|
|
|
/*
|
|
* Generate cipher stream
|
|
*/
|
|
void WiderWake_41_BE::generate(size_t length)
|
|
{
|
|
u32bit R0 = state[0], R1 = state[1],
|
|
R2 = state[2], R3 = state[3],
|
|
R4 = state[4];
|
|
|
|
for(size_t i = 0; i != length; i += 8)
|
|
{
|
|
u32bit R0a;
|
|
|
|
store_be(R3, &buffer[i]);
|
|
|
|
R0a = R4 + R3; R3 += R2; R2 += R1; R1 += R0;
|
|
R0a = (R0a >> 8) ^ T[(R0a & 0xFF)];
|
|
R1 = (R1 >> 8) ^ T[(R1 & 0xFF)];
|
|
R2 = (R2 >> 8) ^ T[(R2 & 0xFF)];
|
|
R3 = (R3 >> 8) ^ T[(R3 & 0xFF)];
|
|
R4 = R0; R0 = R0a;
|
|
|
|
store_be(R3, &buffer[i + 4]);
|
|
|
|
R0a = R4 + R3; R3 += R2; R2 += R1; R1 += R0;
|
|
R0a = (R0a >> 8) ^ T[(R0a & 0xFF)];
|
|
R1 = (R1 >> 8) ^ T[(R1 & 0xFF)];
|
|
R2 = (R2 >> 8) ^ T[(R2 & 0xFF)];
|
|
R3 = (R3 >> 8) ^ T[(R3 & 0xFF)];
|
|
R4 = R0; R0 = R0a;
|
|
}
|
|
|
|
state[0] = R0;
|
|
state[1] = R1;
|
|
state[2] = R2;
|
|
state[3] = R3;
|
|
state[4] = R4;
|
|
|
|
position = 0;
|
|
}
|
|
|
|
/*
|
|
* WiderWake Key Schedule
|
|
*/
|
|
void WiderWake_41_BE::key_schedule(const byte key[], size_t)
|
|
{
|
|
for(size_t i = 0; i != 4; ++i)
|
|
t_key[i] = load_be<u32bit>(key, i);
|
|
|
|
static const u32bit MAGIC[8] = {
|
|
0x726A8F3B, 0xE69A3B5C, 0xD3C71FE5, 0xAB3C73D2,
|
|
0x4D3A8EB3, 0x0396D6E8, 0x3D4C2F7A, 0x9EE27CF3 };
|
|
|
|
for(size_t i = 0; i != 4; ++i)
|
|
T[i] = t_key[i];
|
|
|
|
for(size_t i = 4; i != 256; ++i)
|
|
{
|
|
u32bit X = T[i-1] + T[i-4];
|
|
T[i] = (X >> 3) ^ MAGIC[X % 8];
|
|
}
|
|
|
|
for(size_t i = 0; i != 23; ++i)
|
|
T[i] += T[i+89];
|
|
|
|
u32bit X = T[33];
|
|
u32bit Z = (T[59] | 0x01000001) & 0xFF7FFFFF;
|
|
for(size_t i = 0; i != 256; ++i)
|
|
{
|
|
X = (X & 0xFF7FFFFF) + Z;
|
|
T[i] = (T[i] & 0x00FFFFFF) ^ X;
|
|
}
|
|
|
|
X = (T[X & 0xFF] ^ X) & 0xFF;
|
|
Z = T[0];
|
|
T[0] = T[X];
|
|
for(size_t i = 1; i != 256; ++i)
|
|
{
|
|
T[X] = T[i];
|
|
X = (T[i ^ X] ^ X) & 0xFF;
|
|
T[i] = T[X];
|
|
}
|
|
T[X] = Z;
|
|
|
|
position = 0;
|
|
|
|
const byte ZEROS[8] = { 0 };
|
|
set_iv(ZEROS, sizeof(ZEROS));
|
|
}
|
|
|
|
/*
|
|
* Resynchronization
|
|
*/
|
|
void WiderWake_41_BE::set_iv(const byte iv[], size_t length)
|
|
{
|
|
if(!valid_iv_length(length))
|
|
throw Invalid_IV_Length(name(), length);
|
|
|
|
for(size_t i = 0; i != 4; ++i)
|
|
state[i] = t_key[i];
|
|
|
|
state[4] = load_be<u32bit>(iv, 0);
|
|
state[0] ^= state[4];
|
|
state[2] ^= load_be<u32bit>(iv, 1);
|
|
|
|
generate(8*4);
|
|
generate(buffer.size());
|
|
}
|
|
|
|
/*
|
|
* Clear memory of sensitive data
|
|
*/
|
|
void WiderWake_41_BE::clear()
|
|
{
|
|
position = 0;
|
|
zeroise(t_key);
|
|
zeroise(state);
|
|
zeroise(T);
|
|
zeroise(buffer);
|
|
}
|
|
|
|
}
|
|
/*
|
|
* Runtime assertion checking
|
|
* (C) 2010 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
#include <sstream>
|
|
|
|
namespace Botan {
|
|
|
|
void assertion_failure(const char* expr_str,
|
|
const char* msg,
|
|
const char* func,
|
|
const char* file,
|
|
int line)
|
|
{
|
|
std::ostringstream format;
|
|
|
|
format << "Assertion " << expr_str << " failed ";
|
|
|
|
if(msg)
|
|
format << "(" << msg << ") ";
|
|
|
|
if(func)
|
|
format << "in " << func << " ";
|
|
|
|
format << "@" << file << ":" << line;
|
|
|
|
throw Internal_Error(format.str());
|
|
}
|
|
|
|
}
|
|
/*
|
|
* Character Set Handling
|
|
* (C) 1999-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
#include <cctype>
|
|
|
|
namespace Botan {
|
|
|
|
namespace Charset {
|
|
|
|
namespace {
|
|
|
|
/*
|
|
* Convert from UCS-2 to ISO 8859-1
|
|
*/
|
|
std::string ucs2_to_latin1(const std::string& ucs2)
|
|
{
|
|
if(ucs2.size() % 2 == 1)
|
|
throw Decoding_Error("UCS-2 string has an odd number of bytes");
|
|
|
|
std::string latin1;
|
|
|
|
for(size_t i = 0; i != ucs2.size(); i += 2)
|
|
{
|
|
const byte c1 = ucs2[i];
|
|
const byte c2 = ucs2[i+1];
|
|
|
|
if(c1 != 0)
|
|
throw Decoding_Error("UCS-2 has non-Latin1 characters");
|
|
|
|
latin1 += static_cast<char>(c2);
|
|
}
|
|
|
|
return latin1;
|
|
}
|
|
|
|
/*
|
|
* Convert from UTF-8 to ISO 8859-1
|
|
*/
|
|
std::string utf8_to_latin1(const std::string& utf8)
|
|
{
|
|
std::string iso8859;
|
|
|
|
size_t position = 0;
|
|
while(position != utf8.size())
|
|
{
|
|
const byte c1 = static_cast<byte>(utf8[position++]);
|
|
|
|
if(c1 <= 0x7F)
|
|
iso8859 += static_cast<char>(c1);
|
|
else if(c1 >= 0xC0 && c1 <= 0xC7)
|
|
{
|
|
if(position == utf8.size())
|
|
throw Decoding_Error("UTF-8: sequence truncated");
|
|
|
|
const byte c2 = static_cast<byte>(utf8[position++]);
|
|
const byte iso_char = ((c1 & 0x07) << 6) | (c2 & 0x3F);
|
|
|
|
if(iso_char <= 0x7F)
|
|
throw Decoding_Error("UTF-8: sequence longer than needed");
|
|
|
|
iso8859 += static_cast<char>(iso_char);
|
|
}
|
|
else
|
|
throw Decoding_Error("UTF-8: Unicode chars not in Latin1 used");
|
|
}
|
|
|
|
return iso8859;
|
|
}
|
|
|
|
/*
|
|
* Convert from ISO 8859-1 to UTF-8
|
|
*/
|
|
std::string latin1_to_utf8(const std::string& iso8859)
|
|
{
|
|
std::string utf8;
|
|
for(size_t i = 0; i != iso8859.size(); ++i)
|
|
{
|
|
const byte c = static_cast<byte>(iso8859[i]);
|
|
|
|
if(c <= 0x7F)
|
|
utf8 += static_cast<char>(c);
|
|
else
|
|
{
|
|
utf8 += static_cast<char>((0xC0 | (c >> 6)));
|
|
utf8 += static_cast<char>((0x80 | (c & 0x3F)));
|
|
}
|
|
}
|
|
return utf8;
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
* Perform character set transcoding
|
|
*/
|
|
std::string transcode(const std::string& str,
|
|
Character_Set to, Character_Set from)
|
|
{
|
|
if(to == LOCAL_CHARSET)
|
|
to = LATIN1_CHARSET;
|
|
if(from == LOCAL_CHARSET)
|
|
from = LATIN1_CHARSET;
|
|
|
|
if(to == from)
|
|
return str;
|
|
|
|
if(from == LATIN1_CHARSET && to == UTF8_CHARSET)
|
|
return latin1_to_utf8(str);
|
|
if(from == UTF8_CHARSET && to == LATIN1_CHARSET)
|
|
return utf8_to_latin1(str);
|
|
if(from == UCS2_CHARSET && to == LATIN1_CHARSET)
|
|
return ucs2_to_latin1(str);
|
|
|
|
throw Invalid_Argument("Unknown transcoding operation from " +
|
|
to_string(from) + " to " + to_string(to));
|
|
}
|
|
|
|
/*
|
|
* Check if a character represents a digit
|
|
*/
|
|
bool is_digit(char c)
|
|
{
|
|
if(c == '0' || c == '1' || c == '2' || c == '3' || c == '4' ||
|
|
c == '5' || c == '6' || c == '7' || c == '8' || c == '9')
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
* Check if a character represents whitespace
|
|
*/
|
|
bool is_space(char c)
|
|
{
|
|
if(c == ' ' || c == '\t' || c == '\n' || c == '\r')
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
* Convert a character to a digit
|
|
*/
|
|
byte char2digit(char c)
|
|
{
|
|
switch(c)
|
|
{
|
|
case '0': return 0;
|
|
case '1': return 1;
|
|
case '2': return 2;
|
|
case '3': return 3;
|
|
case '4': return 4;
|
|
case '5': return 5;
|
|
case '6': return 6;
|
|
case '7': return 7;
|
|
case '8': return 8;
|
|
case '9': return 9;
|
|
}
|
|
|
|
throw Invalid_Argument("char2digit: Input is not a digit character");
|
|
}
|
|
|
|
/*
|
|
* Convert a digit to a character
|
|
*/
|
|
char digit2char(byte b)
|
|
{
|
|
switch(b)
|
|
{
|
|
case 0: return '0';
|
|
case 1: return '1';
|
|
case 2: return '2';
|
|
case 3: return '3';
|
|
case 4: return '4';
|
|
case 5: return '5';
|
|
case 6: return '6';
|
|
case 7: return '7';
|
|
case 8: return '8';
|
|
case 9: return '9';
|
|
}
|
|
|
|
throw Invalid_Argument("digit2char: Input is not a digit");
|
|
}
|
|
|
|
/*
|
|
* Case-insensitive character comparison
|
|
*/
|
|
bool caseless_cmp(char a, char b)
|
|
{
|
|
return (std::tolower(static_cast<unsigned char>(a)) ==
|
|
std::tolower(static_cast<unsigned char>(b)));
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
/*
|
|
* Runtime CPU detection
|
|
* (C) 2009-2010 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
#if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
|
|
|
|
#if defined(BOTAN_TARGET_OS_IS_DARWIN)
|
|
#include <sys/sysctl.h>
|
|
#endif
|
|
|
|
#if defined(BOTAN_TARGET_OS_IS_OPENBSD)
|
|
#include <sys/param.h>
|
|
#include <sys/sysctl.h>
|
|
#include <machine/cpu.h>
|
|
#endif
|
|
|
|
#endif
|
|
|
|
#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
|
|
|
|
#if defined(BOTAN_BUILD_COMPILER_IS_MSVC)
|
|
|
|
#include <intrin.h>
|
|
#define CALL_CPUID(type, out) do { __cpuid((int*)out, type); } while(0)
|
|
|
|
#elif defined(BOTAN_BUILD_COMPILER_IS_INTEL)
|
|
|
|
#include <ia32intrin.h>
|
|
#define CALL_CPUID(type, out) do { __cpuid((int*)out, type); } while(0)
|
|
|
|
#elif defined(BOTAN_BUILD_COMPILER_IS_GCC) && (BOTAN_GCC_VERSION >= 430)
|
|
|
|
// Only available starting in GCC 4.3
|
|
#include <cpuid.h>
|
|
|
|
namespace {
|
|
|
|
/*
|
|
* Prevent inlining to work around GCC bug 44174
|
|
*/
|
|
void __attribute__((__noinline__)) call_gcc_cpuid(Botan::u32bit type,
|
|
Botan::u32bit out[4])
|
|
{
|
|
__get_cpuid(type, out, out+1, out+2, out+3);
|
|
}
|
|
|
|
#define CALL_CPUID call_gcc_cpuid
|
|
|
|
}
|
|
|
|
#elif defined(BOTAN_TARGET_ARCH_IS_X86_64) && \
|
|
(defined(BOTAN_BUILD_COMPILER_IS_CLANG) || defined(BOTAN_BUILD_COMPILER_IS_GCC))
|
|
|
|
/*
|
|
* We can't safely use this on x86-32 as some 32-bit ABIs use ebx as
|
|
* a PIC register, and in theory there are some x86-32s still out
|
|
* there that don't support cpuid at all; it requires strange
|
|
* contortions to detect them.
|
|
*/
|
|
|
|
#define CALL_CPUID(type, out) \
|
|
asm("cpuid\n\t" : "=a" (out[0]), "=b" (out[1]), "=c" (out[2]), "=d" (out[3]) \
|
|
: "0" (type))
|
|
|
|
#else
|
|
#warning "No method of calling CPUID for this compiler"
|
|
#endif
|
|
|
|
#endif
|
|
|
|
#ifndef CALL_CPUID
|
|
// In all other cases, just zeroize the supposed cpuid output
|
|
#define CALL_CPUID(type, out) \
|
|
do { out[0] = out[1] = out[2] = out[3] = 0; } while(0);
|
|
#endif
|
|
|
|
namespace Botan {
|
|
|
|
u64bit CPUID::x86_processor_flags = 0;
|
|
size_t CPUID::cache_line = 32;
|
|
bool CPUID::altivec_capable = false;
|
|
|
|
namespace {
|
|
|
|
u32bit get_x86_cache_line_size()
|
|
{
|
|
const u32bit INTEL_CPUID[3] = { 0x756E6547, 0x6C65746E, 0x49656E69 };
|
|
const u32bit AMD_CPUID[3] = { 0x68747541, 0x444D4163, 0x69746E65 };
|
|
|
|
u32bit cpuid[4] = { 0 };
|
|
CALL_CPUID(0, cpuid);
|
|
|
|
if(same_mem(cpuid + 1, INTEL_CPUID, 3))
|
|
{
|
|
CALL_CPUID(1, cpuid);
|
|
return 8 * get_byte(2, cpuid[1]);
|
|
}
|
|
else if(same_mem(cpuid + 1, AMD_CPUID, 3))
|
|
{
|
|
CALL_CPUID(0x80000005, cpuid);
|
|
return get_byte(3, cpuid[2]);
|
|
}
|
|
else
|
|
return 32; // default cache line guess
|
|
}
|
|
|
|
#if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
|
|
|
|
bool altivec_check_sysctl()
|
|
{
|
|
#if defined(BOTAN_TARGET_OS_IS_DARWIN) || defined(BOTAN_TARGET_OS_IS_OPENBSD)
|
|
|
|
#if defined(BOTAN_TARGET_OS_IS_OPENBSD)
|
|
int sels[2] = { CTL_MACHDEP, CPU_ALTIVEC };
|
|
#else
|
|
// From Apple's docs
|
|
int sels[2] = { CTL_HW, HW_VECTORUNIT };
|
|
#endif
|
|
int vector_type = 0;
|
|
size_t length = sizeof(vector_type);
|
|
int error = sysctl(sels, 2, &vector_type, &length, NULL, 0);
|
|
|
|
if(error == 0 && vector_type > 0)
|
|
return true;
|
|
#endif
|
|
|
|
return false;
|
|
}
|
|
|
|
bool altivec_check_pvr_emul()
|
|
{
|
|
bool altivec_capable = false;
|
|
|
|
#if defined(BOTAN_TARGET_OS_IS_LINUX) || defined(BOTAN_TARGET_OS_IS_NETBSD)
|
|
|
|
/*
|
|
On PowerPC, MSR 287 is PVR, the Processor Version Number
|
|
Normally it is only accessible to ring 0, but Linux and NetBSD
|
|
(others, too, maybe?) will trap and emulate it for us.
|
|
|
|
PVR identifiers for various AltiVec enabled CPUs. Taken from
|
|
PearPC and Linux sources, mostly.
|
|
*/
|
|
|
|
const u16bit PVR_G4_7400 = 0x000C;
|
|
const u16bit PVR_G5_970 = 0x0039;
|
|
const u16bit PVR_G5_970FX = 0x003C;
|
|
const u16bit PVR_G5_970MP = 0x0044;
|
|
const u16bit PVR_G5_970GX = 0x0045;
|
|
const u16bit PVR_POWER6 = 0x003E;
|
|
const u16bit PVR_POWER7 = 0x003F;
|
|
const u16bit PVR_CELL_PPU = 0x0070;
|
|
|
|
// Motorola produced G4s with PVR 0x800[0123C] (at least)
|
|
const u16bit PVR_G4_74xx_24 = 0x800;
|
|
|
|
u32bit pvr = 0;
|
|
|
|
asm volatile("mfspr %0, 287" : "=r" (pvr));
|
|
|
|
// Top 16 bit suffice to identify model
|
|
pvr >>= 16;
|
|
|
|
altivec_capable |= (pvr == PVR_G4_7400);
|
|
altivec_capable |= ((pvr >> 4) == PVR_G4_74xx_24);
|
|
altivec_capable |= (pvr == PVR_G5_970);
|
|
altivec_capable |= (pvr == PVR_G5_970FX);
|
|
altivec_capable |= (pvr == PVR_G5_970MP);
|
|
altivec_capable |= (pvr == PVR_G5_970GX);
|
|
altivec_capable |= (pvr == PVR_POWER6);
|
|
altivec_capable |= (pvr == PVR_POWER7);
|
|
altivec_capable |= (pvr == PVR_CELL_PPU);
|
|
#endif
|
|
|
|
return altivec_capable;
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
void CPUID::initialize()
|
|
{
|
|
u32bit cpuid[4] = { 0 };
|
|
CALL_CPUID(1, cpuid);
|
|
|
|
x86_processor_flags = (static_cast<u64bit>(cpuid[2]) << 32) | cpuid[3];
|
|
|
|
#if defined(BOTAN_TARGET_ARCH_IS_X86_64)
|
|
/*
|
|
* If we don't have access to CPUID, we can still safely assume that
|
|
* any x86-64 processor has SSE2.
|
|
*/
|
|
if(x86_processor_flags == 0)
|
|
x86_processor_flags |= (1 << CPUID_SSE2_BIT);
|
|
#endif
|
|
|
|
cache_line = get_x86_cache_line_size();
|
|
|
|
altivec_capable = false;
|
|
|
|
#if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
|
|
if(altivec_check_sysctl() || altivec_check_pvr_emul())
|
|
altivec_capable = true;
|
|
#endif
|
|
}
|
|
|
|
}
|
|
/*
|
|
* Data Store
|
|
* (C) 1999-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* Default Matcher transform operation (identity)
|
|
*/
|
|
std::pair<std::string, std::string>
|
|
Data_Store::Matcher::transform(const std::string& key,
|
|
const std::string& value) const
|
|
{
|
|
return std::make_pair(key, value);
|
|
}
|
|
|
|
/*
|
|
* Data_Store Equality Comparison
|
|
*/
|
|
bool Data_Store::operator==(const Data_Store& other) const
|
|
{
|
|
return (contents == other.contents);
|
|
}
|
|
|
|
/*
|
|
* Check if this key has at least one value
|
|
*/
|
|
bool Data_Store::has_value(const std::string& key) const
|
|
{
|
|
return (contents.lower_bound(key) != contents.end());
|
|
}
|
|
|
|
/*
|
|
* Search based on an arbitrary predicate
|
|
*/
|
|
std::multimap<std::string, std::string>
|
|
Data_Store::search_with(const Matcher& matcher) const
|
|
{
|
|
std::multimap<std::string, std::string> out;
|
|
|
|
std::multimap<std::string, std::string>::const_iterator i =
|
|
contents.begin();
|
|
|
|
while(i != contents.end())
|
|
{
|
|
if(matcher(i->first, i->second))
|
|
{
|
|
std::pair<std::string, std::string> p(
|
|
matcher.transform(i->first, i->second));
|
|
|
|
multimap_insert(out, p.first, p.second);
|
|
}
|
|
|
|
++i;
|
|
}
|
|
|
|
return out;
|
|
}
|
|
|
|
/*
|
|
* Search based on key equality
|
|
*/
|
|
std::vector<std::string> Data_Store::get(const std::string& looking_for) const
|
|
{
|
|
typedef std::multimap<std::string, std::string>::const_iterator iter;
|
|
|
|
std::pair<iter, iter> range = contents.equal_range(looking_for);
|
|
|
|
std::vector<std::string> out;
|
|
for(iter i = range.first; i != range.second; ++i)
|
|
out.push_back(i->second);
|
|
return out;
|
|
}
|
|
|
|
/*
|
|
* Get a single atom
|
|
*/
|
|
std::string Data_Store::get1(const std::string& key) const
|
|
{
|
|
std::vector<std::string> vals = get(key);
|
|
|
|
if(vals.empty())
|
|
throw Invalid_State("Data_Store::get1: Not values for " + key);
|
|
if(vals.size() > 1)
|
|
throw Invalid_State("Data_Store::get1: More than one value for " + key);
|
|
|
|
return vals[0];
|
|
}
|
|
|
|
/*
|
|
* Get a single MemoryVector atom
|
|
*/
|
|
MemoryVector<byte>
|
|
Data_Store::get1_memvec(const std::string& key) const
|
|
{
|
|
std::vector<std::string> vals = get(key);
|
|
|
|
if(vals.empty())
|
|
return MemoryVector<byte>();
|
|
|
|
if(vals.size() > 1)
|
|
throw Invalid_State("Data_Store::get1_memvec: Multiple values for " +
|
|
key);
|
|
|
|
return hex_decode(vals[0]);
|
|
}
|
|
|
|
/*
|
|
* Get a single u32bit atom
|
|
*/
|
|
u32bit Data_Store::get1_u32bit(const std::string& key,
|
|
u32bit default_val) const
|
|
{
|
|
std::vector<std::string> vals = get(key);
|
|
|
|
if(vals.empty())
|
|
return default_val;
|
|
else if(vals.size() > 1)
|
|
throw Invalid_State("Data_Store::get1_u32bit: Multiple values for " +
|
|
key);
|
|
|
|
return to_u32bit(vals[0]);
|
|
}
|
|
|
|
/*
|
|
* Insert a single key and value
|
|
*/
|
|
void Data_Store::add(const std::string& key, const std::string& val)
|
|
{
|
|
multimap_insert(contents, key, val);
|
|
}
|
|
|
|
/*
|
|
* Insert a single key and value
|
|
*/
|
|
void Data_Store::add(const std::string& key, u32bit val)
|
|
{
|
|
add(key, to_string(val));
|
|
}
|
|
|
|
/*
|
|
* Insert a single key and value
|
|
*/
|
|
void Data_Store::add(const std::string& key, const MemoryRegion<byte>& val)
|
|
{
|
|
add(key, hex_encode(&val[0], val.size()));
|
|
}
|
|
|
|
/*
|
|
* Insert a mapping of key/value pairs
|
|
*/
|
|
void Data_Store::add(const std::multimap<std::string, std::string>& in)
|
|
{
|
|
std::multimap<std::string, std::string>::const_iterator i = in.begin();
|
|
while(i != in.end())
|
|
{
|
|
contents.insert(*i);
|
|
++i;
|
|
}
|
|
}
|
|
|
|
}
|
|
/**
|
|
* Dynamically Loaded Object
|
|
* (C) 2010 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
#include <stdexcept>
|
|
|
|
#if defined(BOTAN_TARGET_OS_HAS_DLOPEN)
|
|
#include <dlfcn.h>
|
|
#elif defined(BOTAN_TARGET_OS_HAS_LOADLIBRARY)
|
|
#include <windows.h>
|
|
#endif
|
|
|
|
namespace Botan {
|
|
|
|
namespace {
|
|
|
|
void raise_runtime_loader_exception(const std::string& lib_name,
|
|
const char* msg)
|
|
{
|
|
throw std::runtime_error("Failed to load " + lib_name + ": " +
|
|
(msg ? msg : "Unknown error"));
|
|
}
|
|
|
|
}
|
|
|
|
Dynamically_Loaded_Library::Dynamically_Loaded_Library(
|
|
const std::string& library) :
|
|
lib_name(library), lib(0)
|
|
{
|
|
#if defined(BOTAN_TARGET_OS_HAS_DLOPEN)
|
|
lib = ::dlopen(lib_name.c_str(), RTLD_LAZY);
|
|
|
|
if(!lib)
|
|
raise_runtime_loader_exception(lib_name, dlerror());
|
|
|
|
#elif defined(BOTAN_TARGET_OS_HAS_LOADLIBRARY)
|
|
lib = ::LoadLibraryA(lib_name.c_str());
|
|
|
|
if(!lib)
|
|
raise_runtime_loader_exception(lib_name, "LoadLibrary failed");
|
|
#endif
|
|
|
|
if(!lib)
|
|
raise_runtime_loader_exception(lib_name, "Dynamic load not supported");
|
|
}
|
|
|
|
Dynamically_Loaded_Library::~Dynamically_Loaded_Library()
|
|
{
|
|
#if defined(BOTAN_TARGET_OS_HAS_DLOPEN)
|
|
::dlclose(lib);
|
|
#elif defined(BOTAN_TARGET_OS_HAS_LOADLIBRARY)
|
|
::FreeLibrary((HMODULE)lib);
|
|
#endif
|
|
}
|
|
|
|
void* Dynamically_Loaded_Library::resolve_symbol(const std::string& symbol)
|
|
{
|
|
void* addr = 0;
|
|
|
|
#if defined(BOTAN_TARGET_OS_HAS_DLOPEN)
|
|
addr = ::dlsym(lib, symbol.c_str());
|
|
#elif defined(BOTAN_TARGET_OS_HAS_LOADLIBRARY)
|
|
addr = reinterpret_cast<void*>(::GetProcAddress((HMODULE)lib,
|
|
symbol.c_str()));
|
|
#endif
|
|
|
|
if(!addr)
|
|
throw std::runtime_error("Failed to resolve symbol " + symbol +
|
|
" in " + lib_name);
|
|
|
|
return addr;
|
|
}
|
|
|
|
}
|
|
/*
|
|
* Memory Locking Functions
|
|
* (C) 1999-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
#if defined(BOTAN_TARGET_OS_HAS_POSIX_MLOCK)
|
|
#include <sys/types.h>
|
|
#include <sys/mman.h>
|
|
#elif defined(BOTAN_TARGET_OS_HAS_WIN32_VIRTUAL_LOCK)
|
|
#include <windows.h>
|
|
#endif
|
|
|
|
namespace Botan {
|
|
|
|
bool has_mlock()
|
|
{
|
|
byte buf[4096];
|
|
if(!lock_mem(&buf, sizeof(buf)))
|
|
return false;
|
|
unlock_mem(&buf, sizeof(buf));
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* Lock an area of memory into RAM
|
|
*/
|
|
bool lock_mem(void* ptr, size_t bytes)
|
|
{
|
|
Q_UNUSED(ptr);
|
|
Q_UNUSED(bytes);
|
|
#if defined(BOTAN_TARGET_OS_HAS_POSIX_MLOCK)
|
|
return (::mlock(static_cast<char*>(ptr), bytes) == 0);
|
|
#elif defined(BOTAN_TARGET_OS_HAS_WIN32_VIRTUAL_LOCK)
|
|
return (::VirtualLock(ptr, bytes) != 0);
|
|
#else
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* Unlock a previously locked region of memory
|
|
*/
|
|
void unlock_mem(void* ptr, size_t bytes)
|
|
{
|
|
Q_UNUSED(ptr);
|
|
Q_UNUSED(bytes);
|
|
#if defined(BOTAN_TARGET_OS_HAS_POSIX_MLOCK)
|
|
::munlock(static_cast<char*>(ptr), bytes);
|
|
#elif defined(BOTAN_TARGET_OS_HAS_WIN32_VIRTUAL_LOCK)
|
|
::VirtualUnlock(ptr, bytes);
|
|
#endif
|
|
}
|
|
|
|
}
|
|
/*
|
|
* Parser Functions
|
|
* (C) 1999-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* Convert a string into an integer
|
|
*/
|
|
u32bit to_u32bit(const std::string& number)
|
|
{
|
|
u32bit n = 0;
|
|
|
|
for(std::string::const_iterator i = number.begin(); i != number.end(); ++i)
|
|
{
|
|
const u32bit OVERFLOW_MARK = 0xFFFFFFFF / 10;
|
|
|
|
if(*i == ' ')
|
|
continue;
|
|
|
|
byte digit = Charset::char2digit(*i);
|
|
|
|
if((n > OVERFLOW_MARK) || (n == OVERFLOW_MARK && digit > 5))
|
|
throw Decoding_Error("to_u32bit: Integer overflow");
|
|
n *= 10;
|
|
n += digit;
|
|
}
|
|
return n;
|
|
}
|
|
|
|
/*
|
|
* Convert an integer into a string
|
|
*/
|
|
std::string to_string(u64bit n, size_t min_len)
|
|
{
|
|
std::string lenstr;
|
|
if(n)
|
|
{
|
|
while(n > 0)
|
|
{
|
|
lenstr = Charset::digit2char(n % 10) + lenstr;
|
|
n /= 10;
|
|
}
|
|
}
|
|
else
|
|
lenstr = "0";
|
|
|
|
while(lenstr.size() < min_len)
|
|
lenstr = "0" + lenstr;
|
|
|
|
return lenstr;
|
|
}
|
|
|
|
/*
|
|
* Convert a string into a time duration
|
|
*/
|
|
u32bit timespec_to_u32bit(const std::string& timespec)
|
|
{
|
|
if(timespec == "")
|
|
return 0;
|
|
|
|
const char suffix = timespec[timespec.size()-1];
|
|
std::string value = timespec.substr(0, timespec.size()-1);
|
|
|
|
u32bit scale = 1;
|
|
|
|
if(Charset::is_digit(suffix))
|
|
value += suffix;
|
|
else if(suffix == 's')
|
|
scale = 1;
|
|
else if(suffix == 'm')
|
|
scale = 60;
|
|
else if(suffix == 'h')
|
|
scale = 60 * 60;
|
|
else if(suffix == 'd')
|
|
scale = 24 * 60 * 60;
|
|
else if(suffix == 'y')
|
|
scale = 365 * 24 * 60 * 60;
|
|
else
|
|
throw Decoding_Error("timespec_to_u32bit: Bad input " + timespec);
|
|
|
|
return scale * to_u32bit(value);
|
|
}
|
|
|
|
/*
|
|
* Parse a SCAN-style algorithm name
|
|
*/
|
|
std::vector<std::string> parse_algorithm_name(const std::string& namex)
|
|
{
|
|
if(namex.find('(') == std::string::npos &&
|
|
namex.find(')') == std::string::npos)
|
|
return std::vector<std::string>(1, namex);
|
|
|
|
std::string name = namex, substring;
|
|
std::vector<std::string> elems;
|
|
size_t level = 0;
|
|
|
|
elems.push_back(name.substr(0, name.find('(')));
|
|
name = name.substr(name.find('('));
|
|
|
|
for(std::string::const_iterator i = name.begin(); i != name.end(); ++i)
|
|
{
|
|
char c = *i;
|
|
|
|
if(c == '(')
|
|
++level;
|
|
if(c == ')')
|
|
{
|
|
if(level == 1 && i == name.end() - 1)
|
|
{
|
|
if(elems.size() == 1)
|
|
elems.push_back(substring.substr(1));
|
|
else
|
|
elems.push_back(substring);
|
|
return elems;
|
|
}
|
|
|
|
if(level == 0 || (level == 1 && i != name.end() - 1))
|
|
throw Invalid_Algorithm_Name(namex);
|
|
--level;
|
|
}
|
|
|
|
if(c == ',' && level == 1)
|
|
{
|
|
if(elems.size() == 1)
|
|
elems.push_back(substring.substr(1));
|
|
else
|
|
elems.push_back(substring);
|
|
substring.clear();
|
|
}
|
|
else
|
|
substring += c;
|
|
}
|
|
|
|
if(substring != "")
|
|
throw Invalid_Algorithm_Name(namex);
|
|
|
|
return elems;
|
|
}
|
|
|
|
/*
|
|
* Split the string on slashes
|
|
*/
|
|
std::vector<std::string> split_on(const std::string& str, char delim)
|
|
{
|
|
std::vector<std::string> elems;
|
|
if(str == "") return elems;
|
|
|
|
std::string substr;
|
|
for(std::string::const_iterator i = str.begin(); i != str.end(); ++i)
|
|
{
|
|
if(*i == delim)
|
|
{
|
|
if(substr != "")
|
|
elems.push_back(substr);
|
|
substr.clear();
|
|
}
|
|
else
|
|
substr += *i;
|
|
}
|
|
|
|
if(substr == "")
|
|
throw Invalid_Argument("Unable to split string: " + str);
|
|
elems.push_back(substr);
|
|
|
|
return elems;
|
|
}
|
|
|
|
/*
|
|
* Parse an ASN.1 OID string
|
|
*/
|
|
std::vector<u32bit> parse_asn1_oid(const std::string& oid)
|
|
{
|
|
std::string substring;
|
|
std::vector<u32bit> oid_elems;
|
|
|
|
for(std::string::const_iterator i = oid.begin(); i != oid.end(); ++i)
|
|
{
|
|
char c = *i;
|
|
|
|
if(c == '.')
|
|
{
|
|
if(substring == "")
|
|
throw Invalid_OID(oid);
|
|
oid_elems.push_back(to_u32bit(substring));
|
|
substring.clear();
|
|
}
|
|
else
|
|
substring += c;
|
|
}
|
|
|
|
if(substring == "")
|
|
throw Invalid_OID(oid);
|
|
oid_elems.push_back(to_u32bit(substring));
|
|
|
|
if(oid_elems.size() < 2)
|
|
throw Invalid_OID(oid);
|
|
|
|
return oid_elems;
|
|
}
|
|
|
|
/*
|
|
* X.500 String Comparison
|
|
*/
|
|
bool x500_name_cmp(const std::string& name1, const std::string& name2)
|
|
{
|
|
std::string::const_iterator p1 = name1.begin();
|
|
std::string::const_iterator p2 = name2.begin();
|
|
|
|
while((p1 != name1.end()) && Charset::is_space(*p1)) ++p1;
|
|
while((p2 != name2.end()) && Charset::is_space(*p2)) ++p2;
|
|
|
|
while(p1 != name1.end() && p2 != name2.end())
|
|
{
|
|
if(Charset::is_space(*p1))
|
|
{
|
|
if(!Charset::is_space(*p2))
|
|
return false;
|
|
|
|
while((p1 != name1.end()) && Charset::is_space(*p1)) ++p1;
|
|
while((p2 != name2.end()) && Charset::is_space(*p2)) ++p2;
|
|
|
|
if(p1 == name1.end() && p2 == name2.end())
|
|
return true;
|
|
}
|
|
|
|
if(!Charset::caseless_cmp(*p1, *p2))
|
|
return false;
|
|
++p1;
|
|
++p2;
|
|
}
|
|
|
|
while((p1 != name1.end()) && Charset::is_space(*p1)) ++p1;
|
|
while((p2 != name2.end()) && Charset::is_space(*p2)) ++p2;
|
|
|
|
if((p1 != name1.end()) || (p2 != name2.end()))
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* Convert a decimal-dotted string to binary IP
|
|
*/
|
|
u32bit string_to_ipv4(const std::string& str)
|
|
{
|
|
std::vector<std::string> parts = split_on(str, '.');
|
|
|
|
if(parts.size() != 4)
|
|
throw Decoding_Error("Invalid IP string " + str);
|
|
|
|
u32bit ip = 0;
|
|
|
|
for(size_t i = 0; i != parts.size(); ++i)
|
|
{
|
|
u32bit octet = to_u32bit(parts[i]);
|
|
|
|
if(octet > 255)
|
|
throw Decoding_Error("Invalid IP string " + str);
|
|
|
|
ip = (ip << 8) | (octet & 0xFF);
|
|
}
|
|
|
|
return ip;
|
|
}
|
|
|
|
/*
|
|
* Convert an IP address to decimal-dotted string
|
|
*/
|
|
std::string ipv4_to_string(u32bit ip)
|
|
{
|
|
std::string str;
|
|
|
|
for(size_t i = 0; i != sizeof(ip); ++i)
|
|
{
|
|
if(i)
|
|
str += ".";
|
|
str += to_string(get_byte(i, ip));
|
|
}
|
|
|
|
return str;
|
|
}
|
|
|
|
}
|
|
/*
|
|
* Time Functions
|
|
* (C) 1999-2010 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
#include <ctime>
|
|
|
|
#if defined(BOTAN_TARGET_OS_HAS_WIN32_GET_SYSTEMTIME)
|
|
#include <windows.h>
|
|
#endif
|
|
|
|
#if defined(BOTAN_TARGET_OS_HAS_GETTIMEOFDAY)
|
|
#include <sys/time.h>
|
|
#endif
|
|
|
|
#if defined(BOTAN_TARGET_OS_HAS_CLOCK_GETTIME)
|
|
|
|
#ifndef _POSIX_C_SOURCE
|
|
#define _POSIX_C_SOURCE 199309
|
|
#endif
|
|
|
|
#include <time.h>
|
|
|
|
#ifndef CLOCK_REALTIME
|
|
#define CLOCK_REALTIME 0
|
|
#endif
|
|
|
|
#endif
|
|
|
|
namespace Botan {
|
|
|
|
namespace {
|
|
|
|
/*
|
|
* Combine a two time values into a single one
|
|
*/
|
|
u64bit combine_timers(u32bit seconds, u32bit parts, u32bit parts_hz)
|
|
{
|
|
static const u64bit NANOSECONDS_UNITS = 1000000000;
|
|
|
|
u64bit res = seconds * NANOSECONDS_UNITS;
|
|
res += parts * (NANOSECONDS_UNITS / parts_hz);
|
|
return res;
|
|
}
|
|
|
|
std::tm do_gmtime(time_t time_val)
|
|
{
|
|
std::tm tm;
|
|
|
|
#if defined(BOTAN_TARGET_OS_HAS_GMTIME_S)
|
|
gmtime_s(&tm, &time_val); // Windows
|
|
#elif defined(BOTAN_TARGET_OS_HAS_GMTIME_R)
|
|
gmtime_r(&time_val, &tm); // Unix/SUSv2
|
|
#else
|
|
std::tm* tm_p = std::gmtime(&time_val);
|
|
if (tm_p == 0)
|
|
throw Encoding_Error("time_t_to_tm could not convert");
|
|
tm = *tm_p;
|
|
#endif
|
|
|
|
return tm;
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
* Get the system clock
|
|
*/
|
|
u64bit system_time()
|
|
{
|
|
return static_cast<u64bit>(std::time(0));
|
|
}
|
|
|
|
/*
|
|
* Convert a time_point to a calendar_point
|
|
*/
|
|
calendar_point calendar_value(u64bit a_time_t)
|
|
{
|
|
std::tm tm = do_gmtime(static_cast<std::time_t>(a_time_t));
|
|
|
|
return calendar_point(tm.tm_year + 1900,
|
|
tm.tm_mon + 1,
|
|
tm.tm_mday,
|
|
tm.tm_hour,
|
|
tm.tm_min,
|
|
tm.tm_sec);
|
|
}
|
|
|
|
u64bit get_nanoseconds_clock()
|
|
{
|
|
#if defined(BOTAN_TARGET_OS_HAS_CLOCK_GETTIME)
|
|
|
|
struct ::timespec tv;
|
|
::clock_gettime(CLOCK_REALTIME, &tv);
|
|
return combine_timers(tv.tv_sec, tv.tv_nsec, 1000000000);
|
|
|
|
#elif defined(BOTAN_TARGET_OS_HAS_GETTIMEOFDAY)
|
|
|
|
struct ::timeval tv;
|
|
::gettimeofday(&tv, 0);
|
|
return combine_timers(tv.tv_sec, tv.tv_usec, 1000000);
|
|
|
|
#elif defined(BOTAN_TARGET_OS_HAS_WIN32_GET_SYSTEMTIME)
|
|
|
|
// Returns time since January 1, 1601 in 100-ns increments
|
|
::FILETIME tv;
|
|
::GetSystemTimeAsFileTime(&tv);
|
|
u64bit tstamp = (static_cast<u64bit>(tv.dwHighDateTime) << 32) |
|
|
tv.dwLowDateTime;
|
|
|
|
return (tstamp * 100); // Scale to 1 nanosecond units
|
|
|
|
#else
|
|
|
|
return combine_timers(static_cast<u32bit>(std::time(0)),
|
|
std::clock(), CLOCKS_PER_SEC);
|
|
|
|
#endif
|
|
}
|
|
|
|
}
|
|
/*
|
|
* User Interface
|
|
* (C) 1999-2007 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* Get a passphrase from the user
|
|
*/
|
|
std::string User_Interface::get_passphrase(const std::string&,
|
|
const std::string&,
|
|
UI_Result& action) const
|
|
{
|
|
action = OK;
|
|
|
|
if(!first_try)
|
|
action = CANCEL_ACTION;
|
|
|
|
return preset_passphrase;
|
|
}
|
|
|
|
/*
|
|
* User_Interface Constructor
|
|
*/
|
|
User_Interface::User_Interface(const std::string& preset) :
|
|
preset_passphrase(preset)
|
|
{
|
|
first_try = true;
|
|
}
|
|
|
|
}
|
|
/*
|
|
* Version Information
|
|
* (C) 1999-2011 Jack Lloyd
|
|
*
|
|
* Distributed under the terms of the Botan license
|
|
*/
|
|
|
|
#include <sstream>
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
These are intentionally compiled rather than inlined, so an
|
|
application running against a shared library can test the true
|
|
version they are running against.
|
|
*/
|
|
|
|
/*
|
|
* Return the version as a string
|
|
*/
|
|
std::string version_string()
|
|
{
|
|
std::ostringstream out;
|
|
|
|
out << "Botan " << version_major() << "."
|
|
<< version_minor() << "."
|
|
<< version_patch() << " (";
|
|
|
|
if(BOTAN_VERSION_DATESTAMP == 0)
|
|
out << "unreleased version";
|
|
else
|
|
out << "released " << version_datestamp();
|
|
|
|
out << ", revision " << BOTAN_VERSION_VC_REVISION;
|
|
out << ", distribution " << BOTAN_DISTRIBUTION_INFO << ")";
|
|
|
|
return out.str();
|
|
}
|
|
|
|
u32bit version_datestamp() { return BOTAN_VERSION_DATESTAMP; }
|
|
|
|
/*
|
|
* Return parts of the version as integers
|
|
*/
|
|
u32bit version_major() { return BOTAN_VERSION_MAJOR; }
|
|
u32bit version_minor() { return BOTAN_VERSION_MINOR; }
|
|
u32bit version_patch() { return BOTAN_VERSION_PATCH; }
|
|
|
|
}
|