Browse Source

made scalar inverse WARN_UNUSED and made it throw. Small fix to sagetest. Changed some places that assumed that success is true, in case I want to adopt the proposal that success is 0

master
Michael Hamburg 9 years ago
parent
commit
e95b7c7f0e
7 changed files with 56 additions and 29 deletions
  1. +1
    -1
      Makefile
  2. +2
    -2
      src/public_include/decaf/decaf_255.h
  3. +25
    -12
      src/public_include/decaf/decaf_255.hxx
  4. +1
    -1
      src/public_include/decaf/decaf_448.h
  5. +23
    -11
      src/public_include/decaf/decaf_448.hxx
  6. +2
    -1
      test/test_decaf.cxx
  7. +2
    -1
      test/test_decaf.sage

+ 1
- 1
Makefile View File

@@ -206,7 +206,7 @@ $(BUILD_ASM)/%.s: test/%.cxx $(HEADERSXX)
sage: $(BUILDPYS) sage: $(BUILDPYS)


sagetest: sage lib sagetest: sage lib
LD_LIBRARY_PATH=$(BUILD_LIB) sage $(BUILD_PY)/test_decaf.sage
$(SAGE) $(BUILD_PY)/test_decaf.sage


$(BUILDPYS): $(SAGES) $(BUILD_OBJ)/timestamp $(BUILDPYS): $(SAGES) $(BUILD_OBJ)/timestamp
cp -f $(SAGES) $(BUILD_PY)/ cp -f $(SAGES) $(BUILD_PY)/


+ 2
- 2
src/public_include/decaf/decaf_255.h View File

