amnezia-client/client/3rd/QtSsh/src/botan/botan.h
2020-12-18 15:26:45 +03:00

16210 lines
418 KiB
C++

/*
* Botan 1.10.2 Amalgamation
* (C) 1999-2011 Jack Lloyd and others
*
* Distributed under the terms of the Botan license
*/
#ifndef BOTAN_AMALGAMATION_H__
#define BOTAN_AMALGAMATION_H__
#ifdef USE_SYSTEM_BOTAN
#include <botan/auto_rng.h>
#include <botan/cbc.h>
#include <botan/ctr.h>
#include <botan/der_enc.h>
#include <botan/dh.h>
#include <botan/dl_group.h>
#include <botan/dsa.h>
#include <botan/ec_group.h>
#include <botan/ecdh.h>
#include <botan/ecdsa.h>
#include <botan/hmac.h>
#include <botan/init.h>
#include <botan/lookup.h>
#include <botan/pem.h>
#include <botan/pubkey.h>
#include <botan/rsa.h>
#include <botan/ui.h>
#else
#include <QtGlobal>
#include <iosfwd>
#include <map>
#include <exception>
#include <string>
#include <algorithm>
#include <cstring>
#include <stdexcept>
#include <vector>
#include <utility>
#define BOTAN_VERSION_MAJOR 1
#define BOTAN_VERSION_MINOR 10
#define BOTAN_VERSION_PATCH 2
#define BOTAN_VERSION_DATESTAMP 0
#define BOTAN_VERSION_VC_REVISION "mtn:2bf8ad2c501213efb4cf9b219330b87666988e91"
#define BOTAN_DISTRIBUTION_INFO "unspecified"
//#ifndef BOTAN_DLL
//#define BOTAN_DLL Q_DECL_IMPORT
//#endif
#define BOTAN_DLL
/* Chunk sizes */
#define BOTAN_DEFAULT_BUFFER_SIZE 4096
#define BOTAN_MEM_POOL_CHUNK_SIZE 64*1024
#define BOTAN_BLOCK_CIPHER_PAR_MULT 4
/* BigInt toggles */
#define BOTAN_MP_WORD_BITS 32
#define BOTAN_KARAT_MUL_THRESHOLD 32
#define BOTAN_KARAT_SQR_THRESHOLD 32
/* PK key consistency checking toggles */
#define BOTAN_PUBLIC_KEY_STRONG_CHECKS_ON_LOAD 1
#define BOTAN_PRIVATE_KEY_STRONG_CHECKS_ON_LOAD 0
#define BOTAN_PRIVATE_KEY_STRONG_CHECKS_ON_GENERATE 1
/* Should we use GCC-style inline assembler? */
#if !defined(BOTAN_USE_GCC_INLINE_ASM) && defined(__GNUG__)
#define BOTAN_USE_GCC_INLINE_ASM 1
#endif
#if !defined(BOTAN_USE_GCC_INLINE_ASM)
#define BOTAN_USE_GCC_INLINE_ASM 0
#endif
#ifdef __GNUC__
#define BOTAN_GCC_VERSION \
(__GNUC__ * 100 + __GNUC_MINOR__ * 10 + __GNUC_PATCHLEVEL__)
#else
#define BOTAN_GCC_VERSION 0
#endif
#define BOTAN_TARGET_CPU_IS_LITTLE_ENDIAN
#define BOTAN_TARGET_CPU_IS_X86_FAMILY
#define BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK 1
#if defined(BOTAN_TARGET_CPU_IS_LITTLE_ENDIAN) || \
defined(BOTAN_TARGET_CPU_IS_BIG_ENDIAN)
#define BOTAN_TARGET_CPU_HAS_KNOWN_ENDIANNESS
#endif
#if defined(_MSC_VER)
// 4250: inherits via dominance (diamond inheritence issue)
// 4251: needs DLL interface (STL DLL exports)
#pragma warning(disable: 4250 4251)
#endif
/*
* Compile-time deprecatation warnings
*/
#if !defined(BOTAN_NO_DEPRECATED_WARNINGS)
#if defined(__clang__)
#define BOTAN_DEPRECATED(msg) __attribute__ ((deprecated))
#elif defined(_MSC_VER)
#define BOTAN_DEPRECATED(msg) __declspec(deprecated(msg))
#elif defined(__GNUG__)
#if BOTAN_GCC_VERSION >= 450 && !defined(__INTEL_COMPILER)
#define BOTAN_DEPRECATED(msg) __attribute__ ((deprecated(msg)))
#else
#define BOTAN_DEPRECATED(msg) __attribute__ ((deprecated))
#endif
#endif
#endif
#if !defined(BOTAN_DEPRECATED)
#define BOTAN_DEPRECATED(msg)
#endif
/*
* Module availability definitions
*/
#define BOTAN_HAS_ADLER32
#define BOTAN_HAS_AES
#define BOTAN_HAS_ALGORITHM_FACTORY
#define BOTAN_HAS_ANSI_X919_MAC
#define BOTAN_HAS_ARC4
#define BOTAN_HAS_ASN1
#define BOTAN_HAS_AUTO_SEEDING_RNG
#define BOTAN_HAS_BASE64_CODEC
#define BOTAN_HAS_BCRYPT
#define BOTAN_HAS_BIGINT
#define BOTAN_HAS_BIGINT_MATH
#define BOTAN_HAS_BIGINT_MP
#define BOTAN_HAS_BLOCK_CIPHER
#define BOTAN_HAS_BLOWFISH
#define BOTAN_HAS_BMW_512
#define BOTAN_HAS_CAMELLIA
#define BOTAN_HAS_CASCADE
#define BOTAN_HAS_CAST
#define BOTAN_HAS_CBC
#define BOTAN_HAS_CBC_MAC
#define BOTAN_HAS_CERTIFICATE_STORE
#define BOTAN_HAS_CFB
#define BOTAN_HAS_CIPHER_MODE_PADDING
#define BOTAN_HAS_CMAC
#define BOTAN_HAS_CODEC_FILTERS
#define BOTAN_HAS_COMB4P
#define BOTAN_HAS_CORE_ENGINE
#define BOTAN_HAS_CRC24
#define BOTAN_HAS_CRC32
#define BOTAN_HAS_CRYPTO_BOX
#define BOTAN_HAS_CTR_BE
#define BOTAN_HAS_CTS
#define BOTAN_HAS_DES
#define BOTAN_HAS_DIFFIE_HELLMAN
#define BOTAN_HAS_DLIES
#define BOTAN_HAS_DL_GROUP
#define BOTAN_HAS_DL_PUBLIC_KEY_FAMILY
#define BOTAN_HAS_DSA
#define BOTAN_HAS_EAX
#define BOTAN_HAS_ECB
#define BOTAN_HAS_ECC_GROUP
#define BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO
#define BOTAN_HAS_ECDH
#define BOTAN_HAS_ECDSA
#define BOTAN_HAS_EC_CURVE_GFP
#define BOTAN_HAS_ELGAMAL
#define BOTAN_HAS_EME1
#define BOTAN_HAS_EME_PKCS1v15
#define BOTAN_HAS_EMSA1
#define BOTAN_HAS_EMSA1_BSI
#define BOTAN_HAS_EMSA2
#define BOTAN_HAS_EMSA3
#define BOTAN_HAS_EMSA4
#define BOTAN_HAS_EMSA_RAW
#define BOTAN_HAS_ENGINES
#define BOTAN_HAS_ENGINE_SIMD
#define BOTAN_HAS_ENTROPY_SRC_HIGH_RESOLUTION_TIMER
#define BOTAN_HAS_FILTERS
#define BOTAN_HAS_FPE_FE1
#define BOTAN_HAS_GOST_28147_89
#define BOTAN_HAS_GOST_34_10_2001
#define BOTAN_HAS_GOST_34_11
#define BOTAN_HAS_HASH_ID
#define BOTAN_HAS_HAS_160
#define BOTAN_HAS_HEX_CODEC
#define BOTAN_HAS_HMAC
#define BOTAN_HAS_HMAC_RNG
#define BOTAN_HAS_IDEA
#define BOTAN_HAS_IF_PUBLIC_KEY_FAMILY
#define BOTAN_HAS_KASUMI
#define BOTAN_HAS_KDF1
#define BOTAN_HAS_KDF2
#define BOTAN_HAS_KDF_BASE
#define BOTAN_HAS_KECCAK
#define BOTAN_HAS_KEYPAIR_TESTING
#define BOTAN_HAS_LIBSTATE_MODULE
#define BOTAN_HAS_LION
#define BOTAN_HAS_LUBY_RACKOFF
#define BOTAN_HAS_MARS
#define BOTAN_HAS_MD2
#define BOTAN_HAS_MD4
#define BOTAN_HAS_MD5
#define BOTAN_HAS_MDX_HASH_FUNCTION
#define BOTAN_HAS_MGF1
#define BOTAN_HAS_MISTY1
#define BOTAN_HAS_MUTEX_NOOP
#define BOTAN_HAS_MUTEX_WRAPPERS
#define BOTAN_HAS_NOEKEON
#define BOTAN_HAS_NOEKEON_SIMD
#define BOTAN_HAS_NYBERG_RUEPPEL
#define BOTAN_HAS_OFB
#define BOTAN_HAS_OID_LOOKUP
#define BOTAN_HAS_OPENPGP_CODEC
#define BOTAN_HAS_PACKAGE_TRANSFORM
#define BOTAN_HAS_PARALLEL_HASH
#define BOTAN_HAS_PASSHASH9
#define BOTAN_HAS_PASSWORD_BASED_ENCRYPTION
#define BOTAN_HAS_PBE_PKCS_V15
#define BOTAN_HAS_PBE_PKCS_V20
#define BOTAN_HAS_PBKDF1
#define BOTAN_HAS_PBKDF2
#define BOTAN_HAS_PEM_CODEC
#define BOTAN_HAS_PGPS2K
#define BOTAN_HAS_PKCS10_REQUESTS
#define BOTAN_HAS_PK_PADDING
#define BOTAN_HAS_PUBLIC_KEY_CRYPTO
#define BOTAN_HAS_PUBLIC_KEY_CRYPTO
#define BOTAN_HAS_RANDPOOL
#define BOTAN_HAS_RC2
#define BOTAN_HAS_RC5
#define BOTAN_HAS_RC6
#define BOTAN_HAS_RFC3394_KEYWRAP
#define BOTAN_HAS_RIPEMD_128
#define BOTAN_HAS_RIPEMD_160
#define BOTAN_HAS_RSA
#define BOTAN_HAS_RUNTIME_BENCHMARKING
#define BOTAN_HAS_RW
#define BOTAN_HAS_SAFER
#define BOTAN_HAS_SALSA20
#define BOTAN_HAS_SEED
#define BOTAN_HAS_SELFTESTS
#define BOTAN_HAS_SERPENT
#define BOTAN_HAS_SERPENT_SIMD
#define BOTAN_HAS_SHA1
#define BOTAN_HAS_SHA2_32
#define BOTAN_HAS_SHA2_64
#define BOTAN_HAS_SIMD_32
#define BOTAN_HAS_SIMD_SCALAR
#define BOTAN_HAS_SKEIN_512
#define BOTAN_HAS_SKIPJACK
#define BOTAN_HAS_SQUARE
#define BOTAN_HAS_SRP6
#define BOTAN_HAS_SSL3_MAC
#define BOTAN_HAS_SSL_V3_PRF
#define BOTAN_HAS_STREAM_CIPHER
#define BOTAN_HAS_TEA
#define BOTAN_HAS_THRESHOLD_SECRET_SHARING
#define BOTAN_HAS_TIGER
#define BOTAN_HAS_TLS_V10_PRF
#define BOTAN_HAS_TURING
#define BOTAN_HAS_TWOFISH
#define BOTAN_HAS_UTIL_FUNCTIONS
#define BOTAN_HAS_WHIRLPOOL
#define BOTAN_HAS_WID_WAKE
#define BOTAN_HAS_X509_CA
#define BOTAN_HAS_X509_CERTIFICATES
#define BOTAN_HAS_X509_CRL
#define BOTAN_HAS_X509_SELF_SIGNED
#define BOTAN_HAS_X509_STORE
#define BOTAN_HAS_X931_RNG
#define BOTAN_HAS_X942_PRF
#define BOTAN_HAS_XTEA
#define BOTAN_HAS_XTEA_SIMD
#define BOTAN_HAS_XTS
/*
* Local configuration options (if any) follow
*/
#include <stddef.h>
/**
* The primary namespace for the botan library
*/
namespace Botan {
/**
* Typedef representing an unsigned 8-bit quantity
*/
typedef unsigned char byte;
/**
* Typedef representing an unsigned 16-bit quantity
*/
typedef unsigned short u16bit;
/**
* Typedef representing an unsigned 32-bit quantity
*/
typedef unsigned int u32bit;
/**
* Typedef representing a signed 32-bit quantity
*/
typedef signed int s32bit;
/**
* Typedef representing an unsigned 64-bit quantity
*/
#if defined(_MSC_VER) || defined(__BORLANDC__)
typedef unsigned __int64 u64bit;
#elif defined(__KCC)
typedef unsigned __long_long u64bit;
#elif defined(__GNUG__)
__extension__ typedef unsigned long long u64bit;
#else
typedef unsigned long long u64bit;
#endif
/**
* A default buffer size; typically a memory page
*/
static const size_t DEFAULT_BUFFERSIZE = BOTAN_DEFAULT_BUFFER_SIZE;
}
namespace Botan_types {
using Botan::byte;
using Botan::u32bit;
}
namespace Botan {
/**
* Allocator Interface
*/
class BOTAN_DLL Allocator
{
public:
/**
* Acquire a pointer to an allocator
* @param locking is true if the allocator should attempt to
* secure the memory (eg for using to store keys)
* @return pointer to an allocator; ownership remains with library,
* so do not delete
*/
static Allocator* get(bool locking);
/**
* Allocate a block of memory
* @param n how many bytes to allocate
* @return pointer to n bytes of memory
*/
virtual void* allocate(size_t n) = 0;
/**
* Deallocate memory allocated with allocate()
* @param ptr the pointer returned by allocate()
* @param n the size of the block pointed to by ptr
*/
virtual void deallocate(void* ptr, size_t n) = 0;
/**
* @return name of this allocator type
*/
virtual std::string type() const = 0;
/**
* Initialize the allocator
*/
virtual void init() {}
/**
* Shutdown the allocator
*/
virtual void destroy() {}
virtual ~Allocator() Q_DECL_NOEXCEPT_EXPR(false) {}
};
}
namespace Botan {
/**
* Copy memory
* @param out the destination array
* @param in the source array
* @param n the number of elements of in/out
*/
template<typename T> inline void copy_mem(T* out, const T* in, size_t n)
{
std::memmove(out, in, sizeof(T)*n);
}
/**
* Zeroize memory
* @param ptr a pointer to an array
* @param n the number of Ts pointed to by ptr
*/
template<typename T> inline void clear_mem(T* ptr, size_t n)
{
if(n) // avoid glibc warning if n == 0
std::memset(ptr, 0, sizeof(T)*n);
}
/**
* Set memory to a fixed value
* @param ptr a pointer to an array
* @param n the number of Ts pointed to by ptr
* @param val the value to set each byte to
*/
template<typename T>
inline void set_mem(T* ptr, size_t n, byte val)
{
std::memset(ptr, val, sizeof(T)*n);
}
/**
* Memory comparison, input insensitive
* @param p1 a pointer to an array
* @param p2 a pointer to another array
* @param n the number of Ts in p1 and p2
* @return true iff p1[i] == p2[i] forall i in [0...n)
*/
template<typename T> inline bool same_mem(const T* p1, const T* p2, size_t n)
{
bool is_same = true;
for(size_t i = 0; i != n; ++i)
is_same &= (p1[i] == p2[i]);
return is_same;
}
}
namespace Botan {
/**
* This class represents variable length memory buffers.
*/
template<typename T>
class MemoryRegion
{
public:
/**
* Find out the size of the buffer, i.e. how many objects of type T it
* contains.
* @return size of the buffer
*/
size_t size() const { return used; }
/**
* Find out whether this buffer is empty.
* @return true if the buffer is empty, false otherwise
*/
bool empty() const { return (used == 0); }
/**
* Get a pointer to the first element in the buffer.
* @return pointer to the first element in the buffer
*/
operator T* () { return buf; }
/**
* Get a constant pointer to the first element in the buffer.
* @return constant pointer to the first element in the buffer
*/
operator const T* () const { return buf; }
/**
* Get a pointer to the first element in the buffer.
* @return pointer to the first element in the buffer
*/
T* begin() { return buf; }
/**
* Get a constant pointer to the first element in the buffer.
* @return constant pointer to the first element in the buffer
*/
const T* begin() const { return buf; }
/**
* Get a pointer to one past the last element in the buffer.
* @return pointer to one past the last element in the buffer
*/
T* end() { return (buf + size()); }
/**
* Get a const pointer to one past the last element in the buffer.
* @return const pointer to one past the last element in the buffer
*/
const T* end() const { return (buf + size()); }
/**
* Check two buffers for equality.
* @return true iff the content of both buffers is byte-wise equal
*/
bool operator==(const MemoryRegion<T>& other) const
{
return (size() == other.size() &&
same_mem(buf, other.buf, size()));
}
/**
* Compare two buffers
* @return true iff this is ordered before other
*/
bool operator<(const MemoryRegion<T>& other) const;
/**
* Check two buffers for inequality.
* @return false if the content of both buffers is byte-wise equal, true
* otherwise.
*/
bool operator!=(const MemoryRegion<T>& other) const
{ return (!(*this == other)); }
/**
* Copy the contents of another buffer into this buffer.
* The former contents of *this are discarded.
* @param other the buffer to copy the contents from.
* @return reference to *this
*/
MemoryRegion<T>& operator=(const MemoryRegion<T>& other)
{
if(this != &other)
{
this->resize(other.size());
this->copy(&other[0], other.size());
}
return (*this);
}
/**
* Copy the contents of an array of objects of type T into this buffer.
* The former contents of *this are discarded.
* The length of *this must be at least n, otherwise memory errors occur.
* @param in the array to copy the contents from
* @param n the length of in
*/
void copy(const T in[], size_t n)
{
copy_mem(buf, in, std::min(n, size()));
}
/**
* Copy the contents of an array of objects of type T into this buffer.
* The former contents of *this are discarded.
* The length of *this must be at least n, otherwise memory errors occur.
* @param off the offset position inside this buffer to start inserting
* the copied bytes
* @param in the array to copy the contents from
* @param n the length of in
*/
void copy(size_t off, const T in[], size_t n)
{
copy_mem(buf + off, in, std::min(n, size() - off));
}
/**
* Append a single element.
* @param x the element to append
*/
void push_back(T x)
{
resize(size() + 1);
buf[size()-1] = x;
}
/**
* Reset this buffer to an empty buffer with size zero.
*/
void clear() { resize(0); }
/**
* Inserts or erases elements at the end such that the size
* becomes n, leaving elements in the range 0...n unmodified if
* set or otherwise zero-initialized
* @param n length of the new buffer
*/
void resize(size_t n);
/**
* Swap this buffer with another object.
*/
void swap(MemoryRegion<T>& other);
virtual ~MemoryRegion() { deallocate(buf, allocated); }
protected:
MemoryRegion() : buf(0), used(0), allocated(0), alloc(0) {}
/**
* Copy constructor
* @param other the other region to copy
*/
MemoryRegion(const MemoryRegion<T>& other) :
buf(0),
used(0),
allocated(0),
alloc(other.alloc)
{
resize(other.size());
copy(&other[0], other.size());
}
/**
* @param locking should we use a locking allocator
* @param length the initial length to use
*/
void init(bool locking, size_t length = 0)
{ alloc = Allocator::get(locking); resize(length); }
private:
T* allocate(size_t n)
{
return static_cast<T*>(alloc->allocate(sizeof(T)*n));
}
void deallocate(T* p, size_t n)
{ if(alloc && p && n) alloc->deallocate(p, sizeof(T)*n); }
T* buf;
size_t used;
size_t allocated;
Allocator* alloc;
};
/*
* Change the size of the buffer
*/
template<typename T>
void MemoryRegion<T>::resize(size_t n)
{
if(n <= allocated)
{
size_t zap = std::min(used, n);
clear_mem(buf + zap, allocated - zap);
used = n;
}
else
{
T* new_buf = allocate(n);
copy_mem(new_buf, buf, used);
deallocate(buf, allocated);
buf = new_buf;
allocated = used = n;
}
}
/*
* Compare this buffer with another one
*/
template<typename T>
bool MemoryRegion<T>::operator<(const MemoryRegion<T>& other) const
{
const size_t min_size = std::min(size(), other.size());
// This should probably be rewritten to run in constant time
for(size_t i = 0; i != min_size; ++i)
{
if(buf[i] < other[i])
return true;
if(buf[i] > other[i])
return false;
}
// First min_size bytes are equal, shorter is first
return (size() < other.size());
}
/*
* Swap this buffer with another one
*/
template<typename T>
void MemoryRegion<T>::swap(MemoryRegion<T>& x)
{
std::swap(buf, x.buf);
std::swap(used, x.used);
std::swap(allocated, x.allocated);
std::swap(alloc, x.alloc);
}
/**
* This class represents variable length buffers that do not
* make use of memory locking.
*/
template<typename T>
class MemoryVector : public MemoryRegion<T>
{
public:
/**
* Copy the contents of another buffer into this buffer.
* @param in the buffer to copy the contents from
* @return reference to *this
*/
MemoryVector<T>& operator=(const MemoryRegion<T>& in)
{
if(this != &in)
{
this->resize(in.size());
this->copy(&in[0], in.size());
}
return (*this);
}
/**
* Create a buffer of the specified length.
* @param n the length of the buffer to create.
*/
MemoryVector(size_t n = 0) { this->init(false, n); }
/**
* Create a buffer with the specified contents.
* @param in the array containing the data to be initially copied
* into the newly created buffer
* @param n the size of the arry in
*/
MemoryVector(const T in[], size_t n)
{
this->init(false);
this->resize(n);
this->copy(in, n);
}
/**
* Copy constructor.
*/
MemoryVector(const MemoryRegion<T>& in)
{
this->init(false);
this->resize(in.size());
this->copy(&in[0], in.size());
}
};
/**
* This class represents variable length buffers using the operating
* systems capability to lock memory, i.e. keeping it from being
* swapped out to disk. In this way, a security hole allowing attackers
* to find swapped out secret keys is closed.
*/
template<typename T>
class SecureVector : public MemoryRegion<T>
{
public:
/**
* Copy the contents of another buffer into this buffer.
* @param other the buffer to copy the contents from
* @return reference to *this
*/
SecureVector<T>& operator=(const MemoryRegion<T>& other)
{
if(this != &other)
{
this->resize(other.size());
this->copy(&other[0], other.size());
}
return (*this);
}
/**
* Create a buffer of the specified length.
* @param n the length of the buffer to create.
*/
SecureVector(size_t n = 0) { this->init(true, n); }
/**
* Create a buffer with the specified contents.
* @param in the array containing the data to be initially copied
* into the newly created buffer
* @param n the size of the array in
*/
SecureVector(const T in[], size_t n)
{
this->init(true);
this->resize(n);
this->copy(&in[0], n);
}
/**
* Create a buffer with contents specified contents.
* @param in the buffer holding the contents that will be
* copied into the newly created buffer.
*/
SecureVector(const MemoryRegion<T>& in)
{
this->init(true);
this->resize(in.size());
this->copy(&in[0], in.size());
}
};
template<typename T>
MemoryRegion<T>& operator+=(MemoryRegion<T>& out,
const MemoryRegion<T>& in)
{
const size_t copy_offset = out.size();
out.resize(out.size() + in.size());
copy_mem(&out[copy_offset], &in[0], in.size());
return out;
}
template<typename T>
MemoryRegion<T>& operator+=(MemoryRegion<T>& out,
T in)
{
out.push_back(in);
return out;
}
template<typename T, typename L>
MemoryRegion<T>& operator+=(MemoryRegion<T>& out,
const std::pair<const T*, L>& in)
{
const size_t copy_offset = out.size();
out.resize(out.size() + in.second);
copy_mem(&out[copy_offset], in.first, in.second);
return out;
}
template<typename T, typename L>
MemoryRegion<T>& operator+=(MemoryRegion<T>& out,
const std::pair<T*, L>& in)
{
const size_t copy_offset = out.size();
out.resize(out.size() + in.second);
copy_mem(&out[copy_offset], in.first, in.second);
return out;
}
/**
* Zeroise the values; length remains unchanged
* @param vec the vector to zeroise
*/
template<typename T>
void zeroise(MemoryRegion<T>& vec)
{
clear_mem(&vec[0], vec.size());
}
}
namespace std {
template<typename T>
inline void swap(Botan::MemoryRegion<T>& x, Botan::MemoryRegion<T>& y)
{
x.swap(y);
}
}
namespace Botan {
/**
* Byte extraction
* @param byte_num which byte to extract, 0 == highest byte
* @param input the value to extract from
* @return byte byte_num of input
*/
template<typename T> inline byte get_byte(size_t byte_num, T input)
{
return static_cast<byte>(
input >> ((sizeof(T)-1-(byte_num&(sizeof(T)-1))) << 3)
);
}
}
namespace Botan {
/**
* This class represents any kind of computation which uses an internal
* state, such as hash functions or MACs
*/
class BOTAN_DLL Buffered_Computation
{
public:
/**
* @return length of the output of this function in bytes
*/
virtual size_t output_length() const = 0;
/**
* Add new input to process.
* @param in the input to process as a byte array
* @param length of param in in bytes
*/
void update(const byte in[], size_t length) { add_data(in, length); }
/**
* Add new input to process.
* @param in the input to process as a MemoryRegion
*/
void update(const MemoryRegion<byte>& in)
{
add_data(&in[0], in.size());
}
/**
* Add an integer in big-endian order
* @param in the value
*/
template<typename T> void update_be(const T in)
{
for(size_t i = 0; i != sizeof(T); ++i)
{
byte b = get_byte(i, in);
add_data(&b, 1);
}
}
/**
* Add new input to process.
* @param str the input to process as a std::string. Will be interpreted
* as a byte array based on
* the strings encoding.
*/
void update(const std::string& str)
{
add_data(reinterpret_cast<const byte*>(str.data()), str.size());
}
/**
* Process a single byte.
* @param in the byte to process
*/
void update(byte in) { add_data(&in, 1); }
/**
* Complete the computation and retrieve the
* final result.
* @param out The byte array to be filled with the result.
* Must be of length output_length()
*/
void final(byte out[]) { final_result(out); }
/**
* Complete the computation and retrieve the
* final result.
* @return SecureVector holding the result
*/
SecureVector<byte> final()
{
SecureVector<byte> output(output_length());
final_result(&output[0]);
return output;
}
/**
* Update and finalize computation. Does the same as calling update()
* and final() consecutively.
* @param in the input to process as a byte array
* @param length the length of the byte array
* @result the result of the call to final()
*/
SecureVector<byte> process(const byte in[], size_t length)
{
add_data(in, length);
return final();
}
/**
* Update and finalize computation. Does the same as calling update()
* and final() consecutively.
* @param in the input to process
* @result the result of the call to final()
*/
SecureVector<byte> process(const MemoryRegion<byte>& in)
{
add_data(&in[0], in.size());
return final();
}
/**
* Update and finalize computation. Does the same as calling update()
* and final() consecutively.
* @param in the input to process as a string
* @result the result of the call to final()
*/
SecureVector<byte> process(const std::string& in)
{
update(in);
return final();
}
virtual ~Buffered_Computation() {}
private:
/**
* Add more data to the computation
* @param input is an input buffer
* @param length is the length of input in bytes
*/
virtual void add_data(const byte input[], size_t length) = 0;
/**
* Write the final output to out
* @param out is an output buffer of output_length()
*/
virtual void final_result(byte out[]) = 0;
};
}
namespace Botan {
/**
* Class used to accumulate the poll results of EntropySources
*/
class BOTAN_DLL Entropy_Accumulator
{
public:
/**
* Initialize an Entropy_Accumulator
* @param goal is how many bits we would like to collect
*/
Entropy_Accumulator(size_t goal) :
entropy_goal(goal), collected_bits(0) {}
virtual ~Entropy_Accumulator() {}
/**
* Get a cached I/O buffer (purely for minimizing allocation
* overhead to polls)
*
* @param size requested size for the I/O buffer
* @return cached I/O buffer for repeated polls
*/
MemoryRegion<byte>& get_io_buffer(size_t size)
{ io_buffer.resize(size); return io_buffer; }
/**
* @return number of bits collected so far
*/
size_t bits_collected() const
{ return static_cast<size_t>(collected_bits); }
/**
* @return if our polling goal has been achieved
*/
bool polling_goal_achieved() const
{ return (collected_bits >= entropy_goal); }
/**
* @return how many bits we need to reach our polling goal
*/
size_t desired_remaining_bits() const
{
if(collected_bits >= entropy_goal)
return 0;
return static_cast<size_t>(entropy_goal - collected_bits);
}
/**
* Add entropy to the accumulator
* @param bytes the input bytes
* @param length specifies how many bytes the input is
* @param entropy_bits_per_byte is a best guess at how much
* entropy per byte is in this input
*/
void add(const void* bytes, size_t length, double entropy_bits_per_byte)
{
add_bytes(reinterpret_cast<const byte*>(bytes), length);
collected_bits += entropy_bits_per_byte * length;
}
/**
* Add entropy to the accumulator
* @param v is some value
* @param entropy_bits_per_byte is a best guess at how much
* entropy per byte is in this input
*/
template<typename T>
void add(const T& v, double entropy_bits_per_byte)
{
add(&v, sizeof(T), entropy_bits_per_byte);
}
private:
virtual void add_bytes(const byte bytes[], size_t length) = 0;
SecureVector<byte> io_buffer;
size_t entropy_goal;
double collected_bits;
};
/**
* Entropy accumulator that puts the input into a Buffered_Computation
*/
class BOTAN_DLL Entropy_Accumulator_BufferedComputation :
public Entropy_Accumulator
{
public:
/**
* @param sink the hash or MAC we are feeding the poll data into
* @param goal is how many bits we want to collect in this poll
*/
Entropy_Accumulator_BufferedComputation(Buffered_Computation& sink,
size_t goal) :
Entropy_Accumulator(goal), entropy_sink(sink) {}
private:
virtual void add_bytes(const byte bytes[], size_t length)
{
entropy_sink.update(bytes, length);
}
Buffered_Computation& entropy_sink;
};
/**
* Abstract interface to a source of (hopefully unpredictable) system entropy
*/
class BOTAN_DLL EntropySource
{
public:
/**
* @return name identifying this entropy source
*/
virtual std::string name() const = 0;
/**
* Perform an entropy gathering poll
* @param accum is an accumulator object that will be given entropy
*/
virtual void poll(Entropy_Accumulator& accum) = 0;
virtual ~EntropySource() {}
};
}
namespace Botan {
/**
* Parse a SCAN-style algorithm name
* @param scan_name the name
* @return the name components
*/
BOTAN_DLL std::vector<std::string>
parse_algorithm_name(const std::string& scan_name);
/**
* Split a string
* @param str the input string
* @param delim the delimitor
* @return string split by delim
*/
BOTAN_DLL std::vector<std::string> split_on(
const std::string& str, char delim);
/**
* Parse an ASN.1 OID
* @param oid the OID in string form
* @return OID components
*/
BOTAN_DLL std::vector<u32bit> parse_asn1_oid(const std::string& oid);
/**
* Compare two names using the X.509 comparison algorithm
* @param name1 the first name
* @param name2 the second name
* @return true if name1 is the same as name2 by the X.509 comparison rules
*/
BOTAN_DLL bool x500_name_cmp(const std::string& name1,
const std::string& name2);
/**
* Convert a number to a string
* @param n the integer to convert to a string
* @param min_len the min length of the output string
* @return n convert to a string
*/
BOTAN_DLL std::string to_string(u64bit n, size_t min_len = 0);
/**
* Convert a string to a number
* @param str the string to convert
* @return number value of the string
*/
BOTAN_DLL u32bit to_u32bit(const std::string& str);
/**
* Convert a time specification to a number
* @param timespec the time specification
* @return number of seconds represented by timespec
*/
BOTAN_DLL u32bit timespec_to_u32bit(const std::string& timespec);
/**
* Convert a string representation of an IPv4 address to a number
* @param ip_str the string representation
* @return integer IPv4 address
*/
BOTAN_DLL u32bit string_to_ipv4(const std::string& ip_str);
/**
* Convert an IPv4 address to a string
* @param ip_addr the IPv4 address to convert
* @return string representation of the IPv4 address
*/
BOTAN_DLL std::string ipv4_to_string(u32bit ip_addr);
}
namespace Botan {
typedef std::runtime_error Exception;
typedef std::invalid_argument Invalid_Argument;
/**
* Invalid_State Exception
*/
struct BOTAN_DLL Invalid_State : public Exception
{
Invalid_State(const std::string& err) :
Exception(err)
{}
};
/**
* Lookup_Error Exception
*/
struct BOTAN_DLL Lookup_Error : public Exception
{
Lookup_Error(const std::string& err) :
Exception(err)
{}
};
/**
* Internal_Error Exception
*/
struct BOTAN_DLL Internal_Error : public Exception
{
Internal_Error(const std::string& err) :
Exception("Internal error: " + err)
{}
};
/**
* Invalid_Key_Length Exception
*/
struct BOTAN_DLL Invalid_Key_Length : public Invalid_Argument
{
Invalid_Key_Length(const std::string& name, size_t length) :
Invalid_Argument(name + " cannot accept a key of length " +
to_string(length))
{}
};
/**
* Invalid_Block_Size Exception
*/
struct BOTAN_DLL Invalid_Block_Size : public Invalid_Argument
{
Invalid_Block_Size(const std::string& mode,
const std::string& pad) :
Invalid_Argument("Padding method " + pad +
" cannot be used with " + mode)
{}
};
/**
* Invalid_IV_Length Exception
*/
struct BOTAN_DLL Invalid_IV_Length : public Invalid_Argument
{
Invalid_IV_Length(const std::string& mode, size_t bad_len) :
Invalid_Argument("IV length " + to_string(bad_len) +
" is invalid for " + mode)
{}
};
/**
* PRNG_Unseeded Exception
*/
struct BOTAN_DLL PRNG_Unseeded : public Invalid_State
{
PRNG_Unseeded(const std::string& algo) :
Invalid_State("PRNG not seeded: " + algo)
{}
};
/**
* Policy_Violation Exception
*/
struct BOTAN_DLL Policy_Violation : public Invalid_State
{
Policy_Violation(const std::string& err) :
Invalid_State("Policy violation: " + err)
{}
};
/**
* Algorithm_Not_Found Exception
*/
struct BOTAN_DLL Algorithm_Not_Found : public Lookup_Error
{
Algorithm_Not_Found(const std::string& name) :
Lookup_Error("Could not find any algorithm named \"" + name + "\"")
{}
};
/**
* Invalid_Algorithm_Name Exception
*/
struct BOTAN_DLL Invalid_Algorithm_Name : public Invalid_Argument
{
Invalid_Algorithm_Name(const std::string& name):
Invalid_Argument("Invalid algorithm name: " + name)
{}
};
/**
* Encoding_Error Exception
*/
struct BOTAN_DLL Encoding_Error : public Invalid_Argument
{
Encoding_Error(const std::string& name) :
Invalid_Argument("Encoding error: " + name) {}
};
/**
* Decoding_Error Exception
*/
struct BOTAN_DLL Decoding_Error : public Invalid_Argument
{
Decoding_Error(const std::string& name) :
Invalid_Argument("Decoding error: " + name) {}
};
/**
* Integrity_Failure Exception
*/
struct BOTAN_DLL Integrity_Failure : public Exception
{
Integrity_Failure(const std::string& msg) :
Exception("Integrity failure: " + msg) {}
};
/**
* Invalid_OID Exception
*/
struct BOTAN_DLL Invalid_OID : public Decoding_Error
{
Invalid_OID(const std::string& oid) :
Decoding_Error("Invalid ASN.1 OID: " + oid) {}
};
/**
* Stream_IO_Error Exception
*/
struct BOTAN_DLL Stream_IO_Error : public Exception
{
Stream_IO_Error(const std::string& err) :
Exception("I/O error: " + err)
{}
};
/**
* Self Test Failure Exception
*/
struct BOTAN_DLL Self_Test_Failure : public Internal_Error
{
Self_Test_Failure(const std::string& err) :
Internal_Error("Self test failed: " + err)
{}
};
/**
* Memory Allocation Exception
*/
struct BOTAN_DLL Memory_Exhaustion : public std::bad_alloc
{
const char* what() const throw()
{ return "Ran out of memory, allocation failed"; }
};
}
namespace Botan {
/**
* This class represents a random number (RNG) generator object.
*/
class BOTAN_DLL RandomNumberGenerator
{
public:
/**
* Create a seeded and active RNG object for general application use
*/
static RandomNumberGenerator* make_rng();
/**
* Randomize a byte array.
* @param output the byte array to hold the random output.
* @param length the length of the byte array output.
*/
virtual void randomize(byte output[], size_t length) = 0;
/**
* Return a random vector
* @param bytes number of bytes in the result
* @return randomized vector of length bytes
*/
SecureVector<byte> random_vec(size_t bytes)
{
SecureVector<byte> output(bytes);
randomize(&output[0], output.size());
return output;
}
/**
* Return a random byte
* @return random byte
*/
byte next_byte();
/**
* Check whether this RNG is seeded.
* @return true if this RNG was already seeded, false otherwise.
*/
virtual bool is_seeded() const { return true; }
/**
* Clear all internally held values of this RNG.
*/
virtual void clear() = 0;
/**
* Return the name of this object
*/
virtual std::string name() const = 0;
/**
* Seed this RNG using the entropy sources it contains.
* @param bits_to_collect is the number of bits of entropy to
attempt to gather from the entropy sources
*/
virtual void reseed(size_t bits_to_collect) = 0;
/**
* Add this entropy source to the RNG object
* @param source the entropy source which will be retained and used by RNG
*/
virtual void add_entropy_source(EntropySource* source) = 0;
/**
* Add entropy to this RNG.
* @param in a byte array containg the entropy to be added
* @param length the length of the byte array in
*/
virtual void add_entropy(const byte in[], size_t length) = 0;
RandomNumberGenerator() {}
virtual ~RandomNumberGenerator() {}
private:
RandomNumberGenerator(const RandomNumberGenerator&) {}
RandomNumberGenerator& operator=(const RandomNumberGenerator&)
{ return (*this); }
};
/**
* Null/stub RNG - fails if you try to use it for anything
*/
class BOTAN_DLL Null_RNG : public RandomNumberGenerator
{
public:
void randomize(byte[], size_t) { throw PRNG_Unseeded("Null_RNG"); }
void clear() {}
std::string name() const { return "Null_RNG"; }
void reseed(size_t) {}
bool is_seeded() const { return false; }
void add_entropy(const byte[], size_t) {}
void add_entropy_source(EntropySource* es) { delete es; }
};
}
namespace Botan {
/**
* Encoding Method for Signatures, Appendix
*/
class BOTAN_DLL EMSA
{
public:
/**
* Add more data to the signature computation
* @param input some data
* @param length length of input in bytes
*/
virtual void update(const byte input[], size_t length) = 0;
/**
* @return raw hash
*/
virtual SecureVector<byte> raw_data() = 0;
/**
* Return the encoding of a message
* @param msg the result of raw_data()
* @param output_bits the desired output bit size
* @param rng a random number generator
* @return encoded signature
*/
virtual SecureVector<byte> encoding_of(const MemoryRegion<byte>& msg,
size_t output_bits,
RandomNumberGenerator& rng) = 0;
/**
* Verify the encoding
* @param coded the received (coded) message representative
* @param raw the computed (local, uncoded) message representative
* @param key_bits the size of the key in bits
* @return true if coded is a valid encoding of raw, otherwise false
*/
virtual bool verify(const MemoryRegion<byte>& coded,
const MemoryRegion<byte>& raw,
size_t key_bits) = 0;
virtual ~EMSA() {}
};
}
namespace Botan {
/**
* This class represents an algorithm of some kind
*/
class BOTAN_DLL Algorithm
{
public:
/**
* Zeroize internal state
*/
virtual void clear() = 0;
/**
* @return name of this algorithm
*/
virtual std::string name() const = 0;
Algorithm() {}
virtual ~Algorithm() {}
private:
Algorithm(const Algorithm&) {}
Algorithm& operator=(const Algorithm&) { return (*this); }
};
}
namespace Botan {
/**
* This class represents hash function (message digest) objects
*/
class BOTAN_DLL HashFunction : public Buffered_Computation,
public Algorithm
{
public:
/**
* Get a new object representing the same algorithm as *this
*/
virtual HashFunction* clone() const = 0;
/**
* The hash block size as defined for this algorithm
*/
virtual size_t hash_block_size() const { return 0; }
};
}
namespace Botan {
/**
* EMSA1 from IEEE 1363
* Essentially, sign the hash directly
*/
class BOTAN_DLL EMSA1 : public EMSA
{
public:
/**
* @param h the hash object to use
*/
EMSA1(HashFunction* h) : hash(h) {}
~EMSA1() { delete hash; }
protected:
/**
* @return const pointer to the underlying hash
*/
const HashFunction* hash_ptr() const { return hash; }
private:
void update(const byte[], size_t);
SecureVector<byte> raw_data();
SecureVector<byte> encoding_of(const MemoryRegion<byte>&, size_t,
RandomNumberGenerator& rng);
bool verify(const MemoryRegion<byte>&, const MemoryRegion<byte>&,
size_t);
HashFunction* hash;
};
}
namespace Botan {
/**
* Keccak[1600], a SHA-3 candidate
*/
class BOTAN_DLL Keccak_1600 : public HashFunction
{
public:
/**
* @param output_bits the size of the hash output; must be one of
* 224, 256, 384, or 512
*/
Keccak_1600(size_t output_bits = 512);
size_t hash_block_size() const { return bitrate / 8; }
size_t output_length() const { return output_bits / 8; }
HashFunction* clone() const;
std::string name() const;
void clear();
private:
void add_data(const byte input[], size_t length);
void final_result(byte out[]);
size_t output_bits, bitrate;
SecureVector<u64bit> S;
size_t S_pos;
};
}
namespace Botan {
/**
A class encapsulating a SCAN name (similar to JCE conventions)
http://www.users.zetnet.co.uk/hopwood/crypto/scan/
*/
class BOTAN_DLL SCAN_Name
{
public:
/**
* @param algo_spec A SCAN-format name
*/
SCAN_Name(std::string algo_spec);
/**
* @return original input string
*/
std::string as_string() const { return orig_algo_spec; }
/**
* @return algorithm name
*/
std::string algo_name() const { return alg_name; }
/**
* @return algorithm name plus any arguments
*/
std::string algo_name_and_args() const;
/**
* @return number of arguments
*/
size_t arg_count() const { return args.size(); }
/**
* @param lower is the lower bound
* @param upper is the upper bound
* @return if the number of arguments is between lower and upper
*/
bool arg_count_between(size_t lower, size_t upper) const
{ return ((arg_count() >= lower) && (arg_count() <= upper)); }
/**
* @param i which argument
* @return ith argument
*/
std::string arg(size_t i) const;
/**
* @param i which argument
* @param def_value the default value
* @return ith argument or the default value
*/
std::string arg(size_t i, const std::string& def_value) const;
/**
* @param i which argument
* @param def_value the default value
* @return ith argument as an integer, or the default value
*/
size_t arg_as_integer(size_t i, size_t def_value) const;
/**
* @return cipher mode (if any)
*/
std::string cipher_mode() const
{ return (mode_info.size() >= 1) ? mode_info[0] : ""; }
/**
* @return cipher mode padding (if any)
*/
std::string cipher_mode_pad() const
{ return (mode_info.size() >= 2) ? mode_info[1] : ""; }
private:
std::string orig_algo_spec;
std::string alg_name;
std::vector<std::string> args;
std::vector<std::string> mode_info;
};
}
namespace Botan {
/**
* Represents the length requirements on an algorithm key
*/
class BOTAN_DLL Key_Length_Specification
{
public:
/**
* Constructor for fixed length keys
* @param keylen the supported key length
*/
Key_Length_Specification(size_t keylen) :
min_keylen(keylen),
max_keylen(keylen),
keylen_mod(1)
{
}
/**
* Constructor for variable length keys
* @param min_k the smallest supported key length
* @param max_k the largest supported key length
* @param k_mod the number of bytes the key must be a multiple of
*/
Key_Length_Specification(size_t min_k,
size_t max_k,
size_t k_mod = 1) :
min_keylen(min_k),
max_keylen(max_k ? max_k : min_k),
keylen_mod(k_mod)
{
}
/**
* @param length is a key length in bytes
* @return true iff this length is a valid length for this algo
*/
bool valid_keylength(size_t length) const
{
return ((length >= min_keylen) &&
(length <= max_keylen) &&
(length % keylen_mod == 0));
}
/**
* @return minimum key length in bytes
*/
size_t minimum_keylength() const
{
return min_keylen;
}
/**
* @return maximum key length in bytes
*/
size_t maximum_keylength() const
{
return max_keylen;
}
/**
* @return key length multiple in bytes
*/
size_t keylength_multiple() const
{
return keylen_mod;
}
private:
size_t min_keylen, max_keylen, keylen_mod;
};
}
namespace Botan {
/**
* Octet String
*/
class BOTAN_DLL OctetString
{
public:
/**
* @return size of this octet string in bytes
*/
size_t length() const { return bits.size(); }
/**
* @return this object as a SecureVector<byte>
*/
SecureVector<byte> bits_of() const { return bits; }
/**
* @return start of this string
*/
const byte* begin() const { return &bits[0]; }
/**
* @return end of this string
*/
const byte* end() const { return &bits[bits.size()]; }
/**
* @return this encoded as hex
*/
std::string as_string() const;
/**
* XOR the contents of another octet string into this one
* @param other octet string
* @return reference to this
*/
OctetString& operator^=(const OctetString& other);
/**
* Force to have odd parity
*/
void set_odd_parity();
/**
* Change the contents of this octet string
* @param hex_string a hex encoded bytestring
*/
void change(const std::string& hex_string);
/**
* Change the contents of this octet string
* @param in the input
* @param length of in in bytes
*/
void change(const byte in[], size_t length);
/**
* Change the contents of this octet string
* @param in the input
*/
void change(const MemoryRegion<byte>& in) { bits = in; }
/**
* Create a new random OctetString
* @param rng is a random number generator
* @param len is the desired length in bytes
*/
OctetString(class RandomNumberGenerator& rng, size_t len);
/**
* Create a new OctetString
* @param str is a hex encoded string
*/
OctetString(const std::string& str = "") { change(str); }
/**
* Create a new OctetString
* @param in is an array
* @param len is the length of in in bytes
*/
OctetString(const byte in[], size_t len) { change(in, len); }
/**
* Create a new OctetString
* @param in a bytestring
*/
OctetString(const MemoryRegion<byte>& in) { change(in); }
private:
SecureVector<byte> bits;
};
/**
* Compare two strings
* @param x an octet string
* @param y an octet string
* @return if x is equal to y
*/
BOTAN_DLL bool operator==(const OctetString& x,
const OctetString& y);
/**
* Compare two strings
* @param x an octet string
* @param y an octet string
* @return if x is not equal to y
*/
BOTAN_DLL bool operator!=(const OctetString& x,
const OctetString& y);
/**
* Concatenate two strings
* @param x an octet string
* @param y an octet string
* @return x concatenated with y
*/
BOTAN_DLL OctetString operator+(const OctetString& x,
const OctetString& y);
/**
* XOR two strings
* @param x an octet string
* @param y an octet string
* @return x XORed with y
*/
BOTAN_DLL OctetString operator^(const OctetString& x,
const OctetString& y);
/**
* Alternate name for octet string showing intent to use as a key
*/
typedef OctetString SymmetricKey;
/**
* Alternate name for octet string showing intent to use as an IV
*/
typedef OctetString InitializationVector;
}
namespace Botan {
/**
* This class represents a symmetric algorithm object.
*/
class BOTAN_DLL SymmetricAlgorithm : public Algorithm
{
public:
/**
* @return object describing limits on key size
*/
virtual Key_Length_Specification key_spec() const = 0;
/**
* @return minimum allowed key length
*/
size_t maximum_keylength() const
{
return key_spec().maximum_keylength();
}
/**
* @return maxmium allowed key length
*/
size_t minimum_keylength() const
{
return key_spec().minimum_keylength();
}
/**
* Check whether a given key length is valid for this algorithm.
* @param length the key length to be checked.
* @return true if the key length is valid.
*/
bool valid_keylength(size_t length) const
{
return key_spec().valid_keylength(length);
}
/**
* Set the symmetric key of this object.
* @param key the SymmetricKey to be set.
*/
void set_key(const SymmetricKey& key)
{ set_key(key.begin(), key.length()); }
/**
* Set the symmetric key of this object.
* @param key the to be set as a byte array.
* @param length in bytes of key param
*/
void set_key(const byte key[], size_t length)
{
if(!valid_keylength(length))
throw Invalid_Key_Length(name(), length);
key_schedule(key, length);
}
private:
/**
* Run the key schedule
* @param key the key
* @param length of key
*/
virtual void key_schedule(const byte key[], size_t length) = 0;
};
/**
* The two possible directions for cipher filters, determining whether they
* actually perform encryption or decryption.
*/
enum Cipher_Dir { ENCRYPTION, DECRYPTION };
}
namespace Botan {
/**
* This class represents a block cipher object.
*/
class BOTAN_DLL BlockCipher : public SymmetricAlgorithm
{
public:
/**
* @return block size of this algorithm
*/
virtual size_t block_size() const = 0;
/**
* @return native parallelism of this cipher in blocks
*/
virtual size_t parallelism() const { return 1; }
/**
* @return prefererred parallelism of this cipher in bytes
*/
size_t parallel_bytes() const
{
return parallelism() * block_size() * BOTAN_BLOCK_CIPHER_PAR_MULT;
}
/**
* Encrypt a block.
* @param in The plaintext block to be encrypted as a byte array.
* Must be of length block_size().
* @param out The byte array designated to hold the encrypted block.
* Must be of length block_size().
*/
void encrypt(const byte in[], byte out[]) const
{ encrypt_n(in, out, 1); }
/**
* Decrypt a block.
* @param in The ciphertext block to be decypted as a byte array.
* Must be of length block_size().
* @param out The byte array designated to hold the decrypted block.
* Must be of length block_size().
*/
void decrypt(const byte in[], byte out[]) const
{ decrypt_n(in, out, 1); }
/**
* Encrypt a block.
* @param block the plaintext block to be encrypted
* Must be of length block_size(). Will hold the result when the function
* has finished.
*/
void encrypt(byte block[]) const { encrypt_n(block, block, 1); }
/**
* Decrypt a block.
* @param block the ciphertext block to be decrypted
* Must be of length block_size(). Will hold the result when the function
* has finished.
*/
void decrypt(byte block[]) const { decrypt_n(block, block, 1); }
/**
* Encrypt one or more blocks
* @param in the input buffer (multiple of block_size())
* @param out the output buffer (same size as in)
* @param blocks the number of blocks to process
*/
virtual void encrypt_n(const byte in[], byte out[],
size_t blocks) const = 0;
/**
* Decrypt one or more blocks
* @param in the input buffer (multiple of block_size())
* @param out the output buffer (same size as in)
* @param blocks the number of blocks to process
*/
virtual void decrypt_n(const byte in[], byte out[],
size_t blocks) const = 0;
/**
* Get a new object representing the same algorithm as *this
*/
virtual BlockCipher* clone() const = 0;
};
/**
* Represents a block cipher with a single fixed block size
*/
template<size_t BS, size_t KMIN, size_t KMAX = 0, size_t KMOD = 1>
class Block_Cipher_Fixed_Params : public BlockCipher
{
public:
enum { BLOCK_SIZE = BS };
size_t block_size() const { return BS; }
Key_Length_Specification key_spec() const
{
return Key_Length_Specification(KMIN, KMAX, KMOD);
}
};
}
namespace Botan {
/**
* Base class for all stream ciphers
*/
class BOTAN_DLL StreamCipher : public SymmetricAlgorithm
{
public:
/**
* Encrypt or decrypt a message
* @param in the plaintext
* @param out the byte array to hold the output, i.e. the ciphertext
* @param len the length of both in and out in bytes
*/
virtual void cipher(const byte in[], byte out[], size_t len) = 0;
/**
* Encrypt or decrypt a message
* @param buf the plaintext / ciphertext
* @param len the length of buf in bytes
*/
void cipher1(byte buf[], size_t len)
{ cipher(buf, buf, len); }
/**
* Resync the cipher using the IV
* @param iv the initialization vector
* @param iv_len the length of the IV in bytes
*/
virtual void set_iv(const byte iv[], size_t iv_len);
/**
* @param iv_len the length of the IV in bytes
* @return if the length is valid for this algorithm
*/
virtual bool valid_iv_length(size_t iv_len) const;
/**
* Get a new object representing the same algorithm as *this
*/
virtual StreamCipher* clone() const = 0;
};
}
namespace Botan {
/**
* This class represents Message Authentication Code (MAC) objects.
*/
class BOTAN_DLL MessageAuthenticationCode : public Buffered_Computation,
public SymmetricAlgorithm
{
public:
/**
* Verify a MAC.
* @param in the MAC to verify as a byte array
* @param length the length of param in
* @return true if the MAC is valid, false otherwise
*/
virtual bool verify_mac(const byte in[], size_t length);
/**
* Get a new object representing the same algorithm as *this
*/
virtual MessageAuthenticationCode* clone() const = 0;
/**
* Get the name of this algorithm.
* @return name of this algorithm
*/
virtual std::string name() const = 0;
};
}
namespace Botan {
/**
* Base class for PBKDF (password based key derivation function)
* implementations. Converts a password into a key using a salt
* and iterated hashing to make brute force attacks harder.
*/
class BOTAN_DLL PBKDF : public Algorithm
{
public:
/**
* @return new instance of this same algorithm
*/
virtual PBKDF* clone() const = 0;
void clear() {}
/**
* Derive a key from a passphrase
* @param output_len the desired length of the key to produce
* @param passphrase the password to derive the key from
* @param salt a randomly chosen salt
* @param salt_len length of salt in bytes
* @param iterations the number of iterations to use (use 10K or more)
*/
virtual OctetString derive_key(size_t output_len,
const std::string& passphrase,
const byte salt[], size_t salt_len,
size_t iterations) const = 0;
};
/**
* For compatability with 1.8
*/
typedef PBKDF S2K;
}
namespace Botan {
#if (BOTAN_MP_WORD_BITS == 8)
typedef byte word;
#elif (BOTAN_MP_WORD_BITS == 16)
typedef u16bit word;
#elif (BOTAN_MP_WORD_BITS == 32)
typedef u32bit word;
#elif (BOTAN_MP_WORD_BITS == 64)
typedef u64bit word;
#else
#error BOTAN_MP_WORD_BITS must be 8, 16, 32, or 64
#endif
const word MP_WORD_MASK = ~static_cast<word>(0);
const word MP_WORD_TOP_BIT = static_cast<word>(1) << (8*sizeof(word) - 1);
const word MP_WORD_MAX = MP_WORD_MASK;
}
namespace Botan {
/**
* Arbitrary precision integer
*/
class BOTAN_DLL BigInt
{
public:
/**
* Base enumerator for encoding and decoding
*/
enum Base { Octal = 8, Decimal = 10, Hexadecimal = 16, Binary = 256 };
/**
* Sign symbol definitions for positive and negative numbers
*/
enum Sign { Negative = 0, Positive = 1 };
/**
* Number types (currently only power-of-2 supported)
*/
enum NumberType { Power2 };
/**
* DivideByZero Exception
*/
struct BOTAN_DLL DivideByZero : public Exception
{ DivideByZero() : Exception("BigInt divide by zero") {} };
/**
* += operator
* @param y the BigInt to add to this
*/
BigInt& operator+=(const BigInt& y);
/**
* -= operator
* @param y the BigInt to subtract from this
*/
BigInt& operator-=(const BigInt& y);
/**
* *= operator
* @param y the BigInt to multiply with this
*/
BigInt& operator*=(const BigInt& y);
/**
* /= operator
* @param y the BigInt to divide this by
*/
BigInt& operator/=(const BigInt& y);
/**
* Modulo operator
* @param y the modulus to reduce this by
*/
BigInt& operator%=(const BigInt& y);
/**
* Modulo operator
* @param y the modulus (word) to reduce this by
*/
word operator%=(word y);
/**
* Left shift operator
* @param shift the number of bits to shift this left by
*/
BigInt& operator<<=(size_t shift);
/**
* Right shift operator
* @param shift the number of bits to shift this right by
*/
BigInt& operator>>=(size_t shift);
/**
* Increment operator
*/
BigInt& operator++() { return (*this += 1); }
/**
* Decrement operator
*/
BigInt& operator--() { return (*this -= 1); }
/**
* Postfix increment operator
*/
BigInt operator++(int) { BigInt x = (*this); ++(*this); return x; }
/**
* Postfix decrement operator
*/
BigInt operator--(int) { BigInt x = (*this); --(*this); return x; }
/**
* Unary negation operator
* @return negative this
*/
BigInt operator-() const;
/**
* ! operator
* @return true iff this is zero, otherwise false
*/
bool operator !() const { return (!is_nonzero()); }
/**
* [] operator (array access)
* @param i a word index
* @return the word at index i
*/
word& operator[](size_t i) { return reg[i]; }
/**
* [] operator (array access)
* @param i a word index
* @return the word at index i
*/
const word& operator[](size_t i) const { return reg[i]; }
/**
* Zeroize the BigInt
*/
void clear() { zeroise(reg); }
/**
* Compare this to another BigInt
* @param n the BigInt value to compare with
* @param check_signs include sign in comparison?
* @result if (this<n) return -1, if (this>n) return 1, if both
* values are identical return 0 [like Perl's <=> operator]
*/
s32bit cmp(const BigInt& n, bool check_signs = true) const;
/**
* Test if the integer has an even value
* @result true if the integer is even, false otherwise
*/
bool is_even() const { return (get_bit(0) == 0); }
/**
* Test if the integer has an odd value
* @result true if the integer is odd, false otherwise
*/
bool is_odd() const { return (get_bit(0) == 1); }
/**
* Test if the integer is not zero
* @result true if the integer is non-zero, false otherwise
*/
bool is_nonzero() const { return (!is_zero()); }
/**
* Test if the integer is zero
* @result true if the integer is zero, false otherwise
*/
bool is_zero() const
{
const size_t sw = sig_words();
for(size_t i = 0; i != sw; ++i)
if(reg[i])
return false;
return true;
}
/**
* Set bit at specified position
* @param n bit position to set
*/
void set_bit(size_t n);
/**
* Clear bit at specified position
* @param n bit position to clear
*/
void clear_bit(size_t n);
/**
* Clear all but the lowest n bits
* @param n amount of bits to keep
*/
void mask_bits(size_t n);
/**
* Return bit value at specified position
* @param n the bit offset to test
* @result true, if the bit at position n is set, false otherwise
*/
bool get_bit(size_t n) const;
/**
* Return (a maximum of) 32 bits of the complete value
* @param offset the offset to start extracting
* @param length amount of bits to extract (starting at offset)
* @result the integer extracted from the register starting at
* offset with specified length
*/
u32bit get_substring(size_t offset, size_t length) const;
/**
* Convert this value into a u32bit, if it is in the range
* [0 ... 2**32-1], or otherwise throw an exception.
* @result the value as a u32bit if conversion is possible
*/
u32bit to_u32bit() const;
/**
* @param n the offset to get a byte from
* @result byte at offset n
*/
byte byte_at(size_t n) const;
/**
* Return the word at a specified position of the internal register
* @param n position in the register
* @return value at position n
*/
word word_at(size_t n) const
{ return ((n < size()) ? reg[n] : 0); }
/**
* Tests if the sign of the integer is negative
* @result true, iff the integer has a negative sign
*/
bool is_negative() const { return (sign() == Negative); }
/**
* Tests if the sign of the integer is positive
* @result true, iff the integer has a positive sign
*/
bool is_positive() const { return (sign() == Positive); }
/**
* Return the sign of the integer
* @result the sign of the integer
*/
Sign sign() const { return (signedness); }
/**
* @result the opposite sign of the represented integer value
*/
Sign reverse_sign() const;
/**
* Flip the sign of this BigInt
*/
void flip_sign();
/**
* Set sign of the integer
* @param sign new Sign to set
*/
void set_sign(Sign sign);
/**
* @result absolute (positive) value of this
*/
BigInt abs() const;
/**
* Give size of internal register
* @result size of internal register in words
*/
size_t size() const { return get_reg().size(); }
/**
* Return how many words we need to hold this value
* @result significant words of the represented integer value
*/
size_t sig_words() const
{
const word* x = &reg[0];
size_t sig = reg.size();
while(sig && (x[sig-1] == 0))
sig--;
return sig;
}
/**
* Give byte length of the integer
* @result byte length of the represented integer value
*/
size_t bytes() const;
/**
* Get the bit length of the integer
* @result bit length of the represented integer value
*/
size_t bits() const;
/**
* Return a pointer to the big integer word register
* @result a pointer to the start of the internal register of
* the integer value
*/
const word* data() const { return &reg[0]; }
/**
* return a reference to the internal register containing the value
* @result a reference to the word-array (SecureVector<word>)
* with the internal register value (containing the integer
* value)
*/
SecureVector<word>& get_reg() { return reg; }
/**
* return a const reference to the internal register containing the value
* @result a const reference to the word-array (SecureVector<word>)
* with the internal register value (containing the integer value)
*/
const SecureVector<word>& get_reg() const { return reg; }
/**
* Assign using a plain word array
*/
void assign(const word x[], size_t length)
{
reg.resize(length);
copy_mem(&reg[0], x, length);
}
/**
* Increase internal register buffer by n words
* @param n increase by n words
*/
void grow_reg(size_t n);
void grow_to(size_t n);
/**
* Fill BigInt with a random number with size of bitsize
* @param rng the random number generator to use
* @param bitsize number of bits the created random value should have
*/
void randomize(RandomNumberGenerator& rng, size_t bitsize = 0);
/**
* Store BigInt-value in a given byte array
* @param buf destination byte array for the integer value
*/
void binary_encode(byte buf[]) const;
/**
* Read integer value from a byte array with given size
* @param buf byte array buffer containing the integer
* @param length size of buf
*/
void binary_decode(const byte buf[], size_t length);
/**
* Read integer value from a byte array (MemoryRegion<byte>)
* @param buf the array to load from
*/
void binary_decode(const MemoryRegion<byte>& buf);
/**
* @param base the base to measure the size for
* @return size of this integer in base base
*/
size_t encoded_size(Base base = Binary) const;
/**
* @param rng a random number generator
* @param min the minimum value
* @param max the maximum value
* @return random integer between min and max
*/
static BigInt random_integer(RandomNumberGenerator& rng,
const BigInt& min,
const BigInt& max);
/**
* Encode the integer value from a BigInt to a SecureVector of bytes
* @param n the BigInt to use as integer source
* @param base number-base of resulting byte array representation
* @result SecureVector of bytes containing the integer with given base
*/
static SecureVector<byte> encode(const BigInt& n, Base base = Binary);
/**
* Encode the integer value from a BigInt to a byte array
* @param buf destination byte array for the encoded integer
* value with given base
* @param n the BigInt to use as integer source
* @param base number-base of resulting byte array representation
*/
static void encode(byte buf[], const BigInt& n, Base base = Binary);
/**
* Create a BigInt from an integer in a byte array
* @param buf the binary value to load
* @param length size of buf
* @param base number-base of the integer in buf
* @result BigInt representing the integer in the byte array
*/
static BigInt decode(const byte buf[], size_t length,
Base base = Binary);
/**
* Create a BigInt from an integer in a byte array
* @param buf the binary value to load
* @param base number-base of the integer in buf
* @result BigInt representing the integer in the byte array
*/
static BigInt decode(const MemoryRegion<byte>& buf,
Base base = Binary);
/**
* Encode a BigInt to a byte array according to IEEE 1363
* @param n the BigInt to encode
* @param bytes the length of the resulting SecureVector<byte>
* @result a SecureVector<byte> containing the encoded BigInt
*/
static SecureVector<byte> encode_1363(const BigInt& n, size_t bytes);
/**
* Swap this value with another
* @param other BigInt to swap values with
*/
void swap(BigInt& other);
/**
* Create empty BigInt
*/
BigInt() { signedness = Positive; }
/**
* Create BigInt from 64 bit integer
* @param n initial value of this BigInt
*/
BigInt(u64bit n);
/**
* Copy Constructor
* @param other the BigInt to copy
*/
BigInt(const BigInt& other);
/**
* Create BigInt from a string. If the string starts with 0x the
* rest of the string will be interpreted as hexadecimal digits.
* If the string starts with 0 and the second character is NOT an
* 'x' the string will be interpreted as octal digits. If the
* string starts with non-zero digit, it will be interpreted as a
* decimal number.
*
* @param str the string to parse for an integer value
*/
BigInt(const std::string& str);
/**
* Create a BigInt from an integer in a byte array
* @param buf the byte array holding the value
* @param length size of buf
* @param base is the number base of the integer in buf
*/
BigInt(const byte buf[], size_t length, Base base = Binary);
/**
* Create a random BigInt of the specified size
* @param rng random number generator
* @param bits size in bits
*/
BigInt(RandomNumberGenerator& rng, size_t bits);
/**
* Create BigInt of specified size, all zeros
* @param sign the sign
* @param n size of the internal register in words
*/
BigInt(Sign sign, size_t n);
/**
* Create a number of the specified type and size
* @param type the type of number to create. For Power2,
* will create the integer 2^n
* @param n a size/length parameter, interpretation depends upon
* the value of type
*/
BigInt(NumberType type, size_t n);
private:
SecureVector<word> reg;
Sign signedness;
};
/*
* Arithmetic Operators
*/
BigInt BOTAN_DLL operator+(const BigInt& x, const BigInt& y);
BigInt BOTAN_DLL operator-(const BigInt& x, const BigInt& y);
BigInt BOTAN_DLL operator*(const BigInt& x, const BigInt& y);
BigInt BOTAN_DLL operator/(const BigInt& x, const BigInt& d);
BigInt BOTAN_DLL operator%(const BigInt& x, const BigInt& m);
word BOTAN_DLL operator%(const BigInt& x, word m);
BigInt BOTAN_DLL operator<<(const BigInt& x, size_t n);
BigInt BOTAN_DLL operator>>(const BigInt& x, size_t n);
/*
* Comparison Operators
*/
inline bool operator==(const BigInt& a, const BigInt& b)
{ return (a.cmp(b) == 0); }
inline bool operator!=(const BigInt& a, const BigInt& b)
{ return (a.cmp(b) != 0); }
inline bool operator<=(const BigInt& a, const BigInt& b)
{ return (a.cmp(b) <= 0); }
inline bool operator>=(const BigInt& a, const BigInt& b)
{ return (a.cmp(b) >= 0); }
inline bool operator<(const BigInt& a, const BigInt& b)
{ return (a.cmp(b) < 0); }
inline bool operator>(const BigInt& a, const BigInt& b)
{ return (a.cmp(b) > 0); }
/*
* I/O Operators
*/
BOTAN_DLL std::ostream& operator<<(std::ostream&, const BigInt&);
BOTAN_DLL std::istream& operator>>(std::istream&, BigInt&);
}
namespace std {
template<>
inline void swap(Botan::BigInt& x, Botan::BigInt& y)
{
x.swap(y);
}
}
namespace Botan {
/**
* Modular Exponentiator Interface
*/
class BOTAN_DLL Modular_Exponentiator
{
public:
virtual void set_base(const BigInt&) = 0;
virtual void set_exponent(const BigInt&) = 0;
virtual BigInt execute() const = 0;
virtual Modular_Exponentiator* copy() const = 0;
virtual ~Modular_Exponentiator() {}
};
/**
* Modular Exponentiator Proxy
*/
class BOTAN_DLL Power_Mod
{
public:
enum Usage_Hints {
NO_HINTS = 0x0000,
BASE_IS_FIXED = 0x0001,
BASE_IS_SMALL = 0x0002,
BASE_IS_LARGE = 0x0004,
BASE_IS_2 = 0x0008,
EXP_IS_FIXED = 0x0100,
EXP_IS_SMALL = 0x0200,
EXP_IS_LARGE = 0x0400
};
/*
* Try to choose a good window size
*/
static size_t window_bits(size_t exp_bits, size_t base_bits,
Power_Mod::Usage_Hints hints);
void set_modulus(const BigInt&, Usage_Hints = NO_HINTS) const;
void set_base(const BigInt&) const;
void set_exponent(const BigInt&) const;
BigInt execute() const;
Power_Mod& operator=(const Power_Mod&);
Power_Mod(const BigInt& = 0, Usage_Hints = NO_HINTS);
Power_Mod(const Power_Mod&);
virtual ~Power_Mod();
private:
mutable Modular_Exponentiator* core;
Usage_Hints hints;
};
/**
* Fixed Exponent Modular Exponentiator Proxy
*/
class BOTAN_DLL Fixed_Exponent_Power_Mod : public Power_Mod
{
public:
BigInt operator()(const BigInt& b) const
{ set_base(b); return execute(); }
Fixed_Exponent_Power_Mod() {}
Fixed_Exponent_Power_Mod(const BigInt&, const BigInt&,
Usage_Hints = NO_HINTS);
};
/**
* Fixed Base Modular Exponentiator Proxy
*/
class BOTAN_DLL Fixed_Base_Power_Mod : public Power_Mod
{
public:
BigInt operator()(const BigInt& e) const
{ set_exponent(e); return execute(); }
Fixed_Base_Power_Mod() {}
Fixed_Base_Power_Mod(const BigInt&, const BigInt&,
Usage_Hints = NO_HINTS);
};
}
namespace Botan {
/**
* ASN.1 Type and Class Tags
*/
enum ASN1_Tag {
UNIVERSAL = 0x00,
APPLICATION = 0x40,
CONTEXT_SPECIFIC = 0x80,
PRIVATE = 0xC0,
CONSTRUCTED = 0x20,
EOC = 0x00,
BOOLEAN = 0x01,
INTEGER = 0x02,
BIT_STRING = 0x03,
OCTET_STRING = 0x04,
NULL_TAG = 0x05,
OBJECT_ID = 0x06,
ENUMERATED = 0x0A,
SEQUENCE = 0x10,
SET = 0x11,
UTF8_STRING = 0x0C,
NUMERIC_STRING = 0x12,
PRINTABLE_STRING = 0x13,
T61_STRING = 0x14,
IA5_STRING = 0x16,
VISIBLE_STRING = 0x1A,
BMP_STRING = 0x1E,
UTC_TIME = 0x17,
GENERALIZED_TIME = 0x18,
NO_OBJECT = 0xFF00,
DIRECTORY_STRING = 0xFF01
};
/**
* Basic ASN.1 Object Interface
*/
class BOTAN_DLL ASN1_Object
{
public:
/**
* Encode whatever this object is into to
* @param to the DER_Encoder that will be written to
*/
virtual void encode_into(class DER_Encoder& to) const = 0;
/**
* Decode whatever this object is from from
* @param from the BER_Decoder that will be read from
*/
virtual void decode_from(class BER_Decoder& from) = 0;
virtual ~ASN1_Object() {}
};
/**
* BER Encoded Object
*/
class BOTAN_DLL BER_Object
{
public:
void assert_is_a(ASN1_Tag, ASN1_Tag);
ASN1_Tag type_tag, class_tag;
SecureVector<byte> value;
};
/*
* ASN.1 Utility Functions
*/
class DataSource;
namespace ASN1 {
SecureVector<byte> put_in_sequence(const MemoryRegion<byte>& val);
std::string to_string(const BER_Object& obj);
/**
* Heuristics tests; is this object possibly BER?
* @param src a data source that will be peeked at but not modified
*/
bool maybe_BER(DataSource& src);
}
/**
* General BER Decoding Error Exception
*/
struct BOTAN_DLL BER_Decoding_Error : public Decoding_Error
{
BER_Decoding_Error(const std::string&);
};
/**
* Exception For Incorrect BER Taggings
*/
struct BOTAN_DLL BER_Bad_Tag : public BER_Decoding_Error
{
BER_Bad_Tag(const std::string& msg, ASN1_Tag tag);
BER_Bad_Tag(const std::string& msg, ASN1_Tag tag1, ASN1_Tag tag2);
};
}
namespace Botan {
/**
* This class represents ASN.1 object identifiers.
*/
class BOTAN_DLL OID : public ASN1_Object
{
public:
void encode_into(class DER_Encoder&) const;
void decode_from(class BER_Decoder&);
/**
* Find out whether this OID is empty
* @return true is no OID value is set
*/
bool is_empty() const { return id.size() == 0; }
/**
* Get this OID as list (vector) of its components.
* @return vector representing this OID
*/
std::vector<u32bit> get_id() const { return id; }
/**
* Get this OID as a string
* @return string representing this OID
*/
std::string as_string() const;
/**
* Compare two OIDs.
* @return true if they are equal, false otherwise
*/
bool operator==(const OID&) const;
/**
* Reset this instance to an empty OID.
*/
void clear();
/**
* Add a component to this OID.
* @param new_comp the new component to add to the end of this OID
* @return reference to *this
*/
OID& operator+=(u32bit new_comp);
/**
* Construct an OID from a string.
* @param str a string in the form "a.b.c" etc., where a,b,c are numbers
*/
OID(const std::string& str = "");
private:
std::vector<u32bit> id;
};
/**
* Append another component onto the OID.
* @param oid the OID to add the new component to
* @param new_comp the new component to add
*/
OID operator+(const OID& oid, u32bit new_comp);
/**
* Compare two OIDs.
* @param a the first OID
* @param b the second OID
* @return true if a is not equal to b
*/
bool operator!=(const OID& a, const OID& b);
/**
* Compare two OIDs.
* @param a the first OID
* @param b the second OID
* @return true if a is lexicographically smaller than b
*/
bool operator<(const OID& a, const OID& b);
}
namespace Botan {
/**
* Algorithm Identifier
*/
class BOTAN_DLL AlgorithmIdentifier : public ASN1_Object
{
public:
enum Encoding_Option { USE_NULL_PARAM };
void encode_into(class DER_Encoder&) const;
void decode_from(class BER_Decoder&);
AlgorithmIdentifier() {}
AlgorithmIdentifier(const OID&, Encoding_Option);
AlgorithmIdentifier(const std::string&, Encoding_Option);
AlgorithmIdentifier(const OID&, const MemoryRegion<byte>&);
AlgorithmIdentifier(const std::string&, const MemoryRegion<byte>&);
OID oid;
SecureVector<byte> parameters;
};
/*
* Comparison Operations
*/
bool BOTAN_DLL operator==(const AlgorithmIdentifier&,
const AlgorithmIdentifier&);
bool BOTAN_DLL operator!=(const AlgorithmIdentifier&,
const AlgorithmIdentifier&);
}
namespace Botan {
/**
* Public Key Base Class.
*/
class BOTAN_DLL Public_Key
{
public:
/**
* Get the name of the underlying public key scheme.
* @return name of the public key scheme
*/
virtual std::string algo_name() const = 0;
/**
* Get the OID of the underlying public key scheme.
* @return OID of the public key scheme
*/
virtual OID get_oid() const;
/**
* Test the key values for consistency.
* @param rng rng to use
* @param strong whether to perform strong and lengthy version
* of the test
* @return true if the test is passed
*/
virtual bool check_key(RandomNumberGenerator& rng,
bool strong) const = 0;
/**
* Find out the number of message parts supported by this scheme.
* @return number of message parts
*/
virtual size_t message_parts() const { return 1; }
/**
* Find out the message part size supported by this scheme/key.
* @return size of the message parts in bits
*/
virtual size_t message_part_size() const { return 0; }
/**
* Get the maximum message size in bits supported by this public key.
* @return maximum message size in bits
*/
virtual size_t max_input_bits() const = 0;
/**
* @return X.509 AlgorithmIdentifier for this key
*/
virtual AlgorithmIdentifier algorithm_identifier() const = 0;
/**
* @return X.509 subject key encoding for this key object
*/
virtual MemoryVector<byte> x509_subject_public_key() const = 0;
virtual ~Public_Key() {}
protected:
/**
* Self-test after loading a key
* @param rng a random number generator
*/
virtual void load_check(RandomNumberGenerator& rng) const;
};
/**
* Private Key Base Class
*/
class BOTAN_DLL Private_Key : public virtual Public_Key
{
public:
/**
* @return PKCS #8 private key encoding for this key object
*/
virtual MemoryVector<byte> pkcs8_private_key() const = 0;
/**
* @return PKCS #8 AlgorithmIdentifier for this key
* Might be different from the X.509 identifier, but normally is not
*/
virtual AlgorithmIdentifier pkcs8_algorithm_identifier() const
{ return algorithm_identifier(); }
protected:
/**
* Self-test after loading a key
* @param rng a random number generator
*/
void load_check(RandomNumberGenerator& rng) const;
/**
* Self-test after generating a key
* @param rng a random number generator
*/
void gen_check(RandomNumberGenerator& rng) const;
};
/**
* PK Secret Value Derivation Key
*/
class BOTAN_DLL PK_Key_Agreement_Key : public virtual Private_Key
{
public:
/*
* @return public component of this key
*/
virtual MemoryVector<byte> public_value() const = 0;
virtual ~PK_Key_Agreement_Key() {}
};
/*
* Typedefs
*/
typedef PK_Key_Agreement_Key PK_KA_Key;
typedef Public_Key X509_PublicKey;
typedef Private_Key PKCS8_PrivateKey;
}
namespace Botan {
namespace PK_Ops {
/**
* Public key encryption interface
*/
class BOTAN_DLL Encryption
{
public:
virtual size_t max_input_bits() const = 0;
virtual SecureVector<byte> encrypt(const byte msg[], size_t msg_len,
RandomNumberGenerator& rng) = 0;
virtual ~Encryption() {}
};
/**
* Public key decryption interface
*/
class BOTAN_DLL Decryption
{
public:
virtual size_t max_input_bits() const = 0;
virtual SecureVector<byte> decrypt(const byte msg[],
size_t msg_len) = 0;
virtual ~Decryption() {}
};
/**
* Public key signature creation interface
*/
class BOTAN_DLL Signature
{
public:
/**
* Find out the number of message parts supported by this scheme.
* @return number of message parts
*/
virtual size_t message_parts() const { return 1; }
/**
* Find out the message part size supported by this scheme/key.
* @return size of the message parts
*/
virtual size_t message_part_size() const { return 0; }
/**
* Get the maximum message size in bits supported by this public key.
* @return maximum message in bits
*/
virtual size_t max_input_bits() const = 0;
/*
* Perform a signature operation
* @param msg the message
* @param msg_len the length of msg in bytes
* @param rng a random number generator
*/
virtual SecureVector<byte> sign(const byte msg[], size_t msg_len,
RandomNumberGenerator& rng) = 0;
virtual ~Signature() {}
};
/**
* Public key signature verification interface
*/
class BOTAN_DLL Verification
{
public:
/**
* Get the maximum message size in bits supported by this public key.
* @return maximum message in bits
*/
virtual size_t max_input_bits() const = 0;
/**
* Find out the number of message parts supported by this scheme.
* @return number of message parts
*/
virtual size_t message_parts() const { return 1; }
/**
* Find out the message part size supported by this scheme/key.
* @return size of the message parts
*/
virtual size_t message_part_size() const { return 0; }
/**
* @return boolean specifying if this key type supports message
* recovery and thus if you need to call verify() or verify_mr()
*/
virtual bool with_recovery() const = 0;
/*
* Perform a signature check operation
* @param msg the message
* @param msg_len the length of msg in bytes
* @param sig the signature
* @param sig_len the length of sig in bytes
* @returns if signature is a valid one for message
*/
virtual bool verify(const byte[], size_t,
const byte[], size_t)
{
throw Invalid_State("Message recovery required");
}
/*
* Perform a signature operation (with message recovery)
* Only call this if with_recovery() returns true
* @param msg the message
* @param msg_len the length of msg in bytes
* @returns recovered message
*/
virtual SecureVector<byte> verify_mr(const byte[],
size_t)
{
throw Invalid_State("Message recovery not supported");
}
virtual ~Verification() {}
};
/**
* A generic key agreement Operation (eg DH or ECDH)
*/
class BOTAN_DLL Key_Agreement
{
public:
/*
* Perform a key agreement operation
* @param w the other key value
* @param w_len the length of w in bytes
* @returns the agreed key
*/
virtual SecureVector<byte> agree(const byte w[], size_t w_len) = 0;
virtual ~Key_Agreement() {}
};
}
}
namespace Botan {
class Algorithm_Factory;
class Keyed_Filter;
/**
* Base class for all engines. All non-pure virtual functions simply
* return NULL, indicating the algorithm in question is not
* supported. Subclasses can reimplement whichever function(s)
* they want to hook in a particular type.
*/
class BOTAN_DLL Engine
{
public:
virtual ~Engine() {}
/**
* @return name of this engine
*/
virtual std::string provider_name() const = 0;
/**
* @param algo_spec the algorithm name/specification
* @param af an algorithm factory object
* @return newly allocated object, or NULL
*/
virtual BlockCipher*
find_block_cipher(const SCAN_Name& algo_spec,
Algorithm_Factory& af) const;
/**
* @param algo_spec the algorithm name/specification
* @param af an algorithm factory object
* @return newly allocated object, or NULL
*/
virtual StreamCipher*
find_stream_cipher(const SCAN_Name& algo_spec,
Algorithm_Factory& af) const;
/**
* @param algo_spec the algorithm name/specification
* @param af an algorithm factory object
* @return newly allocated object, or NULL
*/
virtual HashFunction*
find_hash(const SCAN_Name& algo_spec,
Algorithm_Factory& af) const;
/**
* @param algo_spec the algorithm name/specification
* @param af an algorithm factory object
* @return newly allocated object, or NULL
*/
virtual MessageAuthenticationCode*
find_mac(const SCAN_Name& algo_spec,
Algorithm_Factory& af) const;
/**
* @param algo_spec the algorithm name/specification
* @param af an algorithm factory object
* @return newly allocated object, or NULL
*/
virtual PBKDF* find_pbkdf(const SCAN_Name& algo_spec,
Algorithm_Factory& af) const;
/**
* @param n the modulus
* @param hints any use hints
* @return newly allocated object, or NULL
*/
virtual Modular_Exponentiator*
mod_exp(const BigInt& n,
Power_Mod::Usage_Hints hints) const;
/**
* Return a new cipher object
* @param algo_spec the algorithm name/specification
* @param dir specifies if encryption or decryption is desired
* @param af an algorithm factory object
* @return newly allocated object, or NULL
*/
virtual Keyed_Filter* get_cipher(const std::string& algo_spec,
Cipher_Dir dir,
Algorithm_Factory& af);
/**
* Return a new operator object for this key, if possible
* @param key the key we want an operator for
* @return newly allocated operator object, or NULL
*/
virtual PK_Ops::Key_Agreement*
get_key_agreement_op(const Private_Key& key) const;
/**
* Return a new operator object for this key, if possible
* @param key the key we want an operator for
* @return newly allocated operator object, or NULL
*/
virtual PK_Ops::Signature*
get_signature_op(const Private_Key& key) const;
/**
* Return a new operator object for this key, if possible
* @param key the key we want an operator for
* @return newly allocated operator object, or NULL
*/
virtual PK_Ops::Verification*
get_verify_op(const Public_Key& key) const;
/**
* Return a new operator object for this key, if possible
* @param key the key we want an operator for
* @return newly allocated operator object, or NULL
*/
virtual PK_Ops::Encryption*
get_encryption_op(const Public_Key& key) const;
/**
* Return a new operator object for this key, if possible
* @param key the key we want an operator for
* @return newly allocated operator object, or NULL
*/
virtual PK_Ops::Decryption*
get_decryption_op(const Private_Key& key) const;
};
}
namespace Botan {
/**
* Dynamically_Loaded_Engine just proxies the requests to the underlying
* Engine object, and handles load/unload details
*/
class BOTAN_DLL Dynamically_Loaded_Engine : public Engine
{
public:
/**
* @param lib_path full pathname to DLL to load
*/
Dynamically_Loaded_Engine(const std::string& lib_path);
~Dynamically_Loaded_Engine();
std::string provider_name() const { return engine->provider_name(); }
BlockCipher* find_block_cipher(const SCAN_Name& algo_spec,
Algorithm_Factory& af) const
{
return engine->find_block_cipher(algo_spec, af);
}
StreamCipher* find_stream_cipher(const SCAN_Name& algo_spec,
Algorithm_Factory& af) const
{
return engine->find_stream_cipher(algo_spec, af);
}
HashFunction* find_hash(const SCAN_Name& algo_spec,
Algorithm_Factory& af) const
{
return engine->find_hash(algo_spec, af);
}
MessageAuthenticationCode* find_mac(const SCAN_Name& algo_spec,
Algorithm_Factory& af) const
{
return engine->find_mac(algo_spec, af);
}
PBKDF* find_pbkdf(const SCAN_Name& algo_spec,
Algorithm_Factory& af) const
{
return engine->find_pbkdf(algo_spec, af);
}
Modular_Exponentiator* mod_exp(const BigInt& n,
Power_Mod::Usage_Hints hints) const
{
return engine->mod_exp(n, hints);
}
Keyed_Filter* get_cipher(const std::string& algo_spec,
Cipher_Dir dir,
Algorithm_Factory& af)
{
return engine->get_cipher(algo_spec, dir, af);
}
PK_Ops::Key_Agreement*
get_key_agreement_op(const Private_Key& key) const
{
return engine->get_key_agreement_op(key);
}
PK_Ops::Signature*
get_signature_op(const Private_Key& key) const
{
return engine->get_signature_op(key);
}
PK_Ops::Verification*
get_verify_op(const Public_Key& key) const
{
return engine->get_verify_op(key);
}
PK_Ops::Encryption*
get_encryption_op(const Public_Key& key) const
{
return engine->get_encryption_op(key);
}
PK_Ops::Decryption*
get_decryption_op(const Private_Key& key) const
{
return engine->get_decryption_op(key);
}
private:
class Dynamically_Loaded_Library* lib;
Engine* engine;
};
}
namespace Botan {
/**
* Simple String
*/
class BOTAN_DLL ASN1_String : public ASN1_Object
{
public:
void encode_into(class DER_Encoder&) const;
void decode_from(class BER_Decoder&);
std::string value() const;
std::string iso_8859() const;
ASN1_Tag tagging() const;
ASN1_String(const std::string& = "");
ASN1_String(const std::string&, ASN1_Tag);
private:
std::string iso_8859_str;
ASN1_Tag tag;
};
}
namespace Botan {
/**
* Attribute
*/
class BOTAN_DLL Attribute : public ASN1_Object
{
public:
void encode_into(class DER_Encoder& to) const;
void decode_from(class BER_Decoder& from);
OID oid;
MemoryVector<byte> parameters;
Attribute() {}
Attribute(const OID&, const MemoryRegion<byte>&);
Attribute(const std::string&, const MemoryRegion<byte>&);
};
/**
* X.509 Time
*/
class BOTAN_DLL X509_Time : public ASN1_Object
{
public:
void encode_into(class DER_Encoder&) const;
void decode_from(class BER_Decoder&);
std::string as_string() const;
std::string readable_string() const;
bool time_is_set() const;
s32bit cmp(const X509_Time&) const;
void set_to(const std::string&);
void set_to(const std::string&, ASN1_Tag);
X509_Time(u64bit);
X509_Time(const std::string& = "");
X509_Time(const std::string&, ASN1_Tag);
private:
bool passes_sanity_check() const;
u32bit year, month, day, hour, minute, second;
ASN1_Tag tag;
};
/**
* Alternative Name
*/
class BOTAN_DLL AlternativeName : public ASN1_Object
{
public:
void encode_into(class DER_Encoder&) const;
void decode_from(class BER_Decoder&);
std::multimap<std::string, std::string> contents() const;
void add_attribute(const std::string&, const std::string&);
std::multimap<std::string, std::string> get_attributes() const;
void add_othername(const OID&, const std::string&, ASN1_Tag);
std::multimap<OID, ASN1_String> get_othernames() const;
bool has_items() const;
AlternativeName(const std::string& = "", const std::string& = "",
const std::string& = "", const std::string& = "");
private:
std::multimap<std::string, std::string> alt_info;
std::multimap<OID, ASN1_String> othernames;
};
/*
* Comparison Operations
*/
bool BOTAN_DLL operator==(const X509_Time&, const X509_Time&);
bool BOTAN_DLL operator!=(const X509_Time&, const X509_Time&);
bool BOTAN_DLL operator<=(const X509_Time&, const X509_Time&);
bool BOTAN_DLL operator>=(const X509_Time&, const X509_Time&);
bool BOTAN_DLL operator<(const X509_Time&, const X509_Time&);
bool BOTAN_DLL operator>(const X509_Time&, const X509_Time&);
}
namespace Botan {
/**
* This class represents an abstract data source object.
*/
class BOTAN_DLL DataSource
{
public:
/**
* Read from the source. Moves the internal offset so that every
* call to read will return a new portion of the source.
*
* @param out the byte array to write the result to
* @param length the length of the byte array out
* @return length in bytes that was actually read and put
* into out
*/
virtual size_t read(byte out[], size_t length) = 0;
/**
* Read from the source but do not modify the internal
* offset. Consecutive calls to peek() will return portions of
* the source starting at the same position.
*
* @param out the byte array to write the output to
* @param length the length of the byte array out
* @param peek_offset the offset into the stream to read at
* @return length in bytes that was actually read and put
* into out
*/
virtual size_t peek(byte out[], size_t length,
size_t peek_offset) const = 0;
/**
* Test whether the source still has data that can be read.
* @return true if there is still data to read, false otherwise
*/
virtual bool end_of_data() const = 0;
/**
* return the id of this data source
* @return std::string representing the id of this data source
*/
virtual std::string id() const { return ""; }
/**
* Read one byte.
* @param out the byte to read to
* @return length in bytes that was actually read and put
* into out
*/
size_t read_byte(byte& out);
/**
* Peek at one byte.
* @param out an output byte
* @return length in bytes that was actually read and put
* into out
*/
size_t peek_byte(byte& out) const;
/**
* Discard the next N bytes of the data
* @param N the number of bytes to discard
* @return number of bytes actually discarded
*/
size_t discard_next(size_t N);
DataSource() {}
virtual ~DataSource() {}
private:
DataSource& operator=(const DataSource&) { return (*this); }
DataSource(const DataSource&);
};
/**
* This class represents a Memory-Based DataSource
*/
class BOTAN_DLL DataSource_Memory : public DataSource
{
public:
size_t read(byte[], size_t);
size_t peek(byte[], size_t, size_t) const;
bool end_of_data() const;
/**
* Construct a memory source that reads from a string
* @param in the string to read from
*/
DataSource_Memory(const std::string& in);
/**
* Construct a memory source that reads from a byte array
* @param in the byte array to read from
* @param length the length of the byte array
*/
DataSource_Memory(const byte in[], size_t length);
/**
* Construct a memory source that reads from a MemoryRegion
* @param in the MemoryRegion to read from
*/
DataSource_Memory(const MemoryRegion<byte>& in);
private:
SecureVector<byte> source;
size_t offset;
};
/**
* This class represents a Stream-Based DataSource.
*/
class BOTAN_DLL DataSource_Stream : 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;
DataSource_Stream(std::istream&,
const std::string& id = "<std::istream>");
/**
* Construct a Stream-Based DataSource from file
* @param file the name of the file
* @param use_binary whether to treat the file as binary or not
*/
DataSource_Stream(const std::string& file, bool use_binary = false);
~DataSource_Stream();
private:
const std::string identifier;
std::istream* source_p;
std::istream& source;
size_t total_read;
};
}
namespace Botan {
/**
* This class represents general abstract filter objects.
*/
class BOTAN_DLL Filter
{
public:
/**
* @return descriptive name for this filter
*/
virtual std::string name() const = 0;
/**
* Write a portion of a message to this filter.
* @param input the input as a byte array
* @param length the length of the byte array input
*/
virtual void write(const byte input[], size_t length) = 0;
/**
* Start a new message. Must be closed by end_msg() before another
* message can be started.
*/
virtual void start_msg() {}
/**
* Notify that the current message is finished; flush buffers and
* do end-of-message processing (if any).
*/
virtual void end_msg() {}
/**
* Check whether this filter is an attachable filter.
* @return true if this filter is attachable, false otherwise
*/
virtual bool attachable() { return true; }
virtual ~Filter() {}
protected:
/**
* @param in some input for the filter
* @param length the length of in
*/
void send(const byte in[], size_t length);
/**
* @param in some input for the filter
*/
void send(byte in) { send(&in, 1); }
/**
* @param in some input for the filter
*/
void send(const MemoryRegion<byte>& in) { send(&in[0], in.size()); }
/**
* @param in some input for the filter
* @param length the number of bytes of in to send
*/
void send(const MemoryRegion<byte>& in, size_t length)
{
send(&in[0], length);
}
Filter();
private:
Filter(const Filter&) {}
Filter& operator=(const Filter&) { return (*this); }
/**
* Start a new message in *this and all following filters. Only for
* internal use, not intended for use in client applications.
*/
void new_msg();
/**
* End a new message in *this and all following filters. Only for
* internal use, not intended for use in client applications.
*/
void finish_msg();
friend class Pipe;
friend class Fanout_Filter;
size_t total_ports() const;
size_t current_port() const { return port_num; }
/**
* Set the active port
* @param new_port the new value
*/
void set_port(size_t new_port);
size_t owns() const { return filter_owns; }
/**
* Attach another filter to this one
* @param f filter to attach
*/
void attach(Filter* f);
/**
* @param filters the filters to set
* @param count number of items in filters
*/
void set_next(Filter* filters[], size_t count);
Filter* get_next() const;
SecureVector<byte> write_queue;
std::vector<Filter*> next;
size_t port_num, filter_owns;
// true if filter belongs to a pipe --> prohibit filter sharing!
bool owned;
};
/**
* This is the abstract Fanout_Filter base class.
**/
class BOTAN_DLL Fanout_Filter : public Filter
{
protected:
/**
* Increment the number of filters past us that we own
*/
void incr_owns() { ++filter_owns; }
void set_port(size_t n) { Filter::set_port(n); }
void set_next(Filter* f[], size_t n) { Filter::set_next(f, n); }
void attach(Filter* f) { Filter::attach(f); }
};
/**
* The type of checking to be performed by decoders:
* NONE - no checks, IGNORE_WS - perform checks, but ignore
* whitespaces, FULL_CHECK - perform checks, also complain
* about white spaces.
*/
enum Decoder_Checking { NONE, IGNORE_WS, FULL_CHECK };
}
namespace Botan {
/**
* This class represents pipe objects.
* A set of filters can be placed into a pipe, and information flows
* through the pipe until it reaches the end, where the output is
* collected for retrieval. If you're familiar with the Unix shell
* environment, this design will sound quite familiar.
*/
class BOTAN_DLL Pipe : public DataSource
{
public:
/**
* An opaque type that identifies a message in this Pipe
*/
typedef size_t message_id;
/**
* Exception if you use an invalid message as an argument to
* read, remaining, etc
*/
struct BOTAN_DLL Invalid_Message_Number : public Invalid_Argument
{
/**
* @param where the error occured
* @param msg the invalid message id that was used
*/
Invalid_Message_Number(const std::string& where, message_id msg) :
Invalid_Argument("Pipe::" + where + ": Invalid message number " +
to_string(msg))
{}
};
/**
* A meta-id for whatever the last message is
*/
static const message_id LAST_MESSAGE;
/**
* A meta-id for the default message (set with set_default_msg)
*/
static const message_id DEFAULT_MESSAGE;
/**
* Write input to the pipe, i.e. to its first filter.
* @param in the byte array to write
* @param length the length of the byte array in
*/
void write(const byte in[], size_t length);
/**
* Write input to the pipe, i.e. to its first filter.
* @param in the MemoryRegion containing the data to write
*/
void write(const MemoryRegion<byte>& in);
/**
* Write input to the pipe, i.e. to its first filter.
* @param in the string containing the data to write
*/
void write(const std::string& in);
/**
* Write input to the pipe, i.e. to its first filter.
* @param in the DataSource to read the data from
*/
void write(DataSource& in);
/**
* Write input to the pipe, i.e. to its first filter.
* @param in a single byte to be written
*/
void write(byte in);
/**
* Perform start_msg(), write() and end_msg() sequentially.
* @param in the byte array containing the data to write
* @param length the length of the byte array to write
*/
void process_msg(const byte in[], size_t length);
/**
* Perform start_msg(), write() and end_msg() sequentially.
* @param in the MemoryRegion containing the data to write
*/
void process_msg(const MemoryRegion<byte>& in);
/**
* Perform start_msg(), write() and end_msg() sequentially.
* @param in the string containing the data to write
*/
void process_msg(const std::string& in);
/**
* Perform start_msg(), write() and end_msg() sequentially.
* @param in the DataSource providing the data to write
*/
void process_msg(DataSource& in);
/**
* Find out how many bytes are ready to read.
* @param msg the number identifying the message
* for which the information is desired
* @return number of bytes that can still be read
*/
size_t remaining(message_id msg = DEFAULT_MESSAGE) const;
/**
* Read the default message from the pipe. Moves the internal
* offset so that every call to read will return a new portion of
* the message.
*
* @param output the byte array to write the read bytes to
* @param length the length of the byte array output
* @return number of bytes actually read into output
*/
size_t read(byte output[], size_t length);
/**
* Read a specified message from the pipe. Moves the internal
* offset so that every call to read will return a new portion of
* the message.
* @param output the byte array to write the read bytes to
* @param length the length of the byte array output
* @param msg the number identifying the message to read from
* @return number of bytes actually read into output
*/
size_t read(byte output[], size_t length, message_id msg);
/**
* Read a single byte from the pipe. Moves the internal offset so
* that every call to read will return a new portion of the
* message.
*
* @param output the byte to write the result to
* @param msg the message to read from
* @return number of bytes actually read into output
*/
size_t read(byte& output, message_id msg = DEFAULT_MESSAGE);
/**
* Read the full contents of the pipe.
* @param msg the number identifying the message to read from
* @return SecureVector holding the contents of the pipe
*/
SecureVector<byte> read_all(message_id msg = DEFAULT_MESSAGE);
/**
* Read the full contents of the pipe.
* @param msg the number identifying the message to read from
* @return string holding the contents of the pipe
*/
std::string read_all_as_string(message_id = DEFAULT_MESSAGE);
/** Read from the default message but do not modify the internal
* offset. Consecutive calls to peek() will return portions of
* the message starting at the same position.
* @param output the byte array to write the peeked message part to
* @param length the length of the byte array output
* @param offset the offset from the current position in message
* @return number of bytes actually peeked and written into output
*/
size_t peek(byte output[], size_t length, size_t offset) const;
/** Read from the specified message but do not modify the
* internal offset. Consecutive calls to peek() will return
* portions of the message starting at the same position.
* @param output the byte array to write the peeked message part to
* @param length the length of the byte array output
* @param offset the offset from the current position in message
* @param msg the number identifying the message to peek from
* @return number of bytes actually peeked and written into output
*/
size_t peek(byte output[], size_t length,
size_t offset, message_id msg) const;
/** Read a single byte from the specified message but do not
* modify the internal offset. Consecutive calls to peek() will
* return portions of the message starting at the same position.
* @param output the byte to write the peeked message byte to
* @param offset the offset from the current position in message
* @param msg the number identifying the message to peek from
* @return number of bytes actually peeked and written into output
*/
size_t peek(byte& output, size_t offset,
message_id msg = DEFAULT_MESSAGE) const;
/**
* @return currently set default message
*/
size_t default_msg() const { return default_read; }
/**
* Set the default message
* @param msg the number identifying the message which is going to
* be the new default message
*/
void set_default_msg(message_id msg);
/**
* Get the number of messages the are in this pipe.
* @return number of messages the are in this pipe
*/
message_id message_count() const;
/**
* Test whether this pipe has any data that can be read from.
* @return true if there is more data to read, false otherwise
*/
bool end_of_data() const;
/**
* Start a new message in the pipe. A potential other message in this pipe
* must be closed with end_msg() before this function may be called.
*/
void start_msg();
/**
* End the current message.
*/
void end_msg();
/**
* Insert a new filter at the front of the pipe
* @param filt the new filter to insert
*/
void prepend(Filter* filt);
/**
* Insert a new filter at the back of the pipe
* @param filt the new filter to insert
*/
void append(Filter* filt);
/**
* Remove the first filter at the front of the pipe.
*/
void pop();
/**
* Reset this pipe to an empty pipe.
*/
void reset();
/**
* Construct a Pipe of up to four filters. The filters are set up
* in the same order as the arguments.
*/
Pipe(Filter* = 0, Filter* = 0, Filter* = 0, Filter* = 0);
/**
* Construct a Pipe from range of filters passed as an array
* @param filters the set of filters to use
* @param count the number of elements in filters
*/
Pipe(Filter* filters[], size_t count);
~Pipe();
private:
Pipe(const Pipe&) : DataSource() {}
Pipe& operator=(const Pipe&) { return (*this); }
void init();
void destruct(Filter*);
void find_endpoints(Filter*);
void clear_endpoints(Filter*);
message_id get_message_no(const std::string&, message_id) const;
Filter* pipe;
class Output_Buffers* outputs;
message_id default_read;
bool inside_msg;
};
/**
* Stream output operator; dumps the results from pipe's default
* message to the output stream.
* @param out an output stream
* @param pipe the pipe
*/
BOTAN_DLL std::ostream& operator<<(std::ostream& out, Pipe& pipe);
/**
* Stream input operator; dumps the remaining bytes of input
* to the (assumed open) pipe message.
* @param in the input stream
* @param pipe the pipe
*/
BOTAN_DLL std::istream& operator>>(std::istream& in, Pipe& pipe);
}
#if defined(BOTAN_HAS_PIPE_UNIXFD_IO)
namespace Botan {
/**
* Stream output operator; dumps the results from pipe's default
* message to the output stream.
* @param out file descriptor for an open output stream
* @param pipe the pipe
*/
int BOTAN_DLL operator<<(int out, Pipe& pipe);
/**
* File descriptor input operator; dumps the remaining bytes of input
* to the (assumed open) pipe message.
* @param in file descriptor for an open input stream
* @param pipe the pipe
*/
int BOTAN_DLL operator>>(int in, Pipe& pipe);
}
#endif
namespace Botan {
/**
* BER Decoding Object
*/
class BOTAN_DLL BER_Decoder
{
public:
BER_Object get_next_object();
void push_back(const BER_Object&);
bool more_items() const;
BER_Decoder& verify_end();
BER_Decoder& discard_remaining();
BER_Decoder start_cons(ASN1_Tag, ASN1_Tag = UNIVERSAL);
BER_Decoder& end_cons();
BER_Decoder& raw_bytes(MemoryRegion<byte>&);
BER_Decoder& decode_null();
BER_Decoder& decode(bool&);
BER_Decoder& decode(size_t&);
BER_Decoder& decode(class BigInt&);
BER_Decoder& decode(MemoryRegion<byte>&, ASN1_Tag);
BER_Decoder& decode(bool&, ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC);
BER_Decoder& decode(size_t&, ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC);
BER_Decoder& decode(class BigInt&,
ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC);
BER_Decoder& decode(MemoryRegion<byte>&, ASN1_Tag,
ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC);
BER_Decoder& decode(class ASN1_Object&);
BER_Decoder& decode_octet_string_bigint(class BigInt&);
template<typename T>
BER_Decoder& decode_optional(T& out,
ASN1_Tag type_tag,
ASN1_Tag class_tag,
const T& default_value = T());
template<typename T>
BER_Decoder& decode_list(std::vector<T>& out,
bool clear_out = true);
template<typename T>
BER_Decoder& decode_and_check(const T& expected,
const std::string& error_msg)
{
T actual;
decode(actual);
if(actual != expected)
throw Decoding_Error(error_msg);
return (*this);
}
BER_Decoder& decode_optional_string(MemoryRegion<byte>&,
ASN1_Tag, u16bit);
BER_Decoder(DataSource&);
BER_Decoder(const byte[], size_t);
BER_Decoder(const MemoryRegion<byte>&);
BER_Decoder(const BER_Decoder&);
~BER_Decoder();
private:
BER_Decoder& operator=(const BER_Decoder&) { return (*this); }
BER_Decoder* parent;
DataSource* source;
BER_Object pushed;
mutable bool owns;
};
/*
* Decode an OPTIONAL or DEFAULT element
*/
template<typename T>
BER_Decoder& BER_Decoder::decode_optional(T& out,
ASN1_Tag type_tag,
ASN1_Tag class_tag,
const T& default_value)
{
BER_Object obj = get_next_object();
if(obj.type_tag == type_tag && obj.class_tag == class_tag)
{
if(class_tag & CONSTRUCTED)
BER_Decoder(obj.value).decode(out).verify_end();
else
{
push_back(obj);
decode(out, type_tag, class_tag);
}
}
else
{
out = default_value;
push_back(obj);
}
return (*this);
}
/*
* Decode a list of homogenously typed values
*/
template<typename T>
BER_Decoder& BER_Decoder::decode_list(std::vector<T>& vec, bool clear_it)
{
if(clear_it)
vec.clear();
while(more_items())
{
T value;
decode(value);
vec.push_back(value);
}
return (*this);
}
}
namespace Botan {
/**
* X.509v3 Key Constraints.
*/
enum Key_Constraints {
NO_CONSTRAINTS = 0,
DIGITAL_SIGNATURE = 32768,
NON_REPUDIATION = 16384,
KEY_ENCIPHERMENT = 8192,
DATA_ENCIPHERMENT = 4096,
KEY_AGREEMENT = 2048,
KEY_CERT_SIGN = 1024,
CRL_SIGN = 512,
ENCIPHER_ONLY = 256,
DECIPHER_ONLY = 128
};
/**
* BER Decoding Function for key constraints
*/
namespace BER {
void BOTAN_DLL decode(BER_Decoder&, Key_Constraints&);
}
/**
* X.509v2 CRL Reason Code.
*/
enum CRL_Code {
UNSPECIFIED = 0,
KEY_COMPROMISE = 1,
CA_COMPROMISE = 2,
AFFILIATION_CHANGED = 3,
SUPERSEDED = 4,
CESSATION_OF_OPERATION = 5,
CERTIFICATE_HOLD = 6,
REMOVE_FROM_CRL = 8,
PRIVLEDGE_WITHDRAWN = 9,
AA_COMPROMISE = 10,
DELETE_CRL_ENTRY = 0xFF00,
OCSP_GOOD = 0xFF01,
OCSP_UNKNOWN = 0xFF02
};
/*
* Various Other Enumerations
*/
/**
* The two types of X509 encoding supported by Botan.
*/
enum X509_Encoding { RAW_BER, PEM };
}
namespace Botan {
/**
* This class represents abstract X.509 signed objects as
* in the X.500 SIGNED macro
*/
class BOTAN_DLL X509_Object
{
public:
/**
* The underlying data that is to be or was signed
* @return data that is or was signed
*/
MemoryVector<byte> tbs_data() const;
/**
* @return signature on tbs_data()
*/
MemoryVector<byte> signature() const;
/**
* @return signature algorithm that was used to generate signature
*/
AlgorithmIdentifier signature_algorithm() const;
/**
* @return hash algorithm that was used to generate signature
*/
std::string hash_used_for_signature() const;
/**
* Create a signed X509 object.
* @param signer the signer used to sign the object
* @param rng the random number generator to use
* @param alg_id the algorithm identifier of the signature scheme
* @param tbs the tbs bits to be signed
* @return signed X509 object
*/
static MemoryVector<byte> make_signed(class PK_Signer* signer,
RandomNumberGenerator& rng,
const AlgorithmIdentifier& alg_id,
const MemoryRegion<byte>& tbs);
/**
* Check the signature on this data
* @param key the public key purportedly used to sign this data
* @return true if the signature is valid, otherwise false
*/
bool check_signature(class Public_Key& key) const;
/**
* Check the signature on this data
* @param key the public key purportedly used to sign this data
* the pointer will be deleted after use
* @return true if the signature is valid, otherwise false
*/
bool check_signature(class Public_Key* key) const;
/**
* @return BER encoding of this
*/
MemoryVector<byte> BER_encode() const;
/**
* @return PEM encoding of this
*/
std::string PEM_encode() const;
/**
* Encode this to a pipe
* @deprecated use BER_encode or PEM_encode instead
* @param out the pipe to write to
* @param encoding the encoding to use
*/
BOTAN_DEPRECATED("Use BER_encode or PEM_encode")
void encode(Pipe& out, X509_Encoding encoding = PEM) const;
virtual ~X509_Object() {}
protected:
X509_Object(DataSource& src, const std::string& pem_labels);
X509_Object(const std::string& file, const std::string& pem_labels);
void do_decode();
X509_Object() {}
AlgorithmIdentifier sig_algo;
MemoryVector<byte> tbs_bits, sig;
private:
virtual void force_decode() = 0;
void init(DataSource&, const std::string&);
void decode_info(DataSource&);
std::vector<std::string> PEM_labels_allowed;
std::string PEM_label_pref;
};
}
namespace Botan {
/**
* Distinguished Name
*/
class BOTAN_DLL X509_DN : public ASN1_Object
{
public:
void encode_into(class DER_Encoder&) const;
void decode_from(class BER_Decoder&);
std::multimap<OID, std::string> get_attributes() const;
std::vector<std::string> get_attribute(const std::string&) const;
std::multimap<std::string, std::string> contents() const;
void add_attribute(const std::string&, const std::string&);
void add_attribute(const OID&, const std::string&);
static std::string deref_info_field(const std::string&);
MemoryVector<byte> get_bits() const;
X509_DN();
X509_DN(const std::multimap<OID, std::string>&);
X509_DN(const std::multimap<std::string, std::string>&);
private:
std::multimap<OID, ASN1_String> dn_info;
MemoryVector<byte> dn_bits;
};
bool BOTAN_DLL operator==(const X509_DN&, const X509_DN&);
bool BOTAN_DLL operator!=(const X509_DN&, const X509_DN&);
bool BOTAN_DLL operator<(const X509_DN&, const X509_DN&);
}
namespace Botan {
/**
* This namespace contains functions for handling X.509 public keys
*/
namespace X509 {
/**
* BER encode a key
* @param key the public key to encode
* @return BER encoding of this key
*/
BOTAN_DLL MemoryVector<byte> BER_encode(const Public_Key& key);
/**
* PEM encode a public key into a string.
* @param key the key to encode
* @return PEM encoded key
*/
BOTAN_DLL std::string PEM_encode(const Public_Key& key);
/**
* Create a public key from a data source.
* @param source the source providing the DER or PEM encoded key
* @return new public key object
*/
BOTAN_DLL Public_Key* load_key(DataSource& source);
/**
* Create a public key from a file
* @param filename pathname to the file to load
* @return new public key object
*/
BOTAN_DLL Public_Key* load_key(const std::string& filename);
/**
* Create a public key from a memory region.
* @param enc the memory region containing the DER or PEM encoded key
* @return new public key object
*/
BOTAN_DLL Public_Key* load_key(const MemoryRegion<byte>& enc);
/**
* Copy a key.
* @param key the public key to copy
* @return new public key object
*/
BOTAN_DLL Public_Key* copy_key(const Public_Key& key);
/**
* Create the key constraints for a specific public key.
* @param pub_key the public key from which the basic set of
* constraints to be placed in the return value is derived
* @param limits additional limits that will be incorporated into the
* return value
* @return combination of key type specific constraints and
* additional limits
*/
BOTAN_DLL Key_Constraints find_constraints(const Public_Key& pub_key,
Key_Constraints limits);
/**
* Encode a key into a pipe.
* @deprecated Use PEM_encode or BER_encode instead
*
* @param key the public key to encode
* @param pipe the pipe to feed the encoded key into
* @param encoding the encoding type to use
*/
BOTAN_DEPRECATED("Use PEM_encode or BER_encode")
inline void encode(const Public_Key& key,
Pipe& pipe,
X509_Encoding encoding = PEM)
{
if(encoding == PEM)
pipe.write(X509::PEM_encode(key));
else
pipe.write(X509::BER_encode(key));
}
}
}
namespace Botan {
/**
* Data Store
*/
class BOTAN_DLL Data_Store
{
public:
/**
* A search function
*/
class BOTAN_DLL Matcher
{
public:
virtual bool operator()(const std::string&,
const std::string&) const = 0;
virtual std::pair<std::string, std::string>
transform(const std::string&, const std::string&) const;
virtual ~Matcher() {}
};
bool operator==(const Data_Store&) const;
std::multimap<std::string, std::string>
search_with(const Matcher&) const;
std::vector<std::string> get(const std::string&) const;
std::string get1(const std::string&) const;
MemoryVector<byte> get1_memvec(const std::string&) const;
u32bit get1_u32bit(const std::string&, u32bit = 0) const;
bool has_value(const std::string&) const;
void add(const std::multimap<std::string, std::string>&);
void add(const std::string&, const std::string&);
void add(const std::string&, u32bit);
void add(const std::string&, const MemoryRegion<byte>&);
private:
std::multimap<std::string, std::string> contents;
};
}
namespace Botan {
/**
* This class represents X.509 Certificate
*/
class BOTAN_DLL X509_Certificate : public X509_Object
{
public:
/**
* Get the public key associated with this certificate.
* @return subject public key of this certificate
*/
Public_Key* subject_public_key() const;
/**
* Get the issuer certificate DN.
* @return issuer DN of this certificate
*/
X509_DN issuer_dn() const;
/**
* Get the subject certificate DN.
* @return subject DN of this certificate
*/
X509_DN subject_dn() const;
/**
* Get a value for a specific subject_info parameter name.
* @param name the name of the paramter to look up. Possible names are
* "X509.Certificate.version", "X509.Certificate.serial",
* "X509.Certificate.start", "X509.Certificate.end",
* "X509.Certificate.v2.key_id", "X509.Certificate.public_key",
* "X509v3.BasicConstraints.path_constraint",
* "X509v3.BasicConstraints.is_ca", "X509v3.ExtendedKeyUsage",
* "X509v3.CertificatePolicies", "X509v3.SubjectKeyIdentifier" or
* "X509.Certificate.serial".
* @return value(s) of the specified parameter
*/
std::vector<std::string> subject_info(const std::string& name) const;
/**
* Get a value for a specific subject_info parameter name.
* @param name the name of the paramter to look up. Possible names are
* "X509.Certificate.v2.key_id" or "X509v3.AuthorityKeyIdentifier".
* @return value(s) of the specified parameter
*/
std::vector<std::string> issuer_info(const std::string& name) const;
/**
* Get the notBefore of the certificate.
* @return notBefore of the certificate
*/
std::string start_time() const;
/**
* Get the notAfter of the certificate.
* @return notAfter of the certificate
*/
std::string end_time() const;
/**
* Get the X509 version of this certificate object.
* @return X509 version
*/
u32bit x509_version() const;
/**
* Get the serial number of this certificate.
* @return certificates serial number
*/
MemoryVector<byte> serial_number() const;
/**
* Get the DER encoded AuthorityKeyIdentifier of this certificate.
* @return DER encoded AuthorityKeyIdentifier
*/
MemoryVector<byte> authority_key_id() const;
/**
* Get the DER encoded SubjectKeyIdentifier of this certificate.
* @return DER encoded SubjectKeyIdentifier
*/
MemoryVector<byte> subject_key_id() const;
/**
* Check whether this certificate is self signed.
* @return true if this certificate is self signed
*/
bool is_self_signed() const { return self_signed; }
/**
* Check whether this certificate is a CA certificate.
* @return true if this certificate is a CA certificate
*/
bool is_CA_cert() const;
/**
* Get the path limit as defined in the BasicConstraints extension of
* this certificate.
* @return path limit
*/
u32bit path_limit() const;
/**
* Get the key constraints as defined in the KeyUsage extension of this
* certificate.
* @return key constraints
*/
Key_Constraints constraints() const;
/**
* Get the key constraints as defined in the ExtendedKeyUsage
* extension of this
* certificate.
* @return key constraints
*/
std::vector<std::string> ex_constraints() const;
/**
* Get the policies as defined in the CertificatePolicies extension
* of this certificate.
* @return certificate policies
*/
std::vector<std::string> policies() const;
/**
* @return a string describing the certificate
*/
std::string to_string() const;
/**
* Check to certificates for equality.
* @return true both certificates are (binary) equal
*/
bool operator==(const X509_Certificate& other) const;
/**
* Create a certificate from a data source providing the DER or
* PEM encoded certificate.
* @param source the data source
*/
X509_Certificate(DataSource& source);
/**
* Create a certificate from a file containing the DER or PEM
* encoded certificate.
* @param filename the name of the certificate file
*/
X509_Certificate(const std::string& filename);
private:
void force_decode();
friend class X509_CA;
X509_Certificate() {}
Data_Store subject, issuer;
bool self_signed;
};
/**
* Check two certificates for inequality
* @return true if the arguments represent different certificates,
* false if they are binary identical
*/
BOTAN_DLL bool operator!=(const X509_Certificate&, const X509_Certificate&);
/*
* Data Store Extraction Operations
*/
BOTAN_DLL X509_DN create_dn(const Data_Store&);
BOTAN_DLL AlternativeName create_alt_name(const Data_Store&);
}
namespace Botan {
/**
* This class represents CRL entries
*/
class BOTAN_DLL CRL_Entry : public ASN1_Object
{
public:
void encode_into(class DER_Encoder&) const;
void decode_from(class BER_Decoder&);
/**
* Get the serial number of the certificate associated with this entry.
* @return certificate's serial number
*/
MemoryVector<byte> serial_number() const { return serial; }
/**
* Get the revocation date of the certificate associated with this entry
* @return certificate's revocation date
*/
X509_Time expire_time() const { return time; }
/**
* Get the entries reason code
* @return reason code
*/
CRL_Code reason_code() const { return reason; }
/**
* Construct an empty CRL entry.
*/
CRL_Entry(bool throw_on_unknown_critical_extension = false);
/**
* Construct an CRL entry.
* @param cert the certificate to revoke
* @param reason the reason code to set in the entry
*/
CRL_Entry(const X509_Certificate& cert,
CRL_Code reason = UNSPECIFIED);
private:
bool throw_on_unknown_critical;
MemoryVector<byte> serial;
X509_Time time;
CRL_Code reason;
};
/**
* Test two CRL entries for equality in all fields.
*/
BOTAN_DLL bool operator==(const CRL_Entry&, const CRL_Entry&);
/**
* Test two CRL entries for inequality in at least one field.
*/
BOTAN_DLL bool operator!=(const CRL_Entry&, const CRL_Entry&);
}
namespace Botan {
/**
* This class represents X.509 Certificate Revocation Lists (CRLs).
*/
class BOTAN_DLL X509_CRL : public X509_Object
{
public:
/**
* This class represents CRL related errors.
*/
struct BOTAN_DLL X509_CRL_Error : public Exception
{
X509_CRL_Error(const std::string& error) :
Exception("X509_CRL: " + error) {}
};
/**
* Get the entries of this CRL in the form of a vector.
* @return vector containing the entries of this CRL.
*/
std::vector<CRL_Entry> get_revoked() const;
/**
* Get the issuer DN of this CRL.
* @return CRLs issuer DN
*/
X509_DN issuer_dn() const;
/**
* Get the AuthorityKeyIdentifier of this CRL.
* @return this CRLs AuthorityKeyIdentifier
*/
MemoryVector<byte> authority_key_id() const;
/**
* Get the serial number of this CRL.
* @return CRLs serial number
*/
u32bit crl_number() const;
/**
* Get the CRL's thisUpdate value.
* @return CRLs thisUpdate
*/
X509_Time this_update() const;
/**
* Get the CRL's nextUpdate value.
* @return CRLs nextdUpdate
*/
X509_Time next_update() const;
/**
* Construct a CRL from a data source.
* @param source the data source providing the DER or PEM encoded CRL.
* @param throw_on_unknown_critical should we throw an exception
* if an unknown CRL extension marked as critical is encountered.
*/
X509_CRL(DataSource& source, bool throw_on_unknown_critical = false);
/**
* Construct a CRL from a file containing the DER or PEM encoded CRL.
* @param filename the name of the CRL file
* @param throw_on_unknown_critical should we throw an exception
* if an unknown CRL extension marked as critical is encountered.
*/
X509_CRL(const std::string& filename,
bool throw_on_unknown_critical = false);
private:
void force_decode();
bool throw_on_unknown_critical;
std::vector<CRL_Entry> revoked;
Data_Store info;
};
}
namespace Botan {
/**
* Luby-Rackoff block cipher construction
*/
class BOTAN_DLL LubyRackoff : public BlockCipher
{
public:
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
size_t block_size() const { return 2 * hash->output_length(); }
Key_Length_Specification key_spec() const
{
return Key_Length_Specification(2, 32, 2);
}
void clear();
std::string name() const;
BlockCipher* clone() const;
/**
* @param hash function to use to form the block cipher
*/
LubyRackoff(HashFunction* hash);
~LubyRackoff() { delete hash; }
private:
void key_schedule(const byte[], size_t);
HashFunction* hash;
SecureVector<byte> K1, K2;
};
}
namespace Botan {
/**
* EMSA2 from IEEE 1363
* Useful for Rabin-Williams
*/
class BOTAN_DLL EMSA2 : public EMSA
{
public:
/**
* @param hash the hash object to use
*/
EMSA2(HashFunction* hash);
~EMSA2() { delete hash; }
private:
void update(const byte[], size_t);
SecureVector<byte> raw_data();
SecureVector<byte> encoding_of(const MemoryRegion<byte>&, size_t,
RandomNumberGenerator& rng);
bool verify(const MemoryRegion<byte>&, const MemoryRegion<byte>&,
size_t);
SecureVector<byte> empty_hash;
HashFunction* hash;
byte hash_id;
};
}
namespace Botan {
/**
* Fused multiply-add
* @param a an integer
* @param b an integer
* @param c an integer
* @return (a*b)+c
*/
BigInt BOTAN_DLL mul_add(const BigInt& a,
const BigInt& b,
const BigInt& c);
/**
* Fused subtract-multiply
* @param a an integer
* @param b an integer
* @param c an integer
* @return (a-b)*c
*/
BigInt BOTAN_DLL sub_mul(const BigInt& a,
const BigInt& b,
const BigInt& c);
/**
* Return the absolute value
* @param n an integer
* @return absolute value of n
*/
inline BigInt abs(const BigInt& n) { return n.abs(); }
/**
* Compute the greatest common divisor
* @param x a positive integer
* @param y a positive integer
* @return gcd(x,y)
*/
BigInt BOTAN_DLL gcd(const BigInt& x, const BigInt& y);
/**
* Least common multiple
* @param x a positive integer
* @param y a positive integer
* @return z, smallest integer such that z % x == 0 and z % y == 0
*/
BigInt BOTAN_DLL lcm(const BigInt& x, const BigInt& y);
/**
* @param x an integer
* @return (x*x)
*/
BigInt BOTAN_DLL square(const BigInt& x);
/**
* Modular inversion
* @param x a positive integer
* @param modulus a positive integer
* @return y st (x*y) % modulus == 1
*/
BigInt BOTAN_DLL inverse_mod(const BigInt& x,
const BigInt& modulus);
/**
* Compute the Jacobi symbol. If n is prime, this is equivalent
* to the Legendre symbol.
* @see http://mathworld.wolfram.com/JacobiSymbol.html
*
* @param a is a non-negative integer
* @param n is an odd integer > 1
* @return (n / m)
*/
s32bit BOTAN_DLL jacobi(const BigInt& a,
const BigInt& n);
/**
* Modular exponentation
* @param b an integer base
* @param x a positive exponent
* @param m a positive modulus
* @return (b^x) % m
*/
BigInt BOTAN_DLL power_mod(const BigInt& b,
const BigInt& x,
const BigInt& m);
/**
* Compute the square root of x modulo a prime using the
* Shanks-Tonnelli algorithm
*
* @param x the input
* @param p the prime
* @return y such that (y*y)%p == x, or -1 if no such integer
*/
BigInt BOTAN_DLL ressol(const BigInt& x, const BigInt& p);
/**
* @param x an integer
* @return count of the zero bits in x, or, equivalently, the largest
* value of n such that 2^n divides x evently
*/
size_t BOTAN_DLL low_zero_bits(const BigInt& x);
/**
* Primality Testing
* @param n a positive integer to test for primality
* @param rng a random number generator
* @param level how hard to test
* @return true if all primality tests passed, otherwise false
*/
bool BOTAN_DLL primality_test(const BigInt& n,
RandomNumberGenerator& rng,
size_t level = 1);
/**
* Quickly check for primality
* @param n a positive integer to test for primality
* @param rng a random number generator
* @return true if all primality tests passed, otherwise false
*/
inline bool quick_check_prime(const BigInt& n, RandomNumberGenerator& rng)
{ return primality_test(n, rng, 0); }
/**
* Check for primality
* @param n a positive integer to test for primality
* @param rng a random number generator
* @return true if all primality tests passed, otherwise false
*/
inline bool check_prime(const BigInt& n, RandomNumberGenerator& rng)
{ return primality_test(n, rng, 1); }
/**
* Verify primality - this function is slow but useful if you want to
* ensure that a possibly malicious entity did not provide you with
* something that 'looks like' a prime
* @param n a positive integer to test for primality
* @param rng a random number generator
* @return true if all primality tests passed, otherwise false
*/
inline bool verify_prime(const BigInt& n, RandomNumberGenerator& rng)
{ return primality_test(n, rng, 2); }
/**
* Randomly generate a prime
* @param rng a random number generator
* @param bits how large the resulting prime should be in bits
* @param coprime a positive integer the result should be coprime to
* @param equiv a non-negative number that the result should be
equivalent to modulo equiv_mod
* @param equiv_mod the modulus equiv should be checked against
* @return random prime with the specified criteria
*/
BigInt BOTAN_DLL random_prime(RandomNumberGenerator& rng,
size_t bits, const BigInt& coprime = 1,
size_t equiv = 1, size_t equiv_mod = 2);
/**
* Return a 'safe' prime, of the form p=2*q+1 with q prime
* @param rng a random number generator
* @param bits is how long the resulting prime should be
* @return prime randomly chosen from safe primes of length bits
*/
BigInt BOTAN_DLL random_safe_prime(RandomNumberGenerator& rng,
size_t bits);
class Algorithm_Factory;
/**
* Generate DSA parameters using the FIPS 186 kosherizer
* @param rng a random number generator
* @param af an algorithm factory
* @param p_out where the prime p will be stored
* @param q_out where the prime q will be stored
* @param pbits how long p will be in bits
* @param qbits how long q will be in bits
* @return random seed used to generate this parameter set
*/
SecureVector<byte> BOTAN_DLL
generate_dsa_primes(RandomNumberGenerator& rng,
Algorithm_Factory& af,
BigInt& p_out, BigInt& q_out,
size_t pbits, size_t qbits);
/**
* Generate DSA parameters using the FIPS 186 kosherizer
* @param rng a random number generator
* @param af an algorithm factory
* @param p_out where the prime p will be stored
* @param q_out where the prime q will be stored
* @param pbits how long p will be in bits
* @param qbits how long q will be in bits
* @param seed the seed used to generate the parameters
* @return true if seed generated a valid DSA parameter set, otherwise
false. p_out and q_out are only valid if true was returned.
*/
bool BOTAN_DLL
generate_dsa_primes(RandomNumberGenerator& rng,
Algorithm_Factory& af,
BigInt& p_out, BigInt& q_out,
size_t pbits, size_t qbits,
const MemoryRegion<byte>& seed);
/**
* The size of the PRIMES[] array
*/
const size_t PRIME_TABLE_SIZE = 6541;
/**
* A const array of all primes less than 65535
*/
extern const u16bit BOTAN_DLL PRIMES[];
}
namespace Botan {
/**
* This class represents an elliptic curve over GF(p)
*/
class BOTAN_DLL CurveGFp
{
public:
/**
* Create an uninitialized CurveGFp
*/
CurveGFp() {}
/**
* Construct the elliptic curve E: y^2 = x^3 + ax + b over GF(p)
* @param p prime number of the field
* @param a first coefficient
* @param b second coefficient
*/
CurveGFp(const BigInt& p, const BigInt& a, const BigInt& b) :
p(p), a(a), b(b), p_words(p.sig_words())
{
BigInt r(BigInt::Power2, p_words * BOTAN_MP_WORD_BITS);
p_dash = (((r * inverse_mod(r, p)) - 1) / p).word_at(0);
r2 = (r * r) % p;
a_r = (a * r) % p;
b_r = (b * r) % p;
}
// CurveGFp(const CurveGFp& other) = default;
// CurveGFp& operator=(const CurveGFp& other) = default;
/**
* @return curve coefficient a
*/
const BigInt& get_a() const { return a; }
/**
* @return curve coefficient b
*/
const BigInt& get_b() const { return b; }
/**
* Get prime modulus of the field of the curve
* @return prime modulus of the field of the curve
*/
const BigInt& get_p() const { return p; }
/**
* @return Montgomery parameter r^2 % p
*/
const BigInt& get_r2() const { return r2; }
/**
* @return a * r mod p
*/
const BigInt& get_a_r() const { return a_r; }
/**
* @return b * r mod p
*/
const BigInt& get_b_r() const { return b_r; }
/**
* @return Montgomery parameter p-dash
*/
word get_p_dash() const { return p_dash; }
/**
* @return p.sig_words()
*/
size_t get_p_words() const { return p_words; }
/**
* swaps the states of *this and other, does not throw
* @param other curve to swap values with
*/
void swap(CurveGFp& other)
{
std::swap(p, other.p);
std::swap(a, other.a);
std::swap(b, other.b);
std::swap(a_r, other.a_r);
std::swap(b_r, other.b_r);
std::swap(p_words, other.p_words);
std::swap(r2, other.r2);
std::swap(p_dash, other.p_dash);
}
/**
* Equality operator
* @param other curve to compare with
* @return true iff this is the same curve as other
*/
bool operator==(const CurveGFp& other) const
{
/*
Relies on choice of R, but that is fixed by constructor based
on size of p
*/
return (p == other.p && a_r == other.a_r && b_r == other.b_r);
}
private:
// Curve parameters
BigInt p, a, b;
size_t p_words; // cache of p.sig_words()
// Montgomery parameters
BigInt r2, a_r, b_r;
word p_dash;
};
/**
* Equality operator
* @param lhs a curve
* @param rhs a curve
* @return true iff lhs is not the same as rhs
*/
inline bool operator!=(const CurveGFp& lhs, const CurveGFp& rhs)
{
return !(lhs == rhs);
}
}
namespace std {
template<> inline
void swap<Botan::CurveGFp>(Botan::CurveGFp& curve1,
Botan::CurveGFp& curve2)
{
curve1.swap(curve2);
}
} // namespace std
namespace Botan {
/**
* Exception thrown if you try to convert a zero point to an affine
* coordinate
*/
struct BOTAN_DLL Illegal_Transformation : public Exception
{
Illegal_Transformation(const std::string& err =
"Requested transformation is not possible") :
Exception(err) {}
};
/**
* Exception thrown if some form of illegal point is decoded
*/
struct BOTAN_DLL Illegal_Point : public Exception
{
Illegal_Point(const std::string& err = "Malformed ECP point detected") :
Exception(err) {}
};
/**
* This class represents one point on a curve of GF(p)
*/
class BOTAN_DLL PointGFp
{
public:
enum Compression_Type {
UNCOMPRESSED = 0,
COMPRESSED = 1,
HYBRID = 2
};
/**
* Construct an uninitialized PointGFp
*/
PointGFp() {}
/**
* Construct the zero point
* @param curve The base curve
*/
PointGFp(const CurveGFp& curve);
/**
* Construct a point from its affine coordinates
* @param curve the base curve
* @param x affine x coordinate
* @param y affine y coordinate
*/
PointGFp(const CurveGFp& curve, const BigInt& x, const BigInt& y);
//PointGFp(const PointGFp& other) = default;
//PointGFp& operator=(const PointGFp& other) = default;
/**
* += Operator
* @param rhs the PointGFp to add to the local value
* @result resulting PointGFp
*/
PointGFp& operator+=(const PointGFp& rhs);
/**
* -= Operator
* @param rhs the PointGFp to subtract from the local value
* @result resulting PointGFp
*/
PointGFp& operator-=(const PointGFp& rhs);
/**
* *= Operator
* @param scalar the PointGFp to multiply with *this
* @result resulting PointGFp
*/
PointGFp& operator*=(const BigInt& scalar);
/**
* Multiplication Operator
* @param scalar the scalar value
* @param point the point value
* @return scalar*point on the curve
*/
friend BOTAN_DLL PointGFp operator*(const BigInt& scalar, const PointGFp& point);
/**
* Multiexponentiation
* @param p1 a point
* @param z1 a scalar
* @param p2 a point
* @param z2 a scalar
* @result (p1 * z1 + p2 * z2)
*/
friend BOTAN_DLL PointGFp multi_exponentiate(
const PointGFp& p1, const BigInt& z1,
const PointGFp& p2, const BigInt& z2);
/**
* Negate this point
* @return *this
*/
PointGFp& negate()
{
if(!is_zero())
coord_y = curve.get_p() - coord_y;
return *this;
}
/**
* Return base curve of this point
* @result the curve over GF(p) of this point
*/
const CurveGFp& get_curve() const { return curve; }
/**
* get affine x coordinate
* @result affine x coordinate
*/
BigInt get_affine_x() const;
/**
* get affine y coordinate
* @result affine y coordinate
*/
BigInt get_affine_y() const;
/**
* Is this the point at infinity?
* @result true, if this point is at infinity, false otherwise.
*/
bool is_zero() const
{ return (coord_x.is_zero() && coord_z.is_zero()); }
/**
* Checks whether the point is to be found on the underlying
* curve; used to prevent fault attacks.
* @return if the point is on the curve
*/
bool on_the_curve() const;
/**
* swaps the states of *this and other, does not throw!
* @param other the object to swap values with
*/
void swap(PointGFp& other);
/**
* Equality operator
*/
bool operator==(const PointGFp& other) const;
private:
/**
* Montgomery multiplication/reduction
* @param x first multiplicand
* @param y second multiplicand
* @param workspace temp space
*/
BigInt monty_mult(const BigInt& x, const BigInt& y) const
{
BigInt result;
monty_mult(result, x, y);
return result;
}
/**
* Montgomery multiplication/reduction
* @warning z cannot alias x or y
* @param z output
* @param x first multiplicand
* @param y second multiplicand
*/
void monty_mult(BigInt& z, const BigInt& x, const BigInt& y) const;
/**
* Montgomery squaring/reduction
* @param x multiplicand
*/
BigInt monty_sqr(const BigInt& x) const
{
BigInt result;
monty_sqr(result, x);
return result;
}
/**
* Montgomery squaring/reduction
* @warning z cannot alias x
* @param z output
* @param x multiplicand
*/
void monty_sqr(BigInt& z, const BigInt& x) const;
/**
* Point addition
* @param workspace temp space, at least 11 elements
*/
void add(const PointGFp& other, std::vector<BigInt>& workspace);
/**
* Point doubling
* @param workspace temp space, at least 9 elements
*/
void mult2(std::vector<BigInt>& workspace);
CurveGFp curve;
BigInt coord_x, coord_y, coord_z;
mutable SecureVector<word> ws; // workspace for Montgomery
};
// relational operators
inline bool operator!=(const PointGFp& lhs, const PointGFp& rhs)
{
return !(rhs == lhs);
}
// arithmetic operators
inline PointGFp operator-(const PointGFp& lhs)
{
return PointGFp(lhs).negate();
}
inline PointGFp operator+(const PointGFp& lhs, const PointGFp& rhs)
{
PointGFp tmp(lhs);
return tmp += rhs;
}
inline PointGFp operator-(const PointGFp& lhs, const PointGFp& rhs)
{
PointGFp tmp(lhs);
return tmp -= rhs;
}
inline PointGFp operator*(const PointGFp& point, const BigInt& scalar)
{
return scalar * point;
}
// encoding and decoding
SecureVector<byte> BOTAN_DLL EC2OSP(const PointGFp& point, byte format);
PointGFp BOTAN_DLL OS2ECP(const byte data[], size_t data_len,
const CurveGFp& curve);
inline PointGFp OS2ECP(const MemoryRegion<byte>& data, const CurveGFp& curve)
{ return OS2ECP(&data[0], data.size(), curve); }
}
namespace std {
template<>
inline void swap<Botan::PointGFp>(Botan::PointGFp& x, Botan::PointGFp& y)
{ x.swap(y); }
}
namespace Botan {
/**
* This class represents elliptic curce domain parameters
*/
enum EC_Group_Encoding {
EC_DOMPAR_ENC_EXPLICIT = 0,
EC_DOMPAR_ENC_IMPLICITCA = 1,
EC_DOMPAR_ENC_OID = 2
};
/**
* Class representing an elliptic curve
*/
class BOTAN_DLL EC_Group
{
public:
/**
* Construct Domain paramers from specified parameters
* @param curve elliptic curve
* @param base_point a base point
* @param order the order of the base point
* @param cofactor the cofactor
*/
EC_Group(const CurveGFp& curve,
const PointGFp& base_point,
const BigInt& order,
const BigInt& cofactor) :
curve(curve),
base_point(base_point),
order(order),
cofactor(cofactor),
oid("")
{}
/**
* Decode a BER encoded ECC domain parameter set
* @param ber_encoding the bytes of the BER encoding
*/
EC_Group(const MemoryRegion<byte>& ber_encoding);
/**
* Create an EC domain by OID (or throw if unknown)
* @param oid the OID of the EC domain to create
*/
EC_Group(const OID& oid);
/**
* Create an EC domain from PEM encoding (as from PEM_encode),
* or from an OID name (eg "secp160r1", or "1.3.132.0.8")
* @param pem_or_oid PEM-encoded data, or an OID
*/
EC_Group(const std::string& pem_or_oid = "");
/**
* Create the DER encoding of this domain
* @param form of encoding to use
* @returns bytes encododed as DER
*/
SecureVector<byte> DER_encode(EC_Group_Encoding form) const;
/**
* Return the PEM encoding (always in explicit form)
* @return string containing PEM data
*/
std::string PEM_encode() const;
/**
* Return domain parameter curve
* @result domain parameter curve
*/
const CurveGFp& get_curve() const { return curve; }
/**
* Return domain parameter curve
* @result domain parameter curve
*/
const PointGFp& get_base_point() const { return base_point; }
/**
* Return the order of the base point
* @result order of the base point
*/
const BigInt& get_order() const { return order; }
/**
* Return the cofactor
* @result the cofactor
*/
const BigInt& get_cofactor() const { return cofactor; }
bool initialized() const { return !base_point.is_zero(); }
/**
* Return the OID of these domain parameters
* @result the OID
*/
std::string get_oid() const { return oid; }
bool operator==(const EC_Group& other) const
{
return ((get_curve() == other.get_curve()) &&
(get_base_point() == other.get_base_point()) &&
(get_order() == other.get_order()) &&
(get_cofactor() == other.get_cofactor()));
}
private:
CurveGFp curve;
PointGFp base_point;
BigInt order, cofactor;
std::string oid;
};
inline bool operator!=(const EC_Group& lhs,
const EC_Group& rhs)
{
return !(lhs == rhs);
}
// For compatability with 1.8
typedef EC_Group EC_Domain_Params;
}
namespace Botan {
/**
* User Interface
* Only really used for callbacks for PKCS #8 decryption
*/
class BOTAN_DLL User_Interface
{
public:
enum UI_Result { OK, CANCEL_ACTION };
virtual std::string get_passphrase(const std::string&,
const std::string&,
UI_Result&) const;
User_Interface(const std::string& = "");
virtual ~User_Interface() {}
protected:
std::string preset_passphrase;
mutable bool first_try;
};
}
namespace Botan {
/**
* PKCS #8 General Exception
*/
struct BOTAN_DLL PKCS8_Exception : public Decoding_Error
{
PKCS8_Exception(const std::string& error) :
Decoding_Error("PKCS #8: " + error) {}
};
/**
* This namespace contains functions for handling PKCS #8 private keys
*/
namespace PKCS8 {
/**
* BER encode a private key
* @param key the private key to encode
* @return BER encoded key
*/
BOTAN_DLL SecureVector<byte> BER_encode(const Private_Key& key);
/**
* Get a string containing a PEM encoded private key.
* @param key the key to encode
* @return encoded key
*/
BOTAN_DLL std::string PEM_encode(const Private_Key& key);
/**
* Encrypt a key using PKCS #8 encryption
* @param key the key to encode
* @param rng the rng to use
* @param pass the password to use for encryption
* @param pbe_algo the name of the desired password-based encryption
algorithm; if empty ("") a reasonable (portable/secure)
default will be chosen.
* @return encrypted key in binary BER form
*/
BOTAN_DLL SecureVector<byte> BER_encode(const Private_Key& key,
RandomNumberGenerator& rng,
const std::string& pass,
const std::string& pbe_algo = "");
/**
* Get a string containing a PEM encoded private key, encrypting it with a
* password.
* @param key the key to encode
* @param rng the rng to use
* @param pass the password to use for encryption
* @param pbe_algo the name of the desired password-based encryption
algorithm; if empty ("") a reasonable (portable/secure)
default will be chosen.
* @return encrypted key in PEM form
*/
BOTAN_DLL std::string PEM_encode(const Private_Key& key,
RandomNumberGenerator& rng,
const std::string& pass,
const std::string& pbe_algo = "");
/**
* Encode a private key into a pipe.
* @deprecated Use PEM_encode or BER_encode instead
*
* @param key the private key to encode
* @param pipe the pipe to feed the encoded key into
* @param encoding the encoding type to use
*/
BOTAN_DEPRECATED("Use PEM_encode or BER_encode")
inline void encode(const Private_Key& key,
Pipe& pipe,
X509_Encoding encoding = PEM)
{
if(encoding == PEM)
pipe.write(PKCS8::PEM_encode(key));
else
pipe.write(PKCS8::BER_encode(key));
}
/**
* Encode and encrypt a private key into a pipe.
* @deprecated Use PEM_encode or BER_encode instead
*
* @param key the private key to encode
* @param pipe the pipe to feed the encoded key into
* @param pass the password to use for encryption
* @param rng the rng to use
* @param pbe_algo the name of the desired password-based encryption
algorithm; if empty ("") a reasonable (portable/secure)
default will be chosen.
* @param encoding the encoding type to use
*/
BOTAN_DEPRECATED("Use PEM_encode or BER_encode")
inline void encrypt_key(const Private_Key& key,
Pipe& pipe,
RandomNumberGenerator& rng,
const std::string& pass,
const std::string& pbe_algo = "",
X509_Encoding encoding = PEM)
{
if(encoding == PEM)
pipe.write(PKCS8::PEM_encode(key, rng, pass, pbe_algo));
else
pipe.write(PKCS8::BER_encode(key, rng, pass, pbe_algo));
}
/**
* Load a key from a data source.
* @param source the data source providing the encoded key
* @param rng the rng to use
* @param ui the user interface to be used for passphrase dialog
* @return loaded private key object
*/
BOTAN_DLL Private_Key* load_key(DataSource& source,
RandomNumberGenerator& rng,
const User_Interface& ui);
/** Load a key from a data source.
* @param source the data source providing the encoded key
* @param rng the rng to use
* @param pass the passphrase to decrypt the key. Provide an empty
* string if the key is not encoded.
* @return loaded private key object
*/
BOTAN_DLL Private_Key* load_key(DataSource& source,
RandomNumberGenerator& rng,
const std::string& pass = "");
/**
* Load a key from a file.
* @param filename the path to the file containing the encoded key
* @param rng the rng to use
* @param ui the user interface to be used for passphrase dialog
* @return loaded private key object
*/
BOTAN_DLL Private_Key* load_key(const std::string& filename,
RandomNumberGenerator& rng,
const User_Interface& ui);
/** Load a key from a file.
* @param filename the path to the file containing the encoded key
* @param rng the rng to use
* @param pass the passphrase to decrypt the key. Provide an empty
* string if the key is not encoded.
* @return loaded private key object
*/
BOTAN_DLL Private_Key* load_key(const std::string& filename,
RandomNumberGenerator& rng,
const std::string& pass = "");
/**
* Copy an existing encoded key object.
* @param key the key to copy
* @param rng the rng to use
* @return new copy of the key
*/
BOTAN_DLL Private_Key* copy_key(const Private_Key& key,
RandomNumberGenerator& rng);
}
}
namespace Botan {
/**
* This class represents abstract ECC public keys. When encoding a key
* via an encoder that can be accessed via the corresponding member
* functions, the key will decide upon its internally stored encoding
* information whether to encode itself with or without domain
* parameters, or using the domain parameter oid. Furthermore, a public
* key without domain parameters can be decoded. In that case, it
* cannot be used for verification until its domain parameters are set
* by calling the corresponding member function.
*/
class BOTAN_DLL EC_PublicKey : public virtual Public_Key
{
public:
EC_PublicKey(const EC_Group& dom_par,
const PointGFp& pub_point);
EC_PublicKey(const AlgorithmIdentifier& alg_id,
const MemoryRegion<byte>& key_bits);
/**
* Get the public point of this key.
* @throw Invalid_State is thrown if the
* domain parameters of this point are not set
* @result the public point of this key
*/
const PointGFp& public_point() const { return public_key; }
AlgorithmIdentifier algorithm_identifier() const;
MemoryVector<byte> x509_subject_public_key() const;
bool check_key(RandomNumberGenerator& rng,
bool strong) const;
/**
* Get the domain parameters of this key.
* @throw Invalid_State is thrown if the
* domain parameters of this point are not set
* @result the domain parameters of this key
*/
const EC_Group& domain() const { return domain_params; }
/**
* Set the domain parameter encoding to be used when encoding this key.
* @param enc the encoding to use
*/
void set_parameter_encoding(EC_Group_Encoding enc);
/**
* Return the DER encoding of this keys domain in whatever format
* is preset for this particular key
*/
MemoryVector<byte> DER_domain() const
{ return domain().DER_encode(domain_format()); }
/**
* Get the domain parameter encoding to be used when encoding this key.
* @result the encoding to use
*/
EC_Group_Encoding domain_format() const
{ return domain_encoding; }
protected:
EC_PublicKey() : domain_encoding(EC_DOMPAR_ENC_EXPLICIT) {}
EC_Group domain_params;
PointGFp public_key;
EC_Group_Encoding domain_encoding;
};
/**
* This abstract class represents ECC private keys
*/
class BOTAN_DLL EC_PrivateKey : public virtual EC_PublicKey,
public virtual Private_Key
{
public:
EC_PrivateKey(RandomNumberGenerator& rng,
const EC_Group& domain,
const BigInt& private_key);
EC_PrivateKey(const AlgorithmIdentifier& alg_id,
const MemoryRegion<byte>& key_bits);
MemoryVector<byte> pkcs8_private_key() const;
/**
* Get the private key value of this key object.
* @result the private key value of this key object
*/
const BigInt& private_value() const;
protected:
EC_PrivateKey() {}
BigInt private_key;
};
}
namespace Botan {
/**
* GOST-34.10 Public Key
*/
class BOTAN_DLL GOST_3410_PublicKey : public virtual EC_PublicKey
{
public:
/**
* Construct a public key from a given public point.
* @param dom_par the domain parameters associated with this key
* @param public_point the public point defining this key
*/
GOST_3410_PublicKey(const EC_Group& dom_par,
const PointGFp& public_point) :
EC_PublicKey(dom_par, public_point) {}
/**
* Construct from X.509 algorithm id and subject public key bits
*/
GOST_3410_PublicKey(const AlgorithmIdentifier& alg_id,
const MemoryRegion<byte>& key_bits);
/**
* Get this keys algorithm name.
* @result this keys algorithm name
*/
std::string algo_name() const { return "GOST-34.10"; }
AlgorithmIdentifier algorithm_identifier() const;
MemoryVector<byte> x509_subject_public_key() const;
/**
* Get the maximum number of bits allowed to be fed to this key.
* This is the bitlength of the order of the base point.
* @result the maximum number of input bits
*/
size_t max_input_bits() const { return domain().get_order().bits(); }
size_t message_parts() const { return 2; }
size_t message_part_size() const
{ return domain().get_order().bytes(); }
protected:
GOST_3410_PublicKey() {}
};
/**
* GOST-34.10 Private Key
*/
class BOTAN_DLL GOST_3410_PrivateKey : public GOST_3410_PublicKey,
public EC_PrivateKey
{
public:
GOST_3410_PrivateKey(const AlgorithmIdentifier& alg_id,
const MemoryRegion<byte>& key_bits) :
EC_PrivateKey(alg_id, key_bits) {}
/**
* Generate a new private key
* @param rng a random number generator
* @param domain parameters to used for this key
* @param x the private key; if zero, a new random key is generated
*/
GOST_3410_PrivateKey(RandomNumberGenerator& rng,
const EC_Group& domain,
const BigInt& x = 0) :
EC_PrivateKey(rng, domain, x) {}
AlgorithmIdentifier pkcs8_algorithm_identifier() const
{ return EC_PublicKey::algorithm_identifier(); }
};
/**
* GOST-34.10 signature operation
*/
class BOTAN_DLL GOST_3410_Signature_Operation : public PK_Ops::Signature
{
public:
GOST_3410_Signature_Operation(const GOST_3410_PrivateKey& gost_3410);
size_t message_parts() const { return 2; }
size_t message_part_size() const { return order.bytes(); }
size_t max_input_bits() const { return order.bits(); }
SecureVector<byte> sign(const byte msg[], size_t msg_len,
RandomNumberGenerator& rng);
private:
const PointGFp& base_point;
const BigInt& order;
const BigInt& x;
};
/**
* GOST-34.10 verification operation
*/
class BOTAN_DLL GOST_3410_Verification_Operation : public PK_Ops::Verification
{
public:
GOST_3410_Verification_Operation(const GOST_3410_PublicKey& gost);
size_t message_parts() const { return 2; }
size_t message_part_size() const { return order.bytes(); }
size_t max_input_bits() const { return order.bits(); }
bool with_recovery() const { return false; }
bool verify(const byte msg[], size_t msg_len,
const byte sig[], size_t sig_len);
private:
const PointGFp& base_point;
const PointGFp& public_point;
const BigInt& order;
};
}
namespace Botan {
/**
* MDx Hash Function Base Class
*/
class BOTAN_DLL MDx_HashFunction : public HashFunction
{
public:
/**
* @param block_length is the number of bytes per block
* @param big_byte_endian specifies if the hash uses big-endian bytes
* @param big_bit_endian specifies if the hash uses big-endian bits
* @param counter_size specifies the size of the counter var in bytes
*/
MDx_HashFunction(size_t block_length,
bool big_byte_endian,
bool big_bit_endian,
size_t counter_size = 8);
size_t hash_block_size() const { return buffer.size(); }
protected:
void add_data(const byte input[], size_t length);
void final_result(byte output[]);
/**
* Run the hash's compression function over a set of blocks
* @param blocks the input
* @param block_n the number of blocks
*/
virtual void compress_n(const byte blocks[], size_t block_n) = 0;
void clear();
/**
* Copy the output to the buffer
* @param buffer to put the output into
*/
virtual void copy_out(byte buffer[]) = 0;
/**
* Write the count, if used, to this spot
* @param out where to write the counter to
*/
virtual void write_count(byte out[]);
private:
SecureVector<byte> buffer;
u64bit count;
size_t position;
const bool BIG_BYTE_ENDIAN, BIG_BIT_ENDIAN;
const size_t COUNT_SIZE;
};
}
namespace Botan {
/**
* HAS-160, a Korean hash function standardized in
* TTAS.KO-12.0011/R1. Used in conjuction with KCDSA
*/
class BOTAN_DLL HAS_160 : public MDx_HashFunction
{
public:
std::string name() const { return "HAS-160"; }
size_t output_length() const { return 20; }
HashFunction* clone() const { return new HAS_160; }
void clear();
HAS_160() : MDx_HashFunction(64, false, true), X(20), digest(5)
{ clear(); }
private:
void compress_n(const byte[], size_t blocks);
void copy_out(byte[]);
SecureVector<u32bit> X, digest;
};
}
namespace Botan {
/**
* This class represents the Library Initialization/Shutdown Object. It
* has to exceed the lifetime of any Botan object used in an
* application. You can call initialize/deinitialize or use
* LibraryInitializer in the RAII style.
*/
class BOTAN_DLL LibraryInitializer
{
public:
/**
* Initialize the library
* @param options a string listing initialization options
*/
static void initialize(const std::string& options = "");
/**
* Shutdown the library
*/
static void deinitialize();
/**
* Initialize the library
* @param options a string listing initialization options
*/
LibraryInitializer(const std::string& options = "")
{ LibraryInitializer::initialize(options); }
~LibraryInitializer() { LibraryInitializer::deinitialize(); }
};
}
namespace Botan {
/*
* Forward declare to avoid recursive dependency between this header
* and libstate.h
*/
class Library_State;
/**
* Namespace for management of the global state
*/
namespace Global_State_Management {
/**
* Access the global library state
* @return reference to the global library state
*/
BOTAN_DLL Library_State& global_state();
/**
* Set the global state object
* @param state the new global state to use
*/
BOTAN_DLL void set_global_state(Library_State* state);
/**
* Set the global state object unless it is already set
* @param state the new global state to use
* @return true if the state parameter is now being used as the global
* state, or false if one was already set, in which case the
* parameter was deleted immediately
*/
BOTAN_DLL bool set_global_state_unless_set(Library_State* state);
/**
* Swap the current state for another
* @param new_state the new state object to use
* @return previous state (or NULL if none)
*/
BOTAN_DLL Library_State* swap_global_state(Library_State* new_state);
/**
* Query if the library is currently initialized
* @return true iff the library is initialized
*/
BOTAN_DLL bool global_state_exists();
}
/*
* Insert into Botan ns for convenience/backwards compatability
*/
using Global_State_Management::global_state;
}
namespace Botan {
/**
* Forward declarations (don't need full definitions here)
*/
class BlockCipher;
class StreamCipher;
class HashFunction;
class MessageAuthenticationCode;
class PBKDF;
template<typename T> class Algorithm_Cache;
class Engine;
class Mutex_Factory;
/**
* Algorithm Factory
*/
class BOTAN_DLL Algorithm_Factory
{
public:
/**
* Constructor
* @param mf a mutex factory
*/
Algorithm_Factory(Mutex_Factory& mf);
/**
* Destructor
*/
~Algorithm_Factory();
/**
* @param engine to add (Algorithm_Factory takes ownership)
*/
void add_engine(Engine* engine);
/**
* Clear out any cached objects
*/
void clear_caches();
/**
* @param algo_spec the algorithm we are querying
* @returns list of providers of this algorithm
*/
std::vector<std::string> providers_of(const std::string& algo_spec);
/**
* @param algo_spec the algorithm we are setting a provider for
* @param provider the provider we would like to use
*/
void set_preferred_provider(const std::string& algo_spec,
const std::string& provider);
/**
* @param algo_spec the algorithm we want
* @param provider the provider we would like to use
* @returns pointer to const prototype object, ready to clone(), or NULL
*/
const BlockCipher*
prototype_block_cipher(const std::string& algo_spec,
const std::string& provider = "");
/**
* @param algo_spec the algorithm we want
* @param provider the provider we would like to use
* @returns pointer to freshly created instance of the request algorithm
*/
BlockCipher* make_block_cipher(const std::string& algo_spec,
const std::string& provider = "");
/**
* @param algo the algorithm to add
* @param provider the provider of this algorithm
*/
void add_block_cipher(BlockCipher* algo, const std::string& provider);
/**
* @param algo_spec the algorithm we want
* @param provider the provider we would like to use
* @returns pointer to const prototype object, ready to clone(), or NULL
*/
const StreamCipher*
prototype_stream_cipher(const std::string& algo_spec,
const std::string& provider = "");
/**
* @param algo_spec the algorithm we want
* @param provider the provider we would like to use
* @returns pointer to freshly created instance of the request algorithm
*/
StreamCipher* make_stream_cipher(const std::string& algo_spec,
const std::string& provider = "");
/**
* @param algo the algorithm to add
* @param provider the provider of this algorithm
*/
void add_stream_cipher(StreamCipher* algo, const std::string& provider);
/**
* @param algo_spec the algorithm we want
* @param provider the provider we would like to use
* @returns pointer to const prototype object, ready to clone(), or NULL
*/
const HashFunction*
prototype_hash_function(const std::string& algo_spec,
const std::string& provider = "");
/**
* @param algo_spec the algorithm we want
* @param provider the provider we would like to use
* @returns pointer to freshly created instance of the request algorithm
*/
HashFunction* make_hash_function(const std::string& algo_spec,
const std::string& provider = "");
/**
* @param algo the algorithm to add
* @param provider the provider of this algorithm
*/
void add_hash_function(HashFunction* algo, const std::string& provider);
/**
* @param algo_spec the algorithm we want
* @param provider the provider we would like to use
* @returns pointer to const prototype object, ready to clone(), or NULL
*/
const MessageAuthenticationCode*
prototype_mac(const std::string& algo_spec,
const std::string& provider = "");
/**
* @param algo_spec the algorithm we want
* @param provider the provider we would like to use
* @returns pointer to freshly created instance of the request algorithm
*/
MessageAuthenticationCode* make_mac(const std::string& algo_spec,
const std::string& provider = "");
/**
* @param algo the algorithm to add
* @param provider the provider of this algorithm
*/
void add_mac(MessageAuthenticationCode* algo,
const std::string& provider);
/**
* @param algo_spec the algorithm we want
* @param provider the provider we would like to use
* @returns pointer to const prototype object, ready to clone(), or NULL
*/
const PBKDF* prototype_pbkdf(const std::string& algo_spec,
const std::string& provider = "");
/**
* @param algo_spec the algorithm we want
* @param provider the provider we would like to use
* @returns pointer to freshly created instance of the request algorithm
*/
PBKDF* make_pbkdf(const std::string& algo_spec,
const std::string& provider = "");
/**
* @param algo the algorithm to add
* @param provider the provider of this algorithm
*/
void add_pbkdf(PBKDF* algo, const std::string& provider);
/**
* An iterator for the engines in this factory
* @deprecated Avoid in new code
*/
class BOTAN_DLL Engine_Iterator
{
public:
/**
* @return next engine in the sequence
*/
Engine* next() { return af.get_engine_n(n++); }
/**
* @param a an algorithm factory
*/
Engine_Iterator(const Algorithm_Factory& a) :
af(a) { n = 0; }
private:
const Algorithm_Factory& af;
size_t n;
};
friend class Engine_Iterator;
private:
Algorithm_Factory(const Algorithm_Factory&) {}
Algorithm_Factory& operator=(const Algorithm_Factory&)
{ return (*this); }
Engine* get_engine_n(size_t n) const;
std::vector<Engine*> engines;
Algorithm_Cache<BlockCipher>* block_cipher_cache;
Algorithm_Cache<StreamCipher>* stream_cipher_cache;
Algorithm_Cache<HashFunction>* hash_cache;
Algorithm_Cache<MessageAuthenticationCode>* mac_cache;
Algorithm_Cache<PBKDF>* pbkdf_cache;
};
}
namespace Botan {
class Mutex;
/**
* Global state container aka the buritto at the center of it all
*/
class BOTAN_DLL Library_State
{
public:
Library_State();
~Library_State();
/**
* @param thread_safe should a mutex be used for serialization
*/
void initialize(bool thread_safe);
/**
* @return global Algorithm_Factory
*/
Algorithm_Factory& algorithm_factory() const;
/**
* @return global RandomNumberGenerator
*/
RandomNumberGenerator& global_rng();
/**
* @param name the name of the allocator
* @return allocator matching this name, or NULL
*/
Allocator* get_allocator(const std::string& name = "") const;
/**
* Add a new allocator to the list of available ones
* @param alloc the allocator to add
*/
void add_allocator(Allocator* alloc);
/**
* Set the default allocator
* @param name the name of the allocator to use as the default
*/
void set_default_allocator(const std::string& name);
/**
* Get a parameter value as std::string.
* @param section the section of the desired key
* @param key the desired keys name
* @result the value of the parameter
*/
std::string get(const std::string& section,
const std::string& key) const;
/**
* Check whether a certain parameter is set or not.
* @param section the section of the desired key
* @param key the desired keys name
* @result true if the parameters value is set,
* false otherwise
*/
bool is_set(const std::string& section,
const std::string& key) const;
/**
* Set a configuration parameter.
* @param section the section of the desired key
* @param key the desired keys name
* @param value the new value
* @param overwrite if set to true, the parameters value
* will be overwritten even if it is already set, otherwise
* no existing values will be overwritten.
*/
void set(const std::string& section,
const std::string& key,
const std::string& value,
bool overwrite = true);
/**
* Add a parameter value to the "alias" section.
* @param key the name of the parameter which shall have a new alias
* @param value the new alias
*/
void add_alias(const std::string& key,
const std::string& value);
/**
* Resolve an alias.
* @param alias the alias to resolve.
* @return what the alias stands for
*/
std::string deref_alias(const std::string& alias) const;
/**
* @return newly created Mutex (free with delete)
*/
Mutex* get_mutex() const;
private:
static RandomNumberGenerator* make_global_rng(Algorithm_Factory& af,
Mutex* mutex);
void load_default_config();
Library_State(const Library_State&) {}
Library_State& operator=(const Library_State&) { return (*this); }
class Mutex_Factory* mutex_factory;
Mutex* global_rng_lock;
RandomNumberGenerator* global_rng_ptr;
Mutex* config_lock;
std::map<std::string, std::string> config;
Mutex* allocator_lock;
std::string default_allocator_name;
std::map<std::string, Allocator*> alloc_factory;
mutable Allocator* cached_default_allocator;
std::vector<Allocator*> allocators;
Algorithm_Factory* m_algorithm_factory;
};
}
namespace Botan {
/**
* BitBucket is a filter which simply discards all inputs
*/
struct BOTAN_DLL BitBucket : public Filter
{
void write(const byte[], size_t) {}
std::string name() const { return "BitBucket"; }
};
/**
* This class represents Filter chains. A Filter chain is an ordered
* concatenation of Filters, the input to a Chain sequentially passes
* through all the Filters contained in the Chain.
*/
class BOTAN_DLL Chain : public Fanout_Filter
{
public:
void write(const byte input[], size_t length) { send(input, length); }
std::string name() const;
/**
* Construct a chain of up to four filters. The filters are set
* up in the same order as the arguments.
*/
Chain(Filter* = 0, Filter* = 0, Filter* = 0, Filter* = 0);
/**
* Construct a chain from range of filters
* @param filter_arr the list of filters
* @param length how many filters
*/
Chain(Filter* filter_arr[], size_t length);
};
/**
* This class represents a fork filter, whose purpose is to fork the
* flow of data. It causes an input message to result in n messages at
* the end of the filter, where n is the number of forks.
*/
class BOTAN_DLL Fork : public Fanout_Filter
{
public:
void write(const byte input[], size_t length) { send(input, length); }
void set_port(size_t n) { Fanout_Filter::set_port(n); }
std::string name() const;
/**
* Construct a Fork filter with up to four forks.
*/
Fork(Filter*, Filter*, Filter* = 0, Filter* = 0);
/**
* Construct a Fork from range of filters
* @param filter_arr the list of filters
* @param length how many filters
*/
Fork(Filter* filter_arr[], size_t length);
};
}
namespace Botan {
/**
* This class represents keyed filters, i.e. filters that have to be
* fed with a key in order to function.
*/
class BOTAN_DLL Keyed_Filter : public Filter
{
public:
/**
* Set the key of this filter
* @param key the key to use
*/
virtual void set_key(const SymmetricKey& key) = 0;
/**
* Set the initialization vector of this filter. Note: you should
* call set_iv() only after you have called set_key()
* @param iv the initialization vector to use
*/
virtual void set_iv(const InitializationVector& iv);
/**
* Check whether a key length is valid for this filter
* @param length the key length to be checked for validity
* @return true if the key length is valid, false otherwise
*/
virtual bool valid_keylength(size_t length) const = 0;
/**
* Check whether an IV length is valid for this filter
* @param length the IV length to be checked for validity
* @return true if the IV length is valid, false otherwise
*/
virtual bool valid_iv_length(size_t length) const
{ return (length == 0); }
};
}
namespace Botan {
/**
* This class represents abstract data sink objects.
*/
class BOTAN_DLL DataSink : public Filter
{
public:
bool attachable() { return false; }
DataSink() {}
virtual ~DataSink() {}
private:
DataSink& operator=(const DataSink&) { return (*this); }
DataSink(const DataSink&);
};
/**
* This class represents a data sink which writes its output to a stream.
*/
class BOTAN_DLL DataSink_Stream : public DataSink
{
public:
std::string name() const { return identifier; }
void write(const byte[], size_t);
/**
* Construct a DataSink_Stream from a stream.
* @param stream the stream to write to
* @param name identifier
*/
DataSink_Stream(std::ostream& stream,
const std::string& name = "<std::ostream>");
/**
* Construct a DataSink_Stream from a stream.
* @param pathname the name of the file to open a stream to
* @param use_binary indicates whether to treat the file
* as a binary file or not
*/
DataSink_Stream(const std::string& pathname,
bool use_binary = false);
~DataSink_Stream();
private:
const std::string identifier;
std::ostream* sink_p;
std::ostream& sink;
};
}
#if defined(BOTAN_HAS_CODEC_FILTERS)
namespace Botan {
/**
* This class represents a Base64 encoder.
*/
class BOTAN_DLL Base64_Encoder : public Filter
{
public:
std::string name() const { return "Base64_Encoder"; }
/**
* Input a part of a message to the encoder.
* @param input the message to input as a byte array
* @param length the length of the byte array input
*/
void write(const byte input[], size_t length);
/**
* Inform the Encoder that the current message shall be closed.
*/
void end_msg();
/**
* Create a base64 encoder.
* @param breaks whether to use line breaks in the output
* @param length the length of the lines of the output
* @param t_n whether to use a trailing newline
*/
Base64_Encoder(bool breaks = false, size_t length = 72,
bool t_n = false);
private:
void encode_and_send(const byte input[], size_t length,
bool final_inputs = false);
void do_output(const byte output[], size_t length);
const size_t line_length;
const bool trailing_newline;
MemoryVector<byte> in, out;
size_t position, out_position;
};
/**
* This object represents a Base64 decoder.
*/
class BOTAN_DLL Base64_Decoder : public Filter
{
public:
std::string name() const { return "Base64_Decoder"; }
/**
* Input a part of a message to the decoder.
* @param input the message to input as a byte array
* @param length the length of the byte array input
*/
void write(const byte input[], size_t length);
/**
* Finish up the current message
*/
void end_msg();
/**
* Create a base64 decoder.
* @param checking the type of checking that shall be performed by
* the decoder
*/
Base64_Decoder(Decoder_Checking checking = NONE);
private:
const Decoder_Checking checking;
MemoryVector<byte> in, out;
size_t position;
};
}
namespace Botan {
/**
* Converts arbitrary binary data to hex strings, optionally with
* newlines inserted
*/
class BOTAN_DLL Hex_Encoder : public Filter
{
public:
/**
* Whether to use uppercase or lowercase letters for the encoded string.
*/
enum Case { Uppercase, Lowercase };
std::string name() const { return "Hex_Encoder"; }
void write(const byte in[], size_t length);
void end_msg();
/**
* Create a hex encoder.
* @param the_case the case to use in the encoded strings.
*/
Hex_Encoder(Case the_case);
/**
* Create a hex encoder.
* @param newlines should newlines be used
* @param line_length if newlines are used, how long are lines
* @param the_case the case to use in the encoded strings
*/
Hex_Encoder(bool newlines = false,
size_t line_length = 72,
Case the_case = Uppercase);
private:
void encode_and_send(const byte[], size_t);
const Case casing;
const size_t line_length;
MemoryVector<byte> in, out;
size_t position, counter;
};
/**
* Converts hex strings to bytes
*/
class BOTAN_DLL Hex_Decoder : public Filter
{
public:
std::string name() const { return "Hex_Decoder"; }
void write(const byte[], size_t);
void end_msg();
/**
* Construct a Hex Decoder using the specified
* character checking.
* @param checking the checking to use during decoding.
*/
Hex_Decoder(Decoder_Checking checking = NONE);
private:
const Decoder_Checking checking;
MemoryVector<byte> in, out;
size_t position;
};
}
#endif
namespace Botan {
/**
* Stream Cipher Filter.
*/
class BOTAN_DLL StreamCipher_Filter : public Keyed_Filter
{
public:
std::string name() const { return cipher->name(); }
/**
* Write input data
* @param input data
* @param input_len length of input in bytes
*/
void write(const byte input[], size_t input_len);
bool valid_iv_length(size_t iv_len) const
{ return cipher->valid_iv_length(iv_len); }
/**
* Set the initialization vector for this filter.
* @param iv the initialization vector to set
*/
void set_iv(const InitializationVector& iv);
/**
* Set the key of this filter.
* @param key the key to set
*/
void set_key(const SymmetricKey& key) { cipher->set_key(key); }
/**
* Check whether a key length is valid for this filter.
* @param length the key length to be checked for validity
* @return true if the key length is valid, false otherwise
*/
bool valid_keylength(size_t length) const
{ return cipher->valid_keylength(length); }
/**
* Construct a stream cipher filter.
* @param cipher_obj a cipher object to use
*/
StreamCipher_Filter(StreamCipher* cipher_obj);
/**
* Construct a stream cipher filter.
* @param cipher_obj a cipher object to use
* @param key the key to use inside this filter
*/
StreamCipher_Filter(StreamCipher* cipher_obj, const SymmetricKey& key);
/**
* Construct a stream cipher filter.
* @param cipher the name of the desired cipher
*/
StreamCipher_Filter(const std::string& cipher);
/**
* Construct a stream cipher filter.
* @param cipher the name of the desired cipher
* @param key the key to use inside this filter
*/
StreamCipher_Filter(const std::string& cipher, const SymmetricKey& key);
~StreamCipher_Filter() { delete cipher; }
private:
SecureVector<byte> buffer;
StreamCipher* cipher;
};
/**
* Hash Filter.
*/
class BOTAN_DLL Hash_Filter : public Filter
{
public:
void write(const byte input[], size_t len) { hash->update(input, len); }
void end_msg();
std::string name() const { return hash->name(); }
/**
* Construct a hash filter.
* @param hash_fun the hash function to use
* @param len the output length of this filter. Leave the default
* value 0 if you want to use the full output of the hashfunction
* hash. Otherwise, specify a smaller value here so that the
* output of the hash algorithm will be cut off.
*/
Hash_Filter(HashFunction* hash_fun, size_t len = 0) :
OUTPUT_LENGTH(len), hash(hash_fun) {}
/**
* Construct a hash filter.
* @param request the name of the hash algorithm to use
* @param len the output length of this filter. Leave the default
* value 0 if you want to use the full output of the hashfunction
* hash. Otherwise, specify a smaller value here so that the
* output of the hash algorithm will be cut off.
*/
Hash_Filter(const std::string& request, size_t len = 0);
~Hash_Filter() { delete hash; }
private:
const size_t OUTPUT_LENGTH;
HashFunction* hash;
};
/**
* MessageAuthenticationCode Filter.
*/
class BOTAN_DLL MAC_Filter : public Keyed_Filter
{
public:
void write(const byte input[], size_t len) { mac->update(input, len); }
void end_msg();
std::string name() const { return mac->name(); }
/**
* Set the key of this filter.
* @param key the key to set
*/
void set_key(const SymmetricKey& key) { mac->set_key(key); }
/**
* Check whether a key length is valid for this filter.
* @param length the key length to be checked for validity
* @return true if the key length is valid, false otherwise
*/
bool valid_keylength(size_t length) const
{ return mac->valid_keylength(length); }
/**
* Construct a MAC filter. The MAC key will be left empty.
* @param mac_obj the MAC to use
* @param out_len the output length of this filter. Leave the default
* value 0 if you want to use the full output of the
* MAC. Otherwise, specify a smaller value here so that the
* output of the MAC will be cut off.
*/
MAC_Filter(MessageAuthenticationCode* mac_obj,
size_t out_len = 0) : OUTPUT_LENGTH(out_len)
{
mac = mac_obj;
}
/**
* Construct a MAC filter.
* @param mac_obj the MAC to use
* @param key the MAC key to use
* @param out_len the output length of this filter. Leave the default
* value 0 if you want to use the full output of the
* MAC. Otherwise, specify a smaller value here so that the
* output of the MAC will be cut off.
*/
MAC_Filter(MessageAuthenticationCode* mac_obj,
const SymmetricKey& key,
size_t out_len = 0) : OUTPUT_LENGTH(out_len)
{
mac = mac_obj;
mac->set_key(key);
}
/**
* Construct a MAC filter. The MAC key will be left empty.
* @param mac the name of the MAC to use
* @param len the output length of this filter. Leave the default
* value 0 if you want to use the full output of the
* MAC. Otherwise, specify a smaller value here so that the
* output of the MAC will be cut off.
*/
MAC_Filter(const std::string& mac, size_t len = 0);
/**
* Construct a MAC filter.
* @param mac the name of the MAC to use
* @param key the MAC key to use
* @param len the output length of this filter. Leave the default
* value 0 if you want to use the full output of the
* MAC. Otherwise, specify a smaller value here so that the
* output of the MAC will be cut off.
*/
MAC_Filter(const std::string& mac, const SymmetricKey& key,
size_t len = 0);
~MAC_Filter() { delete mac; }
private:
const size_t OUTPUT_LENGTH;
MessageAuthenticationCode* mac;
};
}
namespace Botan {
/**
* Block Cipher Mode Padding Method
* This class is pretty limited, it cannot deal well with
* randomized padding methods, or any padding method that
* wants to add more than one block. For instance, it should
* be possible to define cipher text stealing mode as simply
* a padding mode for CBC, which happens to consume the last
* two block (and requires use of the block cipher).
*/
class BOTAN_DLL BlockCipherModePaddingMethod
{
public:
/**
* @param block output buffer
* @param size of the block
* @param current_position in the last block
*/
virtual void pad(byte block[],
size_t size,
size_t current_position) const = 0;
/**
* @param block the last block
* @param size the of the block
*/
virtual size_t unpad(const byte block[],
size_t size) const = 0;
/**
* @param block_size of the cipher
* @param position in the current block
* @return number of padding bytes that will be appended
*/
virtual size_t pad_bytes(size_t block_size,
size_t position) const;
/**
* @param block_size of the cipher
* @return valid block size for this padding mode
*/
virtual bool valid_blocksize(size_t block_size) const = 0;
/**
* @return name of the mode
*/
virtual std::string name() const = 0;
/**
* virtual destructor
*/
virtual ~BlockCipherModePaddingMethod() {}
};
/**
* PKCS#7 Padding
*/
class BOTAN_DLL PKCS7_Padding : public BlockCipherModePaddingMethod
{
public:
void pad(byte[], size_t, size_t) const;
size_t unpad(const byte[], size_t) const;
bool valid_blocksize(size_t) const;
std::string name() const { return "PKCS7"; }
};
/**
* ANSI X9.23 Padding
*/
class BOTAN_DLL ANSI_X923_Padding : public BlockCipherModePaddingMethod
{
public:
void pad(byte[], size_t, size_t) const;
size_t unpad(const byte[], size_t) const;
bool valid_blocksize(size_t) const;
std::string name() const { return "X9.23"; }
};
/**
* One And Zeros Padding
*/
class BOTAN_DLL OneAndZeros_Padding : public BlockCipherModePaddingMethod
{
public:
void pad(byte[], size_t, size_t) const;
size_t unpad(const byte[], size_t) const;
bool valid_blocksize(size_t) const;
std::string name() const { return "OneAndZeros"; }
};
/**
* Null Padding
*/
class BOTAN_DLL Null_Padding : public BlockCipherModePaddingMethod
{
public:
void pad(byte[], size_t, size_t) const { return; }
size_t unpad(const byte[], size_t size) const { return size; }
size_t pad_bytes(size_t, size_t) const { return 0; }
bool valid_blocksize(size_t) const { return true; }
std::string name() const { return "NoPadding"; }
};
}
namespace Botan {
/**
* Key Derivation Function
*/
class BOTAN_DLL KDF : public Algorithm
{
public:
/**
* Derive a key
* @param key_len the desired output length in bytes
* @param secret the secret input
* @param salt a diversifier
*/
SecureVector<byte> derive_key(size_t key_len,
const MemoryRegion<byte>& secret,
const std::string& salt = "") const;
/**
* Derive a key
* @param key_len the desired output length in bytes
* @param secret the secret input
* @param salt a diversifier
*/
SecureVector<byte> derive_key(size_t key_len,
const MemoryRegion<byte>& secret,
const MemoryRegion<byte>& salt) const;
/**
* Derive a key
* @param key_len the desired output length in bytes
* @param secret the secret input
* @param salt a diversifier
* @param salt_len size of salt in bytes
*/
SecureVector<byte> derive_key(size_t key_len,
const MemoryRegion<byte>& secret,
const byte salt[],
size_t salt_len) const;
/**
* Derive a key
* @param key_len the desired output length in bytes
* @param secret the secret input
* @param secret_len size of secret in bytes
* @param salt a diversifier
*/
SecureVector<byte> derive_key(size_t key_len,
const byte secret[],
size_t secret_len,
const std::string& salt = "") const;
/**
* Derive a key
* @param key_len the desired output length in bytes
* @param secret the secret input
* @param secret_len size of secret in bytes
* @param salt a diversifier
* @param salt_len size of salt in bytes
*/
SecureVector<byte> derive_key(size_t key_len,
const byte secret[],
size_t secret_len,
const byte salt[],
size_t salt_len) const;
void clear() {}
virtual KDF* clone() const = 0;
private:
virtual SecureVector<byte>
derive(size_t key_len,
const byte secret[], size_t secret_len,
const byte salt[], size_t salt_len) const = 0;
};
/**
* Mask Generation Function
*/
class BOTAN_DLL MGF
{
public:
virtual void mask(const byte in[], size_t in_len,
byte out[], size_t out_len) const = 0;
virtual ~MGF() {}
};
}
namespace Botan {
/**
* Encoding Method for Encryption
*/
class BOTAN_DLL EME
{
public:
/**
* Return the maximum input size in bytes we can support
* @param keybits the size of the key in bits
* @return upper bound of input in bytes
*/
virtual size_t maximum_input_size(size_t keybits) const = 0;
/**
* Encode an input
* @param in the plaintext
* @param in_length length of plaintext in bytes
* @param key_length length of the key in bits
* @param rng a random number generator
* @return encoded plaintext
*/
SecureVector<byte> encode(const byte in[],
size_t in_length,
size_t key_length,
RandomNumberGenerator& rng) const;
/**
* Encode an input
* @param in the plaintext
* @param key_length length of the key in bits
* @param rng a random number generator
* @return encoded plaintext
*/
SecureVector<byte> encode(const MemoryRegion<byte>& in,
size_t key_length,
RandomNumberGenerator& rng) const;
/**
* Decode an input
* @param in the encoded plaintext
* @param in_length length of encoded plaintext in bytes
* @param key_length length of the key in bits
* @return plaintext
*/
SecureVector<byte> decode(const byte in[],
size_t in_length,
size_t key_length) const;
/**
* Decode an input
* @param in the encoded plaintext
* @param key_length length of the key in bits
* @return plaintext
*/
SecureVector<byte> decode(const MemoryRegion<byte>& in,
size_t key_length) const;
virtual ~EME() {}
private:
/**
* Encode an input
* @param in the plaintext
* @param in_length length of plaintext in bytes
* @param key_length length of the key in bits
* @param rng a random number generator
* @return encoded plaintext
*/
virtual SecureVector<byte> pad(const byte in[],
size_t in_length,
size_t key_length,
RandomNumberGenerator& rng) const = 0;
/**
* Decode an input
* @param in the encoded plaintext
* @param in_length length of encoded plaintext in bytes
* @param key_length length of the key in bits
* @return plaintext
*/
virtual SecureVector<byte> unpad(const byte in[],
size_t in_length,
size_t key_length) const = 0;
};
}
namespace Botan {
/**
* Retrieve an object prototype from the global factory
* @param algo_spec an algorithm name
* @return constant prototype object (use clone to create usable object),
library retains ownership
*/
inline const BlockCipher*
retrieve_block_cipher(const std::string& algo_spec)
{
Algorithm_Factory& af = global_state().algorithm_factory();
return af.prototype_block_cipher(algo_spec);
}
/**
* Retrieve an object prototype from the global factory
* @param algo_spec an algorithm name
* @return constant prototype object (use clone to create usable object),
library retains ownership
*/
inline const StreamCipher*
retrieve_stream_cipher(const std::string& algo_spec)
{
Algorithm_Factory& af = global_state().algorithm_factory();
return af.prototype_stream_cipher(algo_spec);
}
/**
* Retrieve an object prototype from the global factory
* @param algo_spec an algorithm name
* @return constant prototype object (use clone to create usable object),
library retains ownership
*/
inline const HashFunction*
retrieve_hash(const std::string& algo_spec)
{
Algorithm_Factory& af = global_state().algorithm_factory();
return af.prototype_hash_function(algo_spec);
}
/**
* Retrieve an object prototype from the global factory
* @param algo_spec an algorithm name
* @return constant prototype object (use clone to create usable object),
library retains ownership
*/
inline const MessageAuthenticationCode*
retrieve_mac(const std::string& algo_spec)
{
Algorithm_Factory& af = global_state().algorithm_factory();
return af.prototype_mac(algo_spec);
}
/*
* Get an algorithm object
* NOTE: these functions create and return new objects, letting the
* caller assume ownership of them
*/
/**
* Block cipher factory method.
* @deprecated Call algorithm_factory() directly
*
* @param algo_spec the name of the desired block cipher
* @return pointer to the block cipher object
*/
inline BlockCipher* get_block_cipher(const std::string& algo_spec)
{
Algorithm_Factory& af = global_state().algorithm_factory();
return af.make_block_cipher(algo_spec);
}
/**
* Stream cipher factory method.
* @deprecated Call algorithm_factory() directly
*
* @param algo_spec the name of the desired stream cipher
* @return pointer to the stream cipher object
*/
inline StreamCipher* get_stream_cipher(const std::string& algo_spec)
{
Algorithm_Factory& af = global_state().algorithm_factory();
return af.make_stream_cipher(algo_spec);
}
/**
* Hash function factory method.
* @deprecated Call algorithm_factory() directly
*
* @param algo_spec the name of the desired hash function
* @return pointer to the hash function object
*/
inline HashFunction* get_hash(const std::string& algo_spec)
{
Algorithm_Factory& af = global_state().algorithm_factory();
return af.make_hash_function(algo_spec);
}
/**
* MAC factory method.
* @deprecated Call algorithm_factory() directly
*
* @param algo_spec the name of the desired MAC
* @return pointer to the MAC object
*/
inline MessageAuthenticationCode* get_mac(const std::string& algo_spec)
{
Algorithm_Factory& af = global_state().algorithm_factory();
return af.make_mac(algo_spec);
}
/**
* Password based key derivation function factory method
* @param algo_spec the name of the desired PBKDF algorithm
* @return pointer to newly allocated object of that type
*/
BOTAN_DLL PBKDF* get_pbkdf(const std::string& algo_spec);
/**
* @deprecated Use get_pbkdf
* @param algo_spec the name of the desired algorithm
* @return pointer to newly allocated object of that type
*/
inline PBKDF* get_s2k(const std::string& algo_spec)
{
return get_pbkdf(algo_spec);
}
/*
* Get an EMSA/EME/KDF/MGF function
*/
// NOTE: these functions create and return new objects, letting the
// caller assume ownership of them
/**
* Factory method for EME (message-encoding methods for encryption) objects
* @param algo_spec the name of the EME to create
* @return pointer to newly allocated object of that type
*/
BOTAN_DLL EME* get_eme(const std::string& algo_spec);
/**
* Factory method for EMSA (message-encoding methods for signatures
* with appendix) objects
* @param algo_spec the name of the EME to create
* @return pointer to newly allocated object of that type
*/
BOTAN_DLL EMSA* get_emsa(const std::string& algo_spec);
/**
* Factory method for KDF (key derivation function)
* @param algo_spec the name of the KDF to create
* @return pointer to newly allocated object of that type
*/
BOTAN_DLL KDF* get_kdf(const std::string& algo_spec);
/*
* Get a cipher object
*/
/**
* Factory method for general symmetric cipher filters.
* @param algo_spec the name of the desired cipher
* @param key the key to be used for encryption/decryption performed by
* the filter
* @param iv the initialization vector to be used
* @param direction determines whether the filter will be an encrypting
* or decrypting filter
* @return pointer to newly allocated encryption or decryption filter
*/
BOTAN_DLL Keyed_Filter* get_cipher(const std::string& algo_spec,
const SymmetricKey& key,
const InitializationVector& iv,
Cipher_Dir direction);
/**
* Factory method for general symmetric cipher filters.
* @param algo_spec the name of the desired cipher
* @param key the key to be used for encryption/decryption performed by
* the filter
* @param direction determines whether the filter will be an encrypting
* or decrypting filter
* @return pointer to the encryption or decryption filter
*/
BOTAN_DLL Keyed_Filter* get_cipher(const std::string& algo_spec,
const SymmetricKey& key,
Cipher_Dir direction);
/**
* Factory method for general symmetric cipher filters. No key will be
* set in the filter.
*
* @param algo_spec the name of the desired cipher
* @param direction determines whether the filter will be an encrypting or
* decrypting filter
* @return pointer to the encryption or decryption filter
*/
BOTAN_DLL Keyed_Filter* get_cipher(const std::string& algo_spec,
Cipher_Dir direction);
/**
* Check if an algorithm exists.
* @param algo_spec the name of the algorithm to check for
* @return true if the algorithm exists, false otherwise
*/
BOTAN_DLL bool have_algorithm(const std::string& algo_spec);
/**
* Check if a block cipher algorithm exists.
* @deprecated Call algorithm_factory() directly
*
* @param algo_spec the name of the algorithm to check for
* @return true if the algorithm exists, false otherwise
*/
inline bool have_block_cipher(const std::string& algo_spec)
{
Algorithm_Factory& af = global_state().algorithm_factory();
return (af.prototype_block_cipher(algo_spec) != 0);
}
/**
* Check if a stream cipher algorithm exists.
* @deprecated Call algorithm_factory() directly
*
* @param algo_spec the name of the algorithm to check for
* @return true if the algorithm exists, false otherwise
*/
inline bool have_stream_cipher(const std::string& algo_spec)
{
Algorithm_Factory& af = global_state().algorithm_factory();
return (af.prototype_stream_cipher(algo_spec) != 0);
}
/**
* Check if a hash algorithm exists.
* @deprecated Call algorithm_factory() directly
*
* @param algo_spec the name of the algorithm to check for
* @return true if the algorithm exists, false otherwise
*/
inline bool have_hash(const std::string& algo_spec)
{
Algorithm_Factory& af = global_state().algorithm_factory();
return (af.prototype_hash_function(algo_spec) != 0);
}
/**
* Check if a MAC algorithm exists.
* @deprecated Call algorithm_factory() directly
*
* @param algo_spec the name of the algorithm to check for
* @return true if the algorithm exists, false otherwise
*/
inline bool have_mac(const std::string& algo_spec)
{
Algorithm_Factory& af = global_state().algorithm_factory();
return (af.prototype_mac(algo_spec) != 0);
}
/*
* Query information about an algorithm
*/
/**
* Find out the block size of a certain symmetric algorithm.
* @deprecated Call algorithm_factory() directly
*
* @param algo_spec the name of the algorithm
* @return block size of the specified algorithm
*/
BOTAN_DLL size_t block_size_of(const std::string& algo_spec);
/**
* Find out the output length of a certain symmetric algorithm.
* @deprecated Call algorithm_factory() directly
*
* @param algo_spec the name of the algorithm
* @return output length of the specified algorithm
*/
BOTAN_DLL size_t output_length_of(const std::string& algo_spec);
/**
* Find out the minimum key size of a certain symmetric algorithm.
* @deprecated Call algorithm_factory() directly
*
* @param algo_spec the name of the algorithm
* @return minimum key length of the specified algorithm
*/
BOTAN_DEPRECATED("Retrieve object you want and then call key_spec")
BOTAN_DLL size_t min_keylength_of(const std::string& algo_spec);
/**
* Find out the maximum key size of a certain symmetric algorithm.
* @deprecated Call algorithm_factory() directly
*
* @param algo_spec the name of the algorithm
* @return maximum key length of the specified algorithm
*/
BOTAN_DEPRECATED("Retrieve object you want and then call key_spec")
BOTAN_DLL size_t max_keylength_of(const std::string& algo_spec);
/**
* Find out the size any valid key is a multiple of for a certain algorithm.
* @deprecated Call algorithm_factory() directly
*
* @param algo_spec the name of the algorithm
* @return size any valid key is a multiple of
*/
BOTAN_DEPRECATED("Retrieve object you want and then call key_spec")
BOTAN_DLL size_t keylength_multiple_of(const std::string& algo_spec);
}
namespace Botan {
/*
* Get information describing the version
*/
/**
* Get a human-readable string identifying the version of Botan.
* No particular format should be assumed.
* @return version string
*/
BOTAN_DLL std::string version_string();
/**
* Return the date this version of botan was released, in an integer of
* the form YYYYMMDD. For instance a version released on May 21, 2013
* would return the integer 20130521. If the currently running version
* is not an official release, this function will return 0 instead.
*
* @return release date, or zero if unreleased
*/
BOTAN_DLL u32bit version_datestamp();
/**
* Get the major version number.
* @return major version number
*/
BOTAN_DLL u32bit version_major();
/**
* Get the minor version number.
* @return minor version number
*/
BOTAN_DLL u32bit version_minor();
/**
* Get the patch number.
* @return patch number
*/
BOTAN_DLL u32bit version_patch();
/*
* Macros for compile-time version checks
*/
#define BOTAN_VERSION_CODE_FOR(a,b,c) ((a << 16) | (b << 8) | (c))
/**
* Compare using BOTAN_VERSION_CODE_FOR, as in
* # if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,8,0)
* # error "Botan version too old"
* # endif
*/
#define BOTAN_VERSION_CODE BOTAN_VERSION_CODE_FOR(BOTAN_VERSION_MAJOR, \
BOTAN_VERSION_MINOR, \
BOTAN_VERSION_PATCH)
}
#if defined(BOTAN_HAS_AUTO_SEEDING_RNG)
namespace Botan {
/**
* An automatically seeded PRNG
*/
class BOTAN_DLL AutoSeeded_RNG : public RandomNumberGenerator
{
public:
void randomize(byte out[], size_t len)
{ rng->randomize(out, len); }
bool is_seeded() const { return rng->is_seeded(); }
void clear() { rng->clear(); }
std::string name() const { return rng->name(); }
void reseed(size_t poll_bits = 256) { rng->reseed(poll_bits); }
void add_entropy_source(EntropySource* es)
{ rng->add_entropy_source(es); }
void add_entropy(const byte in[], size_t len)
{ rng->add_entropy(in, len); }
AutoSeeded_RNG() { rng = &global_state().global_rng(); }
private:
RandomNumberGenerator* rng;
};
}
#endif
namespace Botan {
/**
* PKCS #10 Certificate Request.
*/
class BOTAN_DLL PKCS10_Request : public X509_Object
{
public:
/**
* Get the subject public key.
* @return subject public key
*/
Public_Key* subject_public_key() const;
/**
* Get the raw DER encoded public key.
* @return raw DER encoded public key
*/
MemoryVector<byte> raw_public_key() const;
/**
* Get the subject DN.
* @return subject DN
*/
X509_DN subject_dn() const;
/**
* Get the subject alternative name.
* @return subject alternative name.
*/
AlternativeName subject_alt_name() const;
/**
* Get the key constraints for the key associated with this
* PKCS#10 object.
* @return key constraints
*/
Key_Constraints constraints() const;
/**
* Get the extendend key constraints (if any).
* @return extended key constraints
*/
std::vector<OID> ex_constraints() const;
/**
* Find out whether this is a CA request.
* @result true if it is a CA request, false otherwise.
*/
bool is_CA() const;
/**
* Return the constraint on the path length defined
* in the BasicConstraints extension.
* @return path limit
*/
u32bit path_limit() const;
/**
* Get the challenge password for this request
* @return challenge password for this request
*/
std::string challenge_password() const;
/**
* Create a PKCS#10 Request from a data source.
* @param source the data source providing the DER encoded request
*/
PKCS10_Request(DataSource& source);
/**
* Create a PKCS#10 Request from a file.
* @param filename the name of the file containing the DER or PEM
* encoded request file
*/
PKCS10_Request(const std::string& filename);
private:
void force_decode();
void handle_attribute(const Attribute&);
Data_Store info;
};
}
namespace Botan {
/**
* Options for X.509 certificates.
*/
class BOTAN_DLL X509_Cert_Options
{
public:
/**
* the subject common name
*/
std::string common_name;
/**
* the subject counry
*/
std::string country;
/**
* the subject organization
*/
std::string organization;
/**
* the subject organizational unit
*/
std::string org_unit;
/**
* the subject locality
*/
std::string locality;
/**
* the subject state
*/
std::string state;
/**
* the subject serial number
*/
std::string serial_number;
/**
* the subject email adress
*/
std::string email;
/**
* the subject URI
*/
std::string uri;
/**
* the subject IPv4 address
*/
std::string ip;
/**
* the subject DNS
*/
std::string dns;
/**
* the subject XMPP
*/
std::string xmpp;
/**
* the subject challenge password
*/
std::string challenge;
/**
* the subject notBefore
*/
X509_Time start;
/**
* the subject notAfter
*/
X509_Time end;
/**
* Indicates whether the certificate request
*/
bool is_CA;
/**
* Indicates the BasicConstraints path limit
*/
size_t path_limit;
/**
* The key constraints for the subject public key
*/
Key_Constraints constraints;
/**
* The key extended constraints for the subject public key
*/
std::vector<OID> ex_constraints;
/**
* Check the options set in this object for validity.
*/
void sanity_check() const;
/**
* Mark the certificate as a CA certificate and set the path limit.
* @param limit the path limit to be set in the BasicConstraints extension.
*/
void CA_key(size_t limit = 1);
/**
* Set the notBefore of the certificate.
* @param time the notBefore value of the certificate
*/
void not_before(const std::string& time);
/**
* Set the notAfter of the certificate.
* @param time the notAfter value of the certificate
*/
void not_after(const std::string& time);
/**
* Add the key constraints of the KeyUsage extension.
* @param constr the constraints to set
*/
void add_constraints(Key_Constraints constr);
/**
* Add constraints to the ExtendedKeyUsage extension.
* @param oid the oid to add
*/
void add_ex_constraint(const OID& oid);
/**
* Add constraints to the ExtendedKeyUsage extension.
* @param name the name to look up the oid to add
*/
void add_ex_constraint(const std::string& name);
/**
* Construct a new options object
* @param opts define the common name of this object. An example for this
* parameter would be "common_name/country/organization/organizational_unit".
* @param expire_time the expiration time (from the current clock in seconds)
*/
X509_Cert_Options(const std::string& opts = "",
u32bit expire_time = 365 * 24 * 60 * 60);
};
namespace X509 {
/**
* Create a self-signed X.509 certificate.
* @param opts the options defining the certificate to create
* @param key the private key used for signing, i.e. the key
* associated with this self-signed certificate
* @param hash_fn the hash function to use
* @param rng the rng to use
* @return newly created self-signed certificate
*/
BOTAN_DLL X509_Certificate
create_self_signed_cert(const X509_Cert_Options& opts,
const Private_Key& key,
const std::string& hash_fn,
RandomNumberGenerator& rng);
/**
* Create a PKCS#10 certificate request.
* @param opts the options defining the request to create
* @param key the key used to sign this request
* @param rng the rng to use
* @param hash_fn the hash function to use
* @return newly created PKCS#10 request
*/
BOTAN_DLL PKCS10_Request create_cert_req(const X509_Cert_Options& opts,
const Private_Key& key,
const std::string& hash_fn,
RandomNumberGenerator& rng);
}
}
namespace Botan {
class BigInt;
class ASN1_Object;
/**
* General DER Encoding Object
*/
class BOTAN_DLL DER_Encoder
{
public:
SecureVector<byte> get_contents();
DER_Encoder& start_cons(ASN1_Tag type_tag,
ASN1_Tag class_tag = UNIVERSAL);
DER_Encoder& end_cons();
DER_Encoder& start_explicit(u16bit type_tag);
DER_Encoder& end_explicit();
DER_Encoder& raw_bytes(const byte val[], size_t len);
DER_Encoder& raw_bytes(const MemoryRegion<byte>& val);
DER_Encoder& encode_null();
DER_Encoder& encode(bool b);
DER_Encoder& encode(size_t s);
DER_Encoder& encode(const BigInt& n);
DER_Encoder& encode(const MemoryRegion<byte>& v, ASN1_Tag real_type);
DER_Encoder& encode(const byte val[], size_t len, ASN1_Tag real_type);
DER_Encoder& encode(bool b,
ASN1_Tag type_tag,
ASN1_Tag class_tag = CONTEXT_SPECIFIC);
DER_Encoder& encode(size_t s,
ASN1_Tag type_tag,
ASN1_Tag class_tag = CONTEXT_SPECIFIC);
DER_Encoder& encode(const BigInt& n,
ASN1_Tag type_tag,
ASN1_Tag class_tag = CONTEXT_SPECIFIC);
DER_Encoder& encode(const MemoryRegion<byte>& v,
ASN1_Tag real_type,
ASN1_Tag type_tag,
ASN1_Tag class_tag = CONTEXT_SPECIFIC);
DER_Encoder& encode(const byte v[], size_t len,
ASN1_Tag real_type,
ASN1_Tag type_tag,
ASN1_Tag class_tag = CONTEXT_SPECIFIC);
template<typename T>
DER_Encoder& encode_optional(const T& value, const T& default_value)
{
if(value != default_value)
encode(value);
return (*this);
}
template<typename T>
DER_Encoder& encode_list(const std::vector<T>& values)
{
for(size_t i = 0; i != values.size(); ++i)
encode(values[i]);
return (*this);
}
DER_Encoder& encode(const ASN1_Object& obj);
DER_Encoder& encode_if(bool pred, DER_Encoder& enc);
DER_Encoder& add_object(ASN1_Tag type_tag, ASN1_Tag class_tag,
const byte rep[], size_t length);
DER_Encoder& add_object(ASN1_Tag type_tag, ASN1_Tag class_tag,
const MemoryRegion<byte>& rep);
DER_Encoder& add_object(ASN1_Tag type_tag, ASN1_Tag class_tag,
const std::string& str);
DER_Encoder& add_object(ASN1_Tag type_tag, ASN1_Tag class_tag,
byte val);
private:
class DER_Sequence
{
public:
ASN1_Tag tag_of() const;
SecureVector<byte> get_contents();
void add_bytes(const byte[], size_t);
DER_Sequence(ASN1_Tag, ASN1_Tag);
private:
ASN1_Tag type_tag, class_tag;
SecureVector<byte> contents;
std::vector< SecureVector<byte> > set_contents;
};
SecureVector<byte> contents;
std::vector<DER_Sequence> subsequences;
};
}
namespace Botan {
/**
* EME1, aka OAEP
*/
class BOTAN_DLL EME1 : public EME
{
public:
size_t maximum_input_size(size_t) const;
/**
* @param hash object to use for hashing (takes ownership)
* @param P an optional label. Normally empty.
*/
EME1(HashFunction* hash, const std::string& P = "");
~EME1() { delete mgf; }
private:
SecureVector<byte> pad(const byte[], size_t, size_t,
RandomNumberGenerator&) const;
SecureVector<byte> unpad(const byte[], size_t, size_t) const;
SecureVector<byte> Phash;
MGF* mgf;
};
}
namespace Botan {
/**
* The two types of signature format supported by Botan.
*/
enum Signature_Format { IEEE_1363, DER_SEQUENCE };
/**
* Enum marking if protection against fault attacks should be used
*/
enum Fault_Protection {
ENABLE_FAULT_PROTECTION,
DISABLE_FAULT_PROTECTION
};
/**
* Public Key Encryptor
*/
class BOTAN_DLL PK_Encryptor
{
public:
/**
* Encrypt a message.
* @param in the message as a byte array
* @param length the length of the above byte array
* @param rng the random number source to use
* @return encrypted message
*/
SecureVector<byte> encrypt(const byte in[], size_t length,
RandomNumberGenerator& rng) const
{
return enc(in, length, rng);
}
/**
* Encrypt a message.
* @param in the message
* @param rng the random number source to use
* @return encrypted message
*/
SecureVector<byte> encrypt(const MemoryRegion<byte>& in,
RandomNumberGenerator& rng) const
{
return enc(&in[0], in.size(), rng);
}
/**
* Return the maximum allowed message size in bytes.
* @return maximum message size in bytes
*/
virtual size_t maximum_input_size() const = 0;
PK_Encryptor() {}
virtual ~PK_Encryptor() {}
private:
PK_Encryptor(const PK_Encryptor&) {}
PK_Encryptor& operator=(const PK_Encryptor&) { return *this; }
virtual SecureVector<byte> enc(const byte[], size_t,
RandomNumberGenerator&) const = 0;
};
/**
* Public Key Decryptor
*/
class BOTAN_DLL PK_Decryptor
{
public:
/**
* Decrypt a ciphertext.
* @param in the ciphertext as a byte array
* @param length the length of the above byte array
* @return decrypted message
*/
SecureVector<byte> decrypt(const byte in[], size_t length) const
{
return dec(in, length);
}
/**
* Decrypt a ciphertext.
* @param in the ciphertext
* @return decrypted message
*/
SecureVector<byte> decrypt(const MemoryRegion<byte>& in) const
{
return dec(&in[0], in.size());
}
PK_Decryptor() {}
virtual ~PK_Decryptor() {}
private:
PK_Decryptor(const PK_Decryptor&) {}
PK_Decryptor& operator=(const PK_Decryptor&) { return *this; }
virtual SecureVector<byte> dec(const byte[], size_t) const = 0;
};
/**
* Public Key Signer. Use the sign_message() functions for small
* messages. Use multiple calls update() to process large messages and
* generate the signature by finally calling signature().
*/
class BOTAN_DLL PK_Signer
{
public:
/**
* Sign a message.
* @param in the message to sign as a byte array
* @param length the length of the above byte array
* @param rng the rng to use
* @return signature
*/
SecureVector<byte> sign_message(const byte in[], size_t length,
RandomNumberGenerator& rng);
/**
* Sign a message.
* @param in the message to sign
* @param rng the rng to use
* @return signature
*/
SecureVector<byte> sign_message(const MemoryRegion<byte>& in,
RandomNumberGenerator& rng)
{ return sign_message(&in[0], in.size(), rng); }
/**
* Add a message part (single byte).
* @param in the byte to add
*/
void update(byte in) { update(&in, 1); }
/**
* Add a message part.
* @param in the message part to add as a byte array
* @param length the length of the above byte array
*/
void update(const byte in[], size_t length);
/**
* Add a message part.
* @param in the message part to add
*/
void update(const MemoryRegion<byte>& in) { update(&in[0], in.size()); }
/**
* Get the signature of the so far processed message (provided by the
* calls to update()).
* @param rng the rng to use
* @return signature of the total message
*/
SecureVector<byte> signature(RandomNumberGenerator& rng);
/**
* Set the output format of the signature.
* @param format the signature format to use
*/
void set_output_format(Signature_Format format) { sig_format = format; }
/**
* Construct a PK Signer.
* @param key the key to use inside this signer
* @param emsa the EMSA to use
* An example would be "EMSA1(SHA-224)".
* @param format the signature format to use
* @param prot says if fault protection should be enabled
*/
PK_Signer(const Private_Key& key,
const std::string& emsa,
Signature_Format format = IEEE_1363,
Fault_Protection prot = ENABLE_FAULT_PROTECTION);
~PK_Signer() { delete op; delete verify_op; delete emsa; }
private:
bool self_test_signature(const MemoryRegion<byte>& msg,
const MemoryRegion<byte>& sig) const;
PK_Signer(const PK_Signer&) {}
PK_Signer& operator=(const PK_Signer&) { return *this; }
PK_Ops::Signature* op;
PK_Ops::Verification* verify_op;
EMSA* emsa;
Signature_Format sig_format;
};
/**
* Public Key Verifier. Use the verify_message() functions for small
* messages. Use multiple calls update() to process large messages and
* verify the signature by finally calling check_signature().
*/
class BOTAN_DLL PK_Verifier
{
public:
/**
* Verify a signature.
* @param msg the message that the signature belongs to, as a byte array
* @param msg_length the length of the above byte array msg
* @param sig the signature as a byte array
* @param sig_length the length of the above byte array sig
* @return true if the signature is valid
*/
bool verify_message(const byte msg[], size_t msg_length,
const byte sig[], size_t sig_length);
/**
* Verify a signature.
* @param msg the message that the signature belongs to
* @param sig the signature
* @return true if the signature is valid
*/
bool verify_message(const MemoryRegion<byte>& msg,
const MemoryRegion<byte>& sig)
{
return verify_message(&msg[0], msg.size(),
&sig[0], sig.size());
}
/**
* Add a message part (single byte) of the message corresponding to the
* signature to be verified.
* @param in the byte to add
*/
void update(byte in) { update(&in, 1); }
/**
* Add a message part of the message corresponding to the
* signature to be verified.
* @param msg_part the new message part as a byte array
* @param length the length of the above byte array
*/
void update(const byte msg_part[], size_t length);
/**
* Add a message part of the message corresponding to the
* signature to be verified.
* @param in the new message part
*/
void update(const MemoryRegion<byte>& in)
{ update(&in[0], in.size()); }
/**
* Check the signature of the buffered message, i.e. the one build
* by successive calls to update.
* @param sig the signature to be verified as a byte array
* @param length the length of the above byte array
* @return true if the signature is valid, false otherwise
*/
bool check_signature(const byte sig[], size_t length);
/**
* Check the signature of the buffered message, i.e. the one build
* by successive calls to update.
* @param sig the signature to be verified
* @return true if the signature is valid, false otherwise
*/
bool check_signature(const MemoryRegion<byte>& sig)
{
return check_signature(&sig[0], sig.size());
}
/**
* Set the format of the signatures fed to this verifier.
* @param format the signature format to use
*/
void set_input_format(Signature_Format format);
/**
* Construct a PK Verifier.
* @param pub_key the public key to verify against
* @param emsa the EMSA to use (eg "EMSA3(SHA-1)")
* @param format the signature format to use
*/
PK_Verifier(const Public_Key& pub_key,
const std::string& emsa,
Signature_Format format = IEEE_1363);
~PK_Verifier() { delete op; delete emsa; }
private:
PK_Verifier(const PK_Verifier&) {}
PK_Verifier& operator=(const PK_Verifier&) { return *this; }
bool validate_signature(const MemoryRegion<byte>& msg,
const byte sig[], size_t sig_len);
PK_Ops::Verification* op;
EMSA* emsa;
Signature_Format sig_format;
};
/**
* Key used for key agreement
*/
class BOTAN_DLL PK_Key_Agreement
{
public:
/*
* Perform Key Agreement Operation
* @param key_len the desired key output size
* @param in the other parties key
* @param in_len the length of in in bytes
* @param params extra derivation params
* @param params_len the length of params in bytes
*/
SymmetricKey derive_key(size_t key_len,
const byte in[],
size_t in_len,
const byte params[],
size_t params_len) const;
/*
* Perform Key Agreement Operation
* @param key_len the desired key output size
* @param in the other parties key
* @param in_len the length of in in bytes
* @param params extra derivation params
* @param params_len the length of params in bytes
*/
SymmetricKey derive_key(size_t key_len,
const MemoryRegion<byte>& in,
const byte params[],
size_t params_len) const
{
return derive_key(key_len, &in[0], in.size(),
params, params_len);
}
/*
* Perform Key Agreement Operation
* @param key_len the desired key output size
* @param in the other parties key
* @param in_len the length of in in bytes
* @param params extra derivation params
*/
SymmetricKey derive_key(size_t key_len,
const byte in[], size_t in_len,
const std::string& params = "") const
{
return derive_key(key_len, in, in_len,
reinterpret_cast<const byte*>(params.data()),
params.length());
}
/*
* Perform Key Agreement Operation
* @param key_len the desired key output size
* @param in the other parties key
* @param params extra derivation params
*/
SymmetricKey derive_key(size_t key_len,
const MemoryRegion<byte>& in,
const std::string& params = "") const
{
return derive_key(key_len, &in[0], in.size(),
reinterpret_cast<const byte*>(params.data()),
params.length());
}
/**
* Construct a PK Key Agreement.
* @param key the key to use
* @param kdf name of the KDF to use (or 'Raw' for no KDF)
*/
PK_Key_Agreement(const PK_Key_Agreement_Key& key,
const std::string& kdf);
~PK_Key_Agreement() { delete op; delete kdf; }
private:
PK_Key_Agreement(const PK_Key_Agreement_Key&) {}
PK_Key_Agreement& operator=(const PK_Key_Agreement&) { return *this; }
PK_Ops::Key_Agreement* op;
KDF* kdf;
};
/**
* Encryption with an MR algorithm and an EME.
*/
class BOTAN_DLL PK_Encryptor_EME : public PK_Encryptor
{
public:
size_t maximum_input_size() const;
/**
* Construct an instance.
* @param key the key to use inside the decryptor
* @param eme the EME to use
*/
PK_Encryptor_EME(const Public_Key& key,
const std::string& eme);
~PK_Encryptor_EME() { delete op; delete eme; }
private:
SecureVector<byte> enc(const byte[], size_t,
RandomNumberGenerator& rng) const;
PK_Ops::Encryption* op;
const EME* eme;
};
/**
* Decryption with an MR algorithm and an EME.
*/
class BOTAN_DLL PK_Decryptor_EME : public PK_Decryptor
{
public:
/**
* Construct an instance.
* @param key the key to use inside the encryptor
* @param eme the EME to use
*/
PK_Decryptor_EME(const Private_Key& key,
const std::string& eme);
~PK_Decryptor_EME() { delete op; delete eme; }
private:
SecureVector<byte> dec(const byte[], size_t) const;
PK_Ops::Decryption* op;
const EME* eme;
};
/*
* Typedefs for compatability with 1.8
*/
typedef PK_Encryptor_EME PK_Encryptor_MR_with_EME;
typedef PK_Decryptor_EME PK_Decryptor_MR_with_EME;
}
namespace Botan {
/**
* DES
*/
class BOTAN_DLL DES : public Block_Cipher_Fixed_Params<8, 8>
{
public:
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
void clear() { zeroise(round_key); }
std::string name() const { return "DES"; }
BlockCipher* clone() const { return new DES; }
DES() : round_key(32) {}
private:
void key_schedule(const byte[], size_t);
SecureVector<u32bit> round_key;
};
/**
* Triple DES
*/
class BOTAN_DLL TripleDES : public Block_Cipher_Fixed_Params<8, 16, 24, 8>
{
public:
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
void clear() { zeroise(round_key); }
std::string name() const { return "TripleDES"; }
BlockCipher* clone() const { return new TripleDES; }
TripleDES() : round_key(96) {}
private:
void key_schedule(const byte[], size_t);
SecureVector<u32bit> round_key;
};
/*
* DES Tables
*/
extern const u32bit DES_SPBOX1[256];
extern const u32bit DES_SPBOX2[256];
extern const u32bit DES_SPBOX3[256];
extern const u32bit DES_SPBOX4[256];
extern const u32bit DES_SPBOX5[256];
extern const u32bit DES_SPBOX6[256];
extern const u32bit DES_SPBOX7[256];
extern const u32bit DES_SPBOX8[256];
extern const u64bit DES_IPTAB1[256];
extern const u64bit DES_IPTAB2[256];
extern const u64bit DES_FPTAB1[256];
extern const u64bit DES_FPTAB2[256];
}
namespace Botan {
/**
* DESX
*/
class BOTAN_DLL DESX : public Block_Cipher_Fixed_Params<8, 24>
{
public:
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
void clear() { des.clear(); zeroise(K1); zeroise(K2); }
std::string name() const { return "DESX"; }
BlockCipher* clone() const { return new DESX; }
DESX() : K1(8), K2(8) {}
private:
void key_schedule(const byte[], size_t);
SecureVector<byte> K1, K2;
DES des;
};
}
namespace Botan {
/**
* The GOST 28147-89 block cipher uses a set of 4 bit Sboxes, however
* the standard does not actually define these Sboxes; they are
* considered a local configuration issue. Several different sets are
* used.
*/
class BOTAN_DLL GOST_28147_89_Params
{
public:
/**
* @param row the row
* @param col the column
* @return sbox entry at this row/column
*/
byte sbox_entry(size_t row, size_t col) const;
/**
* @return name of this parameter set
*/
std::string param_name() const { return name; }
/**
* Default GOST parameters are the ones given in GOST R 34.11 for
* testing purposes; these sboxes are also used by Crypto++, and,
* at least according to Wikipedia, the Central Bank of Russian
* Federation
* @param name of the parameter set
*/
GOST_28147_89_Params(const std::string& name = "R3411_94_TestParam");
private:
const byte* sboxes;
std::string name;
};
/**
* GOST 28147-89
*/
class BOTAN_DLL GOST_28147_89 : public Block_Cipher_Fixed_Params<8, 32>
{
public:
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
void clear() { zeroise(EK); }
std::string name() const;
BlockCipher* clone() const { return new GOST_28147_89(SBOX); }
/**
* @param params the sbox parameters to use
*/
GOST_28147_89(const GOST_28147_89_Params& params);
private:
GOST_28147_89(const SecureVector<u32bit>& other_SBOX) :
SBOX(other_SBOX), EK(8) {}
void key_schedule(const byte[], size_t);
SecureVector<u32bit> SBOX;
SecureVector<u32bit> EK;
};
}
namespace Botan {
/**
* GOST 34.11
*/
class BOTAN_DLL GOST_34_11 : public HashFunction
{
public:
std::string name() const { return "GOST-R-34.11-94" ; }
size_t output_length() const { return 32; }
size_t hash_block_size() const { return 32; }
HashFunction* clone() const { return new GOST_34_11; }
void clear();
GOST_34_11();
private:
void compress_n(const byte input[], size_t blocks);
void add_data(const byte[], size_t);
void final_result(byte[]);
GOST_28147_89 cipher;
SecureVector<byte> buffer, sum, hash;
size_t position;
u64bit count;
};
}
namespace Botan {
/**
* SHA-384
*/
class BOTAN_DLL SHA_384 : public MDx_HashFunction
{
public:
std::string name() const { return "SHA-384"; }
size_t output_length() const { return 48; }
HashFunction* clone() const { return new SHA_384; }
void clear();
SHA_384() : MDx_HashFunction(128, true, true, 16), digest(8)
{ clear(); }
private:
void compress_n(const byte[], size_t blocks);
void copy_out(byte[]);
SecureVector<u64bit> digest;
};
/**
* SHA-512
*/
class BOTAN_DLL SHA_512 : public MDx_HashFunction
{
public:
std::string name() const { return "SHA-512"; }
size_t output_length() const { return 64; }
HashFunction* clone() const { return new SHA_512; }
void clear();
SHA_512() : MDx_HashFunction(128, true, true, 16), digest(8)
{ clear(); }
private:
void compress_n(const byte[], size_t blocks);
void copy_out(byte[]);
SecureVector<u64bit> digest;
};
}
namespace Botan {
/**
* Password Based Encryption (PBE) Filter.
*/
class BOTAN_DLL PBE : public Filter
{
public:
/**
* Set this filter's key.
* @param pw the password to be used for the encryption
*/
virtual void set_key(const std::string& pw) = 0;
/**
* Create a new random salt value and set the default iterations value.
* @param rng a random number generator
*/
virtual void new_params(RandomNumberGenerator& rng) = 0;
/**
* DER encode the params (the number of iterations and the salt value)
* @return encoded params
*/
virtual MemoryVector<byte> encode_params() const = 0;
/**
* Decode params and use them inside this Filter.
* @param src a data source to read the encoded params from
*/
virtual void decode_params(DataSource& src) = 0;
/**
* Get this PBE's OID.
* @return object identifier
*/
virtual OID get_oid() const = 0;
};
}
namespace Botan {
/**
* KDF1, from IEEE 1363
*/
class BOTAN_DLL KDF1 : public KDF
{
public:
SecureVector<byte> derive(size_t,
const byte secret[], size_t secret_len,
const byte P[], size_t P_len) const;
std::string name() const { return "KDF1(" + hash->name() + ")"; }
KDF* clone() const { return new KDF1(hash->clone()); }
KDF1(HashFunction* h) : hash(h) {}
KDF1(const KDF1& other) : KDF(), hash(other.hash->clone()) {}
~KDF1() { delete hash; }
private:
HashFunction* hash;
};
}
namespace Botan {
/**
* MISTY1
*/
class BOTAN_DLL MISTY1 : public Block_Cipher_Fixed_Params<8, 16>
{
public:
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
void clear() { zeroise(EK); zeroise(DK); }
std::string name() const { return "MISTY1"; }
BlockCipher* clone() const { return new MISTY1; }
/**
* @param rounds the number of rounds. Must be 8 with the current
* implementation
*/
MISTY1(size_t rounds = 8);
private:
void key_schedule(const byte[], size_t);
SecureVector<u16bit> EK, DK;
};
}
namespace Botan {
/**
* 32-bit cyclic redundancy check
*/
class BOTAN_DLL CRC32 : public HashFunction
{
public:
std::string name() const { return "CRC32"; }
size_t output_length() const { return 4; }
HashFunction* clone() const { return new CRC32; }
void clear() { crc = 0xFFFFFFFF; }
CRC32() { clear(); }
~CRC32() { clear(); }
private:
void add_data(const byte[], size_t);
void final_result(byte[]);
u32bit crc;
};
}
namespace Botan {
namespace PEM_Code {
/*
* PEM Encoding/Decoding
*/
BOTAN_DLL std::string encode(const byte[], size_t,
const std::string&, size_t = 64);
BOTAN_DLL std::string encode(const MemoryRegion<byte>&,
const std::string&, size_t = 64);
BOTAN_DLL SecureVector<byte> decode(DataSource&, std::string&);
BOTAN_DLL SecureVector<byte> decode_check_label(DataSource&,
const std::string&);
BOTAN_DLL bool matches(DataSource&, const std::string& = "",
size_t search_range = 4096);
}
}
namespace Botan {
/**
* XTEA
*/
class BOTAN_DLL XTEA : public Block_Cipher_Fixed_Params<8, 16>
{
public:
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
void clear() { zeroise(EK); }
std::string name() const { return "XTEA"; }
BlockCipher* clone() const { return new XTEA; }
XTEA() : EK(64) {}
protected:
/**
* @return const reference to the key schedule
*/
const SecureVector<u32bit>& get_EK() const { return EK; }
private:
void key_schedule(const byte[], size_t);
SecureVector<u32bit> EK;
};
}
namespace Botan {
/**
* KASUMI, the block cipher used in 3G telephony
*/
class BOTAN_DLL KASUMI : public Block_Cipher_Fixed_Params<8, 16>
{
public:
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
void clear() { zeroise(EK); }
std::string name() const { return "KASUMI"; }
BlockCipher* clone() const { return new KASUMI; }
KASUMI() : EK(64) {}
private:
void key_schedule(const byte[], size_t);
SecureVector<u16bit> EK;
};
}
namespace Botan {
/**
* This class represents discrete logarithm groups. It holds a prime p,
* a prime q = (p-1)/2 and g = x^((p-1)/q) mod p.
*/
class BOTAN_DLL DL_Group
{
public:
/**
* Get the prime p.
* @return prime p
*/
const BigInt& get_p() const;
/**
* Get the prime q.
* @return prime q
*/
const BigInt& get_q() const;
/**
* Get the base g.
* @return base g
*/
const BigInt& get_g() const;
/**
* The DL group encoding format variants.
*/
enum Format {
ANSI_X9_42,
ANSI_X9_57,
PKCS_3,
DSA_PARAMETERS = ANSI_X9_57,
DH_PARAMETERS = ANSI_X9_42,
X942_DH_PARAMETERS = ANSI_X9_42,
PKCS3_DH_PARAMETERS = PKCS_3
};
/**
* Determine the prime creation for DL groups.
*/
enum PrimeType { Strong, Prime_Subgroup, DSA_Kosherizer };
/**
* Perform validity checks on the group.
* @param rng the rng to use
* @param strong whether to perform stronger by lengthier tests
* @return true if the object is consistent, false otherwise
*/
bool verify_group(RandomNumberGenerator& rng, bool strong) const;
/**
* Encode this group into a string using PEM encoding.
* @param format the encoding format
* @return string holding the PEM encoded group
*/
std::string PEM_encode(Format format) const;
/**
* Encode this group into a string using DER encoding.
* @param format the encoding format
* @return string holding the DER encoded group
*/
SecureVector<byte> DER_encode(Format format) const;
/**
* Decode a DER/BER encoded group into this instance.
* @param src a DataSource providing the encoded group
* @param format the format of the encoded group
*/
void BER_decode(DataSource& src, Format format);
/**
* Decode a PEM encoded group into this instance.
* @param src a DataSource providing the encoded group
*/
void PEM_decode(DataSource& src);
/**
* Construct a DL group with uninitialized internal value.
* Use this constructor is you wish to set the groups values
* from a DER or PEM encoded group.
*/
DL_Group();
/**
* Construct a DL group that is registered in the configuration.
* @param name the name that is configured in the global configuration
* for the desired group. If no configuration file is specified,
* the default values from the file policy.cpp will be used. For instance,
* use "modp/ietf/768" as name.
*/
DL_Group(const std::string& name);
/**
* Create a new group randomly.
* @param rng the random number generator to use
* @param type specifies how the creation of primes p and q shall
* be performed. If type=Strong, then p will be determined as a
* safe prime, and q will be chosen as (p-1)/2. If
* type=Prime_Subgroup and qbits = 0, then the size of q will be
* determined according to the estimated difficulty of the DL
* problem. If type=DSA_Kosherizer, DSA primes will be created.
* @param pbits the number of bits of p
* @param qbits the number of bits of q. Leave it as 0 to have
* the value determined according to pbits.
*/
DL_Group(RandomNumberGenerator& rng, PrimeType type,
size_t pbits, size_t qbits = 0);
/**
* Create a DSA group with a given seed.
* @param rng the random number generator to use
* @param seed the seed to use to create the random primes
* @param pbits the desired bit size of the prime p
* @param qbits the desired bit size of the prime q.
*/
DL_Group(RandomNumberGenerator& rng, const MemoryRegion<byte>& seed,
size_t pbits = 1024, size_t qbits = 0);
/**
* Create a DL group. The prime q will be determined according to p.
* @param p the prime p
* @param g the base g
*/
DL_Group(const BigInt& p, const BigInt& g);
/**
* Create a DL group.
* @param p the prime p
* @param q the prime q
* @param g the base g
*/
DL_Group(const BigInt& p, const BigInt& q, const BigInt& g);
private:
static BigInt make_dsa_generator(const BigInt&, const BigInt&);
void init_check() const;
void initialize(const BigInt&, const BigInt&, const BigInt&);
bool initialized;
BigInt p, q, g;
};
}
namespace Botan {
/**
* This class represents discrete logarithm (DL) public keys.
*/
class BOTAN_DLL DL_Scheme_PublicKey : public virtual Public_Key
{
public:
bool check_key(RandomNumberGenerator& rng, bool) const;
AlgorithmIdentifier algorithm_identifier() const;
MemoryVector<byte> x509_subject_public_key() const;
/**
* Get the DL domain parameters of this key.
* @return DL domain parameters of this key
*/
const DL_Group& get_domain() const { return group; }
/**
* Get the public value y with y = g^x mod p where x is the secret key.
*/
const BigInt& get_y() const { return y; }
/**
* Get the prime p of the underlying DL group.
* @return prime p
*/
const BigInt& group_p() const { return group.get_p(); }
/**
* Get the prime q of the underlying DL group.
* @return prime q
*/
const BigInt& group_q() const { return group.get_q(); }
/**
* Get the generator g of the underlying DL group.
* @return generator g
*/
const BigInt& group_g() const { return group.get_g(); }
/**
* Get the underlying groups encoding format.
* @return encoding format
*/
virtual DL_Group::Format group_format() const = 0;
DL_Scheme_PublicKey(const AlgorithmIdentifier& alg_id,
const MemoryRegion<byte>& key_bits,
DL_Group::Format group_format);
protected:
DL_Scheme_PublicKey() {}
/**
* The DL public key
*/
BigInt y;
/**
* The DL group
*/
DL_Group group;
};
/**
* This class represents discrete logarithm (DL) private keys.
*/
class BOTAN_DLL DL_Scheme_PrivateKey : public virtual DL_Scheme_PublicKey,
public virtual Private_Key
{
public:
bool check_key(RandomNumberGenerator& rng, bool) const;
/**
* Get the secret key x.
* @return secret key
*/
const BigInt& get_x() const { return x; }
MemoryVector<byte> pkcs8_private_key() const;
DL_Scheme_PrivateKey(const AlgorithmIdentifier& alg_id,
const MemoryRegion<byte>& key_bits,
DL_Group::Format group_format);
protected:
DL_Scheme_PrivateKey() {}
/**
* The DL private key
*/
BigInt x;
};
}
namespace Botan {
/**
* Modular Reducer (using Barrett's technique)
*/
class BOTAN_DLL Modular_Reducer
{
public:
const BigInt& get_modulus() const { return modulus; }
BigInt reduce(const BigInt& x) const;
/**
* Multiply mod p
* @param x
* @param y
* @return (x * y) % p
*/
BigInt multiply(const BigInt& x, const BigInt& y) const
{ return reduce(x * y); }
/**
* Square mod p
* @param x
* @return (x * x) % p
*/
BigInt square(const BigInt& x) const
{ return reduce(Botan::square(x)); }
/**
* Cube mod p
* @param x
* @return (x * x * x) % p
*/
BigInt cube(const BigInt& x) const
{ return multiply(x, this->square(x)); }
bool initialized() const { return (mod_words != 0); }
Modular_Reducer() { mod_words = 0; }
Modular_Reducer(const BigInt& mod);
private:
BigInt modulus, modulus_2, mu;
size_t mod_words;
};
}
namespace Botan {
/**
* Blinding Function Object
*/
class BOTAN_DLL Blinder
{
public:
BigInt blind(const BigInt& x) const;
BigInt unblind(const BigInt& x) const;
bool initialized() const { return reducer.initialized(); }
Blinder() {}
/**
* Construct a blinder
* @param mask the forward (blinding) mask
* @param inverse_mask the inverse of mask (depends on algo)
* @param modulus of the group operations are performed in
*/
Blinder(const BigInt& mask,
const BigInt& inverse_mask,
const BigInt& modulus);
private:
Modular_Reducer reducer;
mutable BigInt e, d;
};
}
namespace Botan {
/**
* This class represents Diffie-Hellman public keys.
*/
class BOTAN_DLL DH_PublicKey : public virtual DL_Scheme_PublicKey
{
public:
std::string algo_name() const { return "DH"; }
MemoryVector<byte> public_value() const;
size_t max_input_bits() const { return group_p().bits(); }
DL_Group::Format group_format() const { return DL_Group::ANSI_X9_42; }
DH_PublicKey(const AlgorithmIdentifier& alg_id,
const MemoryRegion<byte>& key_bits) :
DL_Scheme_PublicKey(alg_id, key_bits, DL_Group::ANSI_X9_42) {}
/**
* Construct a public key with the specified parameters.
* @param grp the DL group to use in the key
* @param y the public value y
*/
DH_PublicKey(const DL_Group& grp, const BigInt& y);
protected:
DH_PublicKey() {}
};
/**
* This class represents Diffie-Hellman private keys.
*/
class BOTAN_DLL DH_PrivateKey : public DH_PublicKey,
public PK_Key_Agreement_Key,
public virtual DL_Scheme_PrivateKey
{
public:
MemoryVector<byte> public_value() const;
/**
* Load a DH private key
* @param alg_id the algorithm id
* @param key_bits the subject public key
* @param rng a random number generator
*/
DH_PrivateKey(const AlgorithmIdentifier& alg_id,
const MemoryRegion<byte>& key_bits,
RandomNumberGenerator& rng);
/**
* Construct a private key with predetermined value.
* @param rng random number generator to use
* @param grp the group to be used in the key
* @param x the key's secret value (or if zero, generate a new key)
*/
DH_PrivateKey(RandomNumberGenerator& rng, const DL_Group& grp,
const BigInt& x = 0);
};
/**
* DH operation
*/
class BOTAN_DLL DH_KA_Operation : public PK_Ops::Key_Agreement
{
public:
DH_KA_Operation(const DH_PrivateKey& key);
SecureVector<byte> agree(const byte w[], size_t w_len);
private:
const BigInt& p;
Fixed_Exponent_Power_Mod powermod_x_p;
Blinder blinder;
};
}
namespace Botan {
/**
* CAST-256
*/
class BOTAN_DLL CAST_256 : public Block_Cipher_Fixed_Params<16, 4, 32, 4>
{
public:
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
void clear() { zeroise(MK); zeroise(RK); }
std::string name() const { return "CAST-256"; }
BlockCipher* clone() const { return new CAST_256; }
CAST_256() : MK(48), RK(48) {}
private:
void key_schedule(const byte[], size_t);
static const u32bit KEY_MASK[192];
static const byte KEY_ROT[32];
SecureVector<u32bit> MK;
SecureVector<byte> RK;
};
extern const u32bit CAST_SBOX1[256];
extern const u32bit CAST_SBOX2[256];
extern const u32bit CAST_SBOX3[256];
extern const u32bit CAST_SBOX4[256];
}
namespace Botan {
/**
* MD2
*/
class BOTAN_DLL MD2 : public HashFunction
{
public:
std::string name() const { return "MD2"; }
size_t output_length() const { return 16; }
size_t hash_block_size() const { return 16; }
HashFunction* clone() const { return new MD2; }
void clear();
MD2() : X(48), checksum(16), buffer(16)
{ clear(); }
private:
void add_data(const byte[], size_t);
void hash(const byte[]);
void final_result(byte[]);
SecureVector<byte> X, checksum, buffer;
size_t position;
};
}
namespace Botan {
/**
* RC6, Ron Rivest's AES candidate
*/
class BOTAN_DLL RC6 : public Block_Cipher_Fixed_Params<16, 1, 32>
{
public:
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
void clear() { zeroise(S); }
std::string name() const { return "RC6"; }
BlockCipher* clone() const { return new RC6; }
RC6() : S(44) {}
private:
void key_schedule(const byte[], size_t);
SecureVector<u32bit> S;
};
}
namespace Botan {
/**
* WiderWake4+1-BE
*
* Note: quite old and possibly not safe; use XSalsa20 or a block
* cipher in counter mode.
*/
class BOTAN_DLL WiderWake_41_BE : public StreamCipher
{
public:
void cipher(const byte[], byte[], size_t);
void set_iv(const byte[], size_t);
bool valid_iv_length(size_t iv_len) const
{ return (iv_len == 8); }
Key_Length_Specification key_spec() const
{
return Key_Length_Specification(16);
}
void clear();
std::string name() const { return "WiderWake4+1-BE"; }
StreamCipher* clone() const { return new WiderWake_41_BE; }
WiderWake_41_BE() : T(256), state(5), t_key(4),
buffer(DEFAULT_BUFFERSIZE), position(0)
{}
private:
void key_schedule(const byte[], size_t);
void generate(size_t);
SecureVector<u32bit> T;
SecureVector<u32bit> state;
SecureVector<u32bit> t_key;
SecureVector<byte> buffer;
size_t position;
};
}
namespace Botan {
/**
* ElGamal Public Key
*/
class BOTAN_DLL ElGamal_PublicKey : public virtual DL_Scheme_PublicKey
{
public:
std::string algo_name() const { return "ElGamal"; }
DL_Group::Format group_format() const { return DL_Group::ANSI_X9_42; }
size_t max_input_bits() const { return (group_p().bits() - 1); }
ElGamal_PublicKey(const AlgorithmIdentifier& alg_id,
const MemoryRegion<byte>& key_bits) :
DL_Scheme_PublicKey(alg_id, key_bits, DL_Group::ANSI_X9_42)
{}
ElGamal_PublicKey(const DL_Group& group, const BigInt& y);
protected:
ElGamal_PublicKey() {}
};
/**
* ElGamal Private Key
*/
class BOTAN_DLL ElGamal_PrivateKey : public ElGamal_PublicKey,
public virtual DL_Scheme_PrivateKey
{
public:
bool check_key(RandomNumberGenerator& rng, bool) const;
ElGamal_PrivateKey(const AlgorithmIdentifier& alg_id,
const MemoryRegion<byte>& key_bits,
RandomNumberGenerator& rng);
ElGamal_PrivateKey(RandomNumberGenerator& rng,
const DL_Group& group,
const BigInt& priv_key = 0);
};
/**
* ElGamal encryption operation
*/
class BOTAN_DLL ElGamal_Encryption_Operation : public PK_Ops::Encryption
{
public:
size_t max_input_bits() const { return mod_p.get_modulus().bits() - 1; }
ElGamal_Encryption_Operation(const ElGamal_PublicKey& key);
SecureVector<byte> encrypt(const byte msg[], size_t msg_len,
RandomNumberGenerator& rng);
private:
Fixed_Base_Power_Mod powermod_g_p, powermod_y_p;
Modular_Reducer mod_p;
};
/**
* ElGamal decryption operation
*/
class BOTAN_DLL ElGamal_Decryption_Operation : public PK_Ops::Decryption
{
public:
size_t max_input_bits() const { return mod_p.get_modulus().bits() - 1; }
ElGamal_Decryption_Operation(const ElGamal_PrivateKey& key);
SecureVector<byte> decrypt(const byte msg[], size_t msg_len);
private:
Fixed_Exponent_Power_Mod powermod_x_p;
Modular_Reducer mod_p;
Blinder blinder;
};
}
namespace Botan {
/**
HMAC_RNG - based on the design described in "On Extract-then-Expand
Key Derivation Functions and an HMAC-based KDF" by Hugo Krawczyk
(henceforce, 'E-t-E')
However it actually can be parameterized with any two MAC functions,
not restricted to HMAC (this variation is also described in Krawczyk's
paper), for instance one could use HMAC(SHA-512) as the extractor
and CMAC(AES-256) as the PRF.
*/
class BOTAN_DLL HMAC_RNG : public RandomNumberGenerator
{
public:
void randomize(byte buf[], size_t len);
bool is_seeded() const { return seeded; }
void clear();
std::string name() const;
void reseed(size_t poll_bits);
void add_entropy_source(EntropySource* es);
void add_entropy(const byte[], size_t);
/**
* @param extractor a MAC used for extracting the entropy
* @param prf a MAC used as a PRF using HKDF construction
*/
HMAC_RNG(MessageAuthenticationCode* extractor,
MessageAuthenticationCode* prf);
~HMAC_RNG();
private:
MessageAuthenticationCode* extractor;
MessageAuthenticationCode* prf;
std::vector<EntropySource*> entropy_sources;
bool seeded;
SecureVector<byte> K, io_buffer;
size_t user_input_len;
u32bit counter;
};
}
namespace Botan {
/**
* A MAC only used in SSLv3. Do not use elsewhere! Use HMAC instead.
*/
class BOTAN_DLL SSL3_MAC : public MessageAuthenticationCode
{
public:
std::string name() const;
size_t output_length() const { return hash->output_length(); }
MessageAuthenticationCode* clone() const;
void clear();
Key_Length_Specification key_spec() const
{
return Key_Length_Specification(hash->output_length());
}
/**
* @param hash the underlying hash to use
*/
SSL3_MAC(HashFunction* hash);
~SSL3_MAC() { delete hash; }
private:
void add_data(const byte[], size_t);
void final_result(byte[]);
void key_schedule(const byte[], size_t);
HashFunction* hash;
SecureVector<byte> i_key, o_key;
};
}
namespace Botan {
/**
EMSA1_BSI is a variant of EMSA1 specified by the BSI. It accepts only
hash values which are less or equal than the maximum key length. The
implementation comes from InSiTo
*/
class BOTAN_DLL EMSA1_BSI : public EMSA1
{
public:
/**
* @param hash the hash object to use
*/
EMSA1_BSI(HashFunction* hash) : EMSA1(hash) {}
private:
SecureVector<byte> encoding_of(const MemoryRegion<byte>&, size_t,
RandomNumberGenerator& rng);
};
}
namespace Botan {
/**
* Serpent, an AES finalist
*/
class BOTAN_DLL Serpent : public Block_Cipher_Fixed_Params<16, 16, 32, 8>
{
public:
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
void clear() { zeroise(round_key); }
std::string name() const { return "Serpent"; }
BlockCipher* clone() const { return new Serpent; }
Serpent() : round_key(132) {}
protected:
/**
* For use by subclasses using SIMD, asm, etc
* @return const reference to the key schedule
*/
const SecureVector<u32bit>& get_round_keys() const
{ return round_key; }
/**
* For use by subclasses that implement the key schedule
* @param ks is the new key schedule value to set
*/
void set_round_keys(const u32bit ks[132])
{
copy_mem(&round_key[0], ks, 132);
}
private:
void key_schedule(const byte key[], size_t length);
SecureVector<u32bit> round_key;
};
}
namespace Botan {
/**
* NIST's SHA-160
*/
class BOTAN_DLL SHA_160 : public MDx_HashFunction
{
public:
std::string name() const { return "SHA-160"; }
size_t output_length() const { return 20; }
HashFunction* clone() const { return new SHA_160; }
void clear();
SHA_160() : MDx_HashFunction(64, true, true), digest(5), W(80)
{
clear();
}
protected:
/**
* Set a custom size for the W array. Normally 80, but some
* subclasses need slightly more for best performance/internal
* constraints
* @param W_size how big to make W
*/
SHA_160(size_t W_size) :
MDx_HashFunction(64, true, true), digest(5), W(W_size)
{
clear();
}
void compress_n(const byte[], size_t blocks);
void copy_out(byte[]);
/**
* The digest value, exposed for use by subclasses (asm, SSE2)
*/
SecureVector<u32bit> digest;
/**
* The message buffer, exposed for use by subclasses (asm, SSE2)
*/
SecureVector<u32bit> W;
};
}
namespace Botan {
/**
* ANSI X9.31 RNG
*/
class BOTAN_DLL ANSI_X931_RNG : public RandomNumberGenerator
{
public:
void randomize(byte[], size_t);
bool is_seeded() const;
void clear();
std::string name() const;
void reseed(size_t poll_bits);
void add_entropy_source(EntropySource*);
void add_entropy(const byte[], size_t);
/**
* @param cipher the block cipher to use in this PRNG
* @param rng the underlying PRNG for generating inputs
* (eg, an HMAC_RNG)
*/
ANSI_X931_RNG(BlockCipher* cipher,
RandomNumberGenerator* rng);
~ANSI_X931_RNG();
private:
void rekey();
void update_buffer();
BlockCipher* cipher;
RandomNumberGenerator* prng;
SecureVector<byte> V, R;
size_t position;
};
}
namespace Botan {
/**
* This class represents ECDSA Public Keys.
*/
class BOTAN_DLL ECDSA_PublicKey : public virtual EC_PublicKey
{
public:
/**
* Construct a public key from a given public point.
* @param dom_par the domain parameters associated with this key
* @param public_point the public point defining this key
*/
ECDSA_PublicKey(const EC_Group& dom_par,
const PointGFp& public_point) :
EC_PublicKey(dom_par, public_point) {}
ECDSA_PublicKey(const AlgorithmIdentifier& alg_id,
const MemoryRegion<byte>& key_bits) :
EC_PublicKey(alg_id, key_bits) {}
/**
* Get this keys algorithm name.
* @result this keys algorithm name ("ECDSA")
*/
std::string algo_name() const { return "ECDSA"; }
/**
* Get the maximum number of bits allowed to be fed to this key.
* This is the bitlength of the order of the base point.
* @result the maximum number of input bits
*/
size_t max_input_bits() const { return domain().get_order().bits(); }
size_t message_parts() const { return 2; }
size_t message_part_size() const
{ return domain().get_order().bytes(); }
protected:
ECDSA_PublicKey() {}
};
/**
* This class represents ECDSA Private Keys
*/
class BOTAN_DLL ECDSA_PrivateKey : public ECDSA_PublicKey,
public EC_PrivateKey
{
public:
/**
* Load a private key
* @param alg_id the X.509 algorithm identifier
* @param key_bits PKCS #8 structure
*/
ECDSA_PrivateKey(const AlgorithmIdentifier& alg_id,
const MemoryRegion<byte>& key_bits) :
EC_PrivateKey(alg_id, key_bits) {}
/**
* Generate a new private key
* @param rng a random number generator
* @param domain parameters to used for this key
* @param x the private key (if zero, generate a ney random key)
*/
ECDSA_PrivateKey(RandomNumberGenerator& rng,
const EC_Group& domain,
const BigInt& x = 0) :
EC_PrivateKey(rng, domain, x) {}
bool check_key(RandomNumberGenerator& rng, bool) const;
};
/**
* ECDSA signature operation
*/
class BOTAN_DLL ECDSA_Signature_Operation : public PK_Ops::Signature
{
public:
ECDSA_Signature_Operation(const ECDSA_PrivateKey& ecdsa);
SecureVector<byte> sign(const byte msg[], size_t msg_len,
RandomNumberGenerator& rng);
size_t message_parts() const { return 2; }
size_t message_part_size() const { return order.bytes(); }
size_t max_input_bits() const { return order.bits(); }
private:
const PointGFp& base_point;
const BigInt& order;
const BigInt& x;
Modular_Reducer mod_order;
};
/**
* ECDSA verification operation
*/
class BOTAN_DLL ECDSA_Verification_Operation : public PK_Ops::Verification
{
public:
ECDSA_Verification_Operation(const ECDSA_PublicKey& ecdsa);
size_t message_parts() const { return 2; }
size_t message_part_size() const { return order.bytes(); }
size_t max_input_bits() const { return order.bits(); }
bool with_recovery() const { return false; }
bool verify(const byte msg[], size_t msg_len,
const byte sig[], size_t sig_len);
private:
const PointGFp& base_point;
const PointGFp& public_point;
const BigInt& order;
};
}
namespace Botan {
/**
* BigInt Division
* @param x an integer
* @param y a non-zero integer
* @param q will be set to x / y
* @param r will be set to x % y
*/
void BOTAN_DLL divide(const BigInt& x,
const BigInt& y,
BigInt& q,
BigInt& r);
}
namespace Botan {
/**
* Square
*/
class BOTAN_DLL Square : public Block_Cipher_Fixed_Params<16, 16>
{
public:
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
void clear();
std::string name() const { return "Square"; }
BlockCipher* clone() const { return new Square; }
Square() : EK(28), DK(28), ME(32), MD(32) {}
private:
void key_schedule(const byte[], size_t);
static void transform(u32bit[4]);
static const byte SE[256];
static const byte SD[256];
static const byte Log[256];
static const byte ALog[255];
static const u32bit TE0[256];
static const u32bit TE1[256];
static const u32bit TE2[256];
static const u32bit TE3[256];
static const u32bit TD0[256];
static const u32bit TD1[256];
static const u32bit TD2[256];
static const u32bit TD3[256];
SecureVector<u32bit> EK, DK;
SecureVector<byte> ME, MD;
};
}
namespace Botan {
/**
* Perform hex encoding
* @param output an array of at least input_length*2 bytes
* @param input is some binary data
* @param input_length length of input in bytes
* @param uppercase should output be upper or lower case?
*/
void BOTAN_DLL hex_encode(char output[],
const byte input[],
size_t input_length,
bool uppercase = true);
/**
* Perform hex encoding
* @param input some input
* @param input_length length of input in bytes
* @param uppercase should output be upper or lower case?
* @return hexadecimal representation of input
*/
std::string BOTAN_DLL hex_encode(const byte input[],
size_t input_length,
bool uppercase = true);
/**
* Perform hex encoding
* @param input some input
* @param uppercase should output be upper or lower case?
* @return hexadecimal representation of input
*/
std::string BOTAN_DLL hex_encode(const MemoryRegion<byte>& input,
bool uppercase = true);
/**
* Perform hex decoding
* @param output an array of at least input_length/2 bytes
* @param input some hex input
* @param input_length length of input in bytes
* @param input_consumed is an output parameter which says how many
* bytes of input were actually consumed. If less than
* input_length, then the range input[consumed:length]
* should be passed in later along with more input.
* @param ignore_ws ignore whitespace on input; if false, throw an
exception if whitespace is encountered
* @return number of bytes written to output
*/
size_t BOTAN_DLL hex_decode(byte output[],
const char input[],
size_t input_length,
size_t& input_consumed,
bool ignore_ws = true);
/**
* Perform hex decoding
* @param output an array of at least input_length/2 bytes
* @param input some hex input
* @param input_length length of input in bytes
* @param ignore_ws ignore whitespace on input; if false, throw an
exception if whitespace is encountered
* @return number of bytes written to output
*/
size_t BOTAN_DLL hex_decode(byte output[],
const char input[],
size_t input_length,
bool ignore_ws = true);
/**
* Perform hex decoding
* @param output an array of at least input_length/2 bytes
* @param input some hex input
* @param ignore_ws ignore whitespace on input; if false, throw an
exception if whitespace is encountered
* @return number of bytes written to output
*/
size_t BOTAN_DLL hex_decode(byte output[],
const std::string& input,
bool ignore_ws = true);
/**
* Perform hex decoding
* @param input some hex input
* @param input_length the length of input in bytes
* @param ignore_ws ignore whitespace on input; if false, throw an
exception if whitespace is encountered
* @return decoded hex output
*/
SecureVector<byte> BOTAN_DLL hex_decode(const char input[],
size_t input_length,
bool ignore_ws = true);
/**
* Perform hex decoding
* @param input some hex input
* @param ignore_ws ignore whitespace on input; if false, throw an
exception if whitespace is encountered
* @return decoded hex output
*/
SecureVector<byte> BOTAN_DLL hex_decode(const std::string& input,
bool ignore_ws = true);
}
namespace Botan {
/**
* Block Cipher Cascade
*/
class BOTAN_DLL Cascade_Cipher : public BlockCipher
{
public:
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
size_t block_size() const { return block; }
Key_Length_Specification key_spec() const
{
return Key_Length_Specification(cipher1->maximum_keylength() +
cipher2->maximum_keylength());
}
void clear();
std::string name() const;
BlockCipher* clone() const;
/**
* Create a cascade of two block ciphers
* @param cipher1 the first cipher
* @param cipher2 the second cipher
*/
Cascade_Cipher(BlockCipher* cipher1, BlockCipher* cipher2);
~Cascade_Cipher();
private:
void key_schedule(const byte[], size_t);
size_t block;
BlockCipher* cipher1;
BlockCipher* cipher2;
};
}
namespace Botan {
/**
* EME from PKCS #1 v1.5
*/
class BOTAN_DLL EME_PKCS1v15 : public EME
{
public:
size_t maximum_input_size(size_t) const;
private:
SecureVector<byte> pad(const byte[], size_t, size_t,
RandomNumberGenerator&) const;
SecureVector<byte> unpad(const byte[], size_t, size_t) const;
};
}
namespace Botan {
/**
* Bit rotation left
* @param input the input word
* @param rot the number of bits to rotate
* @return input rotated left by rot bits
*/
template<typename T> inline T rotate_left(T input, size_t rot)
{
return static_cast<T>((input << rot) | (input >> (8*sizeof(T)-rot)));;
}
/**
* Bit rotation right
* @param input the input word
* @param rot the number of bits to rotate
* @return input rotated right by rot bits
*/
template<typename T> inline T rotate_right(T input, size_t rot)
{
return static_cast<T>((input >> rot) | (input << (8*sizeof(T)-rot)));
}
}
#if defined(BOTAN_TARGET_CPU_HAS_SSE2) && !defined(BOTAN_NO_SSE_INTRINSICS)
#include <emmintrin.h>
#endif
namespace Botan {
/**
* Swap a 16 bit integer
*/
inline u16bit reverse_bytes(u16bit val)
{
return rotate_left(val, 8);
}
/**
* Swap a 32 bit integer
*/
inline u32bit reverse_bytes(u32bit val)
{
#if BOTAN_GCC_VERSION >= 430 && !defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY)
/*
GCC intrinsic added in 4.3, works for a number of CPUs
However avoid under ARM, as it branches to a function in libgcc
instead of generating inline asm, so slower even than the generic
rotate version below.
*/
return __builtin_bswap32(val);
#elif BOTAN_USE_GCC_INLINE_ASM && defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
// GCC-style inline assembly for x86 or x86-64
asm("bswapl %0" : "=r" (val) : "0" (val));
return val;
#elif BOTAN_USE_GCC_INLINE_ASM && defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY)
asm ("eor r3, %1, %1, ror #16\n\t"
"bic r3, r3, #0x00FF0000\n\t"
"mov %0, %1, ror #8\n\t"
"eor %0, %0, r3, lsr #8"
: "=r" (val)
: "0" (val)
: "r3", "cc");
return val;
#else
// Generic implementation
return (rotate_right(val, 8) & 0xFF00FF00) |
(rotate_left (val, 8) & 0x00FF00FF);
#endif
}
/**
* Swap a 64 bit integer
*/
inline u64bit reverse_bytes(u64bit val)
{
#if BOTAN_GCC_VERSION >= 430
// GCC intrinsic added in 4.3, works for a number of CPUs
return __builtin_bswap64(val);
#elif BOTAN_USE_GCC_INLINE_ASM && defined(BOTAN_TARGET_ARCH_IS_X86_64)
// GCC-style inline assembly for x86-64
asm("bswapq %0" : "=r" (val) : "0" (val));
return val;
#else
/* Generic implementation. Defined in terms of 32-bit bswap so any
* optimizations in that version can help here (particularly
* useful for 32-bit x86).
*/
u32bit hi = static_cast<u32bit>(val >> 32);
u32bit lo = static_cast<u32bit>(val);
hi = reverse_bytes(hi);
lo = reverse_bytes(lo);
return (static_cast<u64bit>(lo) << 32) | hi;
#endif
}
/**
* Swap 4 Ts in an array
*/
template<typename T>
inline void bswap_4(T x[4])
{
x[0] = reverse_bytes(x[0]);
x[1] = reverse_bytes(x[1]);
x[2] = reverse_bytes(x[2]);
x[3] = reverse_bytes(x[3]);
}
#if defined(BOTAN_TARGET_CPU_HAS_SSE2) && !defined(BOTAN_NO_SSE_INTRINSICS)
/**
* Swap 4 u32bits in an array using SSE2 shuffle instructions
*/
template<>
inline void bswap_4(u32bit x[4])
{
__m128i T = _mm_loadu_si128(reinterpret_cast<const __m128i*>(x));
T = _mm_shufflehi_epi16(T, _MM_SHUFFLE(2, 3, 0, 1));
T = _mm_shufflelo_epi16(T, _MM_SHUFFLE(2, 3, 0, 1));
T = _mm_or_si128(_mm_srli_epi16(T, 8), _mm_slli_epi16(T, 8));
_mm_storeu_si128(reinterpret_cast<__m128i*>(x), T);
}
#endif
}
namespace Botan {
/**
* MD5
*/
class BOTAN_DLL MD5 : public MDx_HashFunction
{
public:
std::string name() const { return "MD5"; }
size_t output_length() const { return 16; }
HashFunction* clone() const { return new MD5; }
void clear();
MD5() : MDx_HashFunction(64, false, true), M(16), digest(4)
{ clear(); }
protected:
void compress_n(const byte[], size_t blocks);
void copy_out(byte[]);
/**
* The message buffer, exposed for use by subclasses (x86 asm)
*/
SecureVector<u32bit> M;
/**
* The digest value, exposed for use by subclasses (x86 asm)
*/
SecureVector<u32bit> digest;
};
}
namespace Botan {
/**
* Filter mixin that breaks input into blocks, useful for
* cipher modes
*/
class BOTAN_DLL Buffered_Filter
{
public:
/**
* Write bytes into the buffered filter, which will them emit them
* in calls to buffered_block in the subclass
* @param in the input bytes
* @param length of in in bytes
*/
void write(const byte in[], size_t length);
/**
* Finish a message, emitting to buffered_block and buffered_final
* Will throw an exception if less than final_minimum bytes were
* written into the filter.
*/
void end_msg();
/**
* Initialize a Buffered_Filter
* @param block_size the function buffered_block will be called
* with inputs which are a multiple of this size
* @param final_minimum the function buffered_final will be called
* with at least this many bytes.
*/
Buffered_Filter(size_t block_size, size_t final_minimum);
virtual ~Buffered_Filter() {}
protected:
/**
* The block processor, implemented by subclasses
* @param input some input bytes
* @param length the size of input, guaranteed to be a multiple
* of block_size
*/
virtual void buffered_block(const byte input[], size_t length) = 0;
/**
* The final block, implemented by subclasses
* @param input some input bytes
* @param length the size of input, guaranteed to be at least
* final_minimum bytes
*/
virtual void buffered_final(const byte input[], size_t length) = 0;
/**
* @return block size of inputs
*/
size_t buffered_block_size() const { return main_block_mod; }
/**
* @return current position in the buffer
*/
size_t current_position() const { return buffer_pos; }
/**
* Reset the buffer position
*/
void buffer_reset() { buffer_pos = 0; }
private:
size_t main_block_mod, final_minimum;
SecureVector<byte> buffer;
size_t buffer_pos;
};
}
namespace Botan {
/**
* ECB Encryption
*/
class BOTAN_DLL ECB_Encryption : public Keyed_Filter,
private Buffered_Filter
{
public:
std::string name() const;
void set_key(const SymmetricKey& key) { cipher->set_key(key); }
bool valid_keylength(size_t key_len) const
{ return cipher->valid_keylength(key_len); }
ECB_Encryption(BlockCipher* ciph,
BlockCipherModePaddingMethod* pad);
ECB_Encryption(BlockCipher* ciph,
BlockCipherModePaddingMethod* pad,
const SymmetricKey& key);
~ECB_Encryption();
private:
void buffered_block(const byte input[], size_t input_length);
void buffered_final(const byte input[], size_t input_length);
void write(const byte input[], size_t input_length);
void end_msg();
BlockCipher* cipher;
BlockCipherModePaddingMethod* padder;
SecureVector<byte> temp;
};
/**
* ECB Decryption
*/
class BOTAN_DLL ECB_Decryption : public Keyed_Filter,
public Buffered_Filter
{
public:
std::string name() const;
void set_key(const SymmetricKey& key) { cipher->set_key(key); }
bool valid_keylength(size_t key_len) const
{ return cipher->valid_keylength(key_len); }
ECB_Decryption(BlockCipher* ciph,
BlockCipherModePaddingMethod* pad);
ECB_Decryption(BlockCipher* ciph,
BlockCipherModePaddingMethod* pad,
const SymmetricKey& key);
~ECB_Decryption();
private:
void buffered_block(const byte input[], size_t input_length);
void buffered_final(const byte input[], size_t input_length);
void write(const byte input[], size_t input_length);
void end_msg();
BlockCipher* cipher;
BlockCipherModePaddingMethod* padder;
SecureVector<byte> temp;
};
}
namespace Botan {
/**
* The different charsets (nominally) supported by Botan.
*/
enum Character_Set {
LOCAL_CHARSET,
UCS2_CHARSET,
UTF8_CHARSET,
LATIN1_CHARSET
};
namespace Charset {
/*
* Character Set Handling
*/
std::string BOTAN_DLL transcode(const std::string& str,
Character_Set to,
Character_Set from);
bool BOTAN_DLL is_digit(char c);
bool BOTAN_DLL is_space(char c);
bool BOTAN_DLL caseless_cmp(char x, char y);
byte BOTAN_DLL char2digit(char c);
char BOTAN_DLL digit2char(byte b);
}
}
namespace Botan {
/**
* This class represents public keys
* of integer factorization based (IF) public key schemes.
*/
class BOTAN_DLL IF_Scheme_PublicKey : public virtual Public_Key
{
public:
IF_Scheme_PublicKey(const AlgorithmIdentifier& alg_id,
const MemoryRegion<byte>& key_bits);
IF_Scheme_PublicKey(const BigInt& n, const BigInt& e) :
n(n), e(e) {}
bool check_key(RandomNumberGenerator& rng, bool) const;
AlgorithmIdentifier algorithm_identifier() const;
MemoryVector<byte> x509_subject_public_key() const;
/**
* @return public modulus
*/
const BigInt& get_n() const { return n; }
/**
* @return public exponent
*/
const BigInt& get_e() const { return e; }
size_t max_input_bits() const { return (n.bits() - 1); }
protected:
IF_Scheme_PublicKey() {}
BigInt n, e;
};
/**
* This class represents public keys
* of integer factorization based (IF) public key schemes.
*/
class BOTAN_DLL IF_Scheme_PrivateKey : public virtual IF_Scheme_PublicKey,
public virtual Private_Key
{
public:
IF_Scheme_PrivateKey(RandomNumberGenerator& rng,
const BigInt& prime1, const BigInt& prime2,
const BigInt& exp, const BigInt& d_exp,
const BigInt& mod);
IF_Scheme_PrivateKey(RandomNumberGenerator& rng,
const AlgorithmIdentifier& alg_id,
const MemoryRegion<byte>& key_bits);
bool check_key(RandomNumberGenerator& rng, bool) const;
/**
* Get the first prime p.
* @return prime p
*/
const BigInt& get_p() const { return p; }
/**
* Get the second prime q.
* @return prime q
*/
const BigInt& get_q() const { return q; }
/**
* Get d with exp * d = 1 mod (p - 1, q - 1).
* @return d
*/
const BigInt& get_d() const { return d; }
const BigInt& get_c() const { return c; }
const BigInt& get_d1() const { return d1; }
const BigInt& get_d2() const { return d2; }
MemoryVector<byte> pkcs8_private_key() const;
protected:
IF_Scheme_PrivateKey() {}
BigInt d, p, q, d1, d2, c;
};
}
namespace Botan {
/**
* RSA Public Key
*/
class BOTAN_DLL RSA_PublicKey : public virtual IF_Scheme_PublicKey
{
public:
std::string algo_name() const { return "RSA"; }
RSA_PublicKey(const AlgorithmIdentifier& alg_id,
const MemoryRegion<byte>& key_bits) :
IF_Scheme_PublicKey(alg_id, key_bits)
{}
/**
* Create a RSA_PublicKey
* @arg n the modulus
* @arg e the exponent
*/
RSA_PublicKey(const BigInt& n, const BigInt& e) :
IF_Scheme_PublicKey(n, e)
{}
protected:
RSA_PublicKey() {}
};
/**
* RSA Private Key
*/
class BOTAN_DLL RSA_PrivateKey : public RSA_PublicKey,
public IF_Scheme_PrivateKey
{
public:
bool check_key(RandomNumberGenerator& rng, bool) const;
RSA_PrivateKey(const AlgorithmIdentifier& alg_id,
const MemoryRegion<byte>& key_bits,
RandomNumberGenerator& rng) :
IF_Scheme_PrivateKey(rng, alg_id, key_bits) {}
/**
* Construct a private key from the specified parameters.
* @param rng a random number generator
* @param p the first prime
* @param q the second prime
* @param e the exponent
* @param d if specified, this has to be d with
* exp * d = 1 mod (p - 1, q - 1). Leave it as 0 if you wish to
* the constructor to calculate it.
* @param n if specified, this must be n = p * q. Leave it as 0
* if you wish to the constructor to calculate it.
*/
RSA_PrivateKey(RandomNumberGenerator& rng,
const BigInt& p, const BigInt& q,
const BigInt& e, const BigInt& d = 0,
const BigInt& n = 0) :
IF_Scheme_PrivateKey(rng, p, q, e, d, n) {}
/**
* Create a new private key with the specified bit length
* @param rng the random number generator to use
* @param bits the desired bit length of the private key
* @param exp the public exponent to be used
*/
RSA_PrivateKey(RandomNumberGenerator& rng,
size_t bits, size_t exp = 65537);
};
/**
* RSA private (decrypt/sign) operation
*/
class BOTAN_DLL RSA_Private_Operation : public PK_Ops::Signature,
public PK_Ops::Decryption
{
public:
RSA_Private_Operation(const RSA_PrivateKey& rsa);
size_t max_input_bits() const { return (n.bits() - 1); }
SecureVector<byte> sign(const byte msg[], size_t msg_len,
RandomNumberGenerator& rng);
SecureVector<byte> decrypt(const byte msg[], size_t msg_len);
private:
BigInt private_op(const BigInt& m) const;
const BigInt& n;
const BigInt& q;
const BigInt& c;
Fixed_Exponent_Power_Mod powermod_e_n, powermod_d1_p, powermod_d2_q;
Modular_Reducer mod_p;
Blinder blinder;
};
/**
* RSA public (encrypt/verify) operation
*/
class BOTAN_DLL RSA_Public_Operation : public PK_Ops::Verification,
public PK_Ops::Encryption
{
public:
RSA_Public_Operation(const RSA_PublicKey& rsa) :
n(rsa.get_n()), powermod_e_n(rsa.get_e(), rsa.get_n())
{}
size_t max_input_bits() const { return (n.bits() - 1); }
bool with_recovery() const { return true; }
SecureVector<byte> encrypt(const byte msg[], size_t msg_len,
RandomNumberGenerator&)
{
BigInt m(msg, msg_len);
return BigInt::encode_1363(public_op(m), n.bytes());
}
SecureVector<byte> verify_mr(const byte msg[], size_t msg_len)
{
BigInt m(msg, msg_len);
return BigInt::encode(public_op(m));
}
private:
BigInt public_op(const BigInt& m) const
{
if(m >= n)
throw Invalid_Argument("RSA public op - input is too large");
return powermod_e_n(m);
}
const BigInt& n;
Fixed_Exponent_Power_Mod powermod_e_n;
};
}
namespace Botan {
/**
* RIPEMD-160
*/
class BOTAN_DLL RIPEMD_160 : public MDx_HashFunction
{
public:
std::string name() const { return "RIPEMD-160"; }
size_t output_length() const { return 20; }
HashFunction* clone() const { return new RIPEMD_160; }
void clear();
RIPEMD_160() : MDx_HashFunction(64, false, true), M(16), digest(5)
{ clear(); }
private:
void compress_n(const byte[], size_t blocks);
void copy_out(byte[]);
SecureVector<u32bit> M, digest;
};
}
namespace Botan {
/**
* Whirlpool
*/
class BOTAN_DLL Whirlpool : public MDx_HashFunction
{
public:
std::string name() const { return "Whirlpool"; }
size_t output_length() const { return 64; }
HashFunction* clone() const { return new Whirlpool; }
void clear();
Whirlpool() : MDx_HashFunction(64, true, true, 32), M(8), digest(8)
{ clear(); }
private:
void compress_n(const byte[], size_t blocks);
void copy_out(byte[]);
static const u64bit C0[256];
static const u64bit C1[256];
static const u64bit C2[256];
static const u64bit C3[256];
static const u64bit C4[256];
static const u64bit C5[256];
static const u64bit C6[256];
static const u64bit C7[256];
SecureVector<u64bit> M, digest;
};
}
namespace Botan {
/**
* Tiger
*/
class BOTAN_DLL Tiger : public MDx_HashFunction
{
public:
std::string name() const;
size_t output_length() const { return hash_len; }
HashFunction* clone() const
{
return new Tiger(output_length(), passes);
}
void clear();
/**
* @param out_size specifies the output length; can be 16, 20, or 24
* @param passes to make in the algorithm
*/
Tiger(size_t out_size = 24, size_t passes = 3);
private:
void compress_n(const byte[], size_t block);
void copy_out(byte[]);
static void pass(u64bit& A, u64bit& B, u64bit& C,
const MemoryRegion<u64bit>& M,
byte mul);
static const u64bit SBOX1[256];
static const u64bit SBOX2[256];
static const u64bit SBOX3[256];
static const u64bit SBOX4[256];
SecureVector<u64bit> X, digest;
const size_t hash_len, passes;
};
}
namespace Botan {
/**
* SEED, a Korean block cipher
*/
class BOTAN_DLL SEED : public Block_Cipher_Fixed_Params<16, 16>
{
public:
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
void clear() { zeroise(K); }
std::string name() const { return "SEED"; }
BlockCipher* clone() const { return new SEED; }
SEED() : K(32) {}
private:
void key_schedule(const byte[], size_t);
class G_FUNC
{
public:
u32bit operator()(u32bit) const;
private:
static const u32bit S0[256], S1[256], S2[256], S3[256];
};
SecureVector<u32bit> K;
};
}
namespace Botan {
/**
* EMSA3 from IEEE 1363
* aka PKCS #1 v1.5 signature padding
* aka PKCS #1 block type 1
*/
class BOTAN_DLL EMSA3 : public EMSA
{
public:
/**
* @param hash the hash object to use
*/
EMSA3(HashFunction* hash);
~EMSA3();
void update(const byte[], size_t);
SecureVector<byte> raw_data();
SecureVector<byte> encoding_of(const MemoryRegion<byte>&, size_t,
RandomNumberGenerator& rng);
bool verify(const MemoryRegion<byte>&, const MemoryRegion<byte>&,
size_t);
private:
HashFunction* hash;
SecureVector<byte> hash_id;
};
/**
* EMSA3_Raw which is EMSA3 without a hash or digest id (which
* according to QCA docs is "identical to PKCS#11's CKM_RSA_PKCS
* mechanism", something I have not confirmed)
*/
class BOTAN_DLL EMSA3_Raw : public EMSA
{
public:
void update(const byte[], size_t);
SecureVector<byte> raw_data();
SecureVector<byte> encoding_of(const MemoryRegion<byte>&, size_t,
RandomNumberGenerator& rng);
bool verify(const MemoryRegion<byte>&, const MemoryRegion<byte>&,
size_t);
private:
SecureVector<byte> message;
};
}
namespace Botan {
/**
* Twofish, an AES finalist
*/
class BOTAN_DLL Twofish : public Block_Cipher_Fixed_Params<16, 16, 32, 8>
{
public:
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
void clear();
std::string name() const { return "Twofish"; }
BlockCipher* clone() const { return new Twofish; }
Twofish() : SB(1024), RK(40) {}
private:
void key_schedule(const byte[], size_t);
static void rs_mul(byte[4], byte, size_t);
static const u32bit MDS0[256];
static const u32bit MDS1[256];
static const u32bit MDS2[256];
static const u32bit MDS3[256];
static const byte Q0[256];
static const byte Q1[256];
static const byte RS[32];
static const byte EXP_TO_POLY[255];
static const byte POLY_TO_EXP[255];
SecureVector<u32bit> SB, RK;
};
}
namespace Botan {
/**
* Create a password hash using PBKDF2
* @param password the password
* @param rng a random number generator
* @param work_factor how much work to do to slow down guessing attacks
* @param alg_id specifies which PRF to use with PBKDF2
* 0 is HMAC(SHA-1)
* 1 is HMAC(SHA-256)
* 2 is CMAC(Blowfish)
* all other values are currently undefined
*/
std::string BOTAN_DLL generate_passhash9(const std::string& password,
RandomNumberGenerator& rng,
u16bit work_factor = 10,
byte alg_id = 0);
/**
* Check a previously created password hash
* @param password the password to check against
* @param hash the stored hash to check against
*/
bool BOTAN_DLL check_passhash9(const std::string& password,
const std::string& hash);
}
namespace Botan {
/**
* SHA-224
*/
class BOTAN_DLL SHA_224 : public MDx_HashFunction
{
public:
std::string name() const { return "SHA-224"; }
size_t output_length() const { return 28; }
HashFunction* clone() const { return new SHA_224; }
void clear();
SHA_224() : MDx_HashFunction(64, true, true), digest(8)
{ clear(); }
private:
void compress_n(const byte[], size_t blocks);
void copy_out(byte[]);
SecureVector<u32bit> digest;
};
/**
* SHA-256
*/
class BOTAN_DLL SHA_256 : public MDx_HashFunction
{
public:
std::string name() const { return "SHA-256"; }
size_t output_length() const { return 32; }
HashFunction* clone() const { return new SHA_256; }
void clear();
SHA_256() : MDx_HashFunction(64, true, true), digest(8)
{ clear(); }
private:
void compress_n(const byte[], size_t blocks);
void copy_out(byte[]);
SecureVector<u32bit> digest;
};
}
namespace Botan {
/**
* Blue Midnight Wish 512 (Round 2 tweaked version)
*/
class BOTAN_DLL BMW_512 : public MDx_HashFunction
{
public:
std::string name() const { return "BMW512"; }
size_t output_length() const { return 64; }
HashFunction* clone() const { return new BMW_512; }
void clear();
BMW_512() : MDx_HashFunction(128, false, true), H(16), M(16), Q(32)
{ clear(); }
private:
void compress_n(const byte input[], size_t blocks);
void copy_out(byte output[]);
SecureVector<u64bit> H, M, Q;
};
}
namespace Botan {
/**
* @param input the input data
* @param length length of input in bytes
* @param label the human-readable label
* @param headers a set of key/value pairs included in the header
*/
BOTAN_DLL std::string PGP_encode(
const byte input[],
size_t length,
const std::string& label,
const std::map<std::string, std::string>& headers);
/**
* @param input the input data
* @param length length of input in bytes
* @param label the human-readable label
*/
BOTAN_DLL std::string PGP_encode(
const byte input[],
size_t length,
const std::string& label);
/**
* @param source the input source
* @param label is set to the human-readable label
* @param headers is set to any headers
* @return decoded output as raw binary
*/
BOTAN_DLL SecureVector<byte> PGP_decode(
DataSource& source,
std::string& label,
std::map<std::string, std::string>& headers);
/**
* @param source the input source
* @param label is set to the human-readable label
* @return decoded output as raw binary
*/
BOTAN_DLL SecureVector<byte> PGP_decode(
DataSource& source,
std::string& label);
}
namespace Botan {
/**
* Certificate Store Interface
*/
class BOTAN_DLL Certificate_Store
{
public:
virtual ~Certificate_Store() {}
virtual Certificate_Store* clone() const = 0;
/**
* Add a certificate; this may fail if the store is write-only
*/
virtual void add_certificate(const X509_Certificate& cert) = 0;
/**
* Add a CRL; this may fail if the store is write-only
*/
virtual void add_crl(const X509_CRL& crl) = 0;
/**
* Subject DN and (optionally) key identifier
*/
virtual std::vector<X509_Certificate>
find_cert_by_subject_and_key_id(
const X509_DN& subject_dn,
const MemoryRegion<byte>& key_id) const = 0;
/**
* Find CRLs by the DN and key id of the issuer
*/
virtual std::vector<X509_CRL>
find_crl_by_subject_and_key_id(
const X509_DN& issuer_dn,
const MemoryRegion<byte>& key_id) const = 0;
};
/**
* In Memory Certificate Store
*/
class BOTAN_DLL Certificate_Store_Memory : public Certificate_Store
{
public:
Certificate_Store* clone() const;
void add_certificate(const X509_Certificate& cert);
void add_crl(const X509_CRL& crl);
std::vector<X509_Certificate> find_cert_by_subject_and_key_id(
const X509_DN& subject_dn,
const MemoryRegion<byte>& key_id) const;
std::vector<X509_CRL> find_crl_by_subject_and_key_id(
const X509_DN& issuer_dn,
const MemoryRegion<byte>& key_id) const;
Certificate_Store_Memory() {}
private:
// TODO: Add indexing on the DN and key id to avoid linear search?
std::vector<X509_Certificate> certs;
std::vector<X509_CRL> crls;
};
// TODO: file-backed store
}
namespace Botan {
/**
* KDF2, from IEEE 1363
*/
class BOTAN_DLL KDF2 : public KDF
{
public:
SecureVector<byte> derive(size_t, const byte[], size_t,
const byte[], size_t) const;
std::string name() const { return "KDF2(" + hash->name() + ")"; }
KDF* clone() const { return new KDF2(hash->clone()); }
KDF2(HashFunction* h) : hash(h) {}
KDF2(const KDF2& other) : KDF(), hash(other.hash->clone()) {}
~KDF2() { delete hash; }
private:
HashFunction* hash;
};
}
namespace Botan {
namespace KeyPair {
/**
* Tests whether the key is consistent for encryption; whether
* encrypting and then decrypting gives to the original plaintext.
* @param rng the rng to use
* @param key the key to test
* @param padding the encryption padding method to use
* @return true if consistent otherwise false
*/
BOTAN_DLL bool
encryption_consistency_check(RandomNumberGenerator& rng,
const Private_Key& key,
const std::string& padding);
/**
* Tests whether the key is consistent for signatures; whether a
* signature can be created and then verified
* @param rng the rng to use
* @param key the key to test
* @param padding the signature padding method to use
* @return true if consistent otherwise false
*/
BOTAN_DLL bool
signature_consistency_check(RandomNumberGenerator& rng,
const Private_Key& key,
const std::string& padding);
}
}
namespace Botan {
/**
* This namespace holds various high-level crypto functions
*/
namespace CryptoBox {
/**
* Encrypt a message using a passphrase
* @param input the input data
* @param input_len the length of input in bytes
* @param passphrase the passphrase used to encrypt the message
* @param rng a ref to a random number generator, such as AutoSeeded_RNG
*/
BOTAN_DLL std::string encrypt(const byte input[], size_t input_len,
const std::string& passphrase,
RandomNumberGenerator& rng);
/**
* Decrypt a message encrypted with CryptoBox::encrypt
* @param input the input data
* @param input_len the length of input in bytes
* @param passphrase the passphrase used to encrypt the message
*/
BOTAN_DLL std::string decrypt(const byte input[], size_t input_len,
const std::string& passphrase);
/**
* Decrypt a message encrypted with CryptoBox::encrypt
* @param input the input data
* @param passphrase the passphrase used to encrypt the message
*/
BOTAN_DLL std::string decrypt(const std::string& input,
const std::string& passphrase);
}
}
namespace Botan {
/**
* X.509 Certificate Validation Result
*/
enum X509_Code {
VERIFIED,
UNKNOWN_X509_ERROR,
CANNOT_ESTABLISH_TRUST,
CERT_CHAIN_TOO_LONG,
SIGNATURE_ERROR,
POLICY_ERROR,
INVALID_USAGE,
CERT_FORMAT_ERROR,
CERT_ISSUER_NOT_FOUND,
CERT_NOT_YET_VALID,
CERT_HAS_EXPIRED,
CERT_IS_REVOKED,
CRL_FORMAT_ERROR,
CRL_ISSUER_NOT_FOUND,
CRL_NOT_YET_VALID,
CRL_HAS_EXPIRED,
CA_CERT_CANNOT_SIGN,
CA_CERT_NOT_FOR_CERT_ISSUER,
CA_CERT_NOT_FOR_CRL_ISSUER
};
/**
* X.509 Certificate Store
*/
class BOTAN_DLL X509_Store
{
public:
enum Cert_Usage {
ANY = 0x00,
TLS_SERVER = 0x01,
TLS_CLIENT = 0x02,
CODE_SIGNING = 0x04,
EMAIL_PROTECTION = 0x08,
TIME_STAMPING = 0x10,
CRL_SIGNING = 0x20
};
X509_Code validate_cert(const X509_Certificate&, Cert_Usage = ANY);
std::vector<X509_Certificate> get_cert_chain(const X509_Certificate&);
std::string PEM_encode() const;
X509_Code add_crl(const X509_CRL&);
void add_cert(const X509_Certificate&, bool = false);
void add_certs(DataSource&);
void add_trusted_certs(DataSource&);
void add_new_certstore(Certificate_Store*);
X509_Store(u32bit time_slack = 24*60*60,
u32bit cache_results = 30*60);
X509_Store(const X509_Store&);
~X509_Store();
private:
X509_Store& operator=(const X509_Store&) { return (*this); }
class BOTAN_DLL CRL_Data
{
public:
X509_DN issuer;
MemoryVector<byte> serial, auth_key_id;
bool operator==(const CRL_Data&) const;
bool operator!=(const CRL_Data&) const;
bool operator<(const CRL_Data&) const;
};
class BOTAN_DLL Cert_Info
{
public:
bool is_verified(u32bit timeout) const;
bool is_trusted() const;
X509_Code verify_result() const;
void set_result(X509_Code) const;
Cert_Info(const X509_Certificate&, bool = false);
X509_Certificate cert;
bool trusted;
private:
mutable bool checked;
mutable X509_Code result;
mutable u64bit last_checked;
};
static X509_Code check_sig(const X509_Object&, Public_Key*);
size_t find_cert(const X509_DN&, const MemoryRegion<byte>&) const;
X509_Code check_sig(const Cert_Info&, const Cert_Info&) const;
void recompute_revoked_info() const;
void do_add_certs(DataSource&, bool);
X509_Code construct_cert_chain(const X509_Certificate&,
std::vector<size_t>&, bool = false);
size_t find_parent_of(const X509_Certificate&);
bool is_revoked(const X509_Certificate&) const;
static const size_t NO_CERT_FOUND = 0xFFFFFFFF;
std::vector<Cert_Info> certs;
std::vector<CRL_Data> revoked;
std::vector<Certificate_Store*> stores;
u32bit time_slack, validation_cache_timeout;
mutable bool revoked_info_valid;
};
}
namespace Botan {
/**
* Noekeon
*/
class BOTAN_DLL Noekeon : public Block_Cipher_Fixed_Params<16, 16>
{
public:
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
void clear();
std::string name() const { return "Noekeon"; }
BlockCipher* clone() const { return new Noekeon; }
Noekeon() : EK(4), DK(4) {}
protected:
/**
* The Noekeon round constants
*/
static const byte RC[17];
/**
* @return const reference to encryption subkeys
*/
const SecureVector<u32bit>& get_EK() const { return EK; }
/**
* @return const reference to decryption subkeys
*/
const SecureVector<u32bit>& get_DK() const { return DK; }
private:
void key_schedule(const byte[], size_t);
SecureVector<u32bit> EK, DK;
};
}
namespace Botan {
/**
* Create a password hash using Bcrypt
* @param password the password
* @param rng a random number generator
* @param work_factor how much work to do to slow down guessing attacks
*
* @see http://www.usenix.org/events/usenix99/provos/provos_html/
*/
std::string BOTAN_DLL generate_bcrypt(const std::string& password,
RandomNumberGenerator& rng,
u16bit work_factor = 10);
/**
* Check a previously created password hash
* @param password the password to check against
* @param hash the stored hash to check against
*/
bool BOTAN_DLL check_bcrypt(const std::string& password,
const std::string& hash);
}
namespace Botan {
/**
* CFB Encryption
*/
class BOTAN_DLL CFB_Encryption : public Keyed_Filter
{
public:
std::string name() const { return cipher->name() + "/CFB"; }
void set_iv(const InitializationVector&);
void set_key(const SymmetricKey& key) { cipher->set_key(key); }
bool valid_keylength(size_t key_len) const
{ return cipher->valid_keylength(key_len); }
bool valid_iv_length(size_t iv_len) const
{ return (iv_len == cipher->block_size()); }
CFB_Encryption(BlockCipher* cipher, size_t feedback = 0);
CFB_Encryption(BlockCipher* cipher,
const SymmetricKey& key,
const InitializationVector& iv,
size_t feedback = 0);
~CFB_Encryption() { delete cipher; }
private:
void write(const byte[], size_t);
BlockCipher* cipher;
SecureVector<byte> buffer, state;
size_t position, feedback;
};
/**
* CFB Decryption
*/
class BOTAN_DLL CFB_Decryption : public Keyed_Filter
{
public:
std::string name() const { return cipher->name() + "/CFB"; }
void set_iv(const InitializationVector&);
void set_key(const SymmetricKey& key) { cipher->set_key(key); }
bool valid_keylength(size_t key_len) const
{ return cipher->valid_keylength(key_len); }
bool valid_iv_length(size_t iv_len) const
{ return (iv_len == cipher->block_size()); }
CFB_Decryption(BlockCipher* cipher, size_t feedback = 0);
CFB_Decryption(BlockCipher* cipher,
const SymmetricKey& key,
const InitializationVector& iv,
size_t feedback = 0);
~CFB_Decryption() { delete cipher; }
private:
void write(const byte[], size_t);
BlockCipher* cipher;
SecureVector<byte> buffer, state;
size_t position, feedback;
};
}
namespace Botan {
/**
* X.509 Certificate Extension
*/
class BOTAN_DLL Certificate_Extension
{
public:
/**
* @return OID representing this extension
*/
OID oid_of() const;
/**
* Make a copy of this extension
* @return copy of this
*/
virtual Certificate_Extension* copy() const = 0;
/*
* Add the contents of this extension into the information
* for the subject and/or issuer, as necessary.
* @param subject the subject info
* @param issuer the issuer info
*/
virtual void contents_to(Data_Store& subject,
Data_Store& issuer) const = 0;
/*
* @return short readable name
*/
virtual std::string config_id() const = 0;
/*
* @return specific OID name
*/
virtual std::string oid_name() const = 0;
virtual ~Certificate_Extension() {}
protected:
friend class Extensions;
virtual bool should_encode() const { return true; }
virtual MemoryVector<byte> encode_inner() const = 0;
virtual void decode_inner(const MemoryRegion<byte>&) = 0;
};
/**
* X.509 Certificate Extension List
*/
class BOTAN_DLL Extensions : public ASN1_Object
{
public:
void encode_into(class DER_Encoder&) const;
void decode_from(class BER_Decoder&);
void contents_to(Data_Store&, Data_Store&) const;
void add(Certificate_Extension* extn, bool critical = false);
Extensions& operator=(const Extensions&);
Extensions(const Extensions&);
Extensions(bool st = true) : should_throw(st) {}
~Extensions();
private:
static Certificate_Extension* get_extension(const OID&);
std::vector<std::pair<Certificate_Extension*, bool> > extensions;
bool should_throw;
};
namespace Cert_Extension {
static const size_t NO_CERT_PATH_LIMIT = 0xFFFFFFF0;
/**
* Basic Constraints Extension
*/
class BOTAN_DLL Basic_Constraints : public Certificate_Extension
{
public:
Basic_Constraints* copy() const
{ return new Basic_Constraints(is_ca, path_limit); }
Basic_Constraints(bool ca = false, size_t limit = 0) :
is_ca(ca), path_limit(limit) {}
bool get_is_ca() const { return is_ca; }
size_t get_path_limit() const;
private:
std::string config_id() const { return "basic_constraints"; }
std::string oid_name() const { return "X509v3.BasicConstraints"; }
MemoryVector<byte> encode_inner() const;
void decode_inner(const MemoryRegion<byte>&);
void contents_to(Data_Store&, Data_Store&) const;
bool is_ca;
size_t path_limit;
};
/**
* Key Usage Constraints Extension
*/
class BOTAN_DLL Key_Usage : public Certificate_Extension
{
public:
Key_Usage* copy() const { return new Key_Usage(constraints); }
Key_Usage(Key_Constraints c = NO_CONSTRAINTS) : constraints(c) {}
Key_Constraints get_constraints() const { return constraints; }
private:
std::string config_id() const { return "key_usage"; }
std::string oid_name() const { return "X509v3.KeyUsage"; }
bool should_encode() const { return (constraints != NO_CONSTRAINTS); }
MemoryVector<byte> encode_inner() const;
void decode_inner(const MemoryRegion<byte>&);
void contents_to(Data_Store&, Data_Store&) const;
Key_Constraints constraints;
};
/**
* Subject Key Identifier Extension
*/
class BOTAN_DLL Subject_Key_ID : public Certificate_Extension
{
public:
Subject_Key_ID* copy() const { return new Subject_Key_ID(key_id); }
Subject_Key_ID() {}
Subject_Key_ID(const MemoryRegion<byte>&);
MemoryVector<byte> get_key_id() const { return key_id; }
private:
std::string config_id() const { return "subject_key_id"; }
std::string oid_name() const { return "X509v3.SubjectKeyIdentifier"; }
bool should_encode() const { return (key_id.size() > 0); }
MemoryVector<byte> encode_inner() const;
void decode_inner(const MemoryRegion<byte>&);
void contents_to(Data_Store&, Data_Store&) const;
MemoryVector<byte> key_id;
};
/**
* Authority Key Identifier Extension
*/
class BOTAN_DLL Authority_Key_ID : public Certificate_Extension
{
public:
Authority_Key_ID* copy() const { return new Authority_Key_ID(key_id); }
Authority_Key_ID() {}
Authority_Key_ID(const MemoryRegion<byte>& k) : key_id(k) {}
MemoryVector<byte> get_key_id() const { return key_id; }
private:
std::string config_id() const { return "authority_key_id"; }
std::string oid_name() const { return "X509v3.AuthorityKeyIdentifier"; }
bool should_encode() const { return (key_id.size() > 0); }
MemoryVector<byte> encode_inner() const;
void decode_inner(const MemoryRegion<byte>&);
void contents_to(Data_Store&, Data_Store&) const;
MemoryVector<byte> key_id;
};
/**
* Alternative Name Extension Base Class
*/
class BOTAN_DLL Alternative_Name : public Certificate_Extension
{
public:
AlternativeName get_alt_name() const { return alt_name; }
protected:
Alternative_Name(const AlternativeName&,
const std::string&, const std::string&);
Alternative_Name(const std::string&, const std::string&);
private:
std::string config_id() const { return config_name_str; }
std::string oid_name() const { return oid_name_str; }
bool should_encode() const { return alt_name.has_items(); }
MemoryVector<byte> encode_inner() const;
void decode_inner(const MemoryRegion<byte>&);
void contents_to(Data_Store&, Data_Store&) const;
std::string config_name_str, oid_name_str;
AlternativeName alt_name;
};
/**
* Subject Alternative Name Extension
*/
class BOTAN_DLL Subject_Alternative_Name : public Alternative_Name
{
public:
Subject_Alternative_Name* copy() const
{ return new Subject_Alternative_Name(get_alt_name()); }
Subject_Alternative_Name(const AlternativeName& = AlternativeName());
};
/**
* Issuer Alternative Name Extension
*/
class BOTAN_DLL Issuer_Alternative_Name : public Alternative_Name
{
public:
Issuer_Alternative_Name* copy() const
{ return new Issuer_Alternative_Name(get_alt_name()); }
Issuer_Alternative_Name(const AlternativeName& = AlternativeName());
};
/**
* Extended Key Usage Extension
*/
class BOTAN_DLL Extended_Key_Usage : public Certificate_Extension
{
public:
Extended_Key_Usage* copy() const { return new Extended_Key_Usage(oids); }
Extended_Key_Usage() {}
Extended_Key_Usage(const std::vector<OID>& o) : oids(o) {}
std::vector<OID> get_oids() const { return oids; }
private:
std::string config_id() const { return "extended_key_usage"; }
std::string oid_name() const { return "X509v3.ExtendedKeyUsage"; }
bool should_encode() const { return (oids.size() > 0); }
MemoryVector<byte> encode_inner() const;
void decode_inner(const MemoryRegion<byte>&);
void contents_to(Data_Store&, Data_Store&) const;
std::vector<OID> oids;
};
/**
* Certificate Policies Extension
*/
class BOTAN_DLL Certificate_Policies : public Certificate_Extension
{
public:
Certificate_Policies* copy() const
{ return new Certificate_Policies(oids); }
Certificate_Policies() {}
Certificate_Policies(const std::vector<OID>& o) : oids(o) {}
std::vector<OID> get_oids() const { return oids; }
private:
std::string config_id() const { return "policy_info"; }
std::string oid_name() const { return "X509v3.CertificatePolicies"; }
bool should_encode() const { return (oids.size() > 0); }
MemoryVector<byte> encode_inner() const;
void decode_inner(const MemoryRegion<byte>&);
void contents_to(Data_Store&, Data_Store&) const;
std::vector<OID> oids;
};
/**
* CRL Number Extension
*/
class BOTAN_DLL CRL_Number : public Certificate_Extension
{
public:
CRL_Number* copy() const;
CRL_Number() : has_value(false), crl_number(0) {}
CRL_Number(size_t n) : has_value(true), crl_number(n) {}
size_t get_crl_number() const;
private:
std::string config_id() const { return "crl_number"; }
std::string oid_name() const { return "X509v3.CRLNumber"; }
bool should_encode() const { return has_value; }
MemoryVector<byte> encode_inner() const;
void decode_inner(const MemoryRegion<byte>&);
void contents_to(Data_Store&, Data_Store&) const;
bool has_value;
size_t crl_number;
};
/**
* CRL Entry Reason Code Extension
*/
class BOTAN_DLL CRL_ReasonCode : public Certificate_Extension
{
public:
CRL_ReasonCode* copy() const { return new CRL_ReasonCode(reason); }
CRL_ReasonCode(CRL_Code r = UNSPECIFIED) : reason(r) {}
CRL_Code get_reason() const { return reason; }
private:
std::string config_id() const { return "crl_reason"; }
std::string oid_name() const { return "X509v3.ReasonCode"; }
bool should_encode() const { return (reason != UNSPECIFIED); }
MemoryVector<byte> encode_inner() const;
void decode_inner(const MemoryRegion<byte>&);
void contents_to(Data_Store&, Data_Store&) const;
CRL_Code reason;
};
}
}
namespace Botan {
/**
* DSA Public Key
*/
class BOTAN_DLL DSA_PublicKey : public virtual DL_Scheme_PublicKey
{
public:
std::string algo_name() const { return "DSA"; }
DL_Group::Format group_format() const { return DL_Group::ANSI_X9_57; }
size_t message_parts() const { return 2; }
size_t message_part_size() const { return group_q().bytes(); }
size_t max_input_bits() const { return group_q().bits(); }
DSA_PublicKey(const AlgorithmIdentifier& alg_id,
const MemoryRegion<byte>& key_bits) :
DL_Scheme_PublicKey(alg_id, key_bits, DL_Group::ANSI_X9_57)
{
}
DSA_PublicKey(const DL_Group& group, const BigInt& y);
protected:
DSA_PublicKey() {}
};
/**
* DSA Private Key
*/
class BOTAN_DLL DSA_PrivateKey : public DSA_PublicKey,
public virtual DL_Scheme_PrivateKey
{
public:
DSA_PrivateKey(const AlgorithmIdentifier& alg_id,
const MemoryRegion<byte>& key_bits,
RandomNumberGenerator& rng);
DSA_PrivateKey(RandomNumberGenerator& rng,
const DL_Group& group,
const BigInt& private_key = 0);
bool check_key(RandomNumberGenerator& rng, bool strong) const;
};
/**
* Object that can create a DSA signature
*/
class BOTAN_DLL DSA_Signature_Operation : public PK_Ops::Signature
{
public:
DSA_Signature_Operation(const DSA_PrivateKey& dsa);
size_t message_parts() const { return 2; }
size_t message_part_size() const { return q.bytes(); }
size_t max_input_bits() const { return q.bits(); }
SecureVector<byte> sign(const byte msg[], size_t msg_len,
RandomNumberGenerator& rng);
private:
const BigInt& q;
const BigInt& x;
Fixed_Base_Power_Mod powermod_g_p;
Modular_Reducer mod_q;
};
/**
* Object that can verify a DSA signature
*/
class BOTAN_DLL DSA_Verification_Operation : public PK_Ops::Verification
{
public:
DSA_Verification_Operation(const DSA_PublicKey& dsa);
size_t message_parts() const { return 2; }
size_t message_part_size() const { return q.bytes(); }
size_t max_input_bits() const { return q.bits(); }
bool with_recovery() const { return false; }
bool verify(const byte msg[], size_t msg_len,
const byte sig[], size_t sig_len);
private:
const BigInt& q;
const BigInt& y;
Fixed_Base_Power_Mod powermod_g_p, powermod_y_p;
Modular_Reducer mod_p, mod_q;
};
}
namespace Botan {
/**
* PRF from ANSI X9.42
*/
class BOTAN_DLL X942_PRF : public KDF
{
public:
SecureVector<byte> derive(size_t, const byte[], size_t,
const byte[], size_t) const;
std::string name() const { return "X942_PRF(" + key_wrap_oid + ")"; }
KDF* clone() const { return new X942_PRF(key_wrap_oid); }
X942_PRF(const std::string& oid);
private:
std::string key_wrap_oid;
};
}
namespace Botan {
/**
* TEA
*/
class BOTAN_DLL TEA : public Block_Cipher_Fixed_Params<8, 16>
{
public:
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
void clear() { zeroise(K); }
std::string name() const { return "TEA"; }
BlockCipher* clone() const { return new TEA; }
TEA() : K(4) {}
private:
void key_schedule(const byte[], size_t);
SecureVector<u32bit> K;
};
}
namespace Botan {
/**
* Nyberg-Rueppel Public Key
*/
class BOTAN_DLL NR_PublicKey : public virtual DL_Scheme_PublicKey
{
public:
std::string algo_name() const { return "NR"; }
DL_Group::Format group_format() const { return DL_Group::ANSI_X9_57; }
size_t message_parts() const { return 2; }
size_t message_part_size() const { return group_q().bytes(); }
size_t max_input_bits() const { return (group_q().bits() - 1); }
NR_PublicKey(const AlgorithmIdentifier& alg_id,
const MemoryRegion<byte>& key_bits);
NR_PublicKey(const DL_Group& group, const BigInt& pub_key);
protected:
NR_PublicKey() {}
};
/**
* Nyberg-Rueppel Private Key
*/
class BOTAN_DLL NR_PrivateKey : public NR_PublicKey,
public virtual DL_Scheme_PrivateKey
{
public:
bool check_key(RandomNumberGenerator& rng, bool strong) const;
NR_PrivateKey(const AlgorithmIdentifier& alg_id,
const MemoryRegion<byte>& key_bits,
RandomNumberGenerator& rng);
NR_PrivateKey(RandomNumberGenerator& rng,
const DL_Group& group,
const BigInt& x = 0);
};
/**
* Nyberg-Rueppel signature operation
*/
class BOTAN_DLL NR_Signature_Operation : public PK_Ops::Signature
{
public:
NR_Signature_Operation(const NR_PrivateKey& nr);
size_t message_parts() const { return 2; }
size_t message_part_size() const { return q.bytes(); }
size_t max_input_bits() const { return (q.bits() - 1); }
SecureVector<byte> sign(const byte msg[], size_t msg_len,
RandomNumberGenerator& rng);
private:
const BigInt& q;
const BigInt& x;
Fixed_Base_Power_Mod powermod_g_p;
Modular_Reducer mod_q;
};
/**
* Nyberg-Rueppel verification operation
*/
class BOTAN_DLL NR_Verification_Operation : public PK_Ops::Verification
{
public:
NR_Verification_Operation(const NR_PublicKey& nr);
size_t message_parts() const { return 2; }
size_t message_part_size() const { return q.bytes(); }
size_t max_input_bits() const { return (q.bits() - 1); }
bool with_recovery() const { return true; }
SecureVector<byte> verify_mr(const byte msg[], size_t msg_len);
private:
const BigInt& q;
const BigInt& y;
Fixed_Base_Power_Mod powermod_g_p, powermod_y_p;
Modular_Reducer mod_p, mod_q;
};
}
namespace Botan {
/**
* Alleged RC4
*/
class BOTAN_DLL ARC4 : public StreamCipher
{
public:
void cipher(const byte in[], byte out[], size_t length);
void clear();
std::string name() const;
StreamCipher* clone() const { return new ARC4(SKIP); }
Key_Length_Specification key_spec() const
{
return Key_Length_Specification(1, 256);
}
/**
* @param skip skip this many initial bytes in the keystream
*/
ARC4(size_t skip = 0);
~ARC4() { clear(); }
private:
void key_schedule(const byte[], size_t);
void generate();
const size_t SKIP;
byte X, Y;
SecureVector<byte> state;
SecureVector<byte> buffer;
size_t position;
};
}
namespace Botan {
/**
* Rabin-Williams Public Key
*/
class BOTAN_DLL RW_PublicKey : public virtual IF_Scheme_PublicKey
{
public:
std::string algo_name() const { return "RW"; }
RW_PublicKey(const AlgorithmIdentifier& alg_id,
const MemoryRegion<byte>& key_bits) :
IF_Scheme_PublicKey(alg_id, key_bits)
{}
RW_PublicKey(const BigInt& mod, const BigInt& exponent) :
IF_Scheme_PublicKey(mod, exponent)
{}
protected:
RW_PublicKey() {}
};
/**
* Rabin-Williams Private Key
*/
class BOTAN_DLL RW_PrivateKey : public RW_PublicKey,
public IF_Scheme_PrivateKey
{
public:
RW_PrivateKey(const AlgorithmIdentifier& alg_id,
const MemoryRegion<byte>& key_bits,
RandomNumberGenerator& rng) :
IF_Scheme_PrivateKey(rng, alg_id, key_bits) {}
RW_PrivateKey(RandomNumberGenerator& rng,
const BigInt& p, const BigInt& q,
const BigInt& e, const BigInt& d = 0,
const BigInt& n = 0) :
IF_Scheme_PrivateKey(rng, p, q, e, d, n) {}
RW_PrivateKey(RandomNumberGenerator& rng, size_t bits, size_t = 2);
bool check_key(RandomNumberGenerator& rng, bool) const;
};
/**
* Rabin-Williams Signature Operation
*/
class BOTAN_DLL RW_Signature_Operation : public PK_Ops::Signature
{
public:
RW_Signature_Operation(const RW_PrivateKey& rw);
size_t max_input_bits() const { return (n.bits() - 1); }
SecureVector<byte> sign(const byte msg[], size_t msg_len,
RandomNumberGenerator& rng);
private:
const BigInt& n;
const BigInt& e;
const BigInt& q;
const BigInt& c;
Fixed_Exponent_Power_Mod powermod_d1_p, powermod_d2_q;
Modular_Reducer mod_p;
Blinder blinder;
};
/**
* Rabin-Williams Verification Operation
*/
class BOTAN_DLL RW_Verification_Operation : public PK_Ops::Verification
{
public:
RW_Verification_Operation(const RW_PublicKey& rw) :
n(rw.get_n()), powermod_e_n(rw.get_e(), rw.get_n())
{}
size_t max_input_bits() const { return (n.bits() - 1); }
bool with_recovery() const { return true; }
SecureVector<byte> verify_mr(const byte msg[], size_t msg_len);
private:
const BigInt& n;
Fixed_Exponent_Power_Mod powermod_e_n;
};
}
#if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
#if defined(BOTAN_TARGET_CPU_IS_BIG_ENDIAN)
#define BOTAN_ENDIAN_N2B(x) (x)
#define BOTAN_ENDIAN_B2N(x) (x)
#define BOTAN_ENDIAN_N2L(x) reverse_bytes(x)
#define BOTAN_ENDIAN_L2N(x) reverse_bytes(x)
#elif defined(BOTAN_TARGET_CPU_IS_LITTLE_ENDIAN)
#define BOTAN_ENDIAN_N2L(x) (x)
#define BOTAN_ENDIAN_L2N(x) (x)
#define BOTAN_ENDIAN_N2B(x) reverse_bytes(x)
#define BOTAN_ENDIAN_B2N(x) reverse_bytes(x)
#endif
#endif
namespace Botan {
/**
* Make a u16bit from two bytes
* @param i0 the first byte
* @param i1 the second byte
* @return i0 || i1
*/
inline u16bit make_u16bit(byte i0, byte i1)
{
return ((static_cast<u16bit>(i0) << 8) | i1);
}
/**
* Make a u32bit from four bytes
* @param i0 the first byte
* @param i1 the second byte
* @param i2 the third byte
* @param i3 the fourth byte
* @return i0 || i1 || i2 || i3
*/
inline u32bit make_u32bit(byte i0, byte i1, byte i2, byte i3)
{
return ((static_cast<u32bit>(i0) << 24) |
(static_cast<u32bit>(i1) << 16) |
(static_cast<u32bit>(i2) << 8) |
(static_cast<u32bit>(i3)));
}
/**
* Make a u32bit from eight bytes
* @param i0 the first byte
* @param i1 the second byte
* @param i2 the third byte
* @param i3 the fourth byte
* @param i4 the fifth byte
* @param i5 the sixth byte
* @param i6 the seventh byte
* @param i7 the eighth byte
* @return i0 || i1 || i2 || i3 || i4 || i5 || i6 || i7
*/
inline u64bit make_u64bit(byte i0, byte i1, byte i2, byte i3,
byte i4, byte i5, byte i6, byte i7)
{
return ((static_cast<u64bit>(i0) << 56) |
(static_cast<u64bit>(i1) << 48) |
(static_cast<u64bit>(i2) << 40) |
(static_cast<u64bit>(i3) << 32) |
(static_cast<u64bit>(i4) << 24) |
(static_cast<u64bit>(i5) << 16) |
(static_cast<u64bit>(i6) << 8) |
(static_cast<u64bit>(i7)));
}
/**
* Load a big-endian word
* @param in a pointer to some bytes
* @param off an offset into the array
* @return off'th T of in, as a big-endian value
*/
template<typename T>
inline T load_be(const byte in[], size_t off)
{
in += off * sizeof(T);
T out = 0;
for(size_t i = 0; i != sizeof(T); ++i)
out = (out << 8) | in[i];
return out;
}
/**
* Load a little-endian word
* @param in a pointer to some bytes
* @param off an offset into the array
* @return off'th T of in, as a litte-endian value
*/
template<typename T>
inline T load_le(const byte in[], size_t off)
{
in += off * sizeof(T);
T out = 0;
for(size_t i = 0; i != sizeof(T); ++i)
out = (out << 8) | in[sizeof(T)-1-i];
return out;
}
/**
* Load a big-endian u16bit
* @param in a pointer to some bytes
* @param off an offset into the array
* @return off'th u16bit of in, as a big-endian value
*/
template<>
inline u16bit load_be<u16bit>(const byte in[], size_t off)
{
#if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
return BOTAN_ENDIAN_N2B(*(reinterpret_cast<const u16bit*>(in) + off));
#else
in += off * sizeof(u16bit);
return make_u16bit(in[0], in[1]);
#endif
}
/**
* Load a little-endian u16bit
* @param in a pointer to some bytes
* @param off an offset into the array
* @return off'th u16bit of in, as a little-endian value
*/
template<>
inline u16bit load_le<u16bit>(const byte in[], size_t off)
{
#if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
return BOTAN_ENDIAN_N2L(*(reinterpret_cast<const u16bit*>(in) + off));
#else
in += off * sizeof(u16bit);
return make_u16bit(in[1], in[0]);
#endif
}
/**
* Load a big-endian u32bit
* @param in a pointer to some bytes
* @param off an offset into the array
* @return off'th u32bit of in, as a big-endian value
*/
template<>
inline u32bit load_be<u32bit>(const byte in[], size_t off)
{
#if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
return BOTAN_ENDIAN_N2B(*(reinterpret_cast<const u32bit*>(in) + off));
#else
in += off * sizeof(u32bit);
return make_u32bit(in[0], in[1], in[2], in[3]);
#endif
}
/**
* Load a little-endian u32bit
* @param in a pointer to some bytes
* @param off an offset into the array
* @return off'th u32bit of in, as a little-endian value
*/
template<>
inline u32bit load_le<u32bit>(const byte in[], size_t off)
{
#if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
return BOTAN_ENDIAN_N2L(*(reinterpret_cast<const u32bit*>(in) + off));
#else
in += off * sizeof(u32bit);
return make_u32bit(in[3], in[2], in[1], in[0]);
#endif
}
/**
* Load a big-endian u64bit
* @param in a pointer to some bytes
* @param off an offset into the array
* @return off'th u64bit of in, as a big-endian value
*/
template<>
inline u64bit load_be<u64bit>(const byte in[], size_t off)
{
#if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
return BOTAN_ENDIAN_N2B(*(reinterpret_cast<const u64bit*>(in) + off));
#else
in += off * sizeof(u64bit);
return make_u64bit(in[0], in[1], in[2], in[3],
in[4], in[5], in[6], in[7]);
#endif
}
/**
* Load a little-endian u64bit
* @param in a pointer to some bytes
* @param off an offset into the array
* @return off'th u64bit of in, as a little-endian value
*/
template<>
inline u64bit load_le<u64bit>(const byte in[], size_t off)
{
#if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
return BOTAN_ENDIAN_N2L(*(reinterpret_cast<const u64bit*>(in) + off));
#else
in += off * sizeof(u64bit);
return make_u64bit(in[7], in[6], in[5], in[4],
in[3], in[2], in[1], in[0]);
#endif
}
/**
* Load two little-endian words
* @param in a pointer to some bytes
* @param x0 where the first word will be written
* @param x1 where the second word will be written
*/
template<typename T>
inline void load_le(const byte in[], T& x0, T& x1)
{
x0 = load_le<T>(in, 0);
x1 = load_le<T>(in, 1);
}
/**
* Load four little-endian words
* @param in a pointer to some bytes
* @param x0 where the first word will be written
* @param x1 where the second word will be written
* @param x2 where the third word will be written
* @param x3 where the fourth word will be written
*/
template<typename T>
inline void load_le(const byte in[],
T& x0, T& x1, T& x2, T& x3)
{
x0 = load_le<T>(in, 0);
x1 = load_le<T>(in, 1);
x2 = load_le<T>(in, 2);
x3 = load_le<T>(in, 3);
}
/**
* Load eight little-endian words
* @param in a pointer to some bytes
* @param x0 where the first word will be written
* @param x1 where the second word will be written
* @param x2 where the third word will be written
* @param x3 where the fourth word will be written
* @param x4 where the fifth word will be written
* @param x5 where the sixth word will be written
* @param x6 where the seventh word will be written
* @param x7 where the eighth word will be written
*/
template<typename T>
inline void load_le(const byte in[],
T& x0, T& x1, T& x2, T& x3,
T& x4, T& x5, T& x6, T& x7)
{
x0 = load_le<T>(in, 0);
x1 = load_le<T>(in, 1);
x2 = load_le<T>(in, 2);
x3 = load_le<T>(in, 3);
x4 = load_le<T>(in, 4);
x5 = load_le<T>(in, 5);
x6 = load_le<T>(in, 6);
x7 = load_le<T>(in, 7);
}
/**
* Load a variable number of little-endian words
* @param out the output array of words
* @param in the input array of bytes
* @param count how many words are in in
*/
template<typename T>
inline void load_le(T out[],
const byte in[],
size_t count)
{
#if defined(BOTAN_TARGET_CPU_HAS_KNOWN_ENDIANNESS)
std::memcpy(out, in, sizeof(T)*count);
#if defined(BOTAN_TARGET_CPU_IS_BIG_ENDIAN)
const size_t blocks = count - (count % 4);
const size_t left = count - blocks;
for(size_t i = 0; i != blocks; i += 4)
bswap_4(out + i);
for(size_t i = 0; i != left; ++i)
out[blocks+i] = reverse_bytes(out[blocks+i]);
#endif
#else
for(size_t i = 0; i != count; ++i)
out[i] = load_le<T>(in, i);
#endif
}
/**
* Load two big-endian words
* @param in a pointer to some bytes
* @param x0 where the first word will be written
* @param x1 where the second word will be written
*/
template<typename T>
inline void load_be(const byte in[], T& x0, T& x1)
{
x0 = load_be<T>(in, 0);
x1 = load_be<T>(in, 1);
}
/**
* Load four big-endian words
* @param in a pointer to some bytes
* @param x0 where the first word will be written
* @param x1 where the second word will be written
* @param x2 where the third word will be written
* @param x3 where the fourth word will be written
*/
template<typename T>
inline void load_be(const byte in[],
T& x0, T& x1, T& x2, T& x3)
{
x0 = load_be<T>(in, 0);
x1 = load_be<T>(in, 1);
x2 = load_be<T>(in, 2);
x3 = load_be<T>(in, 3);
}
/**
* Load eight big-endian words
* @param in a pointer to some bytes
* @param x0 where the first word will be written
* @param x1 where the second word will be written
* @param x2 where the third word will be written
* @param x3 where the fourth word will be written
* @param x4 where the fifth word will be written
* @param x5 where the sixth word will be written
* @param x6 where the seventh word will be written
* @param x7 where the eighth word will be written
*/
template<typename T>
inline void load_be(const byte in[],
T& x0, T& x1, T& x2, T& x3,
T& x4, T& x5, T& x6, T& x7)
{
x0 = load_be<T>(in, 0);
x1 = load_be<T>(in, 1);
x2 = load_be<T>(in, 2);
x3 = load_be<T>(in, 3);
x4 = load_be<T>(in, 4);
x5 = load_be<T>(in, 5);
x6 = load_be<T>(in, 6);
x7 = load_be<T>(in, 7);
}
/**
* Load a variable number of big-endian words
* @param out the output array of words
* @param in the input array of bytes
* @param count how many words are in in
*/
template<typename T>
inline void load_be(T out[],
const byte in[],
size_t count)
{
#if defined(BOTAN_TARGET_CPU_HAS_KNOWN_ENDIANNESS)
std::memcpy(out, in, sizeof(T)*count);
#if defined(BOTAN_TARGET_CPU_IS_LITTLE_ENDIAN)
const size_t blocks = count - (count % 4);
const size_t left = count - blocks;
for(size_t i = 0; i != blocks; i += 4)
bswap_4(out + i);
for(size_t i = 0; i != left; ++i)
out[blocks+i] = reverse_bytes(out[blocks+i]);
#endif
#else
for(size_t i = 0; i != count; ++i)
out[i] = load_be<T>(in, i);
#endif
}
/**
* Store a big-endian u16bit
* @param in the input u16bit
* @param out the byte array to write to
*/
inline void store_be(u16bit in, byte out[2])
{
#if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
*reinterpret_cast<u16bit*>(out) = BOTAN_ENDIAN_B2N(in);
#else
out[0] = get_byte(0, in);
out[1] = get_byte(1, in);
#endif
}
/**
* Store a little-endian u16bit
* @param in the input u16bit
* @param out the byte array to write to
*/
inline void store_le(u16bit in, byte out[2])
{
#if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
*reinterpret_cast<u16bit*>(out) = BOTAN_ENDIAN_L2N(in);
#else
out[0] = get_byte(1, in);
out[1] = get_byte(0, in);
#endif
}
/**
* Store a big-endian u32bit
* @param in the input u32bit
* @param out the byte array to write to
*/
inline void store_be(u32bit in, byte out[4])
{
#if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
*reinterpret_cast<u32bit*>(out) = BOTAN_ENDIAN_B2N(in);
#else
out[0] = get_byte(0, in);
out[1] = get_byte(1, in);
out[2] = get_byte(2, in);
out[3] = get_byte(3, in);
#endif
}
/**
* Store a little-endian u32bit
* @param in the input u32bit
* @param out the byte array to write to
*/
inline void store_le(u32bit in, byte out[4])
{
#if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
*reinterpret_cast<u32bit*>(out) = BOTAN_ENDIAN_L2N(in);
#else
out[0] = get_byte(3, in);
out[1] = get_byte(2, in);
out[2] = get_byte(1, in);
out[3] = get_byte(0, in);
#endif
}
/**
* Store a big-endian u64bit
* @param in the input u64bit
* @param out the byte array to write to
*/
inline void store_be(u64bit in, byte out[8])
{
#if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
*reinterpret_cast<u64bit*>(out) = BOTAN_ENDIAN_B2N(in);
#else
out[0] = get_byte(0, in);
out[1] = get_byte(1, in);
out[2] = get_byte(2, in);
out[3] = get_byte(3, in);
out[4] = get_byte(4, in);
out[5] = get_byte(5, in);
out[6] = get_byte(6, in);
out[7] = get_byte(7, in);
#endif
}
/**
* Store a little-endian u64bit
* @param in the input u64bit
* @param out the byte array to write to
*/
inline void store_le(u64bit in, byte out[8])
{
#if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
*reinterpret_cast<u64bit*>(out) = BOTAN_ENDIAN_L2N(in);
#else
out[0] = get_byte(7, in);
out[1] = get_byte(6, in);
out[2] = get_byte(5, in);
out[3] = get_byte(4, in);
out[4] = get_byte(3, in);
out[5] = get_byte(2, in);
out[6] = get_byte(1, in);
out[7] = get_byte(0, in);
#endif
}
/**
* Store two little-endian words
* @param out the output byte array
* @param x0 the first word
* @param x1 the second word
*/
template<typename T>
inline void store_le(byte out[], T x0, T x1)
{
store_le(x0, out + (0 * sizeof(T)));
store_le(x1, out + (1 * sizeof(T)));
}
/**
* Store two big-endian words
* @param out the output byte array
* @param x0 the first word
* @param x1 the second word
*/
template<typename T>
inline void store_be(byte out[], T x0, T x1)
{
store_be(x0, out + (0 * sizeof(T)));
store_be(x1, out + (1 * sizeof(T)));
}
/**
* Store four little-endian words
* @param out the output byte array
* @param x0 the first word
* @param x1 the second word
* @param x2 the third word
* @param x3 the fourth word
*/
template<typename T>
inline void store_le(byte out[], T x0, T x1, T x2, T x3)
{
store_le(x0, out + (0 * sizeof(T)));
store_le(x1, out + (1 * sizeof(T)));
store_le(x2, out + (2 * sizeof(T)));
store_le(x3, out + (3 * sizeof(T)));
}
/**
* Store four big-endian words
* @param out the output byte array
* @param x0 the first word
* @param x1 the second word
* @param x2 the third word
* @param x3 the fourth word
*/
template<typename T>
inline void store_be(byte out[], T x0, T x1, T x2, T x3)
{
store_be(x0, out + (0 * sizeof(T)));
store_be(x1, out + (1 * sizeof(T)));
store_be(x2, out + (2 * sizeof(T)));
store_be(x3, out + (3 * sizeof(T)));
}
/**
* Store eight little-endian words
* @param out the output byte array
* @param x0 the first word
* @param x1 the second word
* @param x2 the third word
* @param x3 the fourth word
* @param x4 the fifth word
* @param x5 the sixth word
* @param x6 the seventh word
* @param x7 the eighth word
*/
template<typename T>
inline void store_le(byte out[], T x0, T x1, T x2, T x3,
T x4, T x5, T x6, T x7)
{
store_le(x0, out + (0 * sizeof(T)));
store_le(x1, out + (1 * sizeof(T)));
store_le(x2, out + (2 * sizeof(T)));
store_le(x3, out + (3 * sizeof(T)));
store_le(x4, out + (4 * sizeof(T)));
store_le(x5, out + (5 * sizeof(T)));
store_le(x6, out + (6 * sizeof(T)));
store_le(x7, out + (7 * sizeof(T)));
}
/**
* Store eight big-endian words
* @param out the output byte array
* @param x0 the first word
* @param x1 the second word
* @param x2 the third word
* @param x3 the fourth word
* @param x4 the fifth word
* @param x5 the sixth word
* @param x6 the seventh word
* @param x7 the eighth word
*/
template<typename T>
inline void store_be(byte out[], T x0, T x1, T x2, T x3,
T x4, T x5, T x6, T x7)
{
store_be(x0, out + (0 * sizeof(T)));
store_be(x1, out + (1 * sizeof(T)));
store_be(x2, out + (2 * sizeof(T)));
store_be(x3, out + (3 * sizeof(T)));
store_be(x4, out + (4 * sizeof(T)));
store_be(x5, out + (5 * sizeof(T)));
store_be(x6, out + (6 * sizeof(T)));
store_be(x7, out + (7 * sizeof(T)));
}
}
namespace Botan {
/**
* CBC Encryption
*/
class BOTAN_DLL CBC_Encryption : public Keyed_Filter,
private Buffered_Filter
{
public:
std::string name() const;
void set_iv(const InitializationVector& iv);
void set_key(const SymmetricKey& key) { cipher->set_key(key); }
bool valid_keylength(size_t key_len) const
{ return cipher->valid_keylength(key_len); }
bool valid_iv_length(size_t iv_len) const
{ return (iv_len == cipher->block_size()); }
CBC_Encryption(BlockCipher* cipher,
BlockCipherModePaddingMethod* padding);
CBC_Encryption(BlockCipher* cipher,
BlockCipherModePaddingMethod* padding,
const SymmetricKey& key,
const InitializationVector& iv);
~CBC_Encryption() { delete cipher; delete padder; }
private:
void buffered_block(const byte input[], size_t input_length);
void buffered_final(const byte input[], size_t input_length);
void write(const byte input[], size_t input_length);
void end_msg();
BlockCipher* cipher;
const BlockCipherModePaddingMethod* padder;
SecureVector<byte> state;
};
/**
* CBC Decryption
*/
class BOTAN_DLL CBC_Decryption : public Keyed_Filter,
private Buffered_Filter
{
public:
std::string name() const;
void set_iv(const InitializationVector& iv);
void set_key(const SymmetricKey& key) { cipher->set_key(key); }
bool valid_keylength(size_t key_len) const
{ return cipher->valid_keylength(key_len); }
bool valid_iv_length(size_t iv_len) const
{ return (iv_len == cipher->block_size()); }
CBC_Decryption(BlockCipher* cipher,
BlockCipherModePaddingMethod* padding);
CBC_Decryption(BlockCipher* cipher,
BlockCipherModePaddingMethod* padding,
const SymmetricKey& key,
const InitializationVector& iv);
~CBC_Decryption() { delete cipher; delete padder; }
private:
void buffered_block(const byte input[], size_t input_length);
void buffered_final(const byte input[], size_t input_length);
void write(const byte[], size_t);
void end_msg();
BlockCipher* cipher;
const BlockCipherModePaddingMethod* padder;
SecureVector<byte> state, temp;
};
}
namespace Botan {
/**
* A class handling runtime CPU feature detection
*/
class BOTAN_DLL CPUID
{
public:
/**
* Probe the CPU and see what extensions are supported
*/
static void initialize();
/**
* Return a best guess of the cache line size
*/
static size_t cache_line_size() { return cache_line; }
/**
* Check if the processor supports RDTSC
*/
static bool has_rdtsc()
{ return x86_processor_flags_has(CPUID_RDTSC_BIT); }
/**
* Check if the processor supports SSE2
*/
static bool has_sse2()
{ return x86_processor_flags_has(CPUID_SSE2_BIT); }
/**
* Check if the processor supports SSSE3
*/
static bool has_ssse3()
{ return x86_processor_flags_has(CPUID_SSSE3_BIT); }
/**
* Check if the processor supports SSE4.1
*/
static bool has_sse41()
{ return x86_processor_flags_has(CPUID_SSE41_BIT); }
/**
* Check if the processor supports SSE4.2
*/
static bool has_sse42()
{ return x86_processor_flags_has(CPUID_SSE42_BIT); }
/**
* Check if the processor supports extended AVX vector instructions
*/
static bool has_avx()
{ return x86_processor_flags_has(CPUID_AVX_BIT); }
/**
* Check if the processor supports AES-NI
*/
static bool has_aes_ni()
{ return x86_processor_flags_has(CPUID_AESNI_BIT); }
/**
* Check if the processor supports PCMULUDQ
*/
static bool has_pcmuludq()
{ return x86_processor_flags_has(CPUID_PCMUL_BIT); }
/**
* Check if the processor supports MOVBE
*/
static bool has_movbe()
{ return x86_processor_flags_has(CPUID_MOVBE_BIT); }
/**
* Check if the processor supports RDRAND
*/
static bool has_rdrand()
{ return x86_processor_flags_has(CPUID_RDRAND_BIT); }
/**
* Check if the processor supports AltiVec/VMX
*/
static bool has_altivec() { return altivec_capable; }
private:
enum CPUID_bits {
CPUID_RDTSC_BIT = 4,
CPUID_SSE2_BIT = 26,
CPUID_PCMUL_BIT = 33,
CPUID_SSSE3_BIT = 41,
CPUID_SSE41_BIT = 51,
CPUID_SSE42_BIT = 52,
CPUID_MOVBE_BIT = 54,
CPUID_AESNI_BIT = 57,
CPUID_AVX_BIT = 60,
CPUID_RDRAND_BIT = 62
};
static bool x86_processor_flags_has(u64bit bit)
{
return ((x86_processor_flags >> bit) & 1);
}
static u64bit x86_processor_flags;
static size_t cache_line;
static bool altivec_capable;
};
}
namespace Botan {
/**
* Serpent implementation using SIMD
*/
class BOTAN_DLL Serpent_SIMD : public Serpent
{
public:
size_t parallelism() const { return 4; }
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
BlockCipher* clone() const { return new Serpent_SIMD; }
};
}
namespace Botan {
/**
* PK_Encryptor Filter
*/
class BOTAN_DLL PK_Encryptor_Filter : public Filter
{
public:
void write(const byte[], size_t);
void end_msg();
PK_Encryptor_Filter(PK_Encryptor* c,
RandomNumberGenerator& rng_ref) :
cipher(c), rng(rng_ref) {}
~PK_Encryptor_Filter() { delete cipher; }
private:
PK_Encryptor* cipher;
RandomNumberGenerator& rng;
SecureVector<byte> buffer;
};
/**
* PK_Decryptor Filter
*/
class BOTAN_DLL PK_Decryptor_Filter : public Filter
{
public:
void write(const byte[], size_t);
void end_msg();
PK_Decryptor_Filter(PK_Decryptor* c) : cipher(c) {}
~PK_Decryptor_Filter() { delete cipher; }
private:
PK_Decryptor* cipher;
SecureVector<byte> buffer;
};
/**
* PK_Signer Filter
*/
class BOTAN_DLL PK_Signer_Filter : public Filter
{
public:
void write(const byte[], size_t);
void end_msg();
PK_Signer_Filter(PK_Signer* s,
RandomNumberGenerator& rng_ref) :
signer(s), rng(rng_ref) {}
~PK_Signer_Filter() { delete signer; }
private:
PK_Signer* signer;
RandomNumberGenerator& rng;
};
/**
* PK_Verifier Filter
*/
class BOTAN_DLL PK_Verifier_Filter : public Filter
{
public:
void write(const byte[], size_t);
void end_msg();
void set_signature(const byte[], size_t);
void set_signature(const MemoryRegion<byte>&);
PK_Verifier_Filter(PK_Verifier* v) : verifier(v) {}
PK_Verifier_Filter(PK_Verifier*, const byte[], size_t);
PK_Verifier_Filter(PK_Verifier*, const MemoryRegion<byte>&);
~PK_Verifier_Filter() { delete verifier; }
private:
PK_Verifier* verifier;
SecureVector<byte> signature;
};
}
namespace Botan {
/**
* XTEA implemented using SIMD operations
*/
class BOTAN_DLL XTEA_SIMD : public XTEA
{
public:
size_t parallelism() const { return 8; }
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
BlockCipher* clone() const { return new XTEA_SIMD; }
};
}
namespace Botan {
/**
* A queue that knows how to zeroize itself
*/
class BOTAN_DLL SecureQueue : public Fanout_Filter, public DataSource
{
public:
std::string name() const { return "Queue"; }
void write(const byte[], size_t);
size_t read(byte[], size_t);
size_t peek(byte[], size_t, size_t = 0) const;
bool end_of_data() const;
/**
* @return number of bytes available in the queue
*/
size_t size() const;
bool attachable() { return false; }
/**
* SecureQueue assignment
* @param other the queue to copy
*/
SecureQueue& operator=(const SecureQueue& other);
/**
* SecureQueue default constructor (creates empty queue)
*/
SecureQueue();
/**
* SecureQueue copy constructor
* @param other the queue to copy
*/
SecureQueue(const SecureQueue& other);
~SecureQueue() { destroy(); }
private:
void destroy();
class SecureQueueNode* head;
class SecureQueueNode* tail;
};
}
namespace Botan {
/**
* HMAC
*/
class BOTAN_DLL HMAC : public MessageAuthenticationCode
{
public:
void clear();
std::string name() const;
MessageAuthenticationCode* clone() const;
size_t output_length() const { return hash->output_length(); }
Key_Length_Specification key_spec() const
{
return Key_Length_Specification(0, 2*hash->hash_block_size());
}
/**
* @param hash the hash to use for HMACing
*/
HMAC(HashFunction* hash);
~HMAC() { delete hash; }
private:
void add_data(const byte[], size_t);
void final_result(byte[]);
void key_schedule(const byte[], size_t);
HashFunction* hash;
SecureVector<byte> i_key, o_key;
};
}
namespace Botan {
/**
* OpenPGP's S2K
*/
class BOTAN_DLL OpenPGP_S2K : public PBKDF
{
public:
/**
* @param hash_in the hash function to use
*/
OpenPGP_S2K(HashFunction* hash_in) : hash(hash_in) {}
~OpenPGP_S2K() { delete hash; }
std::string name() const
{
return "OpenPGP-S2K(" + hash->name() + ")";
}
PBKDF* clone() const
{
return new OpenPGP_S2K(hash->clone());
}
OctetString derive_key(size_t output_len,
const std::string& passphrase,
const byte salt[], size_t salt_len,
size_t iterations) const;
private:
HashFunction* hash;
};
}
namespace Botan {
/**
* Lion is a block cipher construction designed by Ross Anderson and
* Eli Biham, described in "Two Practical and Provably Secure Block
* Ciphers: BEAR and LION". It has a variable block size and is
* designed to encrypt very large blocks (up to a megabyte)
* http://www.cl.cam.ac.uk/~rja14/Papers/bear-lion.pdf
*/
class BOTAN_DLL Lion : public BlockCipher
{
public:
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
size_t block_size() const { return BLOCK_SIZE; }
Key_Length_Specification key_spec() const
{
return Key_Length_Specification(2, 2*hash->output_length(), 2);
}
void clear();
std::string name() const;
BlockCipher* clone() const;
/**
* @param hash the hash to use internally
* @param cipher the stream cipher to use internally
* @param block_size the size of the block to use
*/
Lion(HashFunction* hash,
StreamCipher* cipher,
size_t block_size);
~Lion() { delete hash; delete cipher; }
private:
void key_schedule(const byte[], size_t);
const size_t BLOCK_SIZE, LEFT_SIZE, RIGHT_SIZE;
HashFunction* hash;
StreamCipher* cipher;
SecureVector<byte> key1, key2;
};
}
namespace Botan {
/**
* Skipjack, a NSA designed cipher used in Fortezza
*/
class BOTAN_DLL Skipjack : public Block_Cipher_Fixed_Params<8, 10>
{
public:
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
void clear();
std::string name() const { return "Skipjack"; }
BlockCipher* clone() const { return new Skipjack; }
Skipjack() : FTAB(2560) {}
private:
void key_schedule(const byte[], size_t);
SecureVector<byte> FTAB;
};
}
namespace Botan {
namespace FPE {
/**
* Encrypt X from and onto the group Z_n using key and tweak
* @param n the modulus
* @param X the plaintext as a BigInt
* @param key a random key
* @param tweak will modify the ciphertext (think of as an IV)
*/
BigInt BOTAN_DLL fe1_encrypt(const BigInt& n, const BigInt& X,
const SymmetricKey& key,
const MemoryRegion<byte>& tweak);
/**
* Decrypt X from and onto the group Z_n using key and tweak
* @param n the modulus
* @param X the ciphertext as a BigInt
* @param key is the key used for encryption
* @param tweak the same tweak used for encryption
*/
BigInt BOTAN_DLL fe1_decrypt(const BigInt& n, const BigInt& X,
const SymmetricKey& key,
const MemoryRegion<byte>& tweak);
}
}
namespace Botan {
/**
* This class represents ECDH Public Keys.
*/
class BOTAN_DLL ECDH_PublicKey : public virtual EC_PublicKey
{
public:
ECDH_PublicKey(const AlgorithmIdentifier& alg_id,
const MemoryRegion<byte>& key_bits) :
EC_PublicKey(alg_id, key_bits) {}
/**
* Construct a public key from a given public point.
* @param dom_par the domain parameters associated with this key
* @param public_point the public point defining this key
*/
ECDH_PublicKey(const EC_Group& dom_par,
const PointGFp& public_point) :
EC_PublicKey(dom_par, public_point) {}
/**
* Get this keys algorithm name.
* @return this keys algorithm name
*/
std::string algo_name() const { return "ECDH"; }
/**
* Get the maximum number of bits allowed to be fed to this key.
* This is the bitlength of the order of the base point.
* @return maximum number of input bits
*/
size_t max_input_bits() const { return domain().get_order().bits(); }
/**
* @return public point value
*/
MemoryVector<byte> public_value() const
{ return EC2OSP(public_point(), PointGFp::UNCOMPRESSED); }
protected:
ECDH_PublicKey() {}
};
/**
* This class represents ECDH Private Keys.
*/
class BOTAN_DLL ECDH_PrivateKey : public ECDH_PublicKey,
public EC_PrivateKey,
public PK_Key_Agreement_Key
{
public:
ECDH_PrivateKey(const AlgorithmIdentifier& alg_id,
const MemoryRegion<byte>& key_bits) :
EC_PrivateKey(alg_id, key_bits) {}
/**
* Generate a new private key
* @param rng a random number generator
* @param domain parameters to used for this key
* @param x the private key; if zero, a new random key is generated
*/
ECDH_PrivateKey(RandomNumberGenerator& rng,
const EC_Group& domain,
const BigInt& x = 0) :
EC_PrivateKey(rng, domain, x) {}
MemoryVector<byte> public_value() const
{ return ECDH_PublicKey::public_value(); }
};
/**
* ECDH operation
*/
class BOTAN_DLL ECDH_KA_Operation : public PK_Ops::Key_Agreement
{
public:
ECDH_KA_Operation(const ECDH_PrivateKey& key);
SecureVector<byte> agree(const byte w[], size_t w_len);
private:
const CurveGFp& curve;
const BigInt& cofactor;
BigInt l_times_priv;
};
}
namespace Botan {
/**
* AES-128
*/
class BOTAN_DLL AES_128 : public Block_Cipher_Fixed_Params<16, 16>
{
public:
AES_128() : EK(40), DK(40), ME(16), MD(16) {}
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
void clear();
std::string name() const { return "AES-128"; }
BlockCipher* clone() const { return new AES_128; }
private:
void key_schedule(const byte key[], size_t length);
SecureVector<u32bit> EK, DK;
SecureVector<byte> ME, MD;
};
/**
* AES-192
*/
class BOTAN_DLL AES_192 : public Block_Cipher_Fixed_Params<16, 24>
{
public:
AES_192() : EK(48), DK(48), ME(16), MD(16) {}
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
void clear();
std::string name() const { return "AES-192"; }
BlockCipher* clone() const { return new AES_192; }
private:
void key_schedule(const byte key[], size_t length);
SecureVector<u32bit> EK, DK;
SecureVector<byte> ME, MD;
};
/**
* AES-256
*/
class BOTAN_DLL AES_256 : public Block_Cipher_Fixed_Params<16, 32>
{
public:
AES_256() : EK(56), DK(56), ME(16), MD(16) {}
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
void clear();
std::string name() const { return "AES-256"; }
BlockCipher* clone() const { return new AES_256; }
private:
void key_schedule(const byte key[], size_t length);
SecureVector<u32bit> EK, DK;
SecureVector<byte> ME, MD;
};
}
namespace Botan {
/**
* Rivest's Package Tranform
* @param rng the random number generator to use
* @param cipher the block cipher to use
* @param input the input data buffer
* @param input_len the length of the input data in bytes
* @param output the output data buffer (must be at least
* input_len + cipher->BLOCK_SIZE bytes long)
*/
void BOTAN_DLL aont_package(RandomNumberGenerator& rng,
BlockCipher* cipher,
const byte input[], size_t input_len,
byte output[]);
/**
* Rivest's Package Tranform (Inversion)
* @param cipher the block cipher to use
* @param input the input data buffer
* @param input_len the length of the input data in bytes
* @param output the output data buffer (must be at least
* input_len - cipher->BLOCK_SIZE bytes long)
*/
void BOTAN_DLL aont_unpackage(BlockCipher* cipher,
const byte input[], size_t input_len,
byte output[]);
}
namespace Botan {
/**
* Combines two hash functions using a Feistel scheme. Described in
* "On the Security of Hash Function Combiners", Anja Lehmann
*/
class BOTAN_DLL Comb4P : public HashFunction
{
public:
/**
* @param h1 the first hash
* @param h2 the second hash
*/
Comb4P(HashFunction* h1, HashFunction* h2);
~Comb4P() { delete hash1; delete hash2; }
size_t hash_block_size() const;
size_t output_length() const
{
return hash1->output_length() + hash2->output_length();
}
HashFunction* clone() const
{
return new Comb4P(hash1->clone(), hash2->clone());
}
std::string name() const
{
return "Comb4P(" + hash1->name() + "," + hash2->name() + ")";
}
void clear();
private:
void add_data(const byte input[], size_t length);
void final_result(byte out[]);
HashFunction* hash1;
HashFunction* hash2;
};
}
namespace Botan {
/**
* A split secret, using the format from draft-mcgrew-tss-03
*/
class BOTAN_DLL RTSS_Share
{
public:
/**
* @param M the number of shares needed to reconstruct
* @param N the number of shares generated
* @param secret the secret to split
* @param secret_len the length of the secret
* @param identifier the 16 byte share identifier
* @param rng the random number generator to use
*/
static std::vector<RTSS_Share>
split(byte M, byte N,
const byte secret[], u16bit secret_len,
const byte identifier[16],
RandomNumberGenerator& rng);
/**
* @param shares the list of shares
*/
static SecureVector<byte>
reconstruct(const std::vector<RTSS_Share>& shares);
RTSS_Share() {}
/**
* @param hex_input the share encoded in hexadecimal
*/
RTSS_Share(const std::string& hex_input);
/**
* @return hex representation
*/
std::string to_string() const;
/**
* @return share identifier
*/
byte share_id() const;
/**
* @return size of this share in bytes
*/
size_t size() const { return contents.size(); }
/**
* @return if this TSS share was initialized or not
*/
bool initialized() const { return (contents.size() > 0); }
private:
SecureVector<byte> contents;
};
}
namespace Botan {
/**
* RC2
*/
class BOTAN_DLL RC2 : public Block_Cipher_Fixed_Params<8, 1, 32>
{
public:
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
/**
* Return the code of the effective key bits
* @param bits key length
* @return EKB code
*/
static byte EKB_code(size_t bits);
void clear() { zeroise(K); }
std::string name() const { return "RC2"; }
BlockCipher* clone() const { return new RC2; }
RC2() : K(64) {}
private:
void key_schedule(const byte[], size_t);
SecureVector<u16bit> K;
};
}
namespace Botan {
/**
* DJB's Salsa20 (and XSalsa20)
*/
class BOTAN_DLL Salsa20 : public StreamCipher
{
public:
void cipher(const byte in[], byte out[], size_t length);
void set_iv(const byte iv[], size_t iv_len);
bool valid_iv_length(size_t iv_len) const
{ return (iv_len == 8 || iv_len == 24); }
Key_Length_Specification key_spec() const
{
return Key_Length_Specification(16, 32, 16);
}
void clear();
std::string name() const;
StreamCipher* clone() const { return new Salsa20; }
Salsa20() : state(16), buffer(64), position(0) {}
private:
void key_schedule(const byte key[], size_t key_len);
SecureVector<u32bit> state;
SecureVector<byte> buffer;
size_t position;
};
}
namespace Botan {
/**
* RIPEMD-128
*/
class BOTAN_DLL RIPEMD_128 : public MDx_HashFunction
{
public:
std::string name() const { return "RIPEMD-128"; }
size_t output_length() const { return 16; }
HashFunction* clone() const { return new RIPEMD_128; }
void clear();
RIPEMD_128() : MDx_HashFunction(64, false, true), M(16), digest(4)
{ clear(); }
private:
void compress_n(const byte[], size_t blocks);
void copy_out(byte[]);
SecureVector<u32bit> M, digest;
};
}
namespace Botan {
/**
* 24-bit cyclic redundancy check
*/
class BOTAN_DLL CRC24 : public HashFunction
{
public:
std::string name() const { return "CRC24"; }
size_t output_length() const { return 3; }
HashFunction* clone() const { return new CRC24; }
void clear() { crc = 0xB704CE; }
CRC24() { clear(); }
~CRC24() { clear(); }
private:
void add_data(const byte[], size_t);
void final_result(byte[]);
u32bit crc;
};
}
namespace Botan {
/**
* PKCS #5 v1 PBKDF, aka PBKDF1
* Can only generate a key up to the size of the hash output.
* Unless needed for backwards compatability, use PKCS5_PBKDF2
*/
class BOTAN_DLL PKCS5_PBKDF1 : public PBKDF
{
public:
/**
* Create a PKCS #5 instance using the specified hash function.
* @param hash_in pointer to a hash function object to use
*/
PKCS5_PBKDF1(HashFunction* hash_in) : hash(hash_in) {}
/**
* Copy constructor
* @param other the object to copy
*/
PKCS5_PBKDF1(const PKCS5_PBKDF1& other) :
PBKDF(), hash(other.hash->clone()) {}
~PKCS5_PBKDF1() { delete hash; }
std::string name() const
{
return "PBKDF1(" + hash->name() + ")";
}
PBKDF* clone() const
{
return new PKCS5_PBKDF1(hash->clone());
}
OctetString derive_key(size_t output_len,
const std::string& passphrase,
const byte salt[], size_t salt_len,
size_t iterations) const;
private:
HashFunction* hash;
};
}
namespace Botan {
/**
* This class represents X.509 Certificate Authorities (CAs).
*/
class BOTAN_DLL X509_CA
{
public:
/**
* Sign a PKCS#10 Request.
* @param req the request to sign
* @param rng the rng to use
* @param not_before the starting time for the certificate
* @param not_after the expiration time for the certificate
* @return resulting certificate
*/
X509_Certificate sign_request(const PKCS10_Request& req,
RandomNumberGenerator& rng,
const X509_Time& not_before,
const X509_Time& not_after);
/**
* Get the certificate of this CA.
* @return CA certificate
*/
X509_Certificate ca_certificate() const;
/**
* Create a new and empty CRL for this CA.
* @param rng the random number generator to use
* @param next_update the time to set in next update in seconds
* as the offset from the current time
* @return new CRL
*/
X509_CRL new_crl(RandomNumberGenerator& rng,
u32bit next_update = 0) const;
/**
* Create a new CRL by with additional entries.
* @param last_crl the last CRL of this CA to add the new entries to
* @param new_entries contains the new CRL entries to be added to the CRL
* @param rng the random number generator to use
* @param next_update the time to set in next update in seconds
* as the offset from the current time
*/
X509_CRL update_crl(const X509_CRL& last_crl,
const std::vector<CRL_Entry>& new_entries,
RandomNumberGenerator& rng,
u32bit next_update = 0) const;
/**
* Interface for creating new certificates
* @param signer a signing object
* @param rng a random number generator
* @param sig_algo the signature algorithm identifier
* @param pub_key the serialized public key
* @param not_before the start time of the certificate
* @param not_after the end time of the certificate
* @param issuer_dn the DN of the issuer
* @param subject_dn the DN of the subject
* @param extensions an optional list of certificate extensions
* @returns newly minted certificate
*/
static X509_Certificate 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);
/**
* Create a new CA object.
* @param ca_certificate the certificate of the CA
* @param key the private key of the CA
* @param hash_fn name of a hash function to use for signing
*/
X509_CA(const X509_Certificate& ca_certificate,
const Private_Key& key,
const std::string& hash_fn);
~X509_CA();
private:
X509_CA(const X509_CA&) {}
X509_CA& operator=(const X509_CA&) { return (*this); }
X509_CRL make_crl(const std::vector<CRL_Entry>& entries,
u32bit crl_number, u32bit next_update,
RandomNumberGenerator& rng) const;
AlgorithmIdentifier ca_sig_algo;
X509_Certificate cert;
PK_Signer* signer;
};
/**
* Choose the default signature format for a certain public key signature
* scheme.
* @param key will be the key to choose a padding scheme for
* @param hash_fn is the desired hash function
* @param alg_id will be set to the chosen scheme
* @return A PK_Signer object for generating signatures
*/
BOTAN_DLL PK_Signer* choose_sig_format(const Private_Key& key,
const std::string& hash_fn,
AlgorithmIdentifier& alg_id);
}
namespace Botan {
namespace OIDS {
/**
* Register an OID to string mapping.
* @param oid the oid to register
* @param name the name to be associated with the oid
*/
BOTAN_DLL void add_oid(const OID& oid, const std::string& name);
/**
* See if an OID exists in the internal table.
* @param oid the oid to check for
* @return true if the oid is registered
*/
BOTAN_DLL bool have_oid(const std::string& oid);
/**
* Resolve an OID
* @param oid the OID to look up
* @return name associated with this OID
*/
BOTAN_DLL std::string lookup(const OID& oid);
/**
* Find the OID to a name. The lookup will be performed in the
* general OID section of the configuration.
* @param name the name to resolve
* @return OID associated with the specified name
*/
BOTAN_DLL OID lookup(const std::string& name);
/**
* Tests whether the specified OID stands for the specified name.
* @param oid the OID to check
* @param name the name to check
* @return true if the specified OID stands for the specified name
*/
BOTAN_DLL bool name_of(const OID& oid, const std::string& name);
}
}
namespace Botan {
/**
* EAX Base Class
*/
class BOTAN_DLL EAX_Base : public Keyed_Filter
{
public:
void set_key(const SymmetricKey& key);
void set_iv(const InitializationVector& iv);
/**
* Set some additional data that is not included in the
* ciphertext but that will be authenticated.
* @param header the header contents
* @param header_len length of header in bytes
*/
void set_header(const byte header[], size_t header_len);
/**
* @return name of this mode
*/
std::string name() const;
bool valid_keylength(size_t key_len) const;
/**
* EAX supports arbitrary IV lengths
*/
bool valid_iv_length(size_t) const { return true; }
~EAX_Base() { delete ctr; delete cmac; }
protected:
/**
* @param cipher the cipher to use
* @param tag_size is how big the auth tag will be
*/
EAX_Base(BlockCipher* cipher, size_t tag_size);
void start_msg();
/**
* The block size of the underlying cipher
*/
const size_t BLOCK_SIZE;
/**
* The requested tag name
*/
const size_t TAG_SIZE;
/**
* The name of the cipher
*/
std::string cipher_name;
/**
* The stream cipher (CTR mode)
*/
StreamCipher* ctr;
/**
* The MAC (CMAC)
*/
MessageAuthenticationCode* cmac;
/**
* The MAC of the nonce
*/
SecureVector<byte> nonce_mac;
/**
* The MAC of the header
*/
SecureVector<byte> header_mac;
/**
* A buffer for CTR mode encryption
*/
SecureVector<byte> ctr_buf;
};
/**
* EAX Encryption
*/
class BOTAN_DLL EAX_Encryption : public EAX_Base
{
public:
/**
* @param ciph the cipher to use
* @param tag_size is how big the auth tag will be
*/
EAX_Encryption(BlockCipher* ciph, size_t tag_size = 0) :
EAX_Base(ciph, tag_size) {}
/**
* @param ciph the cipher to use
* @param key the key to use
* @param iv the initially set IV
* @param tag_size is how big the auth tag will be
*/
EAX_Encryption(BlockCipher* ciph, const SymmetricKey& key,
const InitializationVector& iv,
size_t tag_size) : EAX_Base(ciph, tag_size)
{
set_key(key);
set_iv(iv);
}
private:
void write(const byte[], size_t);
void end_msg();
};
/**
* EAX Decryption
*/
class BOTAN_DLL EAX_Decryption : public EAX_Base
{
public:
/**
* @param ciph the cipher to use
* @param tag_size is how big the auth tag will be
*/
EAX_Decryption(BlockCipher* ciph, size_t tag_size = 0);
/**
* @param ciph the cipher to use
* @param key the key to use
* @param iv the initially set IV
* @param tag_size is how big the auth tag will be
*/
EAX_Decryption(BlockCipher* ciph, const SymmetricKey& key,
const InitializationVector& iv,
size_t tag_size = 0);
private:
void write(const byte[], size_t);
void do_write(const byte[], size_t);
void end_msg();
SecureVector<byte> queue;
size_t queue_start, queue_end;
};
}
namespace Botan {
/**
* CMAC, also known as OMAC1
*/
class BOTAN_DLL CMAC : public MessageAuthenticationCode
{
public:
std::string name() const;
size_t output_length() const { return e->block_size(); }
MessageAuthenticationCode* clone() const;
void clear();
Key_Length_Specification key_spec() const
{
return e->key_spec();
}
/**
* CMAC's polynomial doubling operation
* @param in the input
* @param polynomial the byte value of the polynomial
*/
static SecureVector<byte> poly_double(const MemoryRegion<byte>& in,
byte polynomial);
/**
* @param cipher the underlying block cipher to use
*/
CMAC(BlockCipher* cipher);
~CMAC();
private:
void add_data(const byte[], size_t);
void final_result(byte[]);
void key_schedule(const byte[], size_t);
BlockCipher* e;
SecureVector<byte> buffer, state, B, P;
size_t position;
byte polynomial;
};
}
namespace Botan {
/**
* Skein-512, a SHA-3 candidate
*/
class BOTAN_DLL Skein_512 : public HashFunction
{
public:
/**
* @param output_bits the output size of Skein in bits
* @param personalization is a string that will paramaterize the
* hash output
*/
Skein_512(size_t output_bits = 512,
const std::string& personalization = "");
size_t hash_block_size() const { return 64; }
size_t output_length() const { return output_bits / 8; }
HashFunction* clone() const;
std::string name() const;
void clear();
private:
void add_data(const byte input[], size_t length);
void final_result(byte out[]);
std::string personalization;
size_t output_bits;
SecureVector<u64bit> H;
SecureVector<u64bit> T;
SecureVector<byte> buffer;
size_t buf_pos;
};
}
namespace Botan {
/**
* CBC encryption with ciphertext stealing
*/
class BOTAN_DLL CTS_Encryption : public Keyed_Filter
{
public:
std::string name() const { return cipher->name() + "/CTS"; }
void set_iv(const InitializationVector&);
void set_key(const SymmetricKey& key) { cipher->set_key(key); }
bool valid_keylength(size_t key_len) const
{ return cipher->valid_keylength(key_len); }
bool valid_iv_length(size_t iv_len) const
{ return (iv_len == cipher->block_size()); }
CTS_Encryption(BlockCipher* cipher);
CTS_Encryption(BlockCipher* cipher,
const SymmetricKey& key,
const InitializationVector& iv);
~CTS_Encryption() { delete cipher; }
private:
void write(const byte[], size_t);
void end_msg();
void encrypt(const byte[]);
BlockCipher* cipher;
SecureVector<byte> buffer, state;
size_t position;
};
/**
* CBC decryption with ciphertext stealing
*/
class BOTAN_DLL CTS_Decryption : public Keyed_Filter
{
public:
std::string name() const { return cipher->name() + "/CTS"; }
void set_iv(const InitializationVector&);
void set_key(const SymmetricKey& key) { cipher->set_key(key); }
bool valid_keylength(size_t key_len) const
{ return cipher->valid_keylength(key_len); }
bool valid_iv_length(size_t iv_len) const
{ return (iv_len == cipher->block_size()); }
CTS_Decryption(BlockCipher* cipher);
CTS_Decryption(BlockCipher* cipher,
const SymmetricKey& key,
const InitializationVector& iv);
~CTS_Decryption() { delete cipher; }
private:
void write(const byte[], size_t);
void end_msg();
void decrypt(const byte[]);
BlockCipher* cipher;
SecureVector<byte> buffer, state, temp;
size_t position;
};
}
namespace Botan {
/**
* Factory function for PBEs.
* @param algo_spec the name of the PBE algorithm to retrieve
* @return pointer to a PBE with randomly created parameters
*/
BOTAN_DLL PBE* get_pbe(const std::string& algo_spec);
/**
* Factory function for PBEs.
* @param pbe_oid the oid of the desired PBE
* @param params a DataSource providing the DER encoded parameters to use
* @return pointer to the PBE with the specified parameters
*/
BOTAN_DLL PBE* get_pbe(const OID& pbe_oid,
DataSource& params);
}
namespace Botan {
/**
* Public key encryptor factory method.
* @deprecated Instantiate object from pubkey.h directly
*
* @param key the key that will work inside the encryptor
* @param eme determines the algorithm and encoding
* @return public key encryptor object
*/
BOTAN_DEPRECATED("Instantiate object directly")
inline PK_Encryptor* get_pk_encryptor(const Public_Key& key,
const std::string& eme)
{
return new PK_Encryptor_EME(key, eme);
}
/**
* Public key decryptor factory method.
* @deprecated Instantiate object from pubkey.h directly
*
* @param key the key that will work inside the decryptor
* @param eme determines the algorithm and encoding
* @return public key decryptor object
*/
BOTAN_DEPRECATED("Instantiate object directly")
inline PK_Decryptor* get_pk_decryptor(const Private_Key& key,
const std::string& eme)
{
return new PK_Decryptor_EME(key, eme);
}
/**
* Public key signer factory method.
* @deprecated Instantiate object from pubkey.h directly
*
* @param key the key that will work inside the signer
* @param emsa determines the algorithm, encoding and hash algorithm
* @param sig_format the signature format to be used
* @return public key signer object
*/
BOTAN_DEPRECATED("Instantiate object directly")
inline PK_Signer* get_pk_signer(const Private_Key& key,
const std::string& emsa,
Signature_Format sig_format = IEEE_1363)
{
return new PK_Signer(key, emsa, sig_format);
}
/**
* Public key verifier factory method.
* @deprecated Instantiate object from pubkey.h directly
*
* @param key the key that will work inside the verifier
* @param emsa determines the algorithm, encoding and hash algorithm
* @param sig_format the signature format to be used
* @return public key verifier object
*/
BOTAN_DEPRECATED("Instantiate object directly")
inline PK_Verifier* get_pk_verifier(const Public_Key& key,
const std::string& emsa,
Signature_Format sig_format = IEEE_1363)
{
return new PK_Verifier(key, emsa, sig_format);
}
/**
* Public key key agreement factory method.
* @deprecated Instantiate object from pubkey.h directly
*
* @param key the key that will work inside the key agreement
* @param kdf the kdf algorithm to use
* @return key agreement algorithm
*/
BOTAN_DEPRECATED("Instantiate object directly")
inline PK_Key_Agreement* get_pk_kas(const PK_Key_Agreement_Key& key,
const std::string& kdf)
{
return new PK_Key_Agreement(key, kdf);
}
}
namespace Botan {
/**
* IDEA
*/
class BOTAN_DLL IDEA : public Block_Cipher_Fixed_Params<8, 16>
{
public:
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
void clear() { zeroise(EK); zeroise(DK); }
std::string name() const { return "IDEA"; }
BlockCipher* clone() const { return new IDEA; }
IDEA() : EK(52), DK(52) {}
protected:
/**
* @return const reference to encryption subkeys
*/
const SecureVector<u16bit>& get_EK() const { return EK; }
/**
* @return const reference to decryption subkeys
*/
const SecureVector<u16bit>& get_DK() const { return DK; }
private:
void key_schedule(const byte[], size_t);
SecureVector<u16bit> EK, DK;
};
}
namespace Botan {
/**
* Return the PKCS #1 hash identifier
* @see RFC 3447 section 9.2
* @param hash_name the name of the hash function
* @return byte sequence identifying the hash
* @throw Invalid_Argument if the hash has no known PKCS #1 hash id
*/
BOTAN_DLL MemoryVector<byte> pkcs_hash_id(const std::string& hash_name);
/**
* Return the IEEE 1363 hash identifier
* @param hash_name the name of the hash function
* @return byte code identifying the hash, or 0 if not known
*/
BOTAN_DLL byte ieee1363_hash_id(const std::string& hash_name);
}
namespace Botan {
/**
* MGF1 from PKCS #1 v2.0
*/
class BOTAN_DLL MGF1 : public MGF
{
public:
void mask(const byte[], size_t, byte[], size_t) const;
/**
MGF1 constructor: takes ownership of hash
*/
MGF1(HashFunction* hash);
~MGF1();
private:
HashFunction* hash;
};
}
namespace Botan {
/**
* IEEE P1619 XTS Encryption
*/
class BOTAN_DLL XTS_Encryption : public Keyed_Filter,
private Buffered_Filter
{
public:
void set_key(const SymmetricKey& key);
void set_iv(const InitializationVector& iv);
bool valid_keylength(size_t key_len) const
{ return cipher->valid_keylength(key_len); }
bool valid_iv_length(size_t iv_len) const
{ return (iv_len == cipher->block_size()); }
std::string name() const;
XTS_Encryption(BlockCipher* ciph);
XTS_Encryption(BlockCipher* ciph,
const SymmetricKey& key,
const InitializationVector& iv);
~XTS_Encryption() { delete cipher; delete cipher2; }
private:
void write(const byte[], size_t);
void end_msg();
void buffered_block(const byte input[], size_t input_length);
void buffered_final(const byte input[], size_t input_length);
BlockCipher* cipher;
BlockCipher* cipher2;
SecureVector<byte> tweak;
};
/**
* IEEE P1619 XTS Encryption
*/
class BOTAN_DLL XTS_Decryption : public Keyed_Filter,
private Buffered_Filter
{
public:
void set_key(const SymmetricKey& key);
void set_iv(const InitializationVector& iv);
bool valid_keylength(size_t key_len) const
{ return cipher->valid_keylength(key_len); }
bool valid_iv_length(size_t iv_len) const
{ return (iv_len == cipher->block_size()); }
std::string name() const;
XTS_Decryption(BlockCipher* ciph);
XTS_Decryption(BlockCipher* ciph,
const SymmetricKey& key,
const InitializationVector& iv);
~XTS_Decryption() { delete cipher; delete cipher2; }
private:
void write(const byte[], size_t);
void end_msg();
void buffered_block(const byte input[], size_t input_length);
void buffered_final(const byte input[], size_t input_length);
BlockCipher* cipher;
BlockCipher* cipher2;
SecureVector<byte> tweak;
};
}
namespace Botan {
/**
* Struct representing a particular date and time
*/
struct BOTAN_DLL calendar_point
{
/** The year */
u32bit year;
/** The month, 1 through 12 for Jan to Dec */
byte month;
/** The day of the month, 1 through 31 (or 28 or 30 based on month */
byte day;
/** Hour in 24-hour form, 0 to 23 */
byte hour;
/** Minutes in the hour, 0 to 60 */
byte minutes;
/** Seconds in the minute, 0 to 60, but might be slightly
larger to deal with leap seconds on some systems
*/
byte seconds;
/**
* Initialize a calendar_point
* @param y the year
* @param mon the month
* @param d the day
* @param h the hour
* @param min the minute
* @param sec the second
*/
calendar_point(u32bit y, byte mon, byte d, byte h, byte min, byte sec) :
year(y), month(mon), day(d), hour(h), minutes(min), seconds(sec) {}
};
/**
* @param time_point a time point from the system clock
* @return calendar_point object representing this time point
*/
BOTAN_DLL calendar_point calendar_value(u64bit time_point);
/**
* @return seconds resolution timestamp, unknown epoch
*/
BOTAN_DLL u64bit system_time();
/**
* @return nanoseconds resolution timestamp, unknown epoch
*/
BOTAN_DLL u64bit get_nanoseconds_clock();
}
namespace Botan {
/**
* EMSA-Raw - sign inputs directly
* Don't use this unless you know what you are doing.
*/
class BOTAN_DLL EMSA_Raw : public EMSA
{
private:
void update(const byte[], size_t);
SecureVector<byte> raw_data();
SecureVector<byte> encoding_of(const MemoryRegion<byte>&, size_t,
RandomNumberGenerator&);
bool verify(const MemoryRegion<byte>&, const MemoryRegion<byte>&,
size_t);
SecureVector<byte> message;
};
}
namespace Botan {
/**
* Perform base64 encoding
* @param output an array of at least input_length*4/3 bytes
* @param input is some binary data
* @param input_length length of input in bytes
* @param input_consumed is an output parameter which says how many
* bytes of input were actually consumed. If less than
* input_length, then the range input[consumed:length]
* should be passed in later along with more input.
* @param final_inputs true iff this is the last input, in which case
padding chars will be applied if needed
* @return number of bytes written to output
*/
size_t BOTAN_DLL base64_encode(char output[],
const byte input[],
size_t input_length,
size_t& input_consumed,
bool final_inputs);
/**
* Perform base64 encoding
* @param input some input
* @param input_length length of input in bytes
* @return base64adecimal representation of input
*/
std::string BOTAN_DLL base64_encode(const byte input[],
size_t input_length);
/**
* Perform base64 encoding
* @param input some input
* @return base64adecimal representation of input
*/
std::string BOTAN_DLL base64_encode(const MemoryRegion<byte>& input);
/**
* Perform base64 decoding
* @param output an array of at least input_length*3/4 bytes
* @param input some base64 input
* @param input_length length of input in bytes
* @param input_consumed is an output parameter which says how many
* bytes of input were actually consumed. If less than
* input_length, then the range input[consumed:length]
* should be passed in later along with more input.
* @param final_inputs true iff this is the last input, in which case
padding is allowed
* @param ignore_ws ignore whitespace on input; if false, throw an
exception if whitespace is encountered
* @return number of bytes written to output
*/
size_t BOTAN_DLL base64_decode(byte output[],
const char input[],
size_t input_length,
size_t& input_consumed,
bool final_inputs,
bool ignore_ws = true);
/**
* Perform base64 decoding
* @param output an array of at least input_length*3/4 bytes
* @param input some base64 input
* @param input_length length of input in bytes
* @param ignore_ws ignore whitespace on input; if false, throw an
exception if whitespace is encountered
* @return number of bytes written to output
*/
size_t BOTAN_DLL base64_decode(byte output[],
const char input[],
size_t input_length,
bool ignore_ws = true);
/**
* Perform base64 decoding
* @param output an array of at least input_length/3*4 bytes
* @param input some base64 input
* @param ignore_ws ignore whitespace on input; if false, throw an
exception if whitespace is encountered
* @return number of bytes written to output
*/
size_t BOTAN_DLL base64_decode(byte output[],
const std::string& input,
bool ignore_ws = true);
/**
* Perform base64 decoding
* @param input some base64 input
* @param input_length the length of input in bytes
* @param ignore_ws ignore whitespace on input; if false, throw an
exception if whitespace is encountered
* @return decoded base64 output
*/
SecureVector<byte> BOTAN_DLL base64_decode(const char input[],
size_t input_length,
bool ignore_ws = true);
/**
* Perform base64 decoding
* @param input some base64 input
* @param ignore_ws ignore whitespace on input; if false, throw an
exception if whitespace is encountered
* @return decoded base64 output
*/
SecureVector<byte> BOTAN_DLL base64_decode(const std::string& input,
bool ignore_ws = true);
}
namespace Botan {
/**
* PRF used in TLS 1.0/1.1
*/
class BOTAN_DLL TLS_PRF : public KDF
{
public:
SecureVector<byte> derive(size_t key_len,
const byte secret[], size_t secret_len,
const byte seed[], size_t seed_len) const;
std::string name() const { return "TLS-PRF"; }
KDF* clone() const { return new TLS_PRF; }
TLS_PRF();
~TLS_PRF();
private:
MessageAuthenticationCode* hmac_md5;
MessageAuthenticationCode* hmac_sha1;
};
/**
* PRF used in TLS 1.2
*/
class BOTAN_DLL TLS_12_PRF : public KDF
{
public:
SecureVector<byte> derive(size_t key_len,
const byte secret[], size_t secret_len,
const byte seed[], size_t seed_len) const;
std::string name() const { return "TLSv12-PRF(" + hmac->name() + ")"; }
KDF* clone() const { return new TLS_12_PRF(hmac->clone()); }
TLS_12_PRF(MessageAuthenticationCode* hmac);
~TLS_12_PRF();
private:
MessageAuthenticationCode* hmac;
};
}
namespace Botan {
/**
* EMSA4 aka PSS-R
*/
class BOTAN_DLL EMSA4 : public EMSA
{
public:
/**
* @param hash the hash object to use
*/
EMSA4(HashFunction* hash);
/**
* @param hash the hash object to use
* @param salt_size the size of the salt to use in bytes
*/
EMSA4(HashFunction* hash, size_t salt_size);
~EMSA4() { delete hash; delete mgf; }
private:
void update(const byte[], size_t);
SecureVector<byte> raw_data();
SecureVector<byte> encoding_of(const MemoryRegion<byte>&, size_t,
RandomNumberGenerator& rng);
bool verify(const MemoryRegion<byte>&, const MemoryRegion<byte>&,
size_t);
size_t SALT_SIZE;
HashFunction* hash;
const MGF* mgf;
};
}
namespace Botan {
/**
* Camellia-128
*/
class BOTAN_DLL Camellia_128 : public Block_Cipher_Fixed_Params<16, 16>
{
public:
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
void clear() { SK.clear(); }
std::string name() const { return "Camellia-128"; }
BlockCipher* clone() const { return new Camellia_128; }
private:
void key_schedule(const byte key[], size_t length);
SecureVector<u64bit> SK;
};
/**
* Camellia-192
*/
class BOTAN_DLL Camellia_192 : public Block_Cipher_Fixed_Params<16, 24>
{
public:
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
void clear() { SK.clear(); }
std::string name() const { return "Camellia-192"; }
BlockCipher* clone() const { return new Camellia_192; }
private:
void key_schedule(const byte key[], size_t length);
SecureVector<u64bit> SK;
};
/**
* Camellia-256
*/
class BOTAN_DLL Camellia_256 : public Block_Cipher_Fixed_Params<16, 32>
{
public:
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
void clear() { SK.clear(); }
std::string name() const { return "Camellia-256"; }
BlockCipher* clone() const { return new Camellia_256; }
private:
void key_schedule(const byte key[], size_t length);
SecureVector<u64bit> SK;
};
}
namespace Botan {
/**
* MD4
*/
class BOTAN_DLL MD4 : public MDx_HashFunction
{
public:
std::string name() const { return "MD4"; }
size_t output_length() const { return 16; }
HashFunction* clone() const { return new MD4; }
void clear();
MD4() : MDx_HashFunction(64, false, true), M(16), digest(4)
{ clear(); }
protected:
void compress_n(const byte input[], size_t blocks);
void copy_out(byte[]);
/**
* The message buffer, exposed for use by subclasses (x86 asm)
*/
SecureVector<u32bit> M;
/**
* The digest value, exposed for use by subclasses (x86 asm)
*/
SecureVector<u32bit> digest;
};
}
namespace Botan {
/**
* Turing
*/
class BOTAN_DLL Turing : public StreamCipher
{
public:
void cipher(const byte in[], byte out[], size_t length);
void set_iv(const byte iv[], size_t iv_length);
bool valid_iv_length(size_t iv_len) const
{ return (iv_len % 4 == 0 && iv_len <= 16); }
Key_Length_Specification key_spec() const
{
return Key_Length_Specification(4, 32, 4);
}
void clear();
std::string name() const { return "Turing"; }
StreamCipher* clone() const { return new Turing; }
Turing() : S0(256), S1(256), S2(256), S3(256),
R(17), buffer(340), position(0) {}
private:
void key_schedule(const byte[], size_t);
void generate();
static u32bit fixedS(u32bit);
static const u32bit Q_BOX[256];
static const byte SBOX[256];
SecureVector<u32bit> S0, S1, S2, S3;
SecureVector<u32bit> R;
SecureVector<u32bit> K;
SecureVector<byte> buffer;
size_t position;
};
}
namespace Botan {
/**
* SRP6a Client side
* @param username the username we are attempting login for
* @param password the password we are attempting to use
* @param group_id specifies the shared SRP group
* @param hash_id specifies a secure hash function
* @param salt is the salt value sent by the server
* @param B is the server's public value
* @param rng is a random number generator
*
* @return (A,K) the client public key and the shared secret key
*/
std::pair<BigInt,SymmetricKey>
BOTAN_DLL srp6_client_agree(const std::string& username,
const std::string& password,
const std::string& group_id,
const std::string& hash_id,
const MemoryRegion<byte>& salt,
const BigInt& B,
RandomNumberGenerator& rng);
/**
* Generate a new SRP-6 verifier
* @param identifier a username or other client identifier
* @param password the secret used to authenticate user
* @param salt a randomly chosen value, at least 128 bits long
*/
BigInt BOTAN_DLL 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);
/**
* Return the group id for this SRP param set, or else thrown an
* exception
*/
std::string BOTAN_DLL srp6_group_identifier(const BigInt& N, const BigInt& g);
/**
* Represents a SRP-6a server session
*/
class BOTAN_DLL SRP6_Server_Session
{
public:
/**
* Server side step 1
* @param v the verification value saved from client registration
*/
BigInt step1(const BigInt& v,
const std::string& group_id,
const std::string& hash_id,
RandomNumberGenerator& rng);
SymmetricKey step2(const BigInt& A);
private:
std::string hash_id;
BigInt B, b, v, S, p;
size_t p_bytes;
};
}
namespace Botan {
/**
* SAFER-SK
*/
class BOTAN_DLL SAFER_SK : public Block_Cipher_Fixed_Params<8, 16>
{
public:
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
void clear() { zeroise(EK); }
std::string name() const;
BlockCipher* clone() const;
/**
* @param rounds the number of rounds to use - must be between 1
* and 13
*/
SAFER_SK(size_t rounds);
private:
size_t get_rounds() const { return (EK.size() - 8) / 16; }
void key_schedule(const byte[], size_t);
SecureVector<byte> EK;
};
}
namespace Botan {
/**
* CAST-128
*/
class BOTAN_DLL CAST_128 : public Block_Cipher_Fixed_Params<8, 11, 16>
{
public:
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
void clear() { zeroise(MK); zeroise(RK); }
std::string name() const { return "CAST-128"; }
BlockCipher* clone() const { return new CAST_128; }
CAST_128() : MK(16), RK(16) {}
private:
void key_schedule(const byte[], size_t);
static void cast_ks(MemoryRegion<u32bit>& ks,
MemoryRegion<u32bit>& user_key);
static const u32bit S5[256];
static const u32bit S6[256];
static const u32bit S7[256];
static const u32bit S8[256];
SecureVector<u32bit> MK, RK;
};
extern const u32bit CAST_SBOX1[256];
extern const u32bit CAST_SBOX2[256];
extern const u32bit CAST_SBOX3[256];
extern const u32bit CAST_SBOX4[256];
}
namespace Botan {
/**
* PKCS #5 v2.0 PBE
*/
class BOTAN_DLL PBE_PKCS5v20 : public PBE
{
public:
/**
* @param cipher names a block cipher
* @return true iff PKCS #5 knows how to use this cipher
*/
static bool known_cipher(const std::string& cipher);
std::string name() const;
void write(const byte[], size_t);
void start_msg();
void end_msg();
/**
* Load a PKCS #5 v2.0 encrypted stream
* @param input is the input source
*/
PBE_PKCS5v20(DataSource& input);
/**
* @param cipher the block cipher to use
* @param hash the hash function to use
*/
PBE_PKCS5v20(BlockCipher* cipher, HashFunction* hash);
~PBE_PKCS5v20();
private:
void set_key(const std::string&);
void new_params(RandomNumberGenerator& rng);
MemoryVector<byte> encode_params() const;
void decode_params(DataSource&);
OID get_oid() const;
void flush_pipe(bool);
Cipher_Dir direction;
BlockCipher* block_cipher;
HashFunction* hash_function;
SecureVector<byte> salt, key, iv;
size_t iterations, key_length;
Pipe pipe;
};
}
namespace Botan {
/**
* Algorithm benchmark
* @param name the name of the algorithm to test (cipher, hash, or MAC)
* @param af the algorithm factory used to create objects
* @param rng the rng to use to generate random inputs
* @param milliseconds total time for the benchmark to run
* @param buf_size size of buffer to benchmark against, in KiB
* @return results a map from provider to speed in mebibytes per second
*/
std::map<std::string, double>
BOTAN_DLL algorithm_benchmark(const std::string& name,
Algorithm_Factory& af,
RandomNumberGenerator& rng,
u32bit milliseconds,
size_t buf_size);
}
namespace Botan {
/**
* CBC-MAC
*/
class BOTAN_DLL CBC_MAC : public MessageAuthenticationCode
{
public:
std::string name() const;
MessageAuthenticationCode* clone() const;
size_t output_length() const { return e->block_size(); }
void clear();
Key_Length_Specification key_spec() const
{
return e->key_spec();
}
/**
* @param cipher the underlying block cipher to use
*/
CBC_MAC(BlockCipher* cipher);
~CBC_MAC();
private:
void add_data(const byte[], size_t);
void final_result(byte[]);
void key_schedule(const byte[], size_t);
BlockCipher* e;
SecureVector<byte> state;
size_t position;
};
}
namespace Botan {
/**
* MARS, IBM's candidate for AES
*/
class BOTAN_DLL MARS : public Block_Cipher_Fixed_Params<16, 16, 32, 4>
{
public:
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
void clear() { zeroise(EK); }
std::string name() const { return "MARS"; }
BlockCipher* clone() const { return new MARS; }
MARS() : EK(40) {}
private:
void key_schedule(const byte[], size_t);
SecureVector<u32bit> EK;
};
}
namespace Botan {
/**
* PKCS #5 PBKDF2
*/
class BOTAN_DLL PKCS5_PBKDF2 : public PBKDF
{
public:
std::string name() const
{
return "PBKDF2(" + mac->name() + ")";
}
PBKDF* clone() const
{
return new PKCS5_PBKDF2(mac->clone());
}
OctetString derive_key(size_t output_len,
const std::string& passphrase,
const byte salt[], size_t salt_len,
size_t iterations) const;
/**
* Create a PKCS #5 instance using the specified message auth code
* @param mac_fn the MAC to use
*/
PKCS5_PBKDF2(MessageAuthenticationCode* mac_fn) : mac(mac_fn) {}
/**
* Destructor
*/
~PKCS5_PBKDF2() { delete mac; }
private:
MessageAuthenticationCode* mac;
};
}
namespace Botan {
class Algorithm_Factory;
/**
* Encrypt a key under a key encryption key using the algorithm
* described in RFC 3394
*
* @param key the plaintext key to encrypt
* @param kek the key encryption key
* @param af an algorithm factory
* @return key encrypted under kek
*/
SecureVector<byte> BOTAN_DLL rfc3394_keywrap(const MemoryRegion<byte>& key,
const SymmetricKey& kek,
Algorithm_Factory& af);
/**
* Decrypt a key under a key encryption key using the algorithm
* described in RFC 3394
*
* @param key the encrypted key to decrypt
* @param kek the key encryption key
* @param af an algorithm factory
* @return key decrypted under kek
*/
SecureVector<byte> BOTAN_DLL rfc3394_keyunwrap(const MemoryRegion<byte>& key,
const SymmetricKey& kek,
Algorithm_Factory& af);
}
namespace Botan {
/**
* DLIES Encryption
*/
class BOTAN_DLL DLIES_Encryptor : public PK_Encryptor
{
public:
DLIES_Encryptor(const PK_Key_Agreement_Key&,
KDF* kdf,
MessageAuthenticationCode* mac,
size_t mac_key_len = 20);
~DLIES_Encryptor();
void set_other_key(const MemoryRegion<byte>&);
private:
SecureVector<byte> enc(const byte[], size_t,
RandomNumberGenerator&) const;
size_t maximum_input_size() const;
SecureVector<byte> other_key, my_key;
PK_Key_Agreement ka;
KDF* kdf;
MessageAuthenticationCode* mac;
size_t mac_keylen;
};
/**
* DLIES Decryption
*/
class BOTAN_DLL DLIES_Decryptor : public PK_Decryptor
{
public:
DLIES_Decryptor(const PK_Key_Agreement_Key&,
KDF* kdf,
MessageAuthenticationCode* mac,
size_t mac_key_len = 20);
~DLIES_Decryptor();
private:
SecureVector<byte> dec(const byte[], size_t) const;
SecureVector<byte> my_key;
PK_Key_Agreement ka;
KDF* kdf;
MessageAuthenticationCode* mac;
size_t mac_keylen;
};
}
namespace Botan {
/**
* Output Feedback Mode
*/
class BOTAN_DLL OFB : public StreamCipher
{
public:
void cipher(const byte in[], byte out[], size_t length);
void set_iv(const byte iv[], size_t iv_len);
bool valid_iv_length(size_t iv_len) const
{ return (iv_len <= permutation->block_size()); }
Key_Length_Specification key_spec() const
{
return permutation->key_spec();
}
std::string name() const;
OFB* clone() const
{ return new OFB(permutation->clone()); }
void clear();
/**
* @param cipher the underlying block cipher to use
*/
OFB(BlockCipher* cipher);
~OFB();
private:
void key_schedule(const byte key[], size_t key_len);
BlockCipher* permutation;
SecureVector<byte> buffer;
size_t position;
};
}
namespace Botan {
/**
* Blowfish
*/
class BOTAN_DLL Blowfish : public Block_Cipher_Fixed_Params<8, 1, 56>
{
public:
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
/**
* Modified EKSBlowfish key schedule, used for bcrypt password hashing
*/
void eks_key_schedule(const byte key[], size_t key_length,
const byte salt[16], size_t workfactor);
void clear();
std::string name() const { return "Blowfish"; }
BlockCipher* clone() const { return new Blowfish; }
Blowfish() : S(1024), P(18) {}
private:
void key_schedule(const byte key[], size_t length);
void key_expansion(const byte key[],
size_t key_length,
const byte salt[16]);
void generate_sbox(MemoryRegion<u32bit>& box,
u32bit& L, u32bit& R,
const byte salt[16],
size_t salt_off) const;
static const u32bit P_INIT[18];
static const u32bit S_INIT[1024];
SecureVector<u32bit> S;
SecureVector<u32bit> P;
};
}
namespace Botan {
/**
* The Adler32 checksum, used in zlib
*/
class BOTAN_DLL Adler32 : public HashFunction
{
public:
std::string name() const { return "Adler32"; }
size_t output_length() const { return 4; }
HashFunction* clone() const { return new Adler32; }
void clear() { S1 = 1; S2 = 0; }
Adler32() { clear(); }
~Adler32() { clear(); }
private:
void add_data(const byte[], size_t);
void final_result(byte[]);
u16bit S1, S2;
};
}
namespace Botan {
/**
* Parallel Hashes
*/
class BOTAN_DLL Parallel : public HashFunction
{
public:
void clear();
std::string name() const;
HashFunction* clone() const;
size_t output_length() const;
/**
* @param hashes a set of hashes to compute in parallel
*/
Parallel(const std::vector<HashFunction*>& hashes);
~Parallel();
private:
void add_data(const byte[], size_t);
void final_result(byte[]);
std::vector<HashFunction*> hashes;
};
}
namespace Botan {
/**
* RC5
*/
class BOTAN_DLL RC5 : public Block_Cipher_Fixed_Params<8, 1, 32>
{
public:
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
void clear() { zeroise(S); }
std::string name() const;
BlockCipher* clone() const { return new RC5(get_rounds()); }
/**
* @param rounds the number of RC5 rounds to run. Must be between
* 8 and 32 and a multiple of 4.
*/
RC5(size_t rounds);
private:
size_t get_rounds() const { return (S.size() - 2) / 2; }
void key_schedule(const byte[], size_t);
SecureVector<u32bit> S;
};
}
namespace Botan {
/**
* Run a set of self tests on some basic algorithms like AES and SHA-1
* @param af an algorithm factory
* @throws Self_Test_Error if a failure occured
*/
BOTAN_DLL void confirm_startup_self_tests(Algorithm_Factory& af);
/**
* Run a set of self tests on some basic algorithms like AES and SHA-1
* @param af an algorithm factory
* @returns false if a failure occured, otherwise true
*/
BOTAN_DLL bool passes_self_tests(Algorithm_Factory& af);
/**
* Run a set of algorithm KATs (known answer tests)
* @param algo_name the algorithm we are testing
* @param vars a set of input variables for this test, all
hex encoded. Keys used: "input", "output", "key", and "iv"
* @param af an algorithm factory
* @returns map from provider name to test result for that provider
*/
BOTAN_DLL std::map<std::string, bool>
algorithm_kat(const SCAN_Name& algo_name,
const std::map<std::string, std::string>& vars,
Algorithm_Factory& af);
}
namespace Botan {
/**
* Noekeon implementation using SIMD operations
*/
class BOTAN_DLL Noekeon_SIMD : public Noekeon
{
public:
size_t parallelism() const { return 4; }
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
BlockCipher* clone() const { return new Noekeon_SIMD; }
};
}
namespace Botan {
/**
* PKCS #5 v1.5 PBE
*/
class BOTAN_DLL PBE_PKCS5v15 : public PBE
{
public:
std::string name() const;
void write(const byte[], size_t);
void start_msg();
void end_msg();
/**
* @param cipher the block cipher to use (DES or RC2)
* @param hash the hash function to use
* @param direction are we encrypting or decrypting
*/
PBE_PKCS5v15(BlockCipher* cipher,
HashFunction* hash,
Cipher_Dir direction);
~PBE_PKCS5v15();
private:
void set_key(const std::string&);
void new_params(RandomNumberGenerator& rng);
MemoryVector<byte> encode_params() const;
void decode_params(DataSource&);
OID get_oid() const;
void flush_pipe(bool);
Cipher_Dir direction;
BlockCipher* block_cipher;
HashFunction* hash_function;
SecureVector<byte> salt, key, iv;
size_t iterations;
Pipe pipe;
};
}
namespace Botan {
/**
* CTR-BE (Counter mode, big-endian)
*/
class BOTAN_DLL CTR_BE : public StreamCipher
{
public:
void cipher(const byte in[], byte out[], size_t length);
void set_iv(const byte iv[], size_t iv_len);
bool valid_iv_length(size_t iv_len) const
{ return (iv_len <= permutation->block_size()); }
Key_Length_Specification key_spec() const
{
return permutation->key_spec();
}
std::string name() const;
CTR_BE* clone() const
{ return new CTR_BE(permutation->clone()); }
void clear();
/**
* @param cipher the underlying block cipher to use
*/
CTR_BE(BlockCipher* cipher);
~CTR_BE();
private:
void key_schedule(const byte key[], size_t key_len);
void increment_counter();
BlockCipher* permutation;
SecureVector<byte> counter, buffer;
size_t position;
};
}
namespace Botan {
/**
* Randpool
*/
class BOTAN_DLL Randpool : public RandomNumberGenerator
{
public:
void randomize(byte[], size_t);
bool is_seeded() const { return seeded; }
void clear();
std::string name() const;
void reseed(size_t bits_to_collect);
void add_entropy_source(EntropySource* es);
void add_entropy(const byte input[], size_t length);
/**
* @param cipher a block cipher to use
* @param mac a message authentication code to use
* @param pool_blocks how many cipher blocks to use for the pool
* @param iterations_before_reseed how many times we'll use the
* internal state to generate output before reseeding
*/
Randpool(BlockCipher* cipher,
MessageAuthenticationCode* mac,
size_t pool_blocks = 32,
size_t iterations_before_reseed = 128);
~Randpool();
private:
void update_buffer();
void mix_pool();
size_t ITERATIONS_BEFORE_RESEED, POOL_BLOCKS;
BlockCipher* cipher;
MessageAuthenticationCode* mac;
std::vector<EntropySource*> entropy_sources;
SecureVector<byte> pool, buffer, counter;
bool seeded;
};
}
namespace Botan {
/**
* PRF used in SSLv3
*/
class BOTAN_DLL SSL3_PRF : public KDF
{
public:
SecureVector<byte> derive(size_t, const byte[], size_t,
const byte[], size_t) const;
std::string name() const { return "SSL3-PRF"; }
KDF* clone() const { return new SSL3_PRF; }
};
}
namespace Botan {
/**
* DES/3DES-based MAC from ANSI X9.19
*/
class BOTAN_DLL ANSI_X919_MAC : public MessageAuthenticationCode
{
public:
void clear();
std::string name() const;
size_t output_length() const { return e->block_size(); }
MessageAuthenticationCode* clone() const;
Key_Length_Specification key_spec() const
{
return Key_Length_Specification(8, 16, 8);
}
/**
* @param cipher the underlying block cipher to use
*/
ANSI_X919_MAC(BlockCipher* cipher);
~ANSI_X919_MAC();
private:
void add_data(const byte[], size_t);
void final_result(byte[]);
void key_schedule(const byte[], size_t);
BlockCipher* e;
BlockCipher* d;
SecureVector<byte> state;
size_t position;
};
}
#endif // USE_SYSTEM_BOTAN
#endif // BOTAN_AMALGAMATION_H__