Commit 1a14abb4 authored by Michael Hamburg's avatar Michael Hamburg

Separate .h files for SHA/SHAKE, STROBE and sponge RNG. TODO: .hxx. Also add a lot of docs

parent 957ec6cd
......@@ -751,7 +751,7 @@ WARN_LOGFILE =
# spaces.
# Note: If this tag is empty the current directory is searched.
INPUT = include
INPUT = build/include
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
......@@ -1548,7 +1548,7 @@ EXTRA_SEARCH_MAPPINGS =
# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output.
# The default value is: YES.
GENERATE_LATEX = YES
GENERATE_LATEX = NO
# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
......
......@@ -243,8 +243,8 @@ $(BUILD_DOC)/timestamp:
mkdir -p `dirname $@`
touch $@
#
# doc: Doxyfile $(BUILD_OBJ)/timestamp $(HEADERS) src/*.c src/$(FIELD)/$(ARCH)/*.c src/$(FIELD)/$(ARCH)/*.h
# doxygen > /dev/null
doc: Doxyfile $(BUILD_OBJ)/timestamp $(HEADERS)
doxygen > /dev/null
# # The eBATS benchmarking script
# bat: $(BATNAME)
......
......@@ -3,14 +3,18 @@ from gen_file import gen_file
crypto_h = gen_file(
name = "decaf/crypto_%(shortname)s.h",
doc = """
@brief Example Decaf crypto routines.
Example Decaf crypto routines.
@warning These are merely examples, though they ought to be secure. But real
protocols will decide differently on magic numbers, formats, which items to
hash, etc.
@warning Experimental! The names, parameter orders etc are likely to change.
""", code = """
#include <decaf/%(c_ns)s.h>
#include <decaf/shake.h>
#include <decaf/strobe.h>
#ifdef __cplusplus
extern "C" {
#endif
/** Number of bytes for a symmetric key (expanded to full key) */
#define %(C_NS)s_SYMMETRIC_KEY_BYTES 32
......@@ -39,13 +43,9 @@ typedef struct {
%(c_ns)s_private_key_s,
/** A private key (gmp array[1] style). */
%(c_ns)s_private_key_t[1];
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Derive a key from its compressed form.
* Derive a key from its compressed form.
* @param [out] priv The derived private key.
* @param [in] proto The compressed or proto-key, which must be 32 random bytes.
*/
......@@ -55,14 +55,14 @@ void %(c_ns)s_derive_private_key (
) NONNULL2 API_VIS;
/**
* @brief Destroy a private key.
* Destroy a private key.
*/
void %(c_ns)s_destroy_private_key (
%(c_ns)s_private_key_t priv
) NONNULL1 API_VIS;
/**
* @brief Convert a private key to a public one.
* Convert a private key to a public one.
* @param [out] pub The extracted private key.
* @param [in] priv The private key.
*/
......@@ -72,7 +72,7 @@ void %(c_ns)s_private_to_public (
) NONNULL2 API_VIS;
/**
* @brief Compute a Diffie-Hellman shared secret.
* Compute a Diffie-Hellman shared secret.
*
* This is an example routine; real protocols would use something
* protocol-specific.
......@@ -96,7 +96,7 @@ decaf_error_t
) NONNULL134 WARN_UNUSED API_VIS;
/**
* @brief Sign a message from a STROBE context.
* Sign a message from a STROBE context.
*
* @param [out] sig The signature.
* @param [in] priv Your private key.
......@@ -110,7 +110,7 @@ void
) NONNULL3 API_VIS;
/**
* @brief Sign a message.
* Sign a message.
*
* @param [out] sig The signature.
* @param [in] priv Your private key.
......@@ -126,7 +126,7 @@ void
) NONNULL3 API_VIS;
/**
* @brief Verify a signed message from its STROBE context.
* Verify a signed message from its STROBE context.
*
* @param [in] sig The signature.
* @param [in] pub The public key.
......@@ -143,7 +143,7 @@ decaf_error_t
) NONNULL3 API_VIS WARN_UNUSED;
/**
* @brief Verify a signed message.
* Verify a signed message.
*
* @param [in] sig The signature.
* @param [in] pub The public key.
......
......@@ -3,7 +3,7 @@ from gen_file import gen_file
crypto_hxx = gen_file(
name = "decaf/crypto_%(shortname)s.hxx",
doc = """
@brief Example Decaf cyrpto routines, C++ wrapper.
Example Decaf cyrpto routines, C++ wrapper.
@warning These are merely examples, though they ought to be secure. But real
protocols will decide differently on magic numbers, formats, which items to
hash, etc.
......@@ -21,51 +21,56 @@ crypto_hxx = gen_file(
/** @endcond */
namespace decaf {
/** A public key for crypto over some Group */
template <typename Group> class PublicKey;
/** A private key for crypto over some Group */
template <typename Group> class PrivateKey;
/** A public key for crypto over %(name)s */
template<> class PublicKey<%(cxx_ns)s>
: public Serializable< PublicKey<%(cxx_ns)s> > {
private:
/** @cond internal */
typedef %(c_ns)s_public_key_t Wrapped;
Wrapped wrapped;
template<class Group> friend class PrivateKey;
/** @endcond */
public:
/** @brief Underlying group */
/** Underlying group */
typedef %(cxx_ns)s Group;
/** @brief Signature size. */
/** Signature size. */
static const size_t SIG_BYTES = sizeof(%(c_ns)s_signature_t);
/** @brief Serialization size. */
/** Serialization size. */
static const size_t SER_BYTES = sizeof(Wrapped);
/* TODO: convenience types like signature? */
/** @brief Read a private key from a string*/
/** Read a private key from a string*/
inline explicit PublicKey(const FixedBlock<SER_BYTES> &b) NOEXCEPT {
memcpy(wrapped,b.data(),sizeof(wrapped));
}
/** @brief Read a private key from a string*/
/** Read a private key from a string*/
inline explicit PublicKey(const PrivateKey<%(cxx_ns)s> &b) NOEXCEPT;
/** @brief Create but don't initialize */
/** Create but don't initialize */
inline explicit PublicKey(const NOINIT&) NOEXCEPT { }
/** @brief Serialize into a buffer. */
/** Serialize into a buffer. */
inline void serializeInto(unsigned char *x) const NOEXCEPT {
memcpy(x,wrapped,sizeof(wrapped));
}
/** @brief Serialization size. */
/** Serialization size. */
inline size_t serSize() const NOEXCEPT { return SER_BYTES; }
/* TODO: verify_strobe */
/** @brief Verify a message */
/** Verify a message */
inline void verify(
const Block &message,
const FixedBlock<SIG_BYTES> &sig
......@@ -76,71 +81,73 @@ public:
}
};
/** A private key for crypto over %(name)s */
template<> class PrivateKey<%(cxx_ns)s>
: public Serializable< PrivateKey<%(cxx_ns)s> > {
private:
/** @cond internal */
typedef %(c_ns)s_private_key_t Wrapped;
Wrapped wrapped;
template<class Group> friend class PublicKey;
/** @endcond */
public:
/** @brief Underlying group */
/** Underlying group */
typedef %(cxx_ns)s Group;
/** @brief Signature size. */
/** Signature size. */
static const size_t SIG_BYTES = sizeof(%(c_ns)s_signature_t);
/** @brief Serialization size. */
/** Serialization size. */
static const size_t SER_BYTES = sizeof(Wrapped);
/** @brief Compressed size. */
/** Compressed size. */
static const size_t SYM_BYTES = %(C_NS)s_SYMMETRIC_KEY_BYTES;
/** @brief Create but don't initialize */
/** Create but don't initialize */
inline explicit PrivateKey(const NOINIT&) NOEXCEPT { }
/** @brief Read a private key from a string*/
/** Read a private key from a string*/
inline explicit PrivateKey(const FixedBlock<SER_BYTES> &b) NOEXCEPT {
memcpy(wrapped,b.data(),sizeof(wrapped));
}
/** @brief Read a private key from a string*/
/** Read a private key from a string*/
inline explicit PrivateKey(const FixedBlock<SYM_BYTES> &b) NOEXCEPT {
%(c_ns)s_derive_private_key(wrapped, b.data());
}
/** @brief Create at random */
/** Create at random */
inline explicit PrivateKey(Rng &r) NOEXCEPT {
FixedArrayBuffer<SYM_BYTES> tmp(r);
%(c_ns)s_derive_private_key(wrapped, tmp.data());
}
/** @brief Secure destructor */
/** Secure destructor */
inline ~PrivateKey() NOEXCEPT {
%(c_ns)s_destroy_private_key(wrapped);
}
/** @brief Serialization size. */
/** Serialization size. */
inline size_t serSize() const NOEXCEPT { return SER_BYTES; }
/** @brief Serialize into a buffer. */
/** Serialize into a buffer. */
inline void serializeInto(unsigned char *x) const NOEXCEPT {
memcpy(x,wrapped,sizeof(wrapped));
}
/** @brief Compressed serialize. */
/** Compressed serialize. */
inline SecureBuffer compress() const throw(std::bad_alloc) {
SecureBuffer ret(sizeof(wrapped->sym));
memcpy(ret.data(),wrapped->sym,sizeof(wrapped->sym));
return ret;
}
/** @brief Get the public key */
/** Get the public key */
inline PublicKey<%(cxx_ns)s> pub() const NOEXCEPT {
PublicKey<%(cxx_ns)s> ret(*this); return ret;
}
/** @brief Derive a shared secret */
/** Derive a shared secret */
inline SecureBuffer sharedSecret(
const PublicKey<%(cxx_ns)s> &pub,
size_t bytes,
......@@ -153,7 +160,7 @@ public:
return ret;
}
/** @brief Sign a message. */
/** Sign a message. */
inline SecureBuffer sign(const Block &message) const {
SecureBuffer sig(SIG_BYTES);
%(c_ns)s_sign(sig.data(), wrapped, message.data(), message.size());
......
......@@ -10,19 +10,23 @@ decaf_h = gen_file(
extern "C" {
#endif
/** @cond internal */
#define %(C_NS)s_LIMBS (%(gf_bits)d/DECAF_WORD_BITS)
#define %(C_NS)s_SCALAR_BITS %(scalar_bits)d
#define %(C_NS)s_SCALAR_LIMBS ((%(scalar_bits)d-1)/DECAF_WORD_BITS+1)
/** @endcond */
/** The number of bits in a scalar */
#define %(C_NS)s_SCALAR_BITS %(scalar_bits)d
/** Galois field element internal structure */
/** @cond internal */
#ifndef __%(C_NS)s_GF_DEFINED__
#define __%(C_NS)s_GF_DEFINED__ 1
/** @brief Galois field element internal structure */
typedef struct gf_%(longnum)s_s {
/** @cond internal */
decaf_word_t limb[%(C_NS)s_LIMBS];
/** @endcond */
} __attribute__((aligned(32))) gf_%(longnum)s_s, gf_%(longnum)s_t[1];
#endif /* __%(C_NS)s_GF_DEFINED__ */
/** @endcond */
/** Number of bytes in a serialized point. */
#define %(C_NS)s_SER_BYTES %(ser_bytes)d
......@@ -393,16 +397,17 @@ void %(c_ns)s_point_double_scalarmul (
const %(c_ns)s_scalar_t scalar2
) API_VIS NONNULL5 NOINLINE;
/*
* @brief Multiply one base point by two scalars:
/**
* Multiply one base point by two scalars:
*
* a1 = scalar1 * base
* a2 = scalar2 * base
*
* Equivalent to two calls to %(c_ns)s_point_scalarmul, but may be
* faster.
*
* @param [out] a1 The first multiple
* @param [out] a2 The second multiple
* @param [out] a1 The first multiple. It may be the same as the input point.
* @param [out] a2 The second multiple. It may be the same as the input point.
* @param [in] base1 A point to be scaled.
* @param [in] scalar1 A first scalar to multiply by.
* @param [in] scalar2 A second scalar to multiply by.
......@@ -410,7 +415,7 @@ void %(c_ns)s_point_double_scalarmul (
void %(c_ns)s_point_dual_scalarmul (
%(c_ns)s_point_t a1,
%(c_ns)s_point_t a2,
const %(c_ns)s_point_t b,
const %(c_ns)s_point_t base1,
const %(c_ns)s_scalar_t scalar1,
const %(c_ns)s_scalar_t scalar2
) API_VIS NONNULL5 NOINLINE;
......@@ -441,7 +446,7 @@ void %(c_ns)s_base_double_scalarmul_non_secret (
* @brief Constant-time decision between two points. If pick_b
* is zero, out = a; else out = b.
*
* @param [out] q The output. It may be the same as either input.
* @param [out] out The output. It may be the same as either input.
* @param [in] a Any point.
* @param [in] b Any point.
* @param [in] pick_b If nonzero, choose point b.
......@@ -457,7 +462,7 @@ void %(c_ns)s_point_cond_sel (
* @brief Constant-time decision between two scalars. If pick_b
* is zero, out = a; else out = b.
*
* @param [out] q The output. It may be the same as either input.
* @param [out] out The output. It may be the same as either input.
* @param [in] a Any scalar.
* @param [in] b Any scalar.
* @param [in] pick_b If nonzero, choose scalar b.
......
This diff is collapsed.
......@@ -34,8 +34,8 @@ crypto_h_code = "\n".join((
))
crypto_h = gen_file(
name = "decaf/crypto.h",
doc = """@brief
@brief Example Decaf crypto routines, metaheader.
doc = """
Example Decaf crypto routines, metaheader.
@warning These are merely examples, though they ought to be secure. But real
protocols will decide differently on magic numbers, formats, which items to
hash, etc.
......@@ -50,8 +50,8 @@ crypto_hxx_code = "\n".join((
))
crypto_hxx = gen_file(
name = "decaf/crypto.hxx",
doc = """@brief
@brief Example Decaf crypto routines, C++, metaheader.
doc = """
Example Decaf crypto routines, C++, metaheader.
@warning These are merely examples, though they ought to be secure. But real
protocols will decide differently on magic numbers, formats, which items to
hash, etc.
......@@ -67,7 +67,7 @@ root_h_code = "\n".join((
decaf_root_hxx = gen_file(
name = "decaf.h",
doc = """
@brief Master header for Decaf library.
Master header for Decaf library.
The Decaf library implements cryptographic operations on a elliptic curve
groups of prime order p. It accomplishes this by using a twisted Edwards
......
......@@ -15,6 +15,10 @@
#include <stdint.h>
#include <sys/types.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Goldilocks' build flags default to hidden and stripping executables. */
/** @cond internal */
#if defined(DOXYGEN) && !defined(__attribute__)
......@@ -43,27 +47,28 @@
*/
#if (defined(__ILP64__) || defined(__amd64__) || defined(__x86_64__) || (((__UINT_FAST32_MAX__)>>30)>>30)) \
&& !defined(DECAF_FORCE_32_BIT)
#define DECAF_WORD_BITS 64
typedef uint64_t decaf_word_t, decaf_bool_t;
typedef __uint128_t decaf_dword_t;
#define DECAF_WORD_BITS 64 /**< The number of bits in a word */
typedef uint64_t decaf_word_t; /**< Word size for internal computations */
typedef uint64_t decaf_bool_t; /**< "Boolean" type, will be set to all-zero or all-one (i.e. -1u) */
typedef __uint128_t decaf_dword_t; /**< Double-word size for internal computations */
#else
#define DECAF_WORD_BITS 32
typedef uint32_t decaf_word_t, decaf_bool_t;
typedef uint64_t decaf_dword_t;
#endif
#ifdef __cplusplus
extern "C" {
#define DECAF_WORD_BITS 32 /**< The number of bits in a word */
typedef uint32_t decaf_word_t; /**< Word size for internal computations */
typedef uint32_t decaf_bool_t; /**< "Boolean" type, will be set to all-zero or all-one (i.e. -1u) */
typedef uint64_t decaf_dword_t; /**< Double-word size for internal computations */
#endif
/** DECAF_TRUE = -1 so that DECAF_TRUE & x = x */
static const decaf_bool_t DECAF_TRUE = -(decaf_bool_t)1, DECAF_FALSE = 0;
static const decaf_bool_t DECAF_TRUE = -(decaf_bool_t)1;
/** DECAF_FALSE = 0 so that DECAF_FALSE & x = 0 */
static const decaf_bool_t DECAF_FALSE = 0;
/* Success or failure */
/** Another boolean type used to indicate success or failure. */
// FIXME: deploy project-wide
typedef enum {
DECAF_SUCCESS = -1,
DECAF_FAILURE = 0
DECAF_SUCCESS = -1, /**< The operation succeeded. */
DECAF_FAILURE = 0 /**< The operation failed. */
} decaf_error_t;
......
......@@ -48,46 +48,30 @@ public:
typedef const T& const_reference;
typedef size_t size_type;
typedef std::ptrdiff_t difference_type;
template<typename U> struct rebind { typedef SanitizingAllocator<U> other; };
inline SanitizingAllocator() NOEXCEPT {}
inline ~SanitizingAllocator() NOEXCEPT {}
inline SanitizingAllocator(const SanitizingAllocator &) NOEXCEPT {}
template<typename U, size_t a> inline SanitizingAllocator(const SanitizingAllocator<U, a> &) NOEXCEPT {}
inline T* address(T& r) const NOEXCEPT { return &r; }
inline const T* address(const T& r) const NOEXCEPT { return &r; }
inline T* allocate (
size_type cnt,
size_type cnt,
typename std::allocator<void>::const_pointer = 0
) throw(std::bad_alloc) {
void *v;
int ret = 0;
if (alignment) ret = posix_memalign(&v, alignment, cnt * sizeof(T));
else v = malloc(cnt * sizeof(T));
if (ret || v==NULL) throw(std::bad_alloc());
return reinterpret_cast<T*>(v);
}
inline void deallocate(T* p, size_t size) NOEXCEPT {
if (p==NULL) return;
really_bzero(reinterpret_cast<void*>(p), size);
free(reinterpret_cast<void*>(p));
}
) throw(std::bad_alloc);
inline void deallocate(T* p, size_t size) NOEXCEPT;
inline size_t max_size() const NOEXCEPT { return std::numeric_limits<size_t>::max() / sizeof(T); }
inline void construct(T* p, const T& t) { new(p) T(t); }
inline void destroy(T* p) { p->~T(); }
inline bool operator==(SanitizingAllocator const&) const NOEXCEPT { return true; }
inline bool operator!=(SanitizingAllocator const&) const NOEXCEPT { return false; }
/** @endcond */
};
/** A variant of std::vector which securely zerozes its state when destructed. */
typedef std::vector<unsigned char, SanitizingAllocator<unsigned char, 0> > SecureBuffer;
/** Constant-time compare two buffers */
......@@ -170,8 +154,10 @@ public:
/** A reference to a block of data, which (when accessed through this base class) is const. */
class Block {
protected:
/** @cond internal */
unsigned char *data_;
size_t size_;
/** @endcond */
public:
/** Null initialization */
......@@ -219,13 +205,13 @@ public:
return Block(data()+off, length);
}
/* Content-wise comparison; constant-time if they are the same length. */
/** Content-wise comparison; constant-time if they are the same length. */
inline decaf_bool_t contents_equal(const Block &b) const NOEXCEPT {
if (b.size() != size()) return false;
return decaf_memeq(b.data(),data(),size());
}
/* Create new block from this */
/** Create new block from this */
inline operator SecureBuffer() const throw(std::bad_alloc) {
return SecureBuffer(data_,data_+size_);
}
......@@ -304,7 +290,9 @@ public:
inline void zeroize() NOEXCEPT { really_bzero(data(),size()); }
private:
/** @cond internal */
inline void operator= (const Block &b) const NOEXCEPT DELETE;
/** @endcond */
};
......@@ -330,7 +318,9 @@ public:
}
private:
/** @cond internal */
inline void operator= (const Block &b) const NOEXCEPT DELETE;
/** @endcond */
};
/** A fixed-size stack-allocated buffer (for NOEXCEPT semantics) */
......@@ -464,6 +454,35 @@ protected:
};
/** @endcond */
/*******************************************/
/* Inline implementations below this point */
/*******************************************/
/** @cond internal */
template<typename T, size_t alignment>
T* SanitizingAllocator<T,alignment>::allocate (
size_type cnt,
typename std::allocator<void>::const_pointer
) throw(std::bad_alloc) {
void *v;
int ret = 0;
if (alignment) ret = posix_memalign(&v, alignment, cnt * sizeof(T));
else v = malloc(cnt * sizeof(T));
if (ret || v==NULL) throw(std::bad_alloc());
return reinterpret_cast<T*>(v);
}
template<typename T, size_t alignment>
void SanitizingAllocator<T,alignment>::deallocate(T* p, size_t size) NOEXCEPT {
if (p==NULL) return;
really_bzero(reinterpret_cast<void*>(p), size);
free(reinterpret_cast<void*>(p));
}
/** @endcond */
} /* namespace decaf */
......
This diff is collapsed.
......@@ -13,6 +13,9 @@
#define __SHAKE_HXX__
#include <decaf/shake.h>
#include <decaf/strobe.h> /* TODO remove */
#include <decaf/spongerng.h> /* TODO remove */
#include <string>
#include <sys/types.h>
#include <errno.h>
......@@ -32,6 +35,7 @@ namespace decaf {
/** A Keccak sponge internal class */
class KeccakSponge {
protected:
/** @cond internal */
/** The C-wrapper sponge state */
keccak_sponge_t sp;
......@@ -40,6 +44,7 @@ protected:
/** No initialization */
inline KeccakSponge(const NOINIT &) NOEXCEPT { }
/** @endcond */
public:
/** Destructor zeroizes state */
......@@ -149,13 +154,16 @@ public:
/** Sponge-based random-number generator */
class SpongeRng : public Rng, private KeccakSponge {
public:
/** Exception thrown when The RNG fails (to seed itself) */
class RngException : public std::exception {
private:
/** @cond internal */
const char *const what_;
/** @endcond */
public:
const int err_code;
const char *what() const NOEXCEPT { return what_; }
RngException(int err_code, const char *what_) NOEXCEPT : what_(what_), err_code(err_code) {}
const int err_code; /**< errno that caused the reseed to fail. */
const char *what() const NOEXCEPT { return what_; } /**< Description of exception. */
RngException(int err_code, const char *what_) NOEXCEPT : what_(what_), err_code(err_code) {} /**< Construct */
};
/** Initialize, deterministically by default, from block */
......@@ -189,116 +197,127 @@ private:
};
/**@endcond*/
/** STROBE protocol framework object */
class Strobe : private KeccakSponge {
public:
/* TODO: pull out parameters */
/** Number of bytes in a default authentication size. */
static const uint16_t DEFAULT_AUTH_SIZE = 16;
/** Am I a server or a client? */
enum client_or_server { SERVER, CLIENT };
/** Create protocol object. */
inline Strobe (
const char *description,
client_or_server whoami,
const kparams_s &params = STROBE_256
const char *description, /**< Description of this protocol. */
client_or_server whoami, /**< Am I client or server? */
const kparams_s &params = STROBE_256 /**< Strength parameters */
) NOEXCEPT : KeccakSponge(NOINIT()) {
strobe_init(sp, &params, description, whoami == CLIENT);
keyed = false;
}
/** Stir in fixed key, from a C++ block. */
inline void fixed_key (
const Block &data
const Block &data /**< The key. */
) throw(ProtocolException) {
strobe_fixed_key(sp, data.data(), data.size());
keyed = true;
}
/** Stir in fixed key, from a serializeable object. */
template<class T> inline void fixed_key (
const Serializable<T> &data
const Serializable<T> &data /**< The key. */
) throw(ProtocolException) {
fixed_key(data.serialize());
}
/** Stir in DH key, from a C++ block. */
inline void dh_key (
const Block &data
const Block &data /**< The key. */
) throw(ProtocolException) {
strobe_dh_key(sp, data.data(), data.size());
keyed = true;
}
/** Stir in DH key, from a serializeable object. */
template<class T> inline void dh_key (
const Serializable<T> &data
const Serializable<T> &data /**< The key. */
) throw(ProtocolException) {
dh_key(data.serialize());
}
/** Stir in an explicit nonce. */
inline void nonce(const Block &data) NOEXCEPT {
strobe_nonce(sp, data.data(), data.size());
}
/* TODO: this doesn't actually send ... maybe think about gluing to socket code? */
/** Stir in data we sent as plaintext. NB This doesn't actually send anything. */
inline void send_plaintext(const Block &data) NOEXCEPT {
strobe_plaintext(sp, data.data(), data.size(), true);
}
/** Stir in serializeable data we sent as plaintext. NB This doesn't actually send anything. */
template<class T> inline void send_plaintext(const Serializable<T> &data) NOEXCEPT {
send_plaintext(data.serialize());
}
/** Stir in data we received as plaintext. NB This doesn't actually receive anything. */
inline void recv_plaintext(const Block &data) NOEXCEPT {
strobe_plaintext(sp, data.data(), data.size(), false);
}
template<class T> inline void recv_plaintext(const Serializable<T> &data) NOEXCEPT {
recv_plaintext(data.serialize());
}
/** Stir in associated data. */
inline void ad(const Block &data) {
strobe_ad(sp, data.data(), data.size());
}
/** Stir in associated serializable data. */
template<class T> inline void ad(const Serializable<T> &data) NOEXCEPT {
ad(data.serialize());
}
/** Encrypt into a buffer, without appending authentication data */
inline void encrypt_no_auth(Buffer out, const Block &data) throw(LengthException,ProtocolException) {
if (!keyed) throw ProtocolException();
if (out.size() != data.size()) throw LengthException();
strobe_encrypt(sp, out.data(), data.data(), data.size());
}
/** Encrypt, without appending authentication data */
inline SecureBuffer encrypt_no_auth(const Block &data) throw(ProtocolException) {
SecureBuffer out(data.size()); encrypt_no_auth(out, data); return out;
}
/** Encrypt a serializable object, without appending authentication data */
template<class T> inline SecureBuffer encrypt_no_auth(const Serializable<T> &data) throw(ProtocolException) {