diff --git a/Makefile b/Makefile index 314ec53..f19c2c5 100644 --- a/Makefile +++ b/Makefile @@ -71,7 +71,7 @@ endif ARCHFLAGS += $(XARCHFLAGS) CFLAGS = $(LANGFLAGS) $(WARNFLAGS) $(INCFLAGS) $(OFLAGS) $(ARCHFLAGS) $(GENFLAGS) $(XCFLAGS) CXXFLAGS = $(LANGXXFLAGS) $(WARNFLAGS) $(INCFLAGS) $(OFLAGS) $(ARCHFLAGS) $(GENFLAGS) $(XCXXFLAGS) -LDFLAGS = $(ARCHFLAGS) $(XLDFLAGS) +LDFLAGS = $(XLDFLAGS) ASFLAGS = $(ARCHFLAGS) $(XASFLAGS) SAGE ?= sage diff --git a/src/public_include/decaf/decaf_255.hxx b/src/public_include/decaf/decaf_255.hxx index 288a181..462cbf0 100644 --- a/src/public_include/decaf/decaf_255.hxx +++ b/src/public_include/decaf/decaf_255.hxx @@ -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 * stack-allocate a 15kiB object anyway. */ -class Precomputed { -private: + +/** @cond internal */ +typedef decaf_255_precomputed_s Precomputed_U; +/** @endcond */ +class Precomputed /** @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 /** @endcond */ +{ public: + /** Destructor securely zeorizes the memory. */ inline ~Precomputed() NOEXCEPT { clear(); } @@ -519,28 +501,29 @@ public: * @warning The empty initializer makes this equal to base, unlike the empty * 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(yours) {} + + +#if __cplusplus >= 201103L + /** @brief Move-assign operator */ + inline Precomputed &operator=(Precomputed &&it) NOEXCEPT { + OwnedOrUnowned::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() { + *this = it; + } + + /** @brief Undelete copy operator */ + inline Precomputed &operator=(const Precomputed &it) NOEXCEPT { + OwnedOrUnowned::operator= (it); return *this; } +#endif /** * @brief Initilaize from point. Must allocate memory, and may throw. @@ -554,25 +537,14 @@ public: /** * @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() { *this = it; } /** * @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() { *this = it; } /** @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; } @@ -581,7 +553,15 @@ public: inline Point operator/ (const Scalar &s) const NOEXCEPT { return (*this) * s.inverse(); } /** @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; + 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 */ diff --git a/src/public_include/decaf/decaf_448.hxx b/src/public_include/decaf/decaf_448.hxx index 145df58..2968d95 100644 --- a/src/public_include/decaf/decaf_448.hxx +++ b/src/public_include/decaf/decaf_448.hxx @@ -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. * 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. - */ -class Precomputed { -private: + *//** @cond internal */ +typedef decaf_448_precomputed_s Precomputed_U; +/** @endcond */ +class Precomputed /** @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 /** @endcond */ +{ public: - /** Destructor securely erases the memory. */ + + /** Destructor securely zeorizes the memory. */ inline ~Precomputed() NOEXCEPT { clear(); } /** @@ -663,28 +643,29 @@ public: * @warning The empty initializer makes this equal to base, unlike the empty * 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(yours) {} + + +#if __cplusplus >= 201103L + /** @brief Move-assign operator */ + inline Precomputed &operator=(Precomputed &&it) NOEXCEPT { + OwnedOrUnowned::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() { + *this = it; + } + + /** @brief Undelete copy operator */ + inline Precomputed &operator=(const Precomputed &it) NOEXCEPT { + OwnedOrUnowned::operator= (it); return *this; } +#endif /** * @brief Initilaize from point. Must allocate memory, and may throw. @@ -698,25 +679,14 @@ public: /** * @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() { *this = it; } /** * @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() { *this = it; } /** @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; } @@ -725,7 +695,15 @@ public: inline Point operator/ (const Scalar &s) const NOEXCEPT { return (*this) * s.inverse(); } /** @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; + 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 */ diff --git a/src/public_include/decaf/secure_buffer.hxx b/src/public_include/decaf/secure_buffer.hxx index 59844c7..7fc6f14 100644 --- a/src/public_include/decaf/secure_buffer.hxx +++ b/src/public_include/decaf/secure_buffer.hxx @@ -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); } @@ -173,7 +173,7 @@ public: inline TmpBuffer slice(size_t off, size_t length) throw(LengthException); /** 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++. */ @@ -198,7 +198,7 @@ public: inline StackBuffer(Rng &r) NOEXCEPT : Buffer(storage, Size) { r.read(*this); } /** Destroy the buffer */ - ~StackBuffer() NOEXCEPT { zeorize(); } + ~StackBuffer() NOEXCEPT { zeroize(); } }; /** @cond internal */ @@ -250,13 +250,13 @@ public: return *this; } - /** Destructor zeorizes data */ + /** Destructor zeroizes data */ ~SecureBuffer() NOEXCEPT { clear(); } /** Clear data */ inline void clear() NOEXCEPT { if (data_ == NULL) return; - zeorize(); + zeroize(); delete[] data_; data_ = NULL; size_ = 0; @@ -293,6 +293,75 @@ inline SecureBuffer Rng::read(size_t length) throw(std::bad_alloc) { } /** @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 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 */