Commit 60b14fb0 authored by Mike Hamburg's avatar Mike Hamburg

add FixedBuffer

parent 538fe688
......@@ -216,11 +216,12 @@ $(BATNAME): include/* src/* src/*/* test/batarch.map $(BUILD_C)/decaf_tables.c #
(cd $(BATNAME)/.. && tar czf $(BATBASE).tgz $(BATBASE) )
# Finds todo items in .h and .c files
TODO_TYPES ?= HACK TODO FIXME BUG XXX PERF FUTURE REMOVE MAGIC
todo::
@(find * -name '*.h' -or -name '*.c' -or -name '*.cxx' -or -name '*.hxx') | xargs egrep --color=auto -w \
'HACK|TODO|FIXME|BUG|XXX|PERF|FUTURE|REMOVE|MAGIC'
`echo $(TODO_TYPES) | tr ' ' '|'`
@echo '============================='
@(for i in FIXME BUG XXX TODO HACK PERF FUTURE REMOVE MAGIC; do \
@(for i in $(TODO_TYPES); do \
(find * -name '*.h' -or -name '*.c' -or -name '*.cxx' -or -name '*.hxx') | xargs egrep -w $$i > /dev/null || continue; \
/bin/echo -n $$i' ' | head -c 10; \
(find * -name '*.h' -or -name '*.c' -or -name '*.cxx' -or -name '*.hxx') | xargs egrep -w $$i| wc -l; \
......@@ -228,7 +229,7 @@ todo::
@echo '============================='
@echo -n 'Total '
@(find * -name '*.h' -or -name '*.c' -or -name '*.cxx' -or -name '*.hxx') | xargs egrep -w \
'HACK|TODO|FIXME|BUG|XXX|PERF|FUTURE|REMOVE|MAGIC' | wc -l
`echo $(TODO_TYPES) | tr ' ' '|'` | wc -l
bench: $(BUILD_IBIN)/bench
./$<
......
......@@ -10,7 +10,7 @@
*
* The Decaf library implements cryptographic operations on a an elliptic curve
* group of prime order p. It accomplishes this by using a twisted Edwards
* curve (isogenous to Ed255-Goldilocks) and wiping out the cofactor.
* curve (isogenous to Curve25519) and wiping out the cofactor.
*
* The formulas are all complete and have no special cases, except that
* decaf_255_decode can fail because not every sequence of bytes is a valid group
......@@ -33,8 +33,6 @@
#include <sys/types.h>
#include <limits.h>
/* TODO: attribute nonnull */
/** @cond internal */
#if __cplusplus >= 201103L
#define NOEXCEPT noexcept
......@@ -46,7 +44,7 @@
namespace decaf {
/**
* @brief Ed255-Goldilocks/Decaf instantiation of group.
* @brief Curve25519/Decaf instantiation of group.
*/
struct Ed255 {
......@@ -60,12 +58,16 @@ class Precomputed;
* Supports the usual arithmetic operations, all in constant time.
*/
class Scalar {
private:
/** @brief wrapped C type */
typedef decaf_255_scalar_t Wrapped;
public:
/** @brief Size of a serialized element */
static const size_t SER_BYTES = DECAF_255_SCALAR_BYTES;
/** @brief access to the underlying scalar object */
decaf_255_scalar_t s;
Wrapped s;
/** @brief Don't initialize. */
inline Scalar(const NOINIT &) NOEXCEPT {}
......@@ -83,7 +85,7 @@ public:
}
/** @brief Construct from decaf_scalar_t object. */
inline Scalar(const decaf_255_scalar_t &t = decaf_255_scalar_zero) NOEXCEPT { decaf_255_scalar_copy(s,t); }
inline Scalar(const Wrapped &t = decaf_255_scalar_zero) NOEXCEPT { decaf_255_scalar_copy(s,t); }
/** @brief Copy constructor. */
inline Scalar(const Scalar &x) NOEXCEPT { *this = x; }
......@@ -118,26 +120,18 @@ public:
* @return DECAF_FAILURE if the scalar is greater than or equal to the group order q.
*/
static inline decaf_bool_t __attribute__((warn_unused_result)) decode (
Scalar &sc, const unsigned char buffer[SER_BYTES]
) NOEXCEPT {
return decaf_255_scalar_decode(sc.s,buffer);
}
/** @brief Decode from correct-length little-endian byte sequence in C++ string. */
static inline decaf_bool_t __attribute__((warn_unused_result)) decode (
Scalar &sc, const Block &buffer
Scalar &sc, const FixedBlock<SER_BYTES> buffer
) NOEXCEPT {
if (buffer.size() != SER_BYTES) return DECAF_FAILURE;
return decaf_255_scalar_decode(sc.s,buffer);
}
/** @brief Encode to fixed-length string */
inline operator SecureBuffer() const NOEXCEPT {
SecureBuffer buf(SER_BYTES); decaf_255_scalar_encode(buf,s); return buf;
SecureBuffer buf(SER_BYTES); encode(buf); return buf;
}
/** @brief Encode to fixed-length buffer */
inline void encode(unsigned char buffer[SER_BYTES]) const NOEXCEPT{
inline void encode(FixedBuffer<SER_BYTES> buffer) const NOEXCEPT{
decaf_255_scalar_encode(buffer, s);
}
......@@ -188,12 +182,7 @@ public:
const Block &in,
decaf_bool_t allow_identity=DECAF_FALSE,
decaf_bool_t short_circuit=DECAF_TRUE
) const throw(CryptoException) {
SecureBuffer out(/*FIXME Point::*/SER_BYTES);
if (!decaf_255_direct_scalarmul(out, in.data(), s, allow_identity, short_circuit))
throw CryptoException();
return out;
}
) const throw(CryptoException);
};
/**
......@@ -201,23 +190,25 @@ public:
*/
class Point {
public:
typedef decaf_255_point_t Wrapped;
/** @brief Size of a serialized element */
static const size_t SER_BYTES = DECAF_255_SER_BYTES;
/** @brief Size of a stegged element */
static const size_t STEG_BYTES = DECAF_255_SER_BYTES + 8;
/** @brief Bytes required for hash */
static const size_t HASH_BYTES = DECAF_255_SER_BYTES;
static const size_t HASH_BYTES = SER_BYTES;
/** @brief Size of a stegged element */
static const size_t STEG_BYTES = HASH_BYTES * 2;
/** The c-level object. */
decaf_255_point_t p;
Wrapped p;
/** @brief Don't initialize. */
inline Point(const NOINIT &) NOEXCEPT {}
/** @brief Constructor sets to identity by default. */
inline Point(const decaf_255_point_t &q = decaf_255_point_identity) NOEXCEPT { decaf_255_point_copy(p,q); }
inline Point(const Wrapped &q = decaf_255_point_identity) NOEXCEPT { decaf_255_point_copy(p,q); }
/** @brief Copy constructor. */
inline Point(const Point &q) NOEXCEPT { *this = q; }
......@@ -251,29 +242,15 @@ public:
}
/**
* @brief Initialize from C fixed-length byte string.
* @brief Initialize from a fixed-length byte string.
* The all-zero string maps to the identity.
*
* @throw CryptoException the string was the wrong length, or wasn't the encoding of a point,
* or was the identity and allow_identity was DECAF_FALSE.
*/
inline explicit Point(const unsigned char buffer[SER_BYTES], decaf_bool_t allow_identity=DECAF_TRUE)
inline explicit Point(const FixedBuffer<SER_BYTES> buffer, decaf_bool_t allow_identity=DECAF_TRUE)
throw(CryptoException) { if (!decode(*this,buffer,allow_identity)) throw CryptoException(); }
/**
* @brief Initialize from C fixed-length byte string.
* The all-zero string maps to the identity.
*
* @retval DECAF_SUCCESS the string was successfully decoded.
* @return DECAF_FAILURE the string wasn't the encoding of a point, or was the identity
* and allow_identity was DECAF_FALSE. Contents of the buffer are undefined.
*/
static inline decaf_bool_t __attribute__((warn_unused_result)) decode (
Point &p, const unsigned char buffer[SER_BYTES], decaf_bool_t allow_identity=DECAF_TRUE
) NOEXCEPT {
return decaf_255_point_decode(p.p,buffer,allow_identity);
}
/**
* @brief Initialize from C++ fixed-length byte string.
* The all-zero string maps to the identity.
......@@ -283,9 +260,8 @@ public:
* or was the identity and allow_identity was DECAF_FALSE. Contents of the buffer are undefined.
*/
static inline decaf_bool_t __attribute__((warn_unused_result)) decode (
Point &p, const Block &buffer, decaf_bool_t allow_identity=DECAF_TRUE
Point &p, const FixedBlock<SER_BYTES> buffer, decaf_bool_t allow_identity=DECAF_TRUE
) NOEXCEPT {
if (buffer.size() != SER_BYTES) return DECAF_FAILURE;
return decaf_255_point_decode(p.p,buffer.data(),allow_identity);
}
......@@ -325,15 +301,13 @@ public:
* @brief Encode to string. The identity encodes to the all-zero string.
*/
inline operator SecureBuffer() const NOEXCEPT {
SecureBuffer buffer(SER_BYTES);
decaf_255_point_encode(buffer, p);
return buffer;
SecureBuffer buffer(SER_BYTES); encode(buffer); return buffer;
}
/**
* @brief Encode to a C buffer. The identity encodes to all zeros.
*/
inline void encode(unsigned char buffer[SER_BYTES]) const NOEXCEPT{
inline void encode(FixedBuffer<SER_BYTES> buffer) const NOEXCEPT {
decaf_255_point_encode(buffer, p);
}
......@@ -393,7 +367,7 @@ public:
static inline Point double_scalarmul (
const Scalar &qs, const Point &q, const Scalar &rs, const Point &r
) NOEXCEPT {
Point p((NOINIT())); decaf_255_point_double_scalarmul(p.p,q.p,qs.s,r.p,rs.s); return p;
return double_scalarmul(q,qs,r,rs);
}
/**
......@@ -407,22 +381,17 @@ public:
/** @brief Return a point equal to *this, whose internal data is rotated by a torsion element. */
inline Point debugging_torque() const NOEXCEPT {
Point q;
decaf_255_point_debugging_torque(q.p,p);
return q;
Point q; decaf_255_point_debugging_torque(q.p,p); return q;
}
/** @brief Return a point equal to *this, whose internal data has a modified representation. */
inline Point debugging_pscale(const uint8_t factor[/*SER_BYTES*/]) const NOEXCEPT {
Point q;
decaf_255_point_debugging_pscale(q.p,p,factor);
return q;
inline Point debugging_pscale(const FixedBlock<SER_BYTES> factor) const NOEXCEPT {
Point q; decaf_255_point_debugging_pscale(q.p,p,factor); return q;
}
/** @brief Return a point equal to *this, whose internal data has a randomized representation. */
inline Point debugging_pscale(Rng &r) const NOEXCEPT {
StackBuffer<SER_BYTES> sb(r);
return debugging_pscale(sb);
StackBuffer<SER_BYTES> sb(r); return debugging_pscale(sb);
}
/**
......@@ -564,7 +533,22 @@ public:
/** @endcond */
};
}; /* struct Decaf255 */
}; /* struct Ed255 */
/** @cond internal */
inline SecureBuffer Ed255::Scalar::direct_scalarmul (
const Block &in,
decaf_bool_t allow_identity,
decaf_bool_t short_circuit
) const throw(CryptoException) {
SecureBuffer out(Ed255::Point::SER_BYTES);
if (!decaf_255_direct_scalarmul(out, in.data(), s, allow_identity, short_circuit))
throw CryptoException();
return out;
}
/** endcond */
#undef NOEXCEPT
} /* namespace decaf */
......
This diff is collapsed.
......@@ -87,8 +87,8 @@ protected:
size_t size_;
public:
/** Empty init */
inline Block() NOEXCEPT : data_(NULL), size_(0) {}
/** Null initialization */
inline Block() : data_(NULL), size_(0) {}
/** Init from C string */
inline Block(const char *data) NOEXCEPT : data_((unsigned char *)data), size_(strlen(data)) {}
......@@ -148,6 +148,18 @@ public:
inline virtual ~Block() {};
};
/** A fixed-size block */
template<size_t Size> class FixedBlock : public Block {
public:
/** Check a block's length. */
inline FixedBlock(const Block &b) throw(LengthException) : Block(b,Size) {
if (Size != b.size()) throw LengthException();
}
/** Explicitly pass a C buffer. */
inline explicit FixedBlock(const uint8_t data[Size]) NOEXCEPT : Block(data,Size) {}
};
/** A reference to a writable block of data */
class Buffer : public Block {
public:
......@@ -176,6 +188,24 @@ public:
inline void zeroize() NOEXCEPT { really_bzero(data(),size()); }
};
/** A fixed-size block */
template<size_t Size> class FixedBuffer : public Buffer {
public:
/** Check a block's length. */
inline FixedBuffer(Buffer &b) throw(LengthException) : Buffer(b,Size) {
if (Size != b.size()) throw LengthException();
}
/** Explicitly pass a C buffer. */
inline explicit FixedBuffer(uint8_t dat[Size]) NOEXCEPT : Buffer(dat,Size) {}
/** Cast to a FixedBlock. */
inline operator FixedBlock<Size>() const NOEXCEPT {
return FixedBlock<Size>(data());
}
};
/** A temporary reference to a writeable buffer, for converting C to C++. */
class TmpBuffer : public Buffer {
public:
......@@ -184,18 +214,20 @@ public:
};
/** A fixed-size stack-allocated buffer (for NOEXCEPT semantics) */
template<size_t Size> class StackBuffer : public Buffer {
template<size_t Size> class StackBuffer : public FixedBuffer<Size> {
private:
uint8_t storage[Size];
public:
using Buffer::zeroize;
/** New buffer initialized to zero. */
inline StackBuffer() NOEXCEPT : Buffer(storage, Size) { memset(storage,0,Size); }
inline explicit StackBuffer() NOEXCEPT : FixedBuffer<Size>(storage) { memset(storage,0,Size); }
/** New uninitialized buffer. */
inline StackBuffer(const NOINIT &) NOEXCEPT : Buffer(storage, Size) { }
inline explicit StackBuffer(const NOINIT &) NOEXCEPT : FixedBuffer<Size>(storage) { }
/** New random buffer */
inline StackBuffer(Rng &r) NOEXCEPT : Buffer(storage, Size) { r.read(*this); }
inline explicit StackBuffer(Rng &r) NOEXCEPT : FixedBuffer<Size>(storage) { r.read(*this); }
/** Destroy the buffer */
~StackBuffer() NOEXCEPT { zeroize(); }
......@@ -212,13 +244,13 @@ public:
inline SecureBuffer() NOEXCEPT : Buffer() {}
/** Construct empty from size */
inline SecureBuffer(size_t size) {
inline SecureBuffer(size_t size) throw(std::bad_alloc) {
data_ = new unsigned char[size_ = size];
memset(data_,0,size);
}
/** Construct from data */
inline SecureBuffer(const unsigned char *data, size_t size) {
inline SecureBuffer(const unsigned char *data, size_t size) throw(std::bad_alloc) {
data_ = new unsigned char[size_ = size];
memcpy(data_, data, size);
}
......@@ -230,7 +262,7 @@ public:
}
/** Copy constructor */
inline SecureBuffer(const Block &copy) : Buffer() { *this = copy; }
inline SecureBuffer(const Block &copy) throw(std::bad_alloc) : Buffer() { *this = copy; }
/** Copy-assign constructor */
inline SecureBuffer& operator=(const Block &copy) throw(std::bad_alloc) {
......@@ -297,12 +329,12 @@ inline SecureBuffer Rng::read(size_t length) throw(std::bad_alloc) {
/** 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>
template <class T, class Wrapped>
class OwnedOrUnowned {
protected:
union {
Underlying *mine;
const Underlying *yours;
Wrapped *mine;
const Wrapped *yours;
} ours;
bool isMine;
......@@ -323,10 +355,10 @@ protected:
}
isMine = true;
}
inline const Underlying *get() const NOEXCEPT { return isMine ? ours.mine : ours.yours; }
inline const Wrapped *get() const NOEXCEPT { return isMine ? ours.mine : ours.yours; }
inline OwnedOrUnowned(
const Underlying &yours = *T::defaultValue()
const Wrapped &yours = *T::defaultValue()
) NOEXCEPT {
ours.yours = &yours;
isMine = false;
......
......@@ -49,7 +49,7 @@ typedef typename Group::Precomputed Precomputed;
static void print(const char *name, const Scalar &x) {
unsigned char buffer[Scalar::SER_BYTES];
x.encode(buffer);
x.encode(decaf::FixedBuffer<Scalar::SER_BYTES>(buffer));
printf(" %s = 0x", name);
for (int i=sizeof(buffer)-1; i>=0; i--) {
printf("%02x", buffer[i]);
......@@ -66,10 +66,10 @@ static void hexprint(const char *name, const decaf::SecureBuffer &buffer) {
}
static void print(const char *name, const Point &x) {
unsigned char buffer[Point::SER_BYTES];
decaf::StackBuffer<Point::SER_BYTES> buffer;
x.encode(buffer);
printf(" %s = 0x", name);
for (int i=sizeof(buffer)-1; i>=0; i--) {
for (int i=Point::SER_BYTES-1; i>=0; i--) {
printf("%02x", buffer[i]);
}
printf("\n");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment