@@ -71,7 +71,7 @@ endif | |||||
ARCHFLAGS += $(XARCHFLAGS) | ARCHFLAGS += $(XARCHFLAGS) | ||||
CFLAGS = $(LANGFLAGS) $(WARNFLAGS) $(INCFLAGS) $(OFLAGS) $(ARCHFLAGS) $(GENFLAGS) $(XCFLAGS) | CFLAGS = $(LANGFLAGS) $(WARNFLAGS) $(INCFLAGS) $(OFLAGS) $(ARCHFLAGS) $(GENFLAGS) $(XCFLAGS) | ||||
CXXFLAGS = $(LANGXXFLAGS) $(WARNFLAGS) $(INCFLAGS) $(OFLAGS) $(ARCHFLAGS) $(GENFLAGS) $(XCXXFLAGS) | CXXFLAGS = $(LANGXXFLAGS) $(WARNFLAGS) $(INCFLAGS) $(OFLAGS) $(ARCHFLAGS) $(GENFLAGS) $(XCXXFLAGS) | ||||
LDFLAGS = $(ARCHFLAGS) $(XLDFLAGS) | |||||
LDFLAGS = $(XLDFLAGS) | |||||
ASFLAGS = $(ARCHFLAGS) $(XASFLAGS) | ASFLAGS = $(ARCHFLAGS) $(XASFLAGS) | ||||
SAGE ?= sage | SAGE ?= sage | ||||
@@ -476,35 +476,17 @@ public: | |||||
* Therefore we have to call malloc() or friends, but that's probably for the best, because you don't want to | * Therefore we have to call malloc() or friends, but that's probably for the best, because you don't want to | ||||
* stack-allocate a 15kiB object anyway. | * stack-allocate a 15kiB object anyway. | ||||
*/ | */ | ||||
class Precomputed { | |||||
private: | |||||
/** @cond internal */ | |||||
typedef decaf_255_precomputed_s Precomputed_U; | |||||
/** @endcond */ | |||||
class Precomputed | |||||
/** @cond internal */ | /** @cond internal */ | ||||
union { | |||||
decaf_255_precomputed_s *mine; | |||||
const decaf_255_precomputed_s *yours; | |||||
} ours; | |||||
bool isMine; | |||||
inline void clear() NOEXCEPT { | |||||
if (isMine) { | |||||
decaf_255_precomputed_destroy(ours.mine); | |||||
free(ours.mine); | |||||
ours.yours = decaf_255_precomputed_base; | |||||
isMine = false; | |||||
} | |||||
} | |||||
inline void alloc() throw(std::bad_alloc) { | |||||
if (isMine) return; | |||||
int ret = posix_memalign((void**)&ours.mine, alignof_decaf_255_precomputed_s,sizeof_decaf_255_precomputed_s); | |||||
if (ret || !ours.mine) { | |||||
isMine = false; | |||||
throw std::bad_alloc(); | |||||
} | |||||
isMine = true; | |||||
} | |||||
inline const decaf_255_precomputed_s *get() const NOEXCEPT { return isMine ? ours.mine : ours.yours; } | |||||
: protected OwnedOrUnowned<Precomputed,Precomputed_U> | |||||
/** @endcond */ | /** @endcond */ | ||||
{ | |||||
public: | public: | ||||
/** Destructor securely zeorizes the memory. */ | /** Destructor securely zeorizes the memory. */ | ||||
inline ~Precomputed() NOEXCEPT { clear(); } | inline ~Precomputed() NOEXCEPT { clear(); } | ||||
@@ -519,28 +501,29 @@ public: | |||||
* @warning The empty initializer makes this equal to base, unlike the empty | * @warning The empty initializer makes this equal to base, unlike the empty | ||||
* initializer for points which makes this equal to the identity. | * initializer for points which makes this equal to the identity. | ||||
*/ | */ | ||||
inline Precomputed( | |||||
const decaf_255_precomputed_s &yours = *decaf_255_precomputed_base | |||||
) NOEXCEPT { | |||||
ours.yours = &yours; | |||||
isMine = false; | |||||
inline Precomputed ( | |||||
const Precomputed_U &yours = *defaultValue() | |||||
) NOEXCEPT : OwnedOrUnowned<Precomputed,Precomputed_U>(yours) {} | |||||
#if __cplusplus >= 201103L | |||||
/** @brief Move-assign operator */ | |||||
inline Precomputed &operator=(Precomputed &&it) NOEXCEPT { | |||||
OwnedOrUnowned<Precomputed,Precomputed_U>::operator= (it); | |||||
return *this; | |||||
} | } | ||||
/** | |||||
* @brief Assign. This may require an allocation and memcpy. | |||||
*/ | |||||
inline Precomputed &operator=(const Precomputed &it) throw(std::bad_alloc) { | |||||
if (this == &it) return *this; | |||||
if (it.isMine) { | |||||
alloc(); | |||||
memcpy(ours.mine,it.ours.mine,sizeof_decaf_255_precomputed_s); | |||||
} else { | |||||
clear(); | |||||
ours.yours = it.ours.yours; | |||||
} | |||||
isMine = it.isMine; | |||||
/** @brief Move constructor */ | |||||
inline Precomputed(Precomputed &&it) NOEXCEPT : OwnedOrUnowned<Precomputed,Precomputed_U>() { | |||||
*this = it; | |||||
} | |||||
/** @brief Undelete copy operator */ | |||||
inline Precomputed &operator=(const Precomputed &it) NOEXCEPT { | |||||
OwnedOrUnowned<Precomputed,Precomputed_U>::operator= (it); | |||||
return *this; | return *this; | ||||
} | } | ||||
#endif | |||||
/** | /** | ||||
* @brief Initilaize from point. Must allocate memory, and may throw. | * @brief Initilaize from point. Must allocate memory, and may throw. | ||||
@@ -554,25 +537,14 @@ public: | |||||
/** | /** | ||||
* @brief Copy constructor. | * @brief Copy constructor. | ||||
*/ | */ | ||||
inline Precomputed(const Precomputed &it) throw(std::bad_alloc) : isMine(false) { *this = it; } | |||||
inline Precomputed(const Precomputed &it) throw(std::bad_alloc) | |||||
: OwnedOrUnowned<Precomputed,Precomputed_U>() { *this = it; } | |||||
/** | /** | ||||
* @brief Constructor which initializes from point. | * @brief Constructor which initializes from point. | ||||
*/ | */ | ||||
inline explicit Precomputed(const Point &it) throw(std::bad_alloc) : isMine(false) { *this = it; } | |||||
#if __cplusplus >= 201103L | |||||
inline Precomputed &operator=(Precomputed &&it) NOEXCEPT { | |||||
if (this == &it) return *this; | |||||
clear(); | |||||
ours = it.ours; | |||||
isMine = it.isMine; | |||||
it.isMine = false; | |||||
it.ours.yours = decaf_255_precomputed_base; | |||||
return *this; | |||||
} | |||||
inline Precomputed(Precomputed &&it) NOEXCEPT : isMine(false) { *this = it; } | |||||
#endif | |||||
inline explicit Precomputed(const Point &it) throw(std::bad_alloc) | |||||
: OwnedOrUnowned<Precomputed,Precomputed_U>() { *this = it; } | |||||
/** @brief Fixed base scalarmul. */ | /** @brief Fixed base scalarmul. */ | ||||
inline Point operator* (const Scalar &s) const NOEXCEPT { Point r; decaf_255_precomputed_scalarmul(r.p,get(),s.s); return r; } | inline Point operator* (const Scalar &s) const NOEXCEPT { Point r; decaf_255_precomputed_scalarmul(r.p,get(),s.s); return r; } | ||||
@@ -581,7 +553,15 @@ public: | |||||
inline Point operator/ (const Scalar &s) const NOEXCEPT { return (*this) * s.inverse(); } | inline Point operator/ (const Scalar &s) const NOEXCEPT { return (*this) * s.inverse(); } | ||||
/** @brief Return the table for the base point. */ | /** @brief Return the table for the base point. */ | ||||
static inline const Precomputed base() NOEXCEPT { return Precomputed(*decaf_255_precomputed_base); } | |||||
static inline const Precomputed base() NOEXCEPT { return Precomputed(); } | |||||
public: | |||||
/** @cond internal */ | |||||
friend class OwnedOrUnowned<Precomputed,Precomputed_U>; | |||||
static inline size_t size() NOEXCEPT { return sizeof_decaf_255_precomputed_s; } | |||||
static inline size_t alignment() NOEXCEPT { return alignof_decaf_255_precomputed_s; } | |||||
static inline const Precomputed_U * defaultValue() NOEXCEPT { return decaf_255_precomputed_base; } | |||||
/** @endcond */ | |||||
}; | }; | ||||
}; /* struct Decaf255 */ | }; /* struct Decaf255 */ | ||||
@@ -619,37 +619,17 @@ public: | |||||
* Minor difficulties arise here because the decaf API doesn't expose, as a constant, how big such an object is. | * Minor difficulties arise here because the decaf API doesn't expose, as a constant, how big such an object is. | ||||
* Therefore we have to call malloc() or friends, but that's probably for the best, because you don't want to | * Therefore we have to call malloc() or friends, but that's probably for the best, because you don't want to | ||||
* stack-allocate a 15kiB object anyway. | * stack-allocate a 15kiB object anyway. | ||||
*/ | |||||
class Precomputed { | |||||
private: | |||||
*//** @cond internal */ | |||||
typedef decaf_448_precomputed_s Precomputed_U; | |||||
/** @endcond */ | |||||
class Precomputed | |||||
/** @cond internal */ | /** @cond internal */ | ||||
union { | |||||
decaf_448_precomputed_s *mine; | |||||
const decaf_448_precomputed_s *yours; | |||||
} ours; | |||||
bool isMine; | |||||
inline void clear() NOEXCEPT { | |||||
if (isMine) { | |||||
decaf_448_precomputed_destroy(ours.mine); | |||||
free(ours.mine); | |||||
ours.yours = decaf_448_precomputed_base; | |||||
isMine = false; | |||||
} | |||||
} | |||||
inline void alloc() throw(std::bad_alloc) { | |||||
if (isMine) return; | |||||
int ret = posix_memalign((void**)&ours.mine, alignof_decaf_448_precomputed_s,sizeof_decaf_448_precomputed_s); | |||||
if (ret || !ours.mine) { | |||||
isMine = false; | |||||
throw std::bad_alloc(); | |||||
} | |||||
isMine = true; | |||||
} | |||||
inline const decaf_448_precomputed_s *get() const NOEXCEPT { return isMine ? ours.mine : ours.yours; } | |||||
: protected OwnedOrUnowned<Precomputed,Precomputed_U> | |||||
/** @endcond */ | /** @endcond */ | ||||
{ | |||||
public: | public: | ||||
/** Destructor securely erases the memory. */ | |||||
/** Destructor securely zeorizes the memory. */ | |||||
inline ~Precomputed() NOEXCEPT { clear(); } | inline ~Precomputed() NOEXCEPT { clear(); } | ||||
/** | /** | ||||
@@ -663,28 +643,29 @@ public: | |||||
* @warning The empty initializer makes this equal to base, unlike the empty | * @warning The empty initializer makes this equal to base, unlike the empty | ||||
* initializer for points which makes this equal to the identity. | * initializer for points which makes this equal to the identity. | ||||
*/ | */ | ||||
inline Precomputed( | |||||
const decaf_448_precomputed_s &yours = *decaf_448_precomputed_base | |||||
) NOEXCEPT { | |||||
ours.yours = &yours; | |||||
isMine = false; | |||||
inline Precomputed ( | |||||
const Precomputed_U &yours = *defaultValue() | |||||
) NOEXCEPT : OwnedOrUnowned<Precomputed,Precomputed_U>(yours) {} | |||||
#if __cplusplus >= 201103L | |||||
/** @brief Move-assign operator */ | |||||
inline Precomputed &operator=(Precomputed &&it) NOEXCEPT { | |||||
OwnedOrUnowned<Precomputed,Precomputed_U>::operator= (it); | |||||
return *this; | |||||
} | } | ||||
/** | |||||
* @brief Assign. This may require an allocation and memcpy. | |||||
*/ | |||||
inline Precomputed &operator=(const Precomputed &it) throw(std::bad_alloc) { | |||||
if (this == &it) return *this; | |||||
if (it.isMine) { | |||||
alloc(); | |||||
memcpy(ours.mine,it.ours.mine,sizeof_decaf_448_precomputed_s); | |||||
} else { | |||||
clear(); | |||||
ours.yours = it.ours.yours; | |||||
} | |||||
isMine = it.isMine; | |||||
/** @brief Move constructor */ | |||||
inline Precomputed(Precomputed &&it) NOEXCEPT : OwnedOrUnowned<Precomputed,Precomputed_U>() { | |||||
*this = it; | |||||
} | |||||
/** @brief Undelete copy operator */ | |||||
inline Precomputed &operator=(const Precomputed &it) NOEXCEPT { | |||||
OwnedOrUnowned<Precomputed,Precomputed_U>::operator= (it); | |||||
return *this; | return *this; | ||||
} | } | ||||
#endif | |||||
/** | /** | ||||
* @brief Initilaize from point. Must allocate memory, and may throw. | * @brief Initilaize from point. Must allocate memory, and may throw. | ||||
@@ -698,25 +679,14 @@ public: | |||||
/** | /** | ||||
* @brief Copy constructor. | * @brief Copy constructor. | ||||
*/ | */ | ||||
inline Precomputed(const Precomputed &it) throw(std::bad_alloc) : isMine(false) { *this = it; } | |||||
inline Precomputed(const Precomputed &it) throw(std::bad_alloc) | |||||
: OwnedOrUnowned<Precomputed,Precomputed_U>() { *this = it; } | |||||
/** | /** | ||||
* @brief Constructor which initializes from point. | * @brief Constructor which initializes from point. | ||||
*/ | */ | ||||
inline explicit Precomputed(const Point &it) throw(std::bad_alloc) : isMine(false) { *this = it; } | |||||
#if __cplusplus >= 201103L | |||||
inline Precomputed &operator=(Precomputed &&it) NOEXCEPT { | |||||
if (this == &it) return *this; | |||||
clear(); | |||||
ours = it.ours; | |||||
isMine = it.isMine; | |||||
it.isMine = false; | |||||
it.ours.yours = decaf_448_precomputed_base; | |||||
return *this; | |||||
} | |||||
inline Precomputed(Precomputed &&it) NOEXCEPT : isMine(false) { *this = it; } | |||||
#endif | |||||
inline explicit Precomputed(const Point &it) throw(std::bad_alloc) | |||||
: OwnedOrUnowned<Precomputed,Precomputed_U>() { *this = it; } | |||||
/** @brief Fixed base scalarmul. */ | /** @brief Fixed base scalarmul. */ | ||||
inline Point operator* (const Scalar &s) const NOEXCEPT { Point r; decaf_448_precomputed_scalarmul(r.p,get(),s.s); return r; } | inline Point operator* (const Scalar &s) const NOEXCEPT { Point r; decaf_448_precomputed_scalarmul(r.p,get(),s.s); return r; } | ||||
@@ -725,7 +695,15 @@ public: | |||||
inline Point operator/ (const Scalar &s) const NOEXCEPT { return (*this) * s.inverse(); } | inline Point operator/ (const Scalar &s) const NOEXCEPT { return (*this) * s.inverse(); } | ||||
/** @brief Return the table for the base point. */ | /** @brief Return the table for the base point. */ | ||||
static inline const Precomputed base() NOEXCEPT { return Precomputed(*decaf_448_precomputed_base); } | |||||
static inline const Precomputed base() NOEXCEPT { return Precomputed(); } | |||||
public: | |||||
/** @cond internal */ | |||||
friend class OwnedOrUnowned<Precomputed,Precomputed_U>; | |||||
static inline size_t size() NOEXCEPT { return sizeof_decaf_448_precomputed_s; } | |||||
static inline size_t alignment() NOEXCEPT { return alignof_decaf_448_precomputed_s; } | |||||
static inline const Precomputed_U * defaultValue() NOEXCEPT { return decaf_448_precomputed_base; } | |||||
/** @endcond */ | |||||
}; | }; | ||||
}; /* struct Decaf448 */ | }; /* struct Decaf448 */ | ||||
@@ -76,7 +76,7 @@ public: | |||||
}; | }; | ||||
/** | /** | ||||
* Securely zeorize contents of memory. | |||||
* Securely zeroize contents of memory. | |||||
*/ | */ | ||||
static inline void really_bzero(void *data, size_t size) { decaf_bzero(data,size); } | static inline void really_bzero(void *data, size_t size) { decaf_bzero(data,size); } | ||||
@@ -173,7 +173,7 @@ public: | |||||
inline TmpBuffer slice(size_t off, size_t length) throw(LengthException); | inline TmpBuffer slice(size_t off, size_t length) throw(LengthException); | ||||
/** Securely set the buffer to 0. */ | /** Securely set the buffer to 0. */ | ||||
inline void zeorize() NOEXCEPT { really_bzero(data(),size()); } | |||||
inline void zeroize() NOEXCEPT { really_bzero(data(),size()); } | |||||
}; | }; | ||||
/** A temporary reference to a writeable buffer, for converting C to C++. */ | /** A temporary reference to a writeable buffer, for converting C to C++. */ | ||||
@@ -198,7 +198,7 @@ public: | |||||
inline StackBuffer(Rng &r) NOEXCEPT : Buffer(storage, Size) { r.read(*this); } | inline StackBuffer(Rng &r) NOEXCEPT : Buffer(storage, Size) { r.read(*this); } | ||||
/** Destroy the buffer */ | /** Destroy the buffer */ | ||||
~StackBuffer() NOEXCEPT { zeorize(); } | |||||
~StackBuffer() NOEXCEPT { zeroize(); } | |||||
}; | }; | ||||
/** @cond internal */ | /** @cond internal */ | ||||
@@ -250,13 +250,13 @@ public: | |||||
return *this; | return *this; | ||||
} | } | ||||
/** Destructor zeorizes data */ | |||||
/** Destructor zeroizes data */ | |||||
~SecureBuffer() NOEXCEPT { clear(); } | ~SecureBuffer() NOEXCEPT { clear(); } | ||||
/** Clear data */ | /** Clear data */ | ||||
inline void clear() NOEXCEPT { | inline void clear() NOEXCEPT { | ||||
if (data_ == NULL) return; | if (data_ == NULL) return; | ||||
zeorize(); | |||||
zeroize(); | |||||
delete[] data_; | delete[] data_; | ||||
data_ = NULL; | data_ = NULL; | ||||
size_ = 0; | size_ = 0; | ||||
@@ -293,6 +293,75 @@ inline SecureBuffer Rng::read(size_t length) throw(std::bad_alloc) { | |||||
} | } | ||||
/** @endcond */ | /** @endcond */ | ||||
/** @cond internal */ | |||||
/** A secure buffer which stores an owned or unowned underlying value. | |||||
* If it is owned, it will be securely zeroed. | |||||
*/ | |||||
template <class T, class Underlying> | |||||
class OwnedOrUnowned { | |||||
protected: | |||||
union { | |||||
Underlying *mine; | |||||
const Underlying *yours; | |||||
} ours; | |||||
bool isMine; | |||||
inline void clear() NOEXCEPT { | |||||
if (isMine) { | |||||
really_bzero(ours.mine, T::size()); | |||||
free(ours.mine); | |||||
ours.yours = T::defaultValue(); | |||||
isMine = false; | |||||
} | |||||
} | |||||
inline void alloc() throw(std::bad_alloc) { | |||||
if (isMine) return; | |||||
int ret = posix_memalign((void**)&ours.mine, T::alignment(), T::size()); | |||||
if (ret || !ours.mine) { | |||||
isMine = false; | |||||
throw std::bad_alloc(); | |||||
} | |||||
isMine = true; | |||||
} | |||||
inline const Underlying *get() const NOEXCEPT { return isMine ? ours.mine : ours.yours; } | |||||
inline OwnedOrUnowned( | |||||
const Underlying &yours = *T::defaultValue() | |||||
) NOEXCEPT { | |||||
ours.yours = &yours; | |||||
isMine = false; | |||||
} | |||||
/** | |||||
* @brief Assign. This may require an allocation and memcpy. | |||||
*/ | |||||
inline T &operator=(const OwnedOrUnowned &it) throw(std::bad_alloc) { | |||||
if (this == &it) return *(T*)this; | |||||
if (it.isMine) { | |||||
alloc(); | |||||
memcpy(ours.mine,it.ours.mine,T::size()); | |||||
} else { | |||||
clear(); | |||||
ours.yours = it.ours.yours; | |||||
} | |||||
isMine = it.isMine; | |||||
return *(T*)this; | |||||
} | |||||
#if __cplusplus >= 201103L | |||||
inline T &operator=(OwnedOrUnowned &&it) NOEXCEPT { | |||||
if (this == &it) return *(T*)this; | |||||
clear(); | |||||
ours = it.ours; | |||||
isMine = it.isMine; | |||||
it.isMine = false; | |||||
it.ours.yours = T::defaultValue; | |||||
return *this; | |||||
} | |||||
#endif | |||||
}; | |||||
/** @endcond */ | |||||
} /* namespace decaf */ | } /* namespace decaf */ | ||||