| @@ -206,7 +206,7 @@ $(BUILD_ASM)/%.s: test/%.cxx $(HEADERSXX) | |||
| sage: $(BUILDPYS) | |||
| 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 | |||
| cp -f $(SAGES) $(BUILD_PY)/ | |||
| @@ -161,12 +161,12 @@ void decaf_255_scalar_mul ( | |||
| * @brief Invert a scalar. When passed zero, return 0. The input and output may alias. | |||
| * @param [in] a A scalar. | |||
| * @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_255_scalar_t out, | |||
| 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 | |||
| @@ -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; } | |||
| /** @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. */ | |||
| 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. */ | |||
| 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 */ | |||
| 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. | |||
| */ | |||
| 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. | |||
| * 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; } | |||
| /** @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. */ | |||
| 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 */ | |||
| 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. */ | |||
| static inline Point double_scalarmul ( | |||
| @@ -403,12 +413,12 @@ public: | |||
| if (buf.size() < HASH_BYTES) { | |||
| ret &= decaf_memeq(&buf2[buf.size()], &buf2[HASH_BYTES], HASH_BYTES - buf.size()); | |||
| } | |||
| if (ret) { | |||
| if (DECAF_SUCCESS == ret) { | |||
| /* TODO: make this constant time?? */ | |||
| memcpy(buf.data(),buf2,(buf.size() < HASH_BYTES) ? buf.size() : HASH_BYTES); | |||
| } | |||
| decaf_bzero(buf2,sizeof(buf2)); | |||
| return !!ret; | |||
| return DECAF_SUCCESS == ret; | |||
| } | |||
| /** @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; } | |||
| /** @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. */ | |||
| static inline const Precomputed base() NOEXCEPT { return Precomputed(); } | |||
| @@ -535,8 +545,11 @@ inline SecureBuffer IsoEd25519::Scalar::direct_scalarmul ( | |||
| decaf_bool_t short_circuit | |||
| ) const throw(CryptoException) { | |||
| 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(); | |||
| } | |||
| return out; | |||
| } | |||
| /** endcond */ | |||
| @@ -164,7 +164,7 @@ void decaf_448_scalar_mul ( | |||
| decaf_bool_t decaf_448_scalar_invert ( | |||
| decaf_448_scalar_t out, | |||
| 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 | |||
| @@ -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; } | |||
| /** @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. */ | |||
| 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. */ | |||
| 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 */ | |||
| inline bool operator!=(const Scalar &q) const NOEXCEPT { return !(*this == q); } | |||
| @@ -190,8 +196,11 @@ public: | |||
| decaf_bool_t short_circuit=DECAF_TRUE | |||
| ) const throw(CryptoException) { | |||
| 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(); | |||
| } | |||
| return out; | |||
| } | |||
| }; | |||
| @@ -247,7 +256,9 @@ public: | |||
| * 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) | |||
| 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. | |||
| @@ -346,13 +357,13 @@ public: | |||
| 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. */ | |||
| 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. */ | |||
| 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 */ | |||
| 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. */ | |||
| static inline Point double_scalarmul ( | |||
| @@ -417,14 +428,15 @@ public: | |||
| ret = decaf_448_invert_elligator_nonuniform(buf2, p, hint); | |||
| } | |||
| 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()); | |||
| } | |||
| if (ret) { | |||
| if (DECAF_SUCCESS == ret) { | |||
| /* TODO: make this constant time?? */ | |||
| memcpy(buf.data(),buf2,(buf.size() < HASH_BYTES) ? buf.size() : HASH_BYTES); | |||
| } | |||
| decaf_bzero(buf2,sizeof(buf2)); | |||
| return !!ret; | |||
| return (ret == DECAF_SUCCESS); | |||
| } | |||
| /** @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; } | |||
| /** @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. */ | |||
| static inline const Precomputed base() NOEXCEPT { return Precomputed(); } | |||
| @@ -158,7 +158,8 @@ static void test_arithmetic() { | |||
| if (i%20) continue; | |||
| 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"); | |||
| } | |||
| } | |||
| @@ -1,7 +1,7 @@ | |||
| from ctypes import * | |||
| from base64 import * | |||
| DECAF = CDLL("libdecaf.so") | |||
| DECAF = CDLL("build/lib/libdecaf.so") | |||
| F = GF(2^448-2^224-1) | |||
| d = -39081 | |||
| @@ -16,6 +16,7 @@ passing = True | |||
| # TODO: pathological cases | |||
| # TODO: Elligator | |||
| # TODO: double scalar mul | |||
| # TODO: Curve25519 | |||
| def random_array(length): | |||
| answer = "".join([chr(randint(0,255)) for i in xrange(length)]) | |||