@@ -161,12 +161,12 @@ void decaf_255_scalar_mul (
* @brief Invert a scalar. When passed zero, return 0. The input and output may alias. * @brief Invert a scalar. When passed zero, return 0. The input and output may alias.
* @param [in] a A scalar. * @param [in] a A scalar.
* @param [out] out 1/a. * @param [out] out 1/a.
* @return DECAF_TRUE The input is nonzero.
* @return DECAF_SUCCESS The input is nonzero.
*/ */
decaf_bool_t decaf_255_scalar_invert ( decaf_bool_t decaf_255_scalar_invert (
decaf_255_scalar_t out, decaf_255_scalar_t out,
const decaf_255_scalar_t a const decaf_255_scalar_t a
) API_VIS NONNULL2 NOINLINE;
) API_VIS WARN_UNUSED NONNULL2 NOINLINE;


/** /**
* @brief Copy a scalar. The scalars may use the same memory, in which * @brief Copy a scalar. The scalars may use the same memory, in which


+ 25
- 12
src/public_include/decaf/decaf_255.hxx View File

@@ -164,13 +164,19 @@ public:
inline Scalar operator- () const NOEXCEPT { Scalar r((NOINIT())); decaf_255_scalar_sub(r.s,decaf_255_scalar_zero,s); return r; } inline Scalar operator- () const NOEXCEPT { Scalar r((NOINIT())); decaf_255_scalar_sub(r.s,decaf_255_scalar_zero,s); return r; }
/** @brief Invert with Fermat's Little Theorem (slow!). If *this == 0, return 0. */ /** @brief Invert with Fermat's Little Theorem (slow!). If *this == 0, return 0. */
inline Scalar inverse() const NOEXCEPT { Scalar r; decaf_255_scalar_invert(r.s,s); return r; }
inline Scalar inverse() const throw(CryptoException) {
Scalar r;
if (DECAF_SUCCESS != decaf_255_scalar_invert(r.s,s)) {
throw CryptoException();
}
return r;
}
/** @brief Divide by inverting q. If q == 0, return 0. */ /** @brief Divide by inverting q. If q == 0, return 0. */
inline Scalar operator/ (const Scalar &q) const NOEXCEPT { return *this * q.inverse(); }
inline Scalar operator/ (const Scalar &q) const throw(CryptoException) { return *this * q.inverse(); }
/** @brief Divide by inverting q. If q == 0, return 0. */ /** @brief Divide by inverting q. If q == 0, return 0. */
inline Scalar &operator/=(const Scalar &q) NOEXCEPT { return *this *= q.inverse(); }
inline Scalar &operator/=(const Scalar &q) throw(CryptoException) { return *this *= q.inverse(); }
/** @brief Compare in constant time */ /** @brief Compare in constant time */
inline bool operator!=(const Scalar &q) const NOEXCEPT { return !(*this == q); } inline bool operator!=(const Scalar &q) const NOEXCEPT { return !(*this == q); }
@@ -245,8 +251,12 @@ public:
* or was the identity and allow_identity was DECAF_FALSE. * or was the identity and allow_identity was DECAF_FALSE.
*/ */
inline explicit Point(const FixedBlock<SER_BYTES> &buffer, decaf_bool_t allow_identity=DECAF_TRUE) inline explicit Point(const FixedBlock<SER_BYTES> &buffer, decaf_bool_t allow_identity=DECAF_TRUE)
throw(CryptoException) { if (!decode(*this,buffer,allow_identity)) throw CryptoException(); }
throw(CryptoException) {
if (DECAF_SUCCESS != decode(*this,buffer,allow_identity)) {
throw CryptoException();
}
}

/** /**
* @brief Initialize from C++ fixed-length byte string. * @brief Initialize from C++ fixed-length byte string.
* The all-zero string maps to the identity. * The all-zero string maps to the identity.
@@ -335,13 +345,13 @@ public:
inline Point &operator*=(const Scalar &s) NOEXCEPT { decaf_255_point_scalarmul(p,p,s.s); return *this; } inline Point &operator*=(const Scalar &s) NOEXCEPT { decaf_255_point_scalarmul(p,p,s.s); return *this; }
/** @brief Multiply by s.inverse(). If s=0, maps to the identity. */ /** @brief Multiply by s.inverse(). If s=0, maps to the identity. */
inline Point operator/ (const Scalar &s) const NOEXCEPT { return (*this) * s.inverse(); }
inline Point operator/ (const Scalar &s) const throw(CryptoException) { return (*this) * s.inverse(); }
/** @brief Multiply by s.inverse(). If s=0, maps to the identity. */ /** @brief Multiply by s.inverse(). If s=0, maps to the identity. */
inline Point &operator/=(const Scalar &s) NOEXCEPT { return (*this) *= s.inverse(); }
inline Point &operator/=(const Scalar &s) throw(CryptoException) { return (*this) *= s.inverse(); }
/** @brief Validate / sanity check */ /** @brief Validate / sanity check */
inline bool validate() const NOEXCEPT { return !!decaf_255_point_valid(p); }
inline bool validate() const NOEXCEPT { return DECAF_SUCCESS == decaf_255_point_valid(p); }
/** @brief Double-scalar multiply, equivalent to q*qs + r*rs but faster. */ /** @brief Double-scalar multiply, equivalent to q*qs + r*rs but faster. */
static inline Point double_scalarmul ( static inline Point double_scalarmul (
@@ -403,12 +413,12 @@ public:
if (buf.size() < HASH_BYTES) { if (buf.size() < HASH_BYTES) {
ret &= decaf_memeq(&buf2[buf.size()], &buf2[HASH_BYTES], HASH_BYTES - buf.size()); ret &= decaf_memeq(&buf2[buf.size()], &buf2[HASH_BYTES], HASH_BYTES - buf.size());
} }
if (ret) {
if (DECAF_SUCCESS == ret) {
/* TODO: make this constant time?? */ /* TODO: make this constant time?? */
memcpy(buf.data(),buf2,(buf.size() < HASH_BYTES) ? buf.size() : HASH_BYTES); memcpy(buf.data(),buf2,(buf.size() < HASH_BYTES) ? buf.size() : HASH_BYTES);
} }
decaf_bzero(buf2,sizeof(buf2)); decaf_bzero(buf2,sizeof(buf2));
return !!ret;
return DECAF_SUCCESS == ret;
} }
/** @brief Steganographically encode this */ /** @brief Steganographically encode this */
@@ -510,7 +520,7 @@ public:
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; }
/** @brief Multiply by s.inverse(). If s=0, maps to the identity. */ /** @brief Multiply by s.inverse(). If s=0, maps to the identity. */
inline Point operator/ (const Scalar &s) const NOEXCEPT { return (*this) * s.inverse(); }
inline Point operator/ (const Scalar &s) const throw(CryptoException) { 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(); } static inline const Precomputed base() NOEXCEPT { return Precomputed(); }
@@ -535,8 +545,11 @@ inline SecureBuffer IsoEd25519::Scalar::direct_scalarmul (
decaf_bool_t short_circuit decaf_bool_t short_circuit
) const throw(CryptoException) { ) const throw(CryptoException) {
SecureBuffer out(IsoEd25519::Point::SER_BYTES); SecureBuffer out(IsoEd25519::Point::SER_BYTES);
if (!decaf_255_direct_scalarmul(out.data(), in.data(), s, allow_identity, short_circuit))
if (DECAF_SUCCESS !=
decaf_255_direct_scalarmul(out.data(), in.data(), s, allow_identity, short_circuit)
) {
throw CryptoException(); throw CryptoException();
}
return out; return out;
} }
/** endcond */ /** endcond */


+ 1
- 1
src/public_include/decaf/decaf_448.h View File

@@ -164,7 +164,7 @@ void decaf_448_scalar_mul (
decaf_bool_t decaf_448_scalar_invert ( decaf_bool_t decaf_448_scalar_invert (
decaf_448_scalar_t out, decaf_448_scalar_t out,
const decaf_448_scalar_t a const decaf_448_scalar_t a
) API_VIS NONNULL2 NOINLINE;
) API_VIS WARN_UNUSED NONNULL2 NOINLINE;


/** /**
* @brief Copy a scalar. The scalars may use the same memory, in which * @brief Copy a scalar. The scalars may use the same memory, in which


+ 23
- 11
src/public_include/decaf/decaf_448.hxx View File

@@ -163,13 +163,19 @@ public:
inline Scalar operator- () const NOEXCEPT { Scalar r((NOINIT())); decaf_448_scalar_sub(r.s,decaf_448_scalar_zero,s); return r; } inline Scalar operator- () const NOEXCEPT { Scalar r((NOINIT())); decaf_448_scalar_sub(r.s,decaf_448_scalar_zero,s); return r; }
/** @brief Invert with Fermat's Little Theorem (slow!). If *this == 0, return 0. */ /** @brief Invert with Fermat's Little Theorem (slow!). If *this == 0, return 0. */
inline Scalar inverse() const NOEXCEPT { Scalar r; decaf_448_scalar_invert(r.s,s); return r; }
inline Scalar inverse() const throw(CryptoException) {
Scalar r;
if (DECAF_SUCCESS != decaf_448_scalar_invert(r.s,s)) {
throw CryptoException();
}
return r;
}
/** @brief Divide by inverting q. If q == 0, return 0. */ /** @brief Divide by inverting q. If q == 0, return 0. */
inline Scalar operator/ (const Scalar &q) const NOEXCEPT { return *this * q.inverse(); }
inline Scalar operator/ (const Scalar &q) const throw(CryptoException) { return *this * q.inverse(); }
/** @brief Divide by inverting q. If q == 0, return 0. */ /** @brief Divide by inverting q. If q == 0, return 0. */
inline Scalar &operator/=(const Scalar &q) NOEXCEPT { return *this *= q.inverse(); }
inline Scalar &operator/=(const Scalar &q) throw(CryptoException) { return *this *= q.inverse(); }
/** @brief Compare in constant time */ /** @brief Compare in constant time */
inline bool operator!=(const Scalar &q) const NOEXCEPT { return !(*this == q); } inline bool operator!=(const Scalar &q) const NOEXCEPT { return !(*this == q); }
@@ -190,8 +196,11 @@ public:
decaf_bool_t short_circuit=DECAF_TRUE decaf_bool_t short_circuit=DECAF_TRUE
) const throw(CryptoException) { ) const throw(CryptoException) {
SecureBuffer out(/*FIXME Point::*/SER_BYTES); SecureBuffer out(/*FIXME Point::*/SER_BYTES);
if (!decaf_448_direct_scalarmul(out.data(), in.data(), s, allow_identity, short_circuit))
if (DECAF_SUCCESS !=
decaf_448_direct_scalarmul(out.data(), in.data(), s, allow_identity, short_circuit)
) {
throw CryptoException(); throw CryptoException();
}
return out; return out;
} }
}; };
@@ -247,7 +256,9 @@ public:
* or was the identity and allow_identity was DECAF_FALSE. * or was the identity and allow_identity was DECAF_FALSE.
*/ */
inline explicit Point(const FixedBlock<SER_BYTES> &buffer, decaf_bool_t allow_identity=DECAF_TRUE) inline explicit Point(const FixedBlock<SER_BYTES> &buffer, decaf_bool_t allow_identity=DECAF_TRUE)
throw(CryptoException) { if (!decode(*this,buffer,allow_identity)) throw CryptoException(); }
throw(CryptoException) {
if (DECAF_SUCCESS != decode(*this,buffer,allow_identity)) throw CryptoException();
}
/** /**
* @brief Initialize from C++ fixed-length byte string. * @brief Initialize from C++ fixed-length byte string.
@@ -346,13 +357,13 @@ public:
inline Point &operator*=(const Scalar &s) NOEXCEPT { decaf_448_point_scalarmul(p,p,s.s); return *this; } inline Point &operator*=(const Scalar &s) NOEXCEPT { decaf_448_point_scalarmul(p,p,s.s); return *this; }
/** @brief Multiply by s.inverse(). If s=0, maps to the identity. */ /** @brief Multiply by s.inverse(). If s=0, maps to the identity. */
inline Point operator/ (const Scalar &s) const NOEXCEPT { return (*this) * s.inverse(); }
inline Point operator/ (const Scalar &s) const throw(CryptoException) { return (*this) * s.inverse(); }
/** @brief Multiply by s.inverse(). If s=0, maps to the identity. */ /** @brief Multiply by s.inverse(). If s=0, maps to the identity. */
inline Point &operator/=(const Scalar &s) NOEXCEPT { return (*this) *= s.inverse(); }
inline Point &operator/=(const Scalar &s) throw(CryptoException) { return (*this) *= s.inverse(); }
/** @brief Validate / sanity check */ /** @brief Validate / sanity check */
inline bool validate() const NOEXCEPT { return !!decaf_448_point_valid(p); }
inline bool validate() const NOEXCEPT { return DECAF_SUCCESS == decaf_448_point_valid(p); }
/** @brief Double-scalar multiply, equivalent to q*qs + r*rs but faster. */ /** @brief Double-scalar multiply, equivalent to q*qs + r*rs but faster. */
static inline Point double_scalarmul ( static inline Point double_scalarmul (
@@ -417,14 +428,15 @@ public:
ret = decaf_448_invert_elligator_nonuniform(buf2, p, hint); ret = decaf_448_invert_elligator_nonuniform(buf2, p, hint);
} }
if (buf.size() < HASH_BYTES) { if (buf.size() < HASH_BYTES) {
// FIXME: this &= will fail if success becomes 0
ret &= decaf_memeq(&buf2[buf.size()], &buf2[HASH_BYTES], HASH_BYTES - buf.size()); ret &= decaf_memeq(&buf2[buf.size()], &buf2[HASH_BYTES], HASH_BYTES - buf.size());
} }
if (ret) {
if (DECAF_SUCCESS == ret) {
/* TODO: make this constant time?? */ /* TODO: make this constant time?? */
memcpy(buf.data(),buf2,(buf.size() < HASH_BYTES) ? buf.size() : HASH_BYTES); memcpy(buf.data(),buf2,(buf.size() < HASH_BYTES) ? buf.size() : HASH_BYTES);
} }
decaf_bzero(buf2,sizeof(buf2)); decaf_bzero(buf2,sizeof(buf2));
return !!ret;
return (ret == DECAF_SUCCESS);
} }
/** @brief Steganographically encode this */ /** @brief Steganographically encode this */
@@ -525,7 +537,7 @@ public:
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; }
/** @brief Multiply by s.inverse(). If s=0, maps to the identity. */ /** @brief Multiply by s.inverse(). If s=0, maps to the identity. */
inline Point operator/ (const Scalar &s) const NOEXCEPT { return (*this) * s.inverse(); }
inline Point operator/ (const Scalar &s) const throw(CryptoException) { 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(); } static inline const Precomputed base() NOEXCEPT { return Precomputed(); }


+ 2
- 1
test/test_decaf.cxx View File

@@ -158,7 +158,8 @@ static void test_arithmetic() {
if (i%20) continue; if (i%20) continue;
if (y!=0) arith_check(test,x,y,z,x*y/y,x,"invert"); if (y!=0) arith_check(test,x,y,z,x*y/y,x,"invert");
arith_check(test,x,y,z,x/0,0,"invert0");
// TODO: negative test, but this throws an exception
//arith_check(test,x,y,z,x/0,0,"invert0");
} }
} }




+ 2
- 1
test/test_decaf.sage View File

@@ -1,7 +1,7 @@
from ctypes import * from ctypes import *
from base64 import * from base64 import *


DECAF = CDLL("libdecaf.so")
DECAF = CDLL("build/lib/libdecaf.so")


F = GF(2^448-2^224-1) F = GF(2^448-2^224-1)
d = -39081 d = -39081
@@ -16,6 +16,7 @@ passing = True
# TODO: pathological cases # TODO: pathological cases
# TODO: Elligator # TODO: Elligator
# TODO: double scalar mul # TODO: double scalar mul
# TODO: Curve25519


def random_array(length): def random_array(length):
answer = "".join([chr(randint(0,255)) for i in xrange(length)]) answer = "".join([chr(randint(0,255)) for i in xrange(length)])


Loading…
Cancel
Save