@@ -32,7 +32,7 @@ DOXYFILE_ENCODING = UTF-8 | |||||
# title of most generated pages and in a few other places. | # title of most generated pages and in a few other places. | ||||
# The default value is: My Project. | # The default value is: My Project. | ||||
PROJECT_NAME = "Ed448-Goldilocks" | |||||
PROJECT_NAME = "libdecaf" | |||||
# The PROJECT_NUMBER tag can be used to enter a project or revision number. This | # The PROJECT_NUMBER tag can be used to enter a project or revision number. This | ||||
# could be handy for archiving the generated documentation or if some version | # could be handy for archiving the generated documentation or if some version | ||||
@@ -751,7 +751,7 @@ WARN_LOGFILE = | |||||
# spaces. | # spaces. | ||||
# Note: If this tag is empty the current directory is searched. | # Note: If this tag is empty the current directory is searched. | ||||
INPUT = build/include | |||||
INPUT = src/GENERATED/include src/GENERATED/include/decaf | |||||
# This tag can be used to specify the character encoding of the source files | # This tag can be used to specify the character encoding of the source files | ||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses | # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses | ||||
@@ -17,6 +17,8 @@ BUILD_INC = src/GENERATED/include | |||||
BUILD_BIN = build/bin | BUILD_BIN = build/bin | ||||
BUILD_IBIN = build/obj/bin | BUILD_IBIN = build/obj/bin | ||||
DOXYGEN ?= doxygen | |||||
ifeq ($(UNAME),Darwin) | ifeq ($(UNAME),Darwin) | ||||
CC = clang | CC = clang | ||||
CXX = clang++ | CXX = clang++ | ||||
@@ -300,8 +302,8 @@ $(BUILD_DOC)/timestamp: | |||||
mkdir -p `dirname $@` | mkdir -p `dirname $@` | ||||
touch $@ | touch $@ | ||||
# | # | ||||
doc: Doxyfile $(BUILD_OBJ)/timestamp $(HEADERS) | |||||
doxygen > /dev/null | |||||
doc: Doxyfile $(BUILD_OBJ)/timestamp gen_code_static | |||||
$(DOXYGEN) > /dev/null | |||||
gen_code_static: $(GEN_CODE) | gen_code_static: $(GEN_CODE) | ||||
gen_code: gen_code_static $(GEN_CODE_P2) | gen_code: gen_code_static $(GEN_CODE_P2) | ||||
@@ -38,12 +38,6 @@ const uint8_t NO_CONTEXT_POINTS_HERE = 0; | |||||
const uint8_t * const DECAF_ED25519_NO_CONTEXT = &NO_CONTEXT_POINTS_HERE; | const uint8_t * const DECAF_ED25519_NO_CONTEXT = &NO_CONTEXT_POINTS_HERE; | ||||
#endif | #endif | ||||
/* EDDSA_BASE_POINT_RATIO = 1 or 2 | |||||
* Because EdDSA25519 is not on E_d but on the isogenous E_sigma_d, | |||||
* its base point is twice ours. | |||||
*/ | |||||
#define EDDSA_BASE_POINT_RATIO (1+EDDSA_USE_SIGMA_ISOGENY) /* TODO: remove */ | |||||
static void clamp ( | static void clamp ( | ||||
uint8_t secret_scalar_ser[DECAF_EDDSA_25519_PRIVATE_BYTES] | uint8_t secret_scalar_ser[DECAF_EDDSA_25519_PRIVATE_BYTES] | ||||
) { | ) { | ||||
@@ -38,12 +38,6 @@ const uint8_t NO_CONTEXT_POINTS_HERE = 0; | |||||
const uint8_t * const DECAF_ED448_NO_CONTEXT = &NO_CONTEXT_POINTS_HERE; | const uint8_t * const DECAF_ED448_NO_CONTEXT = &NO_CONTEXT_POINTS_HERE; | ||||
#endif | #endif | ||||
/* EDDSA_BASE_POINT_RATIO = 1 or 2 | |||||
* Because EdDSA25519 is not on E_d but on the isogenous E_sigma_d, | |||||
* its base point is twice ours. | |||||
*/ | |||||
#define EDDSA_BASE_POINT_RATIO (1+EDDSA_USE_SIGMA_ISOGENY) /* TODO: remove */ | |||||
static void clamp ( | static void clamp ( | ||||
uint8_t secret_scalar_ser[DECAF_EDDSA_448_PRIVATE_BYTES] | uint8_t secret_scalar_ser[DECAF_EDDSA_448_PRIVATE_BYTES] | ||||
) { | ) { | ||||
@@ -18,7 +18,9 @@ | |||||
#include <decaf/point_255.hxx> | #include <decaf/point_255.hxx> | ||||
#include <decaf/point_448.hxx> | #include <decaf/point_448.hxx> | ||||
/** Namespace for all C++ decaf objects. */ | |||||
namespace decaf { | namespace decaf { | ||||
/** Given a template with a "run" function, run it for all curves */ | |||||
template <template<typename Group> class Run> | template <template<typename Group> class Run> | ||||
void run_for_all_curves() { | void run_for_all_curves() { | ||||
Run<Ristretto>::run(); | Run<Ristretto>::run(); | ||||
@@ -21,8 +21,9 @@ extern "C" { | |||||
/* Goldilocks' build flags default to hidden and stripping executables. */ | /* Goldilocks' build flags default to hidden and stripping executables. */ | ||||
/** @cond internal */ | /** @cond internal */ | ||||
#if defined(DOXYGEN) && !defined(__attribute__) | |||||
#define __attribute__((x)) | |||||
#if DOXYGEN || defined(__attribute__) | |||||
#define __attribute__(x) | |||||
#define NOINLINE | |||||
#endif | #endif | ||||
#define DECAF_API_VIS __attribute__((visibility("default"))) | #define DECAF_API_VIS __attribute__((visibility("default"))) | ||||
#define DECAF_NOINLINE __attribute__((noinline)) | #define DECAF_NOINLINE __attribute__((noinline)) | ||||
@@ -36,10 +36,17 @@ extern "C" { | |||||
#define DECAF_EDDSA_25519_SUPPORTS_CONTEXTLESS_SIGS 1 | #define DECAF_EDDSA_25519_SUPPORTS_CONTEXTLESS_SIGS 1 | ||||
extern const uint8_t * const DECAF_ED25519_NO_CONTEXT DECAF_API_VIS; | extern const uint8_t * const DECAF_ED25519_NO_CONTEXT DECAF_API_VIS; | ||||
/** Prehash context renaming macros. */ | |||||
/** Prehash context (raw), because each EdDSA instance has a different prehash. */ | |||||
#define decaf_ed25519_prehash_ctx_s decaf_sha512_ctx_s | #define decaf_ed25519_prehash_ctx_s decaf_sha512_ctx_s | ||||
/** Prehash context, array[1] form. */ | |||||
#define decaf_ed25519_prehash_ctx_t decaf_sha512_ctx_t | #define decaf_ed25519_prehash_ctx_t decaf_sha512_ctx_t | ||||
/** Prehash update. */ | |||||
#define decaf_ed25519_prehash_update decaf_sha512_update | #define decaf_ed25519_prehash_update decaf_sha512_update | ||||
/** Prehash destroy. */ | |||||
#define decaf_ed25519_prehash_destroy decaf_sha512_destroy | #define decaf_ed25519_prehash_destroy decaf_sha512_destroy | ||||
/** EdDSA encoding ratio. */ | /** EdDSA encoding ratio. */ | ||||
@@ -14,7 +14,6 @@ | |||||
#ifndef __DECAF_ED255_HXX__ | #ifndef __DECAF_ED255_HXX__ | ||||
#define __DECAF_ED255_HXX__ 1 | #define __DECAF_ED255_HXX__ 1 | ||||
/* | /* | ||||
* Example Decaf cyrpto routines, C++ wrapper. | * Example Decaf cyrpto routines, C++ wrapper. | ||||
* @warning These are merely examples, though they ought to be secure. But real | * @warning These are merely examples, though they ought to be secure. But real | ||||
@@ -38,6 +37,7 @@ | |||||
#endif | #endif | ||||
/** @endcond */ | /** @endcond */ | ||||
/** Namespace for all libdecaf C++ objects. */ | |||||
namespace decaf { | namespace decaf { | ||||
/** A public key for crypto over some Group */ | /** A public key for crypto over some Group */ | ||||
@@ -55,7 +55,14 @@ typedef class PrivateKeyBase PrivateKey, PrivateKeyPure, PrivateKeyPh; | |||||
typedef class PublicKeyBase PublicKey, PublicKeyPure, PublicKeyPh; | typedef class PublicKeyBase PublicKey, PublicKeyPure, PublicKeyPh; | ||||
/** @endcond */ | /** @endcond */ | ||||
/** | |||||
* Signatures support a "context" block, which allows you to domain separate them if | |||||
* (for some reason) it's annoying to domain separate the message itself. The default | |||||
* is no context. For Ed25519, the spec defining contexts is an extension, and the | |||||
* default is not to use that extension. This makes "no context" different from | |||||
* the empty string. For Ed448, contexts are built-in and mandatory, so "no context" | |||||
* is the same as the empty string. | |||||
*/ | |||||
#if DECAF_EDDSA_25519_SUPPORTS_CONTEXTLESS_SIGS | #if DECAF_EDDSA_25519_SUPPORTS_CONTEXTLESS_SIGS | ||||
static inline const Block NO_CONTEXT() { return Block(DECAF_ED25519_NO_CONTEXT,0); } | static inline const Block NO_CONTEXT() { return Block(DECAF_ED25519_NO_CONTEXT,0); } | ||||
#else | #else | ||||
@@ -65,6 +72,7 @@ static inline const Block NO_CONTEXT() { return Block(NULL,0); } | |||||
/** Prehash context for EdDSA. */ | /** Prehash context for EdDSA. */ | ||||
class Prehash : public SHA512 { | class Prehash : public SHA512 { | ||||
private: | private: | ||||
/** @cond internal */ | |||||
typedef SHA512 Super; | typedef SHA512 Super; | ||||
SecureBuffer context_; | SecureBuffer context_; | ||||
template<class T, Prehashed Ph> friend class Signing; | template<class T, Prehashed Ph> friend class Signing; | ||||
@@ -79,6 +87,7 @@ private: | |||||
decaf_ed25519_prehash_init((decaf_sha512_ctx_s *)wrapped); | decaf_ed25519_prehash_init((decaf_sha512_ctx_s *)wrapped); | ||||
} | } | ||||
/** @endcond */ | |||||
public: | public: | ||||
/** Number of output bytes in prehash */ | /** Number of output bytes in prehash */ | ||||
@@ -108,35 +117,10 @@ public: | |||||
} | } | ||||
}; | }; | ||||
/** Signing (i.e. private) key class template */ | |||||
template<class CRTP, Prehashed ph> class Signing; | template<class CRTP, Prehashed ph> class Signing; | ||||
template<class CRTP> class Signing<CRTP,PREHASHED> { | |||||
public: | |||||
/* Sign a prehash context, and reset the context */ | |||||
inline SecureBuffer sign_prehashed ( const Prehash &ph ) const /*throw(std::bad_alloc)*/ { | |||||
SecureBuffer out(CRTP::SIG_BYTES); | |||||
decaf_ed25519_sign_prehash ( | |||||
out.data(), | |||||
((const CRTP*)this)->priv_.data(), | |||||
((const CRTP*)this)->pub_.data(), | |||||
(const decaf_ed25519_prehash_ctx_s*)ph.wrapped, | |||||
ph.context_.data(), | |||||
ph.context_.size() | |||||
); | |||||
return out; | |||||
} | |||||
/* Sign a message using the prehasher */ | |||||
inline SecureBuffer sign_with_prehash ( | |||||
const Block &message, | |||||
const Block &context = NO_CONTEXT() | |||||
) const /*throw(LengthException,CryptoException)*/ { | |||||
Prehash ph(context); | |||||
ph += message; | |||||
return sign_prehashed(ph); | |||||
} | |||||
}; | |||||
/** Signing (i.e. private) key class, PureEdDSA version */ | |||||
template<class CRTP> class Signing<CRTP,PURE> { | template<class CRTP> class Signing<CRTP,PURE> { | ||||
public: | public: | ||||
/** | /** | ||||
@@ -169,12 +153,42 @@ public: | |||||
} | } | ||||
}; | }; | ||||
/** Signing (i.e. private) key class, prehashed version */ | |||||
template<class CRTP> class Signing<CRTP,PREHASHED> { | |||||
public: | |||||
/** Sign a prehash context, and reset the context */ | |||||
inline SecureBuffer sign_prehashed ( const Prehash &ph ) const /*throw(std::bad_alloc)*/ { | |||||
SecureBuffer out(CRTP::SIG_BYTES); | |||||
decaf_ed25519_sign_prehash ( | |||||
out.data(), | |||||
((const CRTP*)this)->priv_.data(), | |||||
((const CRTP*)this)->pub_.data(), | |||||
(const decaf_ed25519_prehash_ctx_s*)ph.wrapped, | |||||
ph.context_.data(), | |||||
ph.context_.size() | |||||
); | |||||
return out; | |||||
} | |||||
/** Sign a message using the prehasher */ | |||||
inline SecureBuffer sign_with_prehash ( | |||||
const Block &message, | |||||
const Block &context = NO_CONTEXT() | |||||
) const /*throw(LengthException,CryptoException)*/ { | |||||
Prehash ph(context); | |||||
ph += message; | |||||
return sign_prehashed(ph); | |||||
} | |||||
}; | |||||
/** Signing (i.e. private) key base class */ | |||||
class PrivateKeyBase | class PrivateKeyBase | ||||
: public Serializable<PrivateKeyBase> | : public Serializable<PrivateKeyBase> | ||||
, public Signing<PrivateKeyBase,PURE> | , public Signing<PrivateKeyBase,PURE> | ||||
, public Signing<PrivateKeyBase,PREHASHED> { | , public Signing<PrivateKeyBase,PREHASHED> { | ||||
public: | public: | ||||
typedef class PublicKeyBase MyPublicKey; | |||||
/** Type of public key corresponding to this private key */ | |||||
typedef class PublicKeyBase PublicKey; | |||||
private: | private: | ||||
/** @cond internal */ | /** @cond internal */ | ||||
friend class PublicKeyBase; | friend class PublicKeyBase; | ||||
@@ -243,14 +257,13 @@ public: | |||||
} | } | ||||
/** Return the corresponding public key */ | /** Return the corresponding public key */ | ||||
inline MyPublicKey pub() const DECAF_NOEXCEPT { | |||||
MyPublicKey pub(*this); | |||||
inline PublicKey pub() const DECAF_NOEXCEPT { | |||||
PublicKey pub(*this); | |||||
return pub; | return pub; | ||||
} | } | ||||
}; /* class PrivateKey */ | }; /* class PrivateKey */ | ||||
/** Verification (i.e. public) EdDSA key, PureEdDSA version. */ | |||||
template<class CRTP> class Verification<CRTP,PURE> { | template<class CRTP> class Verification<CRTP,PURE> { | ||||
public: | public: | ||||
/** Verify a signature, returning DECAF_FAILURE if verification fails */ | /** Verify a signature, returning DECAF_FAILURE if verification fails */ | ||||
@@ -296,10 +309,10 @@ public: | |||||
} | } | ||||
}; | }; | ||||
/** Verification (i.e. public) EdDSA key, prehashed version. */ | |||||
template<class CRTP> class Verification<CRTP,PREHASHED> { | template<class CRTP> class Verification<CRTP,PREHASHED> { | ||||
public: | public: | ||||
/* Verify a prehash context. */ | |||||
/** Verify that a signature is valid for a given prehashed message, given the context. */ | |||||
inline decaf_error_t DECAF_WARN_UNUSED verify_prehashed_noexcept ( | inline decaf_error_t DECAF_WARN_UNUSED verify_prehashed_noexcept ( | ||||
const FixedBlock<DECAF_EDDSA_25519_SIGNATURE_BYTES> &sig, | const FixedBlock<DECAF_EDDSA_25519_SIGNATURE_BYTES> &sig, | ||||
const Prehash &ph | const Prehash &ph | ||||
@@ -312,8 +325,8 @@ public: | |||||
ph.context_.size() | ph.context_.size() | ||||
); | ); | ||||
} | } | ||||
/* Verify a prehash context. */ | |||||
/** Verify that a signature is valid for a given prehashed message, given the context. */ | |||||
inline void verify_prehashed ( | inline void verify_prehashed ( | ||||
const FixedBlock<DECAF_EDDSA_25519_SIGNATURE_BYTES> &sig, | const FixedBlock<DECAF_EDDSA_25519_SIGNATURE_BYTES> &sig, | ||||
const Prehash &ph | const Prehash &ph | ||||
@@ -329,7 +342,7 @@ public: | |||||
} | } | ||||
} | } | ||||
/* Verify a message using the prehasher */ | |||||
/** Hash and verify a message, using the prehashed verification mode. */ | |||||
inline void verify_with_prehash ( | inline void verify_with_prehash ( | ||||
const FixedBlock<DECAF_EDDSA_25519_SIGNATURE_BYTES> &sig, | const FixedBlock<DECAF_EDDSA_25519_SIGNATURE_BYTES> &sig, | ||||
const Block &message, | const Block &message, | ||||
@@ -341,24 +354,25 @@ public: | |||||
} | } | ||||
}; | }; | ||||
/** EdDSA Public key base class. */ | |||||
class PublicKeyBase | class PublicKeyBase | ||||
: public Serializable<PublicKeyBase> | : public Serializable<PublicKeyBase> | ||||
, public Verification<PublicKeyBase,PURE> | , public Verification<PublicKeyBase,PURE> | ||||
, public Verification<PublicKeyBase,PREHASHED> { | , public Verification<PublicKeyBase,PREHASHED> { | ||||
public: | public: | ||||
typedef class PrivateKeyBase MyPrivateKey; | |||||
/** Private key corresponding to this type of public key */ | |||||
typedef class PrivateKeyBase PrivateKey; | |||||
private: | private: | ||||
/** @cond internal */ | /** @cond internal */ | ||||
friend class PrivateKeyBase; | friend class PrivateKeyBase; | ||||
friend class Verification<PublicKey,PURE>; | friend class Verification<PublicKey,PURE>; | ||||
friend class Verification<PublicKey,PREHASHED>; | friend class Verification<PublicKey,PREHASHED>; | ||||
/** @endcond */ | |||||
private: | private: | ||||
/** The pre-expansion form of the signature */ | /** The pre-expansion form of the signature */ | ||||
FixedArrayBuffer<DECAF_EDDSA_25519_PUBLIC_BYTES> pub_; | FixedArrayBuffer<DECAF_EDDSA_25519_PUBLIC_BYTES> pub_; | ||||
/** @endcond */ | |||||
public: | public: | ||||
/* PERF FUTURE: Pre-cached decoding? Precomputed table?? */ | /* PERF FUTURE: Pre-cached decoding? Precomputed table?? */ | ||||
@@ -372,7 +386,6 @@ public: | |||||
/** Serialization size. */ | /** Serialization size. */ | ||||
static const size_t SER_BYTES = DECAF_EDDSA_25519_PRIVATE_BYTES; | static const size_t SER_BYTES = DECAF_EDDSA_25519_PRIVATE_BYTES; | ||||
/** Create but don't initialize */ | /** Create but don't initialize */ | ||||
inline explicit PublicKeyBase(const NOINIT&) DECAF_NOEXCEPT : pub_((NOINIT())) { } | inline explicit PublicKeyBase(const NOINIT&) DECAF_NOEXCEPT : pub_((NOINIT())) { } | ||||
@@ -383,7 +396,7 @@ public: | |||||
inline PublicKeyBase(const PublicKeyBase &k) DECAF_NOEXCEPT { *this = k; } | inline PublicKeyBase(const PublicKeyBase &k) DECAF_NOEXCEPT { *this = k; } | ||||
/** Copy constructor */ | /** Copy constructor */ | ||||
inline explicit PublicKeyBase(const MyPrivateKey &k) DECAF_NOEXCEPT { *this = k; } | |||||
inline explicit PublicKeyBase(const PrivateKey &k) DECAF_NOEXCEPT { *this = k; } | |||||
/** Assignment from string */ | /** Assignment from string */ | ||||
inline PublicKey &operator=(const FixedBlock<SER_BYTES> &b) DECAF_NOEXCEPT { | inline PublicKey &operator=(const FixedBlock<SER_BYTES> &b) DECAF_NOEXCEPT { | ||||
@@ -397,7 +410,7 @@ public: | |||||
} | } | ||||
/** Assignment from private key */ | /** Assignment from private key */ | ||||
inline PublicKey &operator=(const MyPrivateKey &p) DECAF_NOEXCEPT { | |||||
inline PublicKey &operator=(const PrivateKey &p) DECAF_NOEXCEPT { | |||||
return *this = p.pub_; | return *this = p.pub_; | ||||
} | } | ||||
@@ -35,10 +35,17 @@ extern "C" { | |||||
/** Does EdDSA support non-contextual signatures? */ | /** Does EdDSA support non-contextual signatures? */ | ||||
#define DECAF_EDDSA_448_SUPPORTS_CONTEXTLESS_SIGS 0 | #define DECAF_EDDSA_448_SUPPORTS_CONTEXTLESS_SIGS 0 | ||||
/** Prehash context renaming macros. */ | |||||
/** Prehash context (raw), because each EdDSA instance has a different prehash. */ | |||||
#define decaf_ed448_prehash_ctx_s decaf_shake256_ctx_s | #define decaf_ed448_prehash_ctx_s decaf_shake256_ctx_s | ||||
/** Prehash context, array[1] form. */ | |||||
#define decaf_ed448_prehash_ctx_t decaf_shake256_ctx_t | #define decaf_ed448_prehash_ctx_t decaf_shake256_ctx_t | ||||
/** Prehash update. */ | |||||
#define decaf_ed448_prehash_update decaf_shake256_update | #define decaf_ed448_prehash_update decaf_shake256_update | ||||
/** Prehash destroy. */ | |||||
#define decaf_ed448_prehash_destroy decaf_shake256_destroy | #define decaf_ed448_prehash_destroy decaf_shake256_destroy | ||||
/** EdDSA encoding ratio. */ | /** EdDSA encoding ratio. */ | ||||
@@ -14,7 +14,6 @@ | |||||
#ifndef __DECAF_ED448_HXX__ | #ifndef __DECAF_ED448_HXX__ | ||||
#define __DECAF_ED448_HXX__ 1 | #define __DECAF_ED448_HXX__ 1 | ||||
/* | /* | ||||
* Example Decaf cyrpto routines, C++ wrapper. | * Example Decaf cyrpto routines, C++ wrapper. | ||||
* @warning These are merely examples, though they ought to be secure. But real | * @warning These are merely examples, though they ought to be secure. But real | ||||
@@ -38,6 +37,7 @@ | |||||
#endif | #endif | ||||
/** @endcond */ | /** @endcond */ | ||||
/** Namespace for all libdecaf C++ objects. */ | |||||
namespace decaf { | namespace decaf { | ||||
/** A public key for crypto over some Group */ | /** A public key for crypto over some Group */ | ||||
@@ -55,7 +55,14 @@ typedef class PrivateKeyBase PrivateKey, PrivateKeyPure, PrivateKeyPh; | |||||
typedef class PublicKeyBase PublicKey, PublicKeyPure, PublicKeyPh; | typedef class PublicKeyBase PublicKey, PublicKeyPure, PublicKeyPh; | ||||
/** @endcond */ | /** @endcond */ | ||||
/** | |||||
* Signatures support a "context" block, which allows you to domain separate them if | |||||
* (for some reason) it's annoying to domain separate the message itself. The default | |||||
* is no context. For Ed25519, the spec defining contexts is an extension, and the | |||||
* default is not to use that extension. This makes "no context" different from | |||||
* the empty string. For Ed448, contexts are built-in and mandatory, so "no context" | |||||
* is the same as the empty string. | |||||
*/ | |||||
#if DECAF_EDDSA_448_SUPPORTS_CONTEXTLESS_SIGS | #if DECAF_EDDSA_448_SUPPORTS_CONTEXTLESS_SIGS | ||||
static inline const Block NO_CONTEXT() { return Block(DECAF_ED448_NO_CONTEXT,0); } | static inline const Block NO_CONTEXT() { return Block(DECAF_ED448_NO_CONTEXT,0); } | ||||
#else | #else | ||||
@@ -65,6 +72,7 @@ static inline const Block NO_CONTEXT() { return Block(NULL,0); } | |||||
/** Prehash context for EdDSA. */ | /** Prehash context for EdDSA. */ | ||||
class Prehash : public SHAKE<256> { | class Prehash : public SHAKE<256> { | ||||
private: | private: | ||||
/** @cond internal */ | |||||
typedef SHAKE<256> Super; | typedef SHAKE<256> Super; | ||||
SecureBuffer context_; | SecureBuffer context_; | ||||
template<class T, Prehashed Ph> friend class Signing; | template<class T, Prehashed Ph> friend class Signing; | ||||
@@ -79,6 +87,7 @@ private: | |||||
decaf_ed448_prehash_init((decaf_shake256_ctx_s *)wrapped); | decaf_ed448_prehash_init((decaf_shake256_ctx_s *)wrapped); | ||||
} | } | ||||
/** @endcond */ | |||||
public: | public: | ||||
/** Number of output bytes in prehash */ | /** Number of output bytes in prehash */ | ||||
@@ -108,35 +117,10 @@ public: | |||||
} | } | ||||
}; | }; | ||||
/** Signing (i.e. private) key class template */ | |||||
template<class CRTP, Prehashed ph> class Signing; | template<class CRTP, Prehashed ph> class Signing; | ||||
template<class CRTP> class Signing<CRTP,PREHASHED> { | |||||
public: | |||||
/* Sign a prehash context, and reset the context */ | |||||
inline SecureBuffer sign_prehashed ( const Prehash &ph ) const /*throw(std::bad_alloc)*/ { | |||||
SecureBuffer out(CRTP::SIG_BYTES); | |||||
decaf_ed448_sign_prehash ( | |||||
out.data(), | |||||
((const CRTP*)this)->priv_.data(), | |||||
((const CRTP*)this)->pub_.data(), | |||||
(const decaf_ed448_prehash_ctx_s*)ph.wrapped, | |||||
ph.context_.data(), | |||||
ph.context_.size() | |||||
); | |||||
return out; | |||||
} | |||||
/* Sign a message using the prehasher */ | |||||
inline SecureBuffer sign_with_prehash ( | |||||
const Block &message, | |||||
const Block &context = NO_CONTEXT() | |||||
) const /*throw(LengthException,CryptoException)*/ { | |||||
Prehash ph(context); | |||||
ph += message; | |||||
return sign_prehashed(ph); | |||||
} | |||||
}; | |||||
/** Signing (i.e. private) key class, PureEdDSA version */ | |||||
template<class CRTP> class Signing<CRTP,PURE> { | template<class CRTP> class Signing<CRTP,PURE> { | ||||
public: | public: | ||||
/** | /** | ||||
@@ -169,12 +153,42 @@ public: | |||||
} | } | ||||
}; | }; | ||||
/** Signing (i.e. private) key class, prehashed version */ | |||||
template<class CRTP> class Signing<CRTP,PREHASHED> { | |||||
public: | |||||
/** Sign a prehash context, and reset the context */ | |||||
inline SecureBuffer sign_prehashed ( const Prehash &ph ) const /*throw(std::bad_alloc)*/ { | |||||
SecureBuffer out(CRTP::SIG_BYTES); | |||||
decaf_ed448_sign_prehash ( | |||||
out.data(), | |||||
((const CRTP*)this)->priv_.data(), | |||||
((const CRTP*)this)->pub_.data(), | |||||
(const decaf_ed448_prehash_ctx_s*)ph.wrapped, | |||||
ph.context_.data(), | |||||
ph.context_.size() | |||||
); | |||||
return out; | |||||
} | |||||
/** Sign a message using the prehasher */ | |||||
inline SecureBuffer sign_with_prehash ( | |||||
const Block &message, | |||||
const Block &context = NO_CONTEXT() | |||||
) const /*throw(LengthException,CryptoException)*/ { | |||||
Prehash ph(context); | |||||
ph += message; | |||||
return sign_prehashed(ph); | |||||
} | |||||
}; | |||||
/** Signing (i.e. private) key base class */ | |||||
class PrivateKeyBase | class PrivateKeyBase | ||||
: public Serializable<PrivateKeyBase> | : public Serializable<PrivateKeyBase> | ||||
, public Signing<PrivateKeyBase,PURE> | , public Signing<PrivateKeyBase,PURE> | ||||
, public Signing<PrivateKeyBase,PREHASHED> { | , public Signing<PrivateKeyBase,PREHASHED> { | ||||
public: | public: | ||||
typedef class PublicKeyBase MyPublicKey; | |||||
/** Type of public key corresponding to this private key */ | |||||
typedef class PublicKeyBase PublicKey; | |||||
private: | private: | ||||
/** @cond internal */ | /** @cond internal */ | ||||
friend class PublicKeyBase; | friend class PublicKeyBase; | ||||
@@ -243,14 +257,13 @@ public: | |||||
} | } | ||||
/** Return the corresponding public key */ | /** Return the corresponding public key */ | ||||
inline MyPublicKey pub() const DECAF_NOEXCEPT { | |||||
MyPublicKey pub(*this); | |||||
inline PublicKey pub() const DECAF_NOEXCEPT { | |||||
PublicKey pub(*this); | |||||
return pub; | return pub; | ||||
} | } | ||||
}; /* class PrivateKey */ | }; /* class PrivateKey */ | ||||
/** Verification (i.e. public) EdDSA key, PureEdDSA version. */ | |||||
template<class CRTP> class Verification<CRTP,PURE> { | template<class CRTP> class Verification<CRTP,PURE> { | ||||
public: | public: | ||||
/** Verify a signature, returning DECAF_FAILURE if verification fails */ | /** Verify a signature, returning DECAF_FAILURE if verification fails */ | ||||
@@ -296,10 +309,10 @@ public: | |||||
} | } | ||||
}; | }; | ||||
/** Verification (i.e. public) EdDSA key, prehashed version. */ | |||||
template<class CRTP> class Verification<CRTP,PREHASHED> { | template<class CRTP> class Verification<CRTP,PREHASHED> { | ||||
public: | public: | ||||
/* Verify a prehash context. */ | |||||
/** Verify that a signature is valid for a given prehashed message, given the context. */ | |||||
inline decaf_error_t DECAF_WARN_UNUSED verify_prehashed_noexcept ( | inline decaf_error_t DECAF_WARN_UNUSED verify_prehashed_noexcept ( | ||||
const FixedBlock<DECAF_EDDSA_448_SIGNATURE_BYTES> &sig, | const FixedBlock<DECAF_EDDSA_448_SIGNATURE_BYTES> &sig, | ||||
const Prehash &ph | const Prehash &ph | ||||
@@ -312,8 +325,8 @@ public: | |||||
ph.context_.size() | ph.context_.size() | ||||
); | ); | ||||
} | } | ||||
/* Verify a prehash context. */ | |||||
/** Verify that a signature is valid for a given prehashed message, given the context. */ | |||||
inline void verify_prehashed ( | inline void verify_prehashed ( | ||||
const FixedBlock<DECAF_EDDSA_448_SIGNATURE_BYTES> &sig, | const FixedBlock<DECAF_EDDSA_448_SIGNATURE_BYTES> &sig, | ||||
const Prehash &ph | const Prehash &ph | ||||
@@ -329,7 +342,7 @@ public: | |||||
} | } | ||||
} | } | ||||
/* Verify a message using the prehasher */ | |||||
/** Hash and verify a message, using the prehashed verification mode. */ | |||||
inline void verify_with_prehash ( | inline void verify_with_prehash ( | ||||
const FixedBlock<DECAF_EDDSA_448_SIGNATURE_BYTES> &sig, | const FixedBlock<DECAF_EDDSA_448_SIGNATURE_BYTES> &sig, | ||||
const Block &message, | const Block &message, | ||||
@@ -341,24 +354,25 @@ public: | |||||
} | } | ||||
}; | }; | ||||
/** EdDSA Public key base class. */ | |||||
class PublicKeyBase | class PublicKeyBase | ||||
: public Serializable<PublicKeyBase> | : public Serializable<PublicKeyBase> | ||||
, public Verification<PublicKeyBase,PURE> | , public Verification<PublicKeyBase,PURE> | ||||
, public Verification<PublicKeyBase,PREHASHED> { | , public Verification<PublicKeyBase,PREHASHED> { | ||||
public: | public: | ||||
typedef class PrivateKeyBase MyPrivateKey; | |||||
/** Private key corresponding to this type of public key */ | |||||
typedef class PrivateKeyBase PrivateKey; | |||||
private: | private: | ||||
/** @cond internal */ | /** @cond internal */ | ||||
friend class PrivateKeyBase; | friend class PrivateKeyBase; | ||||
friend class Verification<PublicKey,PURE>; | friend class Verification<PublicKey,PURE>; | ||||
friend class Verification<PublicKey,PREHASHED>; | friend class Verification<PublicKey,PREHASHED>; | ||||
/** @endcond */ | |||||
private: | private: | ||||
/** The pre-expansion form of the signature */ | /** The pre-expansion form of the signature */ | ||||
FixedArrayBuffer<DECAF_EDDSA_448_PUBLIC_BYTES> pub_; | FixedArrayBuffer<DECAF_EDDSA_448_PUBLIC_BYTES> pub_; | ||||
/** @endcond */ | |||||
public: | public: | ||||
/* PERF FUTURE: Pre-cached decoding? Precomputed table?? */ | /* PERF FUTURE: Pre-cached decoding? Precomputed table?? */ | ||||
@@ -372,7 +386,6 @@ public: | |||||
/** Serialization size. */ | /** Serialization size. */ | ||||
static const size_t SER_BYTES = DECAF_EDDSA_448_PRIVATE_BYTES; | static const size_t SER_BYTES = DECAF_EDDSA_448_PRIVATE_BYTES; | ||||
/** Create but don't initialize */ | /** Create but don't initialize */ | ||||
inline explicit PublicKeyBase(const NOINIT&) DECAF_NOEXCEPT : pub_((NOINIT())) { } | inline explicit PublicKeyBase(const NOINIT&) DECAF_NOEXCEPT : pub_((NOINIT())) { } | ||||
@@ -383,7 +396,7 @@ public: | |||||
inline PublicKeyBase(const PublicKeyBase &k) DECAF_NOEXCEPT { *this = k; } | inline PublicKeyBase(const PublicKeyBase &k) DECAF_NOEXCEPT { *this = k; } | ||||
/** Copy constructor */ | /** Copy constructor */ | ||||
inline explicit PublicKeyBase(const MyPrivateKey &k) DECAF_NOEXCEPT { *this = k; } | |||||
inline explicit PublicKeyBase(const PrivateKey &k) DECAF_NOEXCEPT { *this = k; } | |||||
/** Assignment from string */ | /** Assignment from string */ | ||||
inline PublicKey &operator=(const FixedBlock<SER_BYTES> &b) DECAF_NOEXCEPT { | inline PublicKey &operator=(const FixedBlock<SER_BYTES> &b) DECAF_NOEXCEPT { | ||||
@@ -397,7 +410,7 @@ public: | |||||
} | } | ||||
/** Assignment from private key */ | /** Assignment from private key */ | ||||
inline PublicKey &operator=(const MyPrivateKey &p) DECAF_NOEXCEPT { | |||||
inline PublicKey &operator=(const PrivateKey &p) DECAF_NOEXCEPT { | |||||
return *this = p.pub_; | return *this = p.pub_; | ||||
} | } | ||||
@@ -15,7 +15,15 @@ | |||||
#ifndef __DECAF_EDDSA_HXX__ | #ifndef __DECAF_EDDSA_HXX__ | ||||
#define __DECAF_EDDSA_HXX__ 1 | #define __DECAF_EDDSA_HXX__ 1 | ||||
namespace decaf { enum Prehashed { PURE, PREHASHED }; } | |||||
/** Namespace for all libdecaf C++ objects. */ | |||||
namespace decaf { | |||||
/** How signatures handle hashing. */ | |||||
enum Prehashed { | |||||
PURE, /**< Sign the message itself. This can't be done in one pass. */ | |||||
PREHASHED /**< Sign the hash of the message. */ | |||||
}; | |||||
} | |||||
#include <decaf/ed255.hxx> | #include <decaf/ed255.hxx> | ||||
#include <decaf/ed448.hxx> | #include <decaf/ed448.hxx> | ||||
@@ -64,10 +64,10 @@ typedef struct gf_25519_s { | |||||
/** Number of bytes in an x25519 private key */ | /** Number of bytes in an x25519 private key */ | ||||
#define DECAF_X25519_PRIVATE_BYTES 32 | #define DECAF_X25519_PRIVATE_BYTES 32 | ||||
/** Twisted Edwards extended homogeneous coordinates */ | |||||
/** Representation of a point on the elliptic curve. */ | |||||
typedef struct decaf_255_point_s { | typedef struct decaf_255_point_s { | ||||
/** @cond internal */ | /** @cond internal */ | ||||
gf_25519_t x,y,z,t; | |||||
gf_25519_t x,y,z,t; /* Twisted extended homogeneous coordinates */ | |||||
/** @endcond */ | /** @endcond */ | ||||
} decaf_255_point_t[1]; | } decaf_255_point_t[1]; | ||||
@@ -80,26 +80,26 @@ typedef struct decaf_255_precomputed_s decaf_255_precomputed_s; | |||||
/** Size and alignment of precomputed point tables. */ | /** Size and alignment of precomputed point tables. */ | ||||
extern const size_t decaf_255_sizeof_precomputed_s DECAF_API_VIS, decaf_255_alignof_precomputed_s DECAF_API_VIS; | extern const size_t decaf_255_sizeof_precomputed_s DECAF_API_VIS, decaf_255_alignof_precomputed_s DECAF_API_VIS; | ||||
/** Scalar is stored packed, because we don't need the speed. */ | |||||
/** Representation of an element of the scalar field. */ | |||||
typedef struct decaf_255_scalar_s { | typedef struct decaf_255_scalar_s { | ||||
/** @cond internal */ | /** @cond internal */ | ||||
decaf_word_t limb[DECAF_255_SCALAR_LIMBS]; | decaf_word_t limb[DECAF_255_SCALAR_LIMBS]; | ||||
/** @endcond */ | /** @endcond */ | ||||
} decaf_255_scalar_t[1]; | } decaf_255_scalar_t[1]; | ||||
/** A scalar equal to 1. */ | |||||
/** The scalar 1. */ | |||||
extern const decaf_255_scalar_t decaf_255_scalar_one DECAF_API_VIS; | extern const decaf_255_scalar_t decaf_255_scalar_one DECAF_API_VIS; | ||||
/** A scalar equal to 0. */ | |||||
/** The scalar 0. */ | |||||
extern const decaf_255_scalar_t decaf_255_scalar_zero DECAF_API_VIS; | extern const decaf_255_scalar_t decaf_255_scalar_zero DECAF_API_VIS; | ||||
/** The identity point on the curve. */ | |||||
/** The identity (zero) point on the curve. */ | |||||
extern const decaf_255_point_t decaf_255_point_identity DECAF_API_VIS; | extern const decaf_255_point_t decaf_255_point_identity DECAF_API_VIS; | ||||
/** An arbitrarily chosen base point on the curve. */ | |||||
/** An arbitrarily-chosen base point on the curve. */ | |||||
extern const decaf_255_point_t decaf_255_point_base DECAF_API_VIS; | extern const decaf_255_point_t decaf_255_point_base DECAF_API_VIS; | ||||
/** Precomputed table for the base point on the curve. */ | |||||
/** Precomputed table of multiples of the base point on the curve. */ | |||||
extern const struct decaf_255_precomputed_s *decaf_255_precomputed_base DECAF_API_VIS; | extern const struct decaf_255_precomputed_s *decaf_255_precomputed_base DECAF_API_VIS; | ||||
/** | /** | ||||
@@ -386,19 +386,19 @@ decaf_error_t decaf_255_direct_scalarmul ( | |||||
) DECAF_API_VIS DECAF_NONNULL DECAF_WARN_UNUSED DECAF_NOINLINE; | ) DECAF_API_VIS DECAF_NONNULL DECAF_WARN_UNUSED DECAF_NOINLINE; | ||||
/** | /** | ||||
* @brief RFC 7748 Diffie-Hellman scalarmul. This function uses a different | |||||
* (non-Decaf) encoding. | |||||
* @brief RFC 7748 Diffie-Hellman scalarmul, used to compute shared secrets. | |||||
* This function uses a different (non-Decaf) encoding. | |||||
* | * | ||||
* @param [out] scaled The scaled point base*scalar | |||||
* @param [in] base The point to be scaled. | |||||
* @param [in] scalar The scalar to multiply by. | |||||
* @param [out] shared The shared secret base*scalar | |||||
* @param [in] base The other party's public key, used as the base of the scalarmul. | |||||
* @param [in] scalar The private scalar to multiply by. | |||||
* | * | ||||
* @retval DECAF_SUCCESS The scalarmul succeeded. | * @retval DECAF_SUCCESS The scalarmul succeeded. | ||||
* @retval DECAF_FAILURE The scalarmul didn't succeed, because the base | * @retval DECAF_FAILURE The scalarmul didn't succeed, because the base | ||||
* point is in a small subgroup. | * point is in a small subgroup. | ||||
*/ | */ | ||||
decaf_error_t decaf_x25519 ( | decaf_error_t decaf_x25519 ( | ||||
uint8_t out[DECAF_X25519_PUBLIC_BYTES], | |||||
uint8_t shared[DECAF_X25519_PUBLIC_BYTES], | |||||
const uint8_t base[DECAF_X25519_PUBLIC_BYTES], | const uint8_t base[DECAF_X25519_PUBLIC_BYTES], | ||||
const uint8_t scalar[DECAF_X25519_PRIVATE_BYTES] | const uint8_t scalar[DECAF_X25519_PRIVATE_BYTES] | ||||
) DECAF_API_VIS DECAF_NONNULL DECAF_WARN_UNUSED DECAF_NOINLINE; | ) DECAF_API_VIS DECAF_NONNULL DECAF_WARN_UNUSED DECAF_NOINLINE; | ||||
@@ -429,7 +429,13 @@ void decaf_255_point_mul_by_ratio_and_encode_like_x25519 ( | |||||
) DECAF_API_VIS DECAF_NONNULL; | ) DECAF_API_VIS DECAF_NONNULL; | ||||
/** The base point for X25519 Diffie-Hellman */ | /** The base point for X25519 Diffie-Hellman */ | ||||
extern const uint8_t decaf_x25519_base_point[DECAF_X25519_PUBLIC_BYTES] DECAF_API_VIS; | |||||
extern const uint8_t | |||||
decaf_x25519_base_point[DECAF_X25519_PUBLIC_BYTES] | |||||
#ifndef DOXYGEN | |||||
/* For some reason Doxygen chokes on this despite the defense in common.h... */ | |||||
DECAF_API_VIS | |||||
#endif | |||||
; | |||||
/** | /** | ||||
* @brief RFC 7748 Diffie-Hellman base point scalarmul. This function uses | * @brief RFC 7748 Diffie-Hellman base point scalarmul. This function uses | ||||
@@ -438,8 +444,8 @@ extern const uint8_t decaf_x25519_base_point[DECAF_X25519_PUBLIC_BYTES] DECAF_AP | |||||
* @deprecated Renamed to decaf_x25519_derive_public_key. | * @deprecated Renamed to decaf_x25519_derive_public_key. | ||||
* I have no particular timeline for removing this name. | * I have no particular timeline for removing this name. | ||||
* | * | ||||
* @param [out] scaled The scaled point base*scalar | |||||
* @param [in] scalar The scalar to multiply by. | |||||
* @param [out] out The public key base*scalar. | |||||
* @param [in] scalar The private scalar. | |||||
*/ | */ | ||||
void decaf_x25519_generate_key ( | void decaf_x25519_generate_key ( | ||||
uint8_t out[DECAF_X25519_PUBLIC_BYTES], | uint8_t out[DECAF_X25519_PUBLIC_BYTES], | ||||
@@ -453,8 +459,8 @@ void decaf_x25519_generate_key ( | |||||
* Does exactly the same thing as decaf_x25519_generate_key, | * Does exactly the same thing as decaf_x25519_generate_key, | ||||
* but has a better name. | * but has a better name. | ||||
* | * | ||||
* @param [out] scaled The scaled point base*scalar | |||||
* @param [in] scalar The scalar to multiply by. | |||||
* @param [out] out The public key base*scalar | |||||
* @param [in] scalar The private scalar. | |||||
*/ | */ | ||||
void decaf_x25519_derive_public_key ( | void decaf_x25519_derive_public_key ( | ||||
uint8_t out[DECAF_X25519_PUBLIC_BYTES], | uint8_t out[DECAF_X25519_PUBLIC_BYTES], | ||||
@@ -737,22 +743,20 @@ decaf_255_invert_elligator_uniform ( | |||||
uint32_t which | uint32_t which | ||||
) DECAF_API_VIS DECAF_NONNULL DECAF_NOINLINE DECAF_WARN_UNUSED; | ) DECAF_API_VIS DECAF_NONNULL DECAF_NOINLINE DECAF_WARN_UNUSED; | ||||
/** | |||||
* @brief Overwrite scalar with zeros. | |||||
*/ | |||||
/** Securely erase a scalar. */ | |||||
void decaf_255_scalar_destroy ( | void decaf_255_scalar_destroy ( | ||||
decaf_255_scalar_t scalar | decaf_255_scalar_t scalar | ||||
) DECAF_NONNULL DECAF_API_VIS; | ) DECAF_NONNULL DECAF_API_VIS; | ||||
/** | |||||
* @brief Overwrite point with zeros. | |||||
/** Securely erase a point by overwriting it with zeros. | |||||
* @warning This causes the point object to become invalid. | |||||
*/ | */ | ||||
void decaf_255_point_destroy ( | void decaf_255_point_destroy ( | ||||
decaf_255_point_t point | decaf_255_point_t point | ||||
) DECAF_NONNULL DECAF_API_VIS; | ) DECAF_NONNULL DECAF_API_VIS; | ||||
/** | |||||
* @brief Overwrite precomputed table with zeros. | |||||
/** Securely erase a precomputed table by overwriting it with zeros. | |||||
* @warning This causes the table object to become invalid. | |||||
*/ | */ | ||||
void decaf_255_precomputed_destroy ( | void decaf_255_precomputed_destroy ( | ||||
decaf_255_precomputed_s *pre | decaf_255_precomputed_s *pre | ||||
@@ -6,18 +6,17 @@ | |||||
* Copyright (c) 2015-2016 Cryptography Research, Inc. \n | * Copyright (c) 2015-2016 Cryptography Research, Inc. \n | ||||
* Released under the MIT License. See LICENSE.txt for license information. | * Released under the MIT License. See LICENSE.txt for license information. | ||||
* | * | ||||
* A group of prime order p, C++ wrapper. | |||||
* A group of prime order, C++ wrapper. | |||||
* | * | ||||
* The Decaf library implements cryptographic operations on a an elliptic curve | * The Decaf library implements cryptographic operations on a an elliptic curve | ||||
* group of prime order p. It accomplishes this by using a twisted Edwards | |||||
* group of prime order. It accomplishes this by using a twisted Edwards | |||||
* curve (isogenous to Curve25519) 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 | |||||
* element. | |||||
* | |||||
* The formulas contain no data-dependent branches, timing or memory accesses, | |||||
* except for decaf_255_base_double_scalarmul_non_secret. | |||||
* Most of the functions in this file run in constant time, can't fail | |||||
* except for ubiquitous reasons like memory exhaustion, and contain no | |||||
* data-dependend branches, timing or memory accesses. There are some | |||||
* exceptions, which should be noted. Typically, decoding functions can | |||||
* fail. | |||||
* | * | ||||
* @warning This file was automatically generated in Python. | * @warning This file was automatically generated in Python. | ||||
* Please do not edit it. | * Please do not edit it. | ||||
@@ -187,8 +186,9 @@ public: | |||||
/** Negate */ | /** Negate */ | ||||
inline Scalar operator- () const DECAF_NOEXCEPT { Scalar r((NOINIT())); decaf_255_scalar_sub(r.s,decaf_255_scalar_zero,s); return r; } | inline Scalar operator- () const DECAF_NOEXCEPT { Scalar r((NOINIT())); decaf_255_scalar_sub(r.s,decaf_255_scalar_zero,s); return r; } | ||||
/** Invert with Fermat's Little Theorem (slow!). If *this == 0, | |||||
* throw CryptoException. */ | |||||
/** Return 1/this. | |||||
* @throw CryptoException if this is 0. | |||||
*/ | |||||
inline Scalar inverse() const /*throw(CryptoException)*/ { | inline Scalar inverse() const /*throw(CryptoException)*/ { | ||||
Scalar r; | Scalar r; | ||||
if (DECAF_SUCCESS != decaf_255_scalar_invert(r.s,s)) { | if (DECAF_SUCCESS != decaf_255_scalar_invert(r.s,s)) { | ||||
@@ -204,10 +204,10 @@ public: | |||||
return decaf_255_scalar_invert(r.s,s); | return decaf_255_scalar_invert(r.s,s); | ||||
} | } | ||||
/** Divide by inverting q. If q == 0, return 0. */ | |||||
/** Return this/q. @throw CryptoException if q == 0. */ | |||||
inline Scalar operator/ (const Scalar &q) const /*throw(CryptoException)*/ { return *this * q.inverse(); } | inline Scalar operator/ (const Scalar &q) const /*throw(CryptoException)*/ { return *this * q.inverse(); } | ||||
/** Divide by inverting q. If q == 0, return 0. */ | |||||
/** Set this to this/q. @throw CryptoException if q == 0. */ | |||||
inline Scalar &operator/=(const Scalar &q) /*throw(CryptoException)*/ { return *this *= q.inverse(); } | inline Scalar &operator/=(const Scalar &q) /*throw(CryptoException)*/ { return *this *= q.inverse(); } | ||||
/** Return half this scalar. Much faster than /2. */ | /** Return half this scalar. Much faster than /2. */ | ||||
@@ -225,7 +225,9 @@ public: | |||||
/** Scalarmul-precomputed with scalar on left. */ | /** Scalarmul-precomputed with scalar on left. */ | ||||
inline Point operator* (const Precomputed &q) const DECAF_NOEXCEPT { return q * (*this); } | inline Point operator* (const Precomputed &q) const DECAF_NOEXCEPT { return q * (*this); } | ||||
/** Direct scalar multiplication. */ | |||||
/** Direct scalar multiplication. | |||||
* @throw CryptoException if the input didn't decode. | |||||
*/ | |||||
inline SecureBuffer direct_scalarmul ( | inline SecureBuffer direct_scalarmul ( | ||||
const FixedBlock<SER_BYTES> &in, | const FixedBlock<SER_BYTES> &in, | ||||
decaf_bool_t allow_identity=DECAF_FALSE, | decaf_bool_t allow_identity=DECAF_FALSE, | ||||
@@ -241,12 +243,10 @@ public: | |||||
) const DECAF_NOEXCEPT; | ) const DECAF_NOEXCEPT; | ||||
}; | }; | ||||
/** | |||||
* Element of prime-order group. | |||||
*/ | |||||
/** Element of prime-order elliptic curve group. */ | |||||
class Point : public Serializable<Point> { | class Point : public Serializable<Point> { | ||||
public: | public: | ||||
/** wrapped C type */ | |||||
/** Wrapped C type */ | |||||
typedef decaf_255_point_t Wrapped; | typedef decaf_255_point_t Wrapped; | ||||
/** Size of a serialized element */ | /** Size of a serialized element */ | ||||
@@ -270,17 +270,8 @@ public: | |||||
/** Ratio due to ladder decoding */ | /** Ratio due to ladder decoding */ | ||||
static const int LADDER_ENCODE_RATIO = DECAF_X25519_ENCODE_RATIO; | static const int LADDER_ENCODE_RATIO = DECAF_X25519_ENCODE_RATIO; | ||||
/** | |||||
* Size of a stegged element. | |||||
* | |||||
* FUTURE: You can use HASH_BYTES * 3/2 (or more likely much less, eg HASH_BYTES + 8) | |||||
* with a random oracle hash function, by hash-expanding everything past the first | |||||
* HASH_BYTES of the element. However, since the internal C invert_elligator is not | |||||
* tied to a hash function, I didn't want to tie the C++ wrapper to a hash function | |||||
* either. But it might be a good idea to do this in the future, either with STROBE | |||||
* or something else. | |||||
* | |||||
* Then again, calling invert_elligator at all is super niche, so maybe who cares? | |||||
/** Size of a steganographically-encoded curve element. If the point is random, the encoding | |||||
* should look statistically close to a uniformly-random sequnece of STEG_BYTES bytes. | |||||
*/ | */ | ||||
static const size_t STEG_BYTES = HASH_BYTES * 2; | static const size_t STEG_BYTES = HASH_BYTES * 2; | ||||
@@ -325,9 +316,9 @@ public: | |||||
* @throw CryptoException the string was the wrong length, or wasn't the encoding of a point, | * @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. | * 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, bool allow_identity=true) | |||||
/*throw(CryptoException)*/ { | /*throw(CryptoException)*/ { | ||||
if (DECAF_SUCCESS != decode(buffer,allow_identity)) { | |||||
if (DECAF_SUCCESS != decode(buffer,allow_identity ? DECAF_TRUE : DECAF_FALSE)) { | |||||
throw CryptoException(); | throw CryptoException(); | ||||
} | } | ||||
} | } | ||||
@@ -341,9 +332,9 @@ public: | |||||
* or was the identity and allow_identity was DECAF_FALSE. Contents of the buffer are undefined. | * or was the identity and allow_identity was DECAF_FALSE. Contents of the buffer are undefined. | ||||
*/ | */ | ||||
inline decaf_error_t DECAF_WARN_UNUSED decode ( | inline decaf_error_t DECAF_WARN_UNUSED decode ( | ||||
const FixedBlock<SER_BYTES> &buffer, decaf_bool_t allow_identity=DECAF_TRUE | |||||
const FixedBlock<SER_BYTES> &buffer, bool allow_identity=true | |||||
) DECAF_NOEXCEPT { | ) DECAF_NOEXCEPT { | ||||
return decaf_255_point_decode(p,buffer.data(),allow_identity); | |||||
return decaf_255_point_decode(p,buffer.data(),allow_identity ? DECAF_TRUE : DECAF_FALSE); | |||||
} | } | ||||
/** | /** | ||||
@@ -393,9 +384,7 @@ public: | |||||
} | } | ||||
/** Multiply by LADDER_ENCODE_RATIO and encode like X25519/X448. */ | /** Multiply by LADDER_ENCODE_RATIO and encode like X25519/X448. */ | ||||
inline void mul_by_ratio_and_encode_like_ladder( | |||||
FixedBuffer<LADDER_BYTES> &out | |||||
) const { | |||||
inline void mul_by_ratio_and_encode_like_ladder(FixedBuffer<LADDER_BYTES> &out) const { | |||||
decaf_255_point_mul_by_ratio_and_encode_like_x25519(out.data(),p); | decaf_255_point_mul_by_ratio_and_encode_like_x25519(out.data(),p); | ||||
} | } | ||||
@@ -431,9 +420,7 @@ public: | |||||
} | } | ||||
} | } | ||||
/** | |||||
* Encode to string. The identity encodes to the all-zero string. | |||||
*/ | |||||
/** Encode to string. The identity encodes to the all-zero string. */ | |||||
inline operator SecureBuffer() const { | inline operator SecureBuffer() const { | ||||
SecureBuffer buffer(SER_BYTES); | SecureBuffer buffer(SER_BYTES); | ||||
decaf_255_point_encode(buffer.data(), p); | decaf_255_point_encode(buffer.data(), p); | ||||
@@ -583,10 +570,10 @@ public: | |||||
return out; | return out; | ||||
} | } | ||||
/** Return the base point */ | |||||
/** Return the base point of the curve. */ | |||||
static inline const Point base() DECAF_NOEXCEPT { return Point(decaf_255_point_base); } | static inline const Point base() DECAF_NOEXCEPT { return Point(decaf_255_point_base); } | ||||
/** Return the identity point */ | |||||
/** Return the identity point of the curve. */ | |||||
static inline const Point identity() DECAF_NOEXCEPT { return Point(decaf_255_point_identity); } | static inline const Point identity() DECAF_NOEXCEPT { return Point(decaf_255_point_identity); } | ||||
}; | }; | ||||
@@ -684,6 +671,7 @@ public: | |||||
/** @endcond */ | /** @endcond */ | ||||
}; | }; | ||||
/** X-only Diffie-Hellman ladder functions */ | |||||
struct DhLadder { | struct DhLadder { | ||||
public: | public: | ||||
/** Bytes in an X25519 public key. */ | /** Bytes in an X25519 public key. */ | ||||
@@ -758,7 +746,8 @@ public: | |||||
* equivalent to shared_secret(base_point(),scalar) but possibly faster. | * equivalent to shared_secret(base_point(),scalar) but possibly faster. | ||||
* @deprecated Renamed to derive_public_key_noexcept. | * @deprecated Renamed to derive_public_key_noexcept. | ||||
*/ | */ | ||||
static inline void DECAF_DEPRECATED("Renamed to derive_public_key_noexcept") | |||||
static inline void | |||||
DECAF_DEPRECATED("Renamed to derive_public_key_noexcept") | |||||
generate_key_noexcept ( | generate_key_noexcept ( | ||||
FixedBuffer<PUBLIC_BYTES> &out, | FixedBuffer<PUBLIC_BYTES> &out, | ||||
const FixedBlock<PRIVATE_BYTES> &scalar | const FixedBlock<PRIVATE_BYTES> &scalar | ||||
@@ -794,6 +783,7 @@ inline decaf_error_t Ristretto::Scalar::direct_scalarmul_noexcept ( | |||||
} | } | ||||
/** @endcond */ | /** @endcond */ | ||||
/** Alternative name for Ristretto, for backwards compatibility */ | |||||
typedef Ristretto IsoEd25519; | typedef Ristretto IsoEd25519; | ||||
@@ -64,10 +64,10 @@ typedef struct gf_448_s { | |||||
/** Number of bytes in an x448 private key */ | /** Number of bytes in an x448 private key */ | ||||
#define DECAF_X448_PRIVATE_BYTES 56 | #define DECAF_X448_PRIVATE_BYTES 56 | ||||
/** Twisted Edwards extended homogeneous coordinates */ | |||||
/** Representation of a point on the elliptic curve. */ | |||||
typedef struct decaf_448_point_s { | typedef struct decaf_448_point_s { | ||||
/** @cond internal */ | /** @cond internal */ | ||||
gf_448_t x,y,z,t; | |||||
gf_448_t x,y,z,t; /* Twisted extended homogeneous coordinates */ | |||||
/** @endcond */ | /** @endcond */ | ||||
} decaf_448_point_t[1]; | } decaf_448_point_t[1]; | ||||
@@ -80,26 +80,26 @@ typedef struct decaf_448_precomputed_s decaf_448_precomputed_s; | |||||
/** Size and alignment of precomputed point tables. */ | /** Size and alignment of precomputed point tables. */ | ||||
extern const size_t decaf_448_sizeof_precomputed_s DECAF_API_VIS, decaf_448_alignof_precomputed_s DECAF_API_VIS; | extern const size_t decaf_448_sizeof_precomputed_s DECAF_API_VIS, decaf_448_alignof_precomputed_s DECAF_API_VIS; | ||||
/** Scalar is stored packed, because we don't need the speed. */ | |||||
/** Representation of an element of the scalar field. */ | |||||
typedef struct decaf_448_scalar_s { | typedef struct decaf_448_scalar_s { | ||||
/** @cond internal */ | /** @cond internal */ | ||||
decaf_word_t limb[DECAF_448_SCALAR_LIMBS]; | decaf_word_t limb[DECAF_448_SCALAR_LIMBS]; | ||||
/** @endcond */ | /** @endcond */ | ||||
} decaf_448_scalar_t[1]; | } decaf_448_scalar_t[1]; | ||||
/** A scalar equal to 1. */ | |||||
/** The scalar 1. */ | |||||
extern const decaf_448_scalar_t decaf_448_scalar_one DECAF_API_VIS; | extern const decaf_448_scalar_t decaf_448_scalar_one DECAF_API_VIS; | ||||
/** A scalar equal to 0. */ | |||||
/** The scalar 0. */ | |||||
extern const decaf_448_scalar_t decaf_448_scalar_zero DECAF_API_VIS; | extern const decaf_448_scalar_t decaf_448_scalar_zero DECAF_API_VIS; | ||||
/** The identity point on the curve. */ | |||||
/** The identity (zero) point on the curve. */ | |||||
extern const decaf_448_point_t decaf_448_point_identity DECAF_API_VIS; | extern const decaf_448_point_t decaf_448_point_identity DECAF_API_VIS; | ||||
/** An arbitrarily chosen base point on the curve. */ | |||||
/** An arbitrarily-chosen base point on the curve. */ | |||||
extern const decaf_448_point_t decaf_448_point_base DECAF_API_VIS; | extern const decaf_448_point_t decaf_448_point_base DECAF_API_VIS; | ||||
/** Precomputed table for the base point on the curve. */ | |||||
/** Precomputed table of multiples of the base point on the curve. */ | |||||
extern const struct decaf_448_precomputed_s *decaf_448_precomputed_base DECAF_API_VIS; | extern const struct decaf_448_precomputed_s *decaf_448_precomputed_base DECAF_API_VIS; | ||||
/** | /** | ||||
@@ -386,19 +386,19 @@ decaf_error_t decaf_448_direct_scalarmul ( | |||||
) DECAF_API_VIS DECAF_NONNULL DECAF_WARN_UNUSED DECAF_NOINLINE; | ) DECAF_API_VIS DECAF_NONNULL DECAF_WARN_UNUSED DECAF_NOINLINE; | ||||
/** | /** | ||||
* @brief RFC 7748 Diffie-Hellman scalarmul. This function uses a different | |||||
* (non-Decaf) encoding. | |||||
* @brief RFC 7748 Diffie-Hellman scalarmul, used to compute shared secrets. | |||||
* This function uses a different (non-Decaf) encoding. | |||||
* | * | ||||
* @param [out] scaled The scaled point base*scalar | |||||
* @param [in] base The point to be scaled. | |||||
* @param [in] scalar The scalar to multiply by. | |||||
* @param [out] shared The shared secret base*scalar | |||||
* @param [in] base The other party's public key, used as the base of the scalarmul. | |||||
* @param [in] scalar The private scalar to multiply by. | |||||
* | * | ||||
* @retval DECAF_SUCCESS The scalarmul succeeded. | * @retval DECAF_SUCCESS The scalarmul succeeded. | ||||
* @retval DECAF_FAILURE The scalarmul didn't succeed, because the base | * @retval DECAF_FAILURE The scalarmul didn't succeed, because the base | ||||
* point is in a small subgroup. | * point is in a small subgroup. | ||||
*/ | */ | ||||
decaf_error_t decaf_x448 ( | decaf_error_t decaf_x448 ( | ||||
uint8_t out[DECAF_X448_PUBLIC_BYTES], | |||||
uint8_t shared[DECAF_X448_PUBLIC_BYTES], | |||||
const uint8_t base[DECAF_X448_PUBLIC_BYTES], | const uint8_t base[DECAF_X448_PUBLIC_BYTES], | ||||
const uint8_t scalar[DECAF_X448_PRIVATE_BYTES] | const uint8_t scalar[DECAF_X448_PRIVATE_BYTES] | ||||
) DECAF_API_VIS DECAF_NONNULL DECAF_WARN_UNUSED DECAF_NOINLINE; | ) DECAF_API_VIS DECAF_NONNULL DECAF_WARN_UNUSED DECAF_NOINLINE; | ||||
@@ -429,7 +429,13 @@ void decaf_448_point_mul_by_ratio_and_encode_like_x448 ( | |||||
) DECAF_API_VIS DECAF_NONNULL; | ) DECAF_API_VIS DECAF_NONNULL; | ||||
/** The base point for X448 Diffie-Hellman */ | /** The base point for X448 Diffie-Hellman */ | ||||
extern const uint8_t decaf_x448_base_point[DECAF_X448_PUBLIC_BYTES] DECAF_API_VIS; | |||||
extern const uint8_t | |||||
decaf_x448_base_point[DECAF_X448_PUBLIC_BYTES] | |||||
#ifndef DOXYGEN | |||||
/* For some reason Doxygen chokes on this despite the defense in common.h... */ | |||||
DECAF_API_VIS | |||||
#endif | |||||
; | |||||
/** | /** | ||||
* @brief RFC 7748 Diffie-Hellman base point scalarmul. This function uses | * @brief RFC 7748 Diffie-Hellman base point scalarmul. This function uses | ||||
@@ -438,8 +444,8 @@ extern const uint8_t decaf_x448_base_point[DECAF_X448_PUBLIC_BYTES] DECAF_API_VI | |||||
* @deprecated Renamed to decaf_x448_derive_public_key. | * @deprecated Renamed to decaf_x448_derive_public_key. | ||||
* I have no particular timeline for removing this name. | * I have no particular timeline for removing this name. | ||||
* | * | ||||
* @param [out] scaled The scaled point base*scalar | |||||
* @param [in] scalar The scalar to multiply by. | |||||
* @param [out] out The public key base*scalar. | |||||
* @param [in] scalar The private scalar. | |||||
*/ | */ | ||||
void decaf_x448_generate_key ( | void decaf_x448_generate_key ( | ||||
uint8_t out[DECAF_X448_PUBLIC_BYTES], | uint8_t out[DECAF_X448_PUBLIC_BYTES], | ||||
@@ -453,8 +459,8 @@ void decaf_x448_generate_key ( | |||||
* Does exactly the same thing as decaf_x448_generate_key, | * Does exactly the same thing as decaf_x448_generate_key, | ||||
* but has a better name. | * but has a better name. | ||||
* | * | ||||
* @param [out] scaled The scaled point base*scalar | |||||
* @param [in] scalar The scalar to multiply by. | |||||
* @param [out] out The public key base*scalar | |||||
* @param [in] scalar The private scalar. | |||||
*/ | */ | ||||
void decaf_x448_derive_public_key ( | void decaf_x448_derive_public_key ( | ||||
uint8_t out[DECAF_X448_PUBLIC_BYTES], | uint8_t out[DECAF_X448_PUBLIC_BYTES], | ||||
@@ -737,22 +743,20 @@ decaf_448_invert_elligator_uniform ( | |||||
uint32_t which | uint32_t which | ||||
) DECAF_API_VIS DECAF_NONNULL DECAF_NOINLINE DECAF_WARN_UNUSED; | ) DECAF_API_VIS DECAF_NONNULL DECAF_NOINLINE DECAF_WARN_UNUSED; | ||||
/** | |||||
* @brief Overwrite scalar with zeros. | |||||
*/ | |||||
/** Securely erase a scalar. */ | |||||
void decaf_448_scalar_destroy ( | void decaf_448_scalar_destroy ( | ||||
decaf_448_scalar_t scalar | decaf_448_scalar_t scalar | ||||
) DECAF_NONNULL DECAF_API_VIS; | ) DECAF_NONNULL DECAF_API_VIS; | ||||
/** | |||||
* @brief Overwrite point with zeros. | |||||
/** Securely erase a point by overwriting it with zeros. | |||||
* @warning This causes the point object to become invalid. | |||||
*/ | */ | ||||
void decaf_448_point_destroy ( | void decaf_448_point_destroy ( | ||||
decaf_448_point_t point | decaf_448_point_t point | ||||
) DECAF_NONNULL DECAF_API_VIS; | ) DECAF_NONNULL DECAF_API_VIS; | ||||
/** | |||||
* @brief Overwrite precomputed table with zeros. | |||||
/** Securely erase a precomputed table by overwriting it with zeros. | |||||
* @warning This causes the table object to become invalid. | |||||
*/ | */ | ||||
void decaf_448_precomputed_destroy ( | void decaf_448_precomputed_destroy ( | ||||
decaf_448_precomputed_s *pre | decaf_448_precomputed_s *pre | ||||
@@ -6,18 +6,17 @@ | |||||
* Copyright (c) 2015-2016 Cryptography Research, Inc. \n | * Copyright (c) 2015-2016 Cryptography Research, Inc. \n | ||||
* Released under the MIT License. See LICENSE.txt for license information. | * Released under the MIT License. See LICENSE.txt for license information. | ||||
* | * | ||||
* A group of prime order p, C++ wrapper. | |||||
* A group of prime order, C++ wrapper. | |||||
* | * | ||||
* The Decaf library implements cryptographic operations on a an elliptic curve | * The Decaf library implements cryptographic operations on a an elliptic curve | ||||
* group of prime order p. It accomplishes this by using a twisted Edwards | |||||
* group of prime order. It accomplishes this by using a twisted Edwards | |||||
* curve (isogenous to Ed448-Goldilocks) and wiping out the cofactor. | * curve (isogenous to Ed448-Goldilocks) and wiping out the cofactor. | ||||
* | * | ||||
* The formulas are all complete and have no special cases, except that | |||||
* decaf_448_decode can fail because not every sequence of bytes is a valid group | |||||
* element. | |||||
* | |||||
* The formulas contain no data-dependent branches, timing or memory accesses, | |||||
* except for decaf_448_base_double_scalarmul_non_secret. | |||||
* Most of the functions in this file run in constant time, can't fail | |||||
* except for ubiquitous reasons like memory exhaustion, and contain no | |||||
* data-dependend branches, timing or memory accesses. There are some | |||||
* exceptions, which should be noted. Typically, decoding functions can | |||||
* fail. | |||||
* | * | ||||
* @warning This file was automatically generated in Python. | * @warning This file was automatically generated in Python. | ||||
* Please do not edit it. | * Please do not edit it. | ||||
@@ -187,8 +186,9 @@ public: | |||||
/** Negate */ | /** Negate */ | ||||
inline Scalar operator- () const DECAF_NOEXCEPT { Scalar r((NOINIT())); decaf_448_scalar_sub(r.s,decaf_448_scalar_zero,s); return r; } | inline Scalar operator- () const DECAF_NOEXCEPT { Scalar r((NOINIT())); decaf_448_scalar_sub(r.s,decaf_448_scalar_zero,s); return r; } | ||||
/** Invert with Fermat's Little Theorem (slow!). If *this == 0, | |||||
* throw CryptoException. */ | |||||
/** Return 1/this. | |||||
* @throw CryptoException if this is 0. | |||||
*/ | |||||
inline Scalar inverse() const /*throw(CryptoException)*/ { | inline Scalar inverse() const /*throw(CryptoException)*/ { | ||||
Scalar r; | Scalar r; | ||||
if (DECAF_SUCCESS != decaf_448_scalar_invert(r.s,s)) { | if (DECAF_SUCCESS != decaf_448_scalar_invert(r.s,s)) { | ||||
@@ -204,10 +204,10 @@ public: | |||||
return decaf_448_scalar_invert(r.s,s); | return decaf_448_scalar_invert(r.s,s); | ||||
} | } | ||||
/** Divide by inverting q. If q == 0, return 0. */ | |||||
/** Return this/q. @throw CryptoException if q == 0. */ | |||||
inline Scalar operator/ (const Scalar &q) const /*throw(CryptoException)*/ { return *this * q.inverse(); } | inline Scalar operator/ (const Scalar &q) const /*throw(CryptoException)*/ { return *this * q.inverse(); } | ||||
/** Divide by inverting q. If q == 0, return 0. */ | |||||
/** Set this to this/q. @throw CryptoException if q == 0. */ | |||||
inline Scalar &operator/=(const Scalar &q) /*throw(CryptoException)*/ { return *this *= q.inverse(); } | inline Scalar &operator/=(const Scalar &q) /*throw(CryptoException)*/ { return *this *= q.inverse(); } | ||||
/** Return half this scalar. Much faster than /2. */ | /** Return half this scalar. Much faster than /2. */ | ||||
@@ -225,7 +225,9 @@ public: | |||||
/** Scalarmul-precomputed with scalar on left. */ | /** Scalarmul-precomputed with scalar on left. */ | ||||
inline Point operator* (const Precomputed &q) const DECAF_NOEXCEPT { return q * (*this); } | inline Point operator* (const Precomputed &q) const DECAF_NOEXCEPT { return q * (*this); } | ||||
/** Direct scalar multiplication. */ | |||||
/** Direct scalar multiplication. | |||||
* @throw CryptoException if the input didn't decode. | |||||
*/ | |||||
inline SecureBuffer direct_scalarmul ( | inline SecureBuffer direct_scalarmul ( | ||||
const FixedBlock<SER_BYTES> &in, | const FixedBlock<SER_BYTES> &in, | ||||
decaf_bool_t allow_identity=DECAF_FALSE, | decaf_bool_t allow_identity=DECAF_FALSE, | ||||
@@ -241,12 +243,10 @@ public: | |||||
) const DECAF_NOEXCEPT; | ) const DECAF_NOEXCEPT; | ||||
}; | }; | ||||
/** | |||||
* Element of prime-order group. | |||||
*/ | |||||
/** Element of prime-order elliptic curve group. */ | |||||
class Point : public Serializable<Point> { | class Point : public Serializable<Point> { | ||||
public: | public: | ||||
/** wrapped C type */ | |||||
/** Wrapped C type */ | |||||
typedef decaf_448_point_t Wrapped; | typedef decaf_448_point_t Wrapped; | ||||
/** Size of a serialized element */ | /** Size of a serialized element */ | ||||
@@ -270,17 +270,8 @@ public: | |||||
/** Ratio due to ladder decoding */ | /** Ratio due to ladder decoding */ | ||||
static const int LADDER_ENCODE_RATIO = DECAF_X448_ENCODE_RATIO; | static const int LADDER_ENCODE_RATIO = DECAF_X448_ENCODE_RATIO; | ||||
/** | |||||
* Size of a stegged element. | |||||
* | |||||
* FUTURE: You can use HASH_BYTES * 3/2 (or more likely much less, eg HASH_BYTES + 8) | |||||
* with a random oracle hash function, by hash-expanding everything past the first | |||||
* HASH_BYTES of the element. However, since the internal C invert_elligator is not | |||||
* tied to a hash function, I didn't want to tie the C++ wrapper to a hash function | |||||
* either. But it might be a good idea to do this in the future, either with STROBE | |||||
* or something else. | |||||
* | |||||
* Then again, calling invert_elligator at all is super niche, so maybe who cares? | |||||
/** Size of a steganographically-encoded curve element. If the point is random, the encoding | |||||
* should look statistically close to a uniformly-random sequnece of STEG_BYTES bytes. | |||||
*/ | */ | ||||
static const size_t STEG_BYTES = HASH_BYTES * 2; | static const size_t STEG_BYTES = HASH_BYTES * 2; | ||||
@@ -325,9 +316,9 @@ public: | |||||
* @throw CryptoException the string was the wrong length, or wasn't the encoding of a point, | * @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. | * 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, bool allow_identity=true) | |||||
/*throw(CryptoException)*/ { | /*throw(CryptoException)*/ { | ||||
if (DECAF_SUCCESS != decode(buffer,allow_identity)) { | |||||
if (DECAF_SUCCESS != decode(buffer,allow_identity ? DECAF_TRUE : DECAF_FALSE)) { | |||||
throw CryptoException(); | throw CryptoException(); | ||||
} | } | ||||
} | } | ||||
@@ -341,9 +332,9 @@ public: | |||||
* or was the identity and allow_identity was DECAF_FALSE. Contents of the buffer are undefined. | * or was the identity and allow_identity was DECAF_FALSE. Contents of the buffer are undefined. | ||||
*/ | */ | ||||
inline decaf_error_t DECAF_WARN_UNUSED decode ( | inline decaf_error_t DECAF_WARN_UNUSED decode ( | ||||
const FixedBlock<SER_BYTES> &buffer, decaf_bool_t allow_identity=DECAF_TRUE | |||||
const FixedBlock<SER_BYTES> &buffer, bool allow_identity=true | |||||
) DECAF_NOEXCEPT { | ) DECAF_NOEXCEPT { | ||||
return decaf_448_point_decode(p,buffer.data(),allow_identity); | |||||
return decaf_448_point_decode(p,buffer.data(),allow_identity ? DECAF_TRUE : DECAF_FALSE); | |||||
} | } | ||||
/** | /** | ||||
@@ -393,9 +384,7 @@ public: | |||||
} | } | ||||
/** Multiply by LADDER_ENCODE_RATIO and encode like X25519/X448. */ | /** Multiply by LADDER_ENCODE_RATIO and encode like X25519/X448. */ | ||||
inline void mul_by_ratio_and_encode_like_ladder( | |||||
FixedBuffer<LADDER_BYTES> &out | |||||
) const { | |||||
inline void mul_by_ratio_and_encode_like_ladder(FixedBuffer<LADDER_BYTES> &out) const { | |||||
decaf_448_point_mul_by_ratio_and_encode_like_x448(out.data(),p); | decaf_448_point_mul_by_ratio_and_encode_like_x448(out.data(),p); | ||||
} | } | ||||
@@ -431,9 +420,7 @@ public: | |||||
} | } | ||||
} | } | ||||
/** | |||||
* Encode to string. The identity encodes to the all-zero string. | |||||
*/ | |||||
/** Encode to string. The identity encodes to the all-zero string. */ | |||||
inline operator SecureBuffer() const { | inline operator SecureBuffer() const { | ||||
SecureBuffer buffer(SER_BYTES); | SecureBuffer buffer(SER_BYTES); | ||||
decaf_448_point_encode(buffer.data(), p); | decaf_448_point_encode(buffer.data(), p); | ||||
@@ -583,10 +570,10 @@ public: | |||||
return out; | return out; | ||||
} | } | ||||
/** Return the base point */ | |||||
/** Return the base point of the curve. */ | |||||
static inline const Point base() DECAF_NOEXCEPT { return Point(decaf_448_point_base); } | static inline const Point base() DECAF_NOEXCEPT { return Point(decaf_448_point_base); } | ||||
/** Return the identity point */ | |||||
/** Return the identity point of the curve. */ | |||||
static inline const Point identity() DECAF_NOEXCEPT { return Point(decaf_448_point_identity); } | static inline const Point identity() DECAF_NOEXCEPT { return Point(decaf_448_point_identity); } | ||||
}; | }; | ||||
@@ -684,6 +671,7 @@ public: | |||||
/** @endcond */ | /** @endcond */ | ||||
}; | }; | ||||
/** X-only Diffie-Hellman ladder functions */ | |||||
struct DhLadder { | struct DhLadder { | ||||
public: | public: | ||||
/** Bytes in an X448 public key. */ | /** Bytes in an X448 public key. */ | ||||
@@ -758,7 +746,8 @@ public: | |||||
* equivalent to shared_secret(base_point(),scalar) but possibly faster. | * equivalent to shared_secret(base_point(),scalar) but possibly faster. | ||||
* @deprecated Renamed to derive_public_key_noexcept. | * @deprecated Renamed to derive_public_key_noexcept. | ||||
*/ | */ | ||||
static inline void DECAF_DEPRECATED("Renamed to derive_public_key_noexcept") | |||||
static inline void | |||||
DECAF_DEPRECATED("Renamed to derive_public_key_noexcept") | |||||
generate_key_noexcept ( | generate_key_noexcept ( | ||||
FixedBuffer<PUBLIC_BYTES> &out, | FixedBuffer<PUBLIC_BYTES> &out, | ||||
const FixedBlock<PRIVATE_BYTES> &scalar | const FixedBlock<PRIVATE_BYTES> &scalar | ||||
@@ -18,21 +18,39 @@ | |||||
extern "C" { | extern "C" { | ||||
#endif | #endif | ||||
/** Hash context for SHA-512 */ | |||||
typedef struct decaf_sha512_ctx_s { | typedef struct decaf_sha512_ctx_s { | ||||
/** @cond internal */ | |||||
uint64_t state[8]; | uint64_t state[8]; | ||||
uint8_t block[128]; | uint8_t block[128]; | ||||
uint64_t bytes_processed; | uint64_t bytes_processed; | ||||
/* @endcond */ | |||||
} decaf_sha512_ctx_s, decaf_sha512_ctx_t[1]; | } decaf_sha512_ctx_s, decaf_sha512_ctx_t[1]; | ||||
/** Initialize a SHA-512 context. */ | |||||
void decaf_sha512_init(decaf_sha512_ctx_t ctx) DECAF_NONNULL DECAF_API_VIS; | void decaf_sha512_init(decaf_sha512_ctx_t ctx) DECAF_NONNULL DECAF_API_VIS; | ||||
void decaf_sha512_update(decaf_sha512_ctx_t ctx, const uint8_t *message, size_t length) DECAF_NONNULL DECAF_API_VIS; | |||||
void decaf_sha512_final(decaf_sha512_ctx_t ctx, uint8_t *out, size_t length) DECAF_NONNULL DECAF_API_VIS; | |||||
/** Update context by hashing part of a message. */ | |||||
void decaf_sha512_update(decaf_sha512_ctx_t ctx, const uint8_t *message, size_t message_len) DECAF_NONNULL DECAF_API_VIS; | |||||
/** Finalize context and write out hash. | |||||
* @param [inout] ctx The context. Will be destroyed and re-initialized on return. | |||||
* @param [out] output Place to store the output hash. | |||||
* @param [in] output_len Length in bytes of the output hash. Must between 0 and 64, inclusive. | |||||
*/ | |||||
void decaf_sha512_final(decaf_sha512_ctx_t ctx, uint8_t *output, size_t output_len) DECAF_NONNULL DECAF_API_VIS; | |||||
/** Securely destroy a SHA512 context. */ | |||||
static inline void decaf_sha512_destroy(decaf_sha512_ctx_t ctx) { | static inline void decaf_sha512_destroy(decaf_sha512_ctx_t ctx) { | ||||
decaf_bzero(ctx,sizeof(*ctx)); | decaf_bzero(ctx,sizeof(*ctx)); | ||||
} | } | ||||
/** Hash a message. | |||||
* @param [out] output Place to store the output hash. | |||||
* @param [in] output_len Length in bytes of the output hash. Must between 0 and 64, inclusive. | |||||
* @param [in] message A message to hash. | |||||
* @param [in] message_len Length in bytes of the input message. | |||||
*/ | |||||
static inline void decaf_sha512_hash( | static inline void decaf_sha512_hash( | ||||
uint8_t *output, | uint8_t *output, | ||||
size_t output_len, | size_t output_len, | ||||
@@ -31,9 +31,9 @@ protected: | |||||
/** @cond internal */ | /** @cond internal */ | ||||
/** The C-wrapper sponge state */ | /** The C-wrapper sponge state */ | ||||
decaf_sha512_ctx_t wrapped; | decaf_sha512_ctx_t wrapped; | ||||
/** @endcond */ | |||||
public: | public: | ||||
/** Number of bytes ouf output */ | /** Number of bytes ouf output */ | ||||
static const size_t OUTPUT_BYTES = 64; | static const size_t OUTPUT_BYTES = 64; | ||||
@@ -1,7 +1,5 @@ | |||||
/** | /** | ||||
* @file decaf/strobe.hxx | |||||
* @file decaf/spongerng.hxx | |||||
* @copyright | * @copyright | ||||
* Based on CC0 code by David Leon Gil, 2015 \n | * Based on CC0 code by David Leon Gil, 2015 \n | ||||
* Copyright (c) 2015 Cryptography Research, Inc. \n | * Copyright (c) 2015 Cryptography Research, Inc. \n | ||||
@@ -20,10 +20,17 @@ extern "C" { | |||||
/** Does EdDSA support non-contextual signatures? */ | /** Does EdDSA support non-contextual signatures? */ | ||||
#define DECAF_EDDSA_$(gf_shortname)_SUPPORTS_CONTEXTLESS_SIGS $(eddsa_no_context) | #define DECAF_EDDSA_$(gf_shortname)_SUPPORTS_CONTEXTLESS_SIGS $(eddsa_no_context) | ||||
$("extern const uint8_t * const DECAF_ED" + gf_shortname + "_NO_CONTEXT DECAF_API_VIS;\n" if eddsa_no_context else "") | $("extern const uint8_t * const DECAF_ED" + gf_shortname + "_NO_CONTEXT DECAF_API_VIS;\n" if eddsa_no_context else "") | ||||
/** Prehash context renaming macros. */ | |||||
/** Prehash context (raw), because each EdDSA instance has a different prehash. */ | |||||
#define decaf_ed$(gf_shortname)_prehash_ctx_s decaf_$(eddsa_hash)_ctx_s | #define decaf_ed$(gf_shortname)_prehash_ctx_s decaf_$(eddsa_hash)_ctx_s | ||||
/** Prehash context, array[1] form. */ | |||||
#define decaf_ed$(gf_shortname)_prehash_ctx_t decaf_$(eddsa_hash)_ctx_t | #define decaf_ed$(gf_shortname)_prehash_ctx_t decaf_$(eddsa_hash)_ctx_t | ||||
/** Prehash update. */ | |||||
#define decaf_ed$(gf_shortname)_prehash_update decaf_$(eddsa_hash)_update | #define decaf_ed$(gf_shortname)_prehash_update decaf_$(eddsa_hash)_update | ||||
/** Prehash destroy. */ | |||||
#define decaf_ed$(gf_shortname)_prehash_destroy decaf_$(eddsa_hash)_destroy | #define decaf_ed$(gf_shortname)_prehash_destroy decaf_$(eddsa_hash)_destroy | ||||
/** EdDSA encoding ratio. */ | /** EdDSA encoding ratio. */ | ||||
@@ -1,4 +1,3 @@ | |||||
/* | /* | ||||
* Example Decaf cyrpto routines, C++ wrapper. | * Example Decaf cyrpto routines, C++ wrapper. | ||||
* @warning These are merely examples, though they ought to be secure. But real | * @warning These are merely examples, though they ought to be secure. But real | ||||
@@ -22,6 +21,7 @@ | |||||
#endif | #endif | ||||
/** @endcond */ | /** @endcond */ | ||||
/** Namespace for all libdecaf C++ objects. */ | |||||
namespace decaf { | namespace decaf { | ||||
/** A public key for crypto over some Group */ | /** A public key for crypto over some Group */ | ||||
@@ -39,7 +39,14 @@ typedef class PrivateKeyBase PrivateKey, PrivateKeyPure, PrivateKeyPh; | |||||
typedef class PublicKeyBase PublicKey, PublicKeyPure, PublicKeyPh; | typedef class PublicKeyBase PublicKey, PublicKeyPure, PublicKeyPh; | ||||
/** @endcond */ | /** @endcond */ | ||||
/** | |||||
* Signatures support a "context" block, which allows you to domain separate them if | |||||
* (for some reason) it's annoying to domain separate the message itself. The default | |||||
* is no context. For Ed25519, the spec defining contexts is an extension, and the | |||||
* default is not to use that extension. This makes "no context" different from | |||||
* the empty string. For Ed448, contexts are built-in and mandatory, so "no context" | |||||
* is the same as the empty string. | |||||
*/ | |||||
#if DECAF_EDDSA_$(gf_shortname)_SUPPORTS_CONTEXTLESS_SIGS | #if DECAF_EDDSA_$(gf_shortname)_SUPPORTS_CONTEXTLESS_SIGS | ||||
static inline const Block NO_CONTEXT() { return Block(DECAF_ED$(gf_shortname)_NO_CONTEXT,0); } | static inline const Block NO_CONTEXT() { return Block(DECAF_ED$(gf_shortname)_NO_CONTEXT,0); } | ||||
#else | #else | ||||
@@ -49,6 +56,7 @@ static inline const Block NO_CONTEXT() { return Block(NULL,0); } | |||||
/** Prehash context for EdDSA. */ | /** Prehash context for EdDSA. */ | ||||
class Prehash : public $(re.sub(r"SHAKE(\d+)",r"SHAKE<\1>", eddsa_hash.upper())) { | class Prehash : public $(re.sub(r"SHAKE(\d+)",r"SHAKE<\1>", eddsa_hash.upper())) { | ||||
private: | private: | ||||
/** @cond internal */ | |||||
typedef $(re.sub(r"SHAKE(\d+)",r"SHAKE<\1>", eddsa_hash.upper())) Super; | typedef $(re.sub(r"SHAKE(\d+)",r"SHAKE<\1>", eddsa_hash.upper())) Super; | ||||
SecureBuffer context_; | SecureBuffer context_; | ||||
template<class T, Prehashed Ph> friend class Signing; | template<class T, Prehashed Ph> friend class Signing; | ||||
@@ -63,6 +71,7 @@ private: | |||||
decaf_ed$(gf_shortname)_prehash_init((decaf_$(eddsa_hash)_ctx_s *)wrapped); | decaf_ed$(gf_shortname)_prehash_init((decaf_$(eddsa_hash)_ctx_s *)wrapped); | ||||
} | } | ||||
/** @endcond */ | |||||
public: | public: | ||||
/** Number of output bytes in prehash */ | /** Number of output bytes in prehash */ | ||||
@@ -92,35 +101,10 @@ public: | |||||
} | } | ||||
}; | }; | ||||
/** Signing (i.e. private) key class template */ | |||||
template<class CRTP, Prehashed ph> class Signing; | template<class CRTP, Prehashed ph> class Signing; | ||||
template<class CRTP> class Signing<CRTP,PREHASHED> { | |||||
public: | |||||
/* Sign a prehash context, and reset the context */ | |||||
inline SecureBuffer sign_prehashed ( const Prehash &ph ) const /*throw(std::bad_alloc)*/ { | |||||
SecureBuffer out(CRTP::SIG_BYTES); | |||||
decaf_ed$(gf_shortname)_sign_prehash ( | |||||
out.data(), | |||||
((const CRTP*)this)->priv_.data(), | |||||
((const CRTP*)this)->pub_.data(), | |||||
(const decaf_ed$(gf_shortname)_prehash_ctx_s*)ph.wrapped, | |||||
ph.context_.data(), | |||||
ph.context_.size() | |||||
); | |||||
return out; | |||||
} | |||||
/* Sign a message using the prehasher */ | |||||
inline SecureBuffer sign_with_prehash ( | |||||
const Block &message, | |||||
const Block &context = NO_CONTEXT() | |||||
) const /*throw(LengthException,CryptoException)*/ { | |||||
Prehash ph(context); | |||||
ph += message; | |||||
return sign_prehashed(ph); | |||||
} | |||||
}; | |||||
/** Signing (i.e. private) key class, PureEdDSA version */ | |||||
template<class CRTP> class Signing<CRTP,PURE> { | template<class CRTP> class Signing<CRTP,PURE> { | ||||
public: | public: | ||||
/** | /** | ||||
@@ -153,12 +137,42 @@ public: | |||||
} | } | ||||
}; | }; | ||||
/** Signing (i.e. private) key class, prehashed version */ | |||||
template<class CRTP> class Signing<CRTP,PREHASHED> { | |||||
public: | |||||
/** Sign a prehash context, and reset the context */ | |||||
inline SecureBuffer sign_prehashed ( const Prehash &ph ) const /*throw(std::bad_alloc)*/ { | |||||
SecureBuffer out(CRTP::SIG_BYTES); | |||||
decaf_ed$(gf_shortname)_sign_prehash ( | |||||
out.data(), | |||||
((const CRTP*)this)->priv_.data(), | |||||
((const CRTP*)this)->pub_.data(), | |||||
(const decaf_ed$(gf_shortname)_prehash_ctx_s*)ph.wrapped, | |||||
ph.context_.data(), | |||||
ph.context_.size() | |||||
); | |||||
return out; | |||||
} | |||||
/** Sign a message using the prehasher */ | |||||
inline SecureBuffer sign_with_prehash ( | |||||
const Block &message, | |||||
const Block &context = NO_CONTEXT() | |||||
) const /*throw(LengthException,CryptoException)*/ { | |||||
Prehash ph(context); | |||||
ph += message; | |||||
return sign_prehashed(ph); | |||||
} | |||||
}; | |||||
/** Signing (i.e. private) key base class */ | |||||
class PrivateKeyBase | class PrivateKeyBase | ||||
: public Serializable<PrivateKeyBase> | : public Serializable<PrivateKeyBase> | ||||
, public Signing<PrivateKeyBase,PURE> | , public Signing<PrivateKeyBase,PURE> | ||||
, public Signing<PrivateKeyBase,PREHASHED> { | , public Signing<PrivateKeyBase,PREHASHED> { | ||||
public: | public: | ||||
typedef class PublicKeyBase MyPublicKey; | |||||
/** Type of public key corresponding to this private key */ | |||||
typedef class PublicKeyBase PublicKey; | |||||
private: | private: | ||||
/** @cond internal */ | /** @cond internal */ | ||||
friend class PublicKeyBase; | friend class PublicKeyBase; | ||||
@@ -227,14 +241,13 @@ public: | |||||
} | } | ||||
/** Return the corresponding public key */ | /** Return the corresponding public key */ | ||||
inline MyPublicKey pub() const DECAF_NOEXCEPT { | |||||
MyPublicKey pub(*this); | |||||
inline PublicKey pub() const DECAF_NOEXCEPT { | |||||
PublicKey pub(*this); | |||||
return pub; | return pub; | ||||
} | } | ||||
}; /* class PrivateKey */ | }; /* class PrivateKey */ | ||||
/** Verification (i.e. public) EdDSA key, PureEdDSA version. */ | |||||
template<class CRTP> class Verification<CRTP,PURE> { | template<class CRTP> class Verification<CRTP,PURE> { | ||||
public: | public: | ||||
/** Verify a signature, returning DECAF_FAILURE if verification fails */ | /** Verify a signature, returning DECAF_FAILURE if verification fails */ | ||||
@@ -280,10 +293,10 @@ public: | |||||
} | } | ||||
}; | }; | ||||
/** Verification (i.e. public) EdDSA key, prehashed version. */ | |||||
template<class CRTP> class Verification<CRTP,PREHASHED> { | template<class CRTP> class Verification<CRTP,PREHASHED> { | ||||
public: | public: | ||||
/* Verify a prehash context. */ | |||||
/** Verify that a signature is valid for a given prehashed message, given the context. */ | |||||
inline decaf_error_t DECAF_WARN_UNUSED verify_prehashed_noexcept ( | inline decaf_error_t DECAF_WARN_UNUSED verify_prehashed_noexcept ( | ||||
const FixedBlock<DECAF_EDDSA_$(gf_shortname)_SIGNATURE_BYTES> &sig, | const FixedBlock<DECAF_EDDSA_$(gf_shortname)_SIGNATURE_BYTES> &sig, | ||||
const Prehash &ph | const Prehash &ph | ||||
@@ -296,8 +309,8 @@ public: | |||||
ph.context_.size() | ph.context_.size() | ||||
); | ); | ||||
} | } | ||||
/* Verify a prehash context. */ | |||||
/** Verify that a signature is valid for a given prehashed message, given the context. */ | |||||
inline void verify_prehashed ( | inline void verify_prehashed ( | ||||
const FixedBlock<DECAF_EDDSA_$(gf_shortname)_SIGNATURE_BYTES> &sig, | const FixedBlock<DECAF_EDDSA_$(gf_shortname)_SIGNATURE_BYTES> &sig, | ||||
const Prehash &ph | const Prehash &ph | ||||
@@ -313,7 +326,7 @@ public: | |||||
} | } | ||||
} | } | ||||
/* Verify a message using the prehasher */ | |||||
/** Hash and verify a message, using the prehashed verification mode. */ | |||||
inline void verify_with_prehash ( | inline void verify_with_prehash ( | ||||
const FixedBlock<DECAF_EDDSA_$(gf_shortname)_SIGNATURE_BYTES> &sig, | const FixedBlock<DECAF_EDDSA_$(gf_shortname)_SIGNATURE_BYTES> &sig, | ||||
const Block &message, | const Block &message, | ||||
@@ -325,24 +338,25 @@ public: | |||||
} | } | ||||
}; | }; | ||||
/** EdDSA Public key base class. */ | |||||
class PublicKeyBase | class PublicKeyBase | ||||
: public Serializable<PublicKeyBase> | : public Serializable<PublicKeyBase> | ||||
, public Verification<PublicKeyBase,PURE> | , public Verification<PublicKeyBase,PURE> | ||||
, public Verification<PublicKeyBase,PREHASHED> { | , public Verification<PublicKeyBase,PREHASHED> { | ||||
public: | public: | ||||
typedef class PrivateKeyBase MyPrivateKey; | |||||
/** Private key corresponding to this type of public key */ | |||||
typedef class PrivateKeyBase PrivateKey; | |||||
private: | private: | ||||
/** @cond internal */ | /** @cond internal */ | ||||
friend class PrivateKeyBase; | friend class PrivateKeyBase; | ||||
friend class Verification<PublicKey,PURE>; | friend class Verification<PublicKey,PURE>; | ||||
friend class Verification<PublicKey,PREHASHED>; | friend class Verification<PublicKey,PREHASHED>; | ||||
/** @endcond */ | |||||
private: | private: | ||||
/** The pre-expansion form of the signature */ | /** The pre-expansion form of the signature */ | ||||
FixedArrayBuffer<DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES> pub_; | FixedArrayBuffer<DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES> pub_; | ||||
/** @endcond */ | |||||
public: | public: | ||||
/* PERF FUTURE: Pre-cached decoding? Precomputed table?? */ | /* PERF FUTURE: Pre-cached decoding? Precomputed table?? */ | ||||
@@ -356,7 +370,6 @@ public: | |||||
/** Serialization size. */ | /** Serialization size. */ | ||||
static const size_t SER_BYTES = DECAF_EDDSA_$(gf_shortname)_PRIVATE_BYTES; | static const size_t SER_BYTES = DECAF_EDDSA_$(gf_shortname)_PRIVATE_BYTES; | ||||
/** Create but don't initialize */ | /** Create but don't initialize */ | ||||
inline explicit PublicKeyBase(const NOINIT&) DECAF_NOEXCEPT : pub_((NOINIT())) { } | inline explicit PublicKeyBase(const NOINIT&) DECAF_NOEXCEPT : pub_((NOINIT())) { } | ||||
@@ -367,7 +380,7 @@ public: | |||||
inline PublicKeyBase(const PublicKeyBase &k) DECAF_NOEXCEPT { *this = k; } | inline PublicKeyBase(const PublicKeyBase &k) DECAF_NOEXCEPT { *this = k; } | ||||
/** Copy constructor */ | /** Copy constructor */ | ||||
inline explicit PublicKeyBase(const MyPrivateKey &k) DECAF_NOEXCEPT { *this = k; } | |||||
inline explicit PublicKeyBase(const PrivateKey &k) DECAF_NOEXCEPT { *this = k; } | |||||
/** Assignment from string */ | /** Assignment from string */ | ||||
inline PublicKey &operator=(const FixedBlock<SER_BYTES> &b) DECAF_NOEXCEPT { | inline PublicKey &operator=(const FixedBlock<SER_BYTES> &b) DECAF_NOEXCEPT { | ||||
@@ -381,7 +394,7 @@ public: | |||||
} | } | ||||
/** Assignment from private key */ | /** Assignment from private key */ | ||||
inline PublicKey &operator=(const MyPrivateKey &p) DECAF_NOEXCEPT { | |||||
inline PublicKey &operator=(const PrivateKey &p) DECAF_NOEXCEPT { | |||||
return *this = p.pub_; | return *this = p.pub_; | ||||
} | } | ||||
@@ -49,10 +49,10 @@ typedef struct gf_$(gf_shortname)_s { | |||||
/** Number of bytes in an x$(gf_shortname) private key */ | /** Number of bytes in an x$(gf_shortname) private key */ | ||||
#define DECAF_X$(gf_shortname)_PRIVATE_BYTES $((gf_bits-1)//8 + 1) | #define DECAF_X$(gf_shortname)_PRIVATE_BYTES $((gf_bits-1)//8 + 1) | ||||
/** Twisted Edwards extended homogeneous coordinates */ | |||||
/** Representation of a point on the elliptic curve. */ | |||||
typedef struct $(c_ns)_point_s { | typedef struct $(c_ns)_point_s { | ||||
/** @cond internal */ | /** @cond internal */ | ||||
gf_$(gf_shortname)_t x,y,z,t; | |||||
gf_$(gf_shortname)_t x,y,z,t; /* Twisted extended homogeneous coordinates */ | |||||
/** @endcond */ | /** @endcond */ | ||||
} $(c_ns)_point_t[1]; | } $(c_ns)_point_t[1]; | ||||
@@ -65,26 +65,26 @@ typedef struct $(c_ns)_precomputed_s $(c_ns)_precomputed_s; | |||||
/** Size and alignment of precomputed point tables. */ | /** Size and alignment of precomputed point tables. */ | ||||
extern const size_t $(c_ns)_sizeof_precomputed_s DECAF_API_VIS, $(c_ns)_alignof_precomputed_s DECAF_API_VIS; | extern const size_t $(c_ns)_sizeof_precomputed_s DECAF_API_VIS, $(c_ns)_alignof_precomputed_s DECAF_API_VIS; | ||||
/** Scalar is stored packed, because we don't need the speed. */ | |||||
/** Representation of an element of the scalar field. */ | |||||
typedef struct $(c_ns)_scalar_s { | typedef struct $(c_ns)_scalar_s { | ||||
/** @cond internal */ | /** @cond internal */ | ||||
decaf_word_t limb[$(C_NS)_SCALAR_LIMBS]; | decaf_word_t limb[$(C_NS)_SCALAR_LIMBS]; | ||||
/** @endcond */ | /** @endcond */ | ||||
} $(c_ns)_scalar_t[1]; | } $(c_ns)_scalar_t[1]; | ||||
/** A scalar equal to 1. */ | |||||
/** The scalar 1. */ | |||||
extern const $(c_ns)_scalar_t $(c_ns)_scalar_one DECAF_API_VIS; | extern const $(c_ns)_scalar_t $(c_ns)_scalar_one DECAF_API_VIS; | ||||
/** A scalar equal to 0. */ | |||||
/** The scalar 0. */ | |||||
extern const $(c_ns)_scalar_t $(c_ns)_scalar_zero DECAF_API_VIS; | extern const $(c_ns)_scalar_t $(c_ns)_scalar_zero DECAF_API_VIS; | ||||
/** The identity point on the curve. */ | |||||
/** The identity (zero) point on the curve. */ | |||||
extern const $(c_ns)_point_t $(c_ns)_point_identity DECAF_API_VIS; | extern const $(c_ns)_point_t $(c_ns)_point_identity DECAF_API_VIS; | ||||
/** An arbitrarily chosen base point on the curve. */ | |||||
/** An arbitrarily-chosen base point on the curve. */ | |||||
extern const $(c_ns)_point_t $(c_ns)_point_base DECAF_API_VIS; | extern const $(c_ns)_point_t $(c_ns)_point_base DECAF_API_VIS; | ||||
/** Precomputed table for the base point on the curve. */ | |||||
/** Precomputed table of multiples of the base point on the curve. */ | |||||
extern const struct $(c_ns)_precomputed_s *$(c_ns)_precomputed_base DECAF_API_VIS; | extern const struct $(c_ns)_precomputed_s *$(c_ns)_precomputed_base DECAF_API_VIS; | ||||
/** | /** | ||||
@@ -371,19 +371,19 @@ decaf_error_t $(c_ns)_direct_scalarmul ( | |||||
) DECAF_API_VIS DECAF_NONNULL DECAF_WARN_UNUSED DECAF_NOINLINE; | ) DECAF_API_VIS DECAF_NONNULL DECAF_WARN_UNUSED DECAF_NOINLINE; | ||||
/** | /** | ||||
* @brief RFC 7748 Diffie-Hellman scalarmul. This function uses a different | |||||
* (non-Decaf) encoding. | |||||
* @brief RFC 7748 Diffie-Hellman scalarmul, used to compute shared secrets. | |||||
* This function uses a different (non-Decaf) encoding. | |||||
* | * | ||||
* @param [out] scaled The scaled point base*scalar | |||||
* @param [in] base The point to be scaled. | |||||
* @param [in] scalar The scalar to multiply by. | |||||
* @param [out] shared The shared secret base*scalar | |||||
* @param [in] base The other party's public key, used as the base of the scalarmul. | |||||
* @param [in] scalar The private scalar to multiply by. | |||||
* | * | ||||
* @retval DECAF_SUCCESS The scalarmul succeeded. | * @retval DECAF_SUCCESS The scalarmul succeeded. | ||||
* @retval DECAF_FAILURE The scalarmul didn't succeed, because the base | * @retval DECAF_FAILURE The scalarmul didn't succeed, because the base | ||||
* point is in a small subgroup. | * point is in a small subgroup. | ||||
*/ | */ | ||||
decaf_error_t decaf_x$(gf_shortname) ( | decaf_error_t decaf_x$(gf_shortname) ( | ||||
uint8_t out[DECAF_X$(gf_shortname)_PUBLIC_BYTES], | |||||
uint8_t shared[DECAF_X$(gf_shortname)_PUBLIC_BYTES], | |||||
const uint8_t base[DECAF_X$(gf_shortname)_PUBLIC_BYTES], | const uint8_t base[DECAF_X$(gf_shortname)_PUBLIC_BYTES], | ||||
const uint8_t scalar[DECAF_X$(gf_shortname)_PRIVATE_BYTES] | const uint8_t scalar[DECAF_X$(gf_shortname)_PRIVATE_BYTES] | ||||
) DECAF_API_VIS DECAF_NONNULL DECAF_WARN_UNUSED DECAF_NOINLINE; | ) DECAF_API_VIS DECAF_NONNULL DECAF_WARN_UNUSED DECAF_NOINLINE; | ||||
@@ -414,7 +414,13 @@ void $(c_ns)_point_mul_by_ratio_and_encode_like_x$(gf_shortname) ( | |||||
) DECAF_API_VIS DECAF_NONNULL; | ) DECAF_API_VIS DECAF_NONNULL; | ||||
/** The base point for X$(gf_shortname) Diffie-Hellman */ | /** The base point for X$(gf_shortname) Diffie-Hellman */ | ||||
extern const uint8_t decaf_x$(gf_shortname)_base_point[DECAF_X$(gf_shortname)_PUBLIC_BYTES] DECAF_API_VIS; | |||||
extern const uint8_t | |||||
decaf_x$(gf_shortname)_base_point[DECAF_X$(gf_shortname)_PUBLIC_BYTES] | |||||
#ifndef DOXYGEN | |||||
/* For some reason Doxygen chokes on this despite the defense in common.h... */ | |||||
DECAF_API_VIS | |||||
#endif | |||||
; | |||||
/** | /** | ||||
* @brief RFC 7748 Diffie-Hellman base point scalarmul. This function uses | * @brief RFC 7748 Diffie-Hellman base point scalarmul. This function uses | ||||
@@ -423,8 +429,8 @@ extern const uint8_t decaf_x$(gf_shortname)_base_point[DECAF_X$(gf_shortname)_PU | |||||
* @deprecated Renamed to decaf_x$(gf_shortname)_derive_public_key. | * @deprecated Renamed to decaf_x$(gf_shortname)_derive_public_key. | ||||
* I have no particular timeline for removing this name. | * I have no particular timeline for removing this name. | ||||
* | * | ||||
* @param [out] scaled The scaled point base*scalar | |||||
* @param [in] scalar The scalar to multiply by. | |||||
* @param [out] out The public key base*scalar. | |||||
* @param [in] scalar The private scalar. | |||||
*/ | */ | ||||
void decaf_x$(gf_shortname)_generate_key ( | void decaf_x$(gf_shortname)_generate_key ( | ||||
uint8_t out[DECAF_X$(gf_shortname)_PUBLIC_BYTES], | uint8_t out[DECAF_X$(gf_shortname)_PUBLIC_BYTES], | ||||
@@ -438,8 +444,8 @@ void decaf_x$(gf_shortname)_generate_key ( | |||||
* Does exactly the same thing as decaf_x$(gf_shortname)_generate_key, | * Does exactly the same thing as decaf_x$(gf_shortname)_generate_key, | ||||
* but has a better name. | * but has a better name. | ||||
* | * | ||||
* @param [out] scaled The scaled point base*scalar | |||||
* @param [in] scalar The scalar to multiply by. | |||||
* @param [out] out The public key base*scalar | |||||
* @param [in] scalar The private scalar. | |||||
*/ | */ | ||||
void decaf_x$(gf_shortname)_derive_public_key ( | void decaf_x$(gf_shortname)_derive_public_key ( | ||||
uint8_t out[DECAF_X$(gf_shortname)_PUBLIC_BYTES], | uint8_t out[DECAF_X$(gf_shortname)_PUBLIC_BYTES], | ||||
@@ -722,22 +728,20 @@ $(c_ns)_invert_elligator_uniform ( | |||||
uint32_t which | uint32_t which | ||||
) DECAF_API_VIS DECAF_NONNULL DECAF_NOINLINE DECAF_WARN_UNUSED; | ) DECAF_API_VIS DECAF_NONNULL DECAF_NOINLINE DECAF_WARN_UNUSED; | ||||
/** | |||||
* @brief Overwrite scalar with zeros. | |||||
*/ | |||||
/** Securely erase a scalar. */ | |||||
void $(c_ns)_scalar_destroy ( | void $(c_ns)_scalar_destroy ( | ||||
$(c_ns)_scalar_t scalar | $(c_ns)_scalar_t scalar | ||||
) DECAF_NONNULL DECAF_API_VIS; | ) DECAF_NONNULL DECAF_API_VIS; | ||||
/** | |||||
* @brief Overwrite point with zeros. | |||||
/** Securely erase a point by overwriting it with zeros. | |||||
* @warning This causes the point object to become invalid. | |||||
*/ | */ | ||||
void $(c_ns)_point_destroy ( | void $(c_ns)_point_destroy ( | ||||
$(c_ns)_point_t point | $(c_ns)_point_t point | ||||
) DECAF_NONNULL DECAF_API_VIS; | ) DECAF_NONNULL DECAF_API_VIS; | ||||
/** | |||||
* @brief Overwrite precomputed table with zeros. | |||||
/** Securely erase a precomputed table by overwriting it with zeros. | |||||
* @warning This causes the table object to become invalid. | |||||
*/ | */ | ||||
void $(c_ns)_precomputed_destroy ( | void $(c_ns)_precomputed_destroy ( | ||||
$(c_ns)_precomputed_s *pre | $(c_ns)_precomputed_s *pre | ||||
@@ -1,16 +1,15 @@ | |||||
/** | /** | ||||
* A group of prime order p, C++ wrapper. | |||||
* A group of prime order, C++ wrapper. | |||||
* | * | ||||
* The Decaf library implements cryptographic operations on a an elliptic curve | * The Decaf library implements cryptographic operations on a an elliptic curve | ||||
* group of prime order p. It accomplishes this by using a twisted Edwards | |||||
* group of prime order. It accomplishes this by using a twisted Edwards | |||||
* curve (isogenous to $(iso_to)) and wiping out the cofactor. | * curve (isogenous to $(iso_to)) and wiping out the cofactor. | ||||
* | * | ||||
* The formulas are all complete and have no special cases, except that | |||||
* $(c_ns)_decode can fail because not every sequence of bytes is a valid group | |||||
* element. | |||||
* | |||||
* The formulas contain no data-dependent branches, timing or memory accesses, | |||||
* except for $(c_ns)_base_double_scalarmul_non_secret. | |||||
* Most of the functions in this file run in constant time, can't fail | |||||
* except for ubiquitous reasons like memory exhaustion, and contain no | |||||
* data-dependend branches, timing or memory accesses. There are some | |||||
* exceptions, which should be noted. Typically, decoding functions can | |||||
* fail. | |||||
*/ | */ | ||||
/** This code uses posix_memalign. */ | /** This code uses posix_memalign. */ | ||||
@@ -174,8 +173,9 @@ public: | |||||
/** Negate */ | /** Negate */ | ||||
inline Scalar operator- () const DECAF_NOEXCEPT { Scalar r((NOINIT())); $(c_ns)_scalar_sub(r.s,$(c_ns)_scalar_zero,s); return r; } | inline Scalar operator- () const DECAF_NOEXCEPT { Scalar r((NOINIT())); $(c_ns)_scalar_sub(r.s,$(c_ns)_scalar_zero,s); return r; } | ||||
/** Invert with Fermat's Little Theorem (slow!). If *this == 0, | |||||
* throw CryptoException. */ | |||||
/** Return 1/this. | |||||
* @throw CryptoException if this is 0. | |||||
*/ | |||||
inline Scalar inverse() const /*throw(CryptoException)*/ { | inline Scalar inverse() const /*throw(CryptoException)*/ { | ||||
Scalar r; | Scalar r; | ||||
if (DECAF_SUCCESS != $(c_ns)_scalar_invert(r.s,s)) { | if (DECAF_SUCCESS != $(c_ns)_scalar_invert(r.s,s)) { | ||||
@@ -191,10 +191,10 @@ public: | |||||
return $(c_ns)_scalar_invert(r.s,s); | return $(c_ns)_scalar_invert(r.s,s); | ||||
} | } | ||||
/** Divide by inverting q. If q == 0, return 0. */ | |||||
/** Return this/q. @throw CryptoException if q == 0. */ | |||||
inline Scalar operator/ (const Scalar &q) const /*throw(CryptoException)*/ { return *this * q.inverse(); } | inline Scalar operator/ (const Scalar &q) const /*throw(CryptoException)*/ { return *this * q.inverse(); } | ||||
/** Divide by inverting q. If q == 0, return 0. */ | |||||
/** Set this to this/q. @throw CryptoException if q == 0. */ | |||||
inline Scalar &operator/=(const Scalar &q) /*throw(CryptoException)*/ { return *this *= q.inverse(); } | inline Scalar &operator/=(const Scalar &q) /*throw(CryptoException)*/ { return *this *= q.inverse(); } | ||||
/** Return half this scalar. Much faster than /2. */ | /** Return half this scalar. Much faster than /2. */ | ||||
@@ -212,7 +212,9 @@ public: | |||||
/** Scalarmul-precomputed with scalar on left. */ | /** Scalarmul-precomputed with scalar on left. */ | ||||
inline Point operator* (const Precomputed &q) const DECAF_NOEXCEPT { return q * (*this); } | inline Point operator* (const Precomputed &q) const DECAF_NOEXCEPT { return q * (*this); } | ||||
/** Direct scalar multiplication. */ | |||||
/** Direct scalar multiplication. | |||||
* @throw CryptoException if the input didn't decode. | |||||
*/ | |||||
inline SecureBuffer direct_scalarmul ( | inline SecureBuffer direct_scalarmul ( | ||||
const FixedBlock<SER_BYTES> &in, | const FixedBlock<SER_BYTES> &in, | ||||
decaf_bool_t allow_identity=DECAF_FALSE, | decaf_bool_t allow_identity=DECAF_FALSE, | ||||
@@ -228,12 +230,10 @@ public: | |||||
) const DECAF_NOEXCEPT; | ) const DECAF_NOEXCEPT; | ||||
}; | }; | ||||
/** | |||||
* Element of prime-order group. | |||||
*/ | |||||
/** Element of prime-order elliptic curve group. */ | |||||
class Point : public Serializable<Point> { | class Point : public Serializable<Point> { | ||||
public: | public: | ||||
/** wrapped C type */ | |||||
/** Wrapped C type */ | |||||
typedef $(c_ns)_point_t Wrapped; | typedef $(c_ns)_point_t Wrapped; | ||||
/** Size of a serialized element */ | /** Size of a serialized element */ | ||||
@@ -257,17 +257,8 @@ public: | |||||
/** Ratio due to ladder decoding */ | /** Ratio due to ladder decoding */ | ||||
static const int LADDER_ENCODE_RATIO = DECAF_X$(gf_shortname)_ENCODE_RATIO; | static const int LADDER_ENCODE_RATIO = DECAF_X$(gf_shortname)_ENCODE_RATIO; | ||||
/** | |||||
* Size of a stegged element. | |||||
* | |||||
* FUTURE: You can use HASH_BYTES * 3/2 (or more likely much less, eg HASH_BYTES + 8) | |||||
* with a random oracle hash function, by hash-expanding everything past the first | |||||
* HASH_BYTES of the element. However, since the internal C invert_elligator is not | |||||
* tied to a hash function, I didn't want to tie the C++ wrapper to a hash function | |||||
* either. But it might be a good idea to do this in the future, either with STROBE | |||||
* or something else. | |||||
* | |||||
* Then again, calling invert_elligator at all is super niche, so maybe who cares? | |||||
/** Size of a steganographically-encoded curve element. If the point is random, the encoding | |||||
* should look statistically close to a uniformly-random sequnece of STEG_BYTES bytes. | |||||
*/ | */ | ||||
static const size_t STEG_BYTES = HASH_BYTES * 2; | static const size_t STEG_BYTES = HASH_BYTES * 2; | ||||
@@ -312,9 +303,9 @@ public: | |||||
* @throw CryptoException the string was the wrong length, or wasn't the encoding of a point, | * @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. | * 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, bool allow_identity=true) | |||||
/*throw(CryptoException)*/ { | /*throw(CryptoException)*/ { | ||||
if (DECAF_SUCCESS != decode(buffer,allow_identity)) { | |||||
if (DECAF_SUCCESS != decode(buffer,allow_identity ? DECAF_TRUE : DECAF_FALSE)) { | |||||
throw CryptoException(); | throw CryptoException(); | ||||
} | } | ||||
} | } | ||||
@@ -328,9 +319,9 @@ public: | |||||
* or was the identity and allow_identity was DECAF_FALSE. Contents of the buffer are undefined. | * or was the identity and allow_identity was DECAF_FALSE. Contents of the buffer are undefined. | ||||
*/ | */ | ||||
inline decaf_error_t DECAF_WARN_UNUSED decode ( | inline decaf_error_t DECAF_WARN_UNUSED decode ( | ||||
const FixedBlock<SER_BYTES> &buffer, decaf_bool_t allow_identity=DECAF_TRUE | |||||
const FixedBlock<SER_BYTES> &buffer, bool allow_identity=true | |||||
) DECAF_NOEXCEPT { | ) DECAF_NOEXCEPT { | ||||
return $(c_ns)_point_decode(p,buffer.data(),allow_identity); | |||||
return $(c_ns)_point_decode(p,buffer.data(),allow_identity ? DECAF_TRUE : DECAF_FALSE); | |||||
} | } | ||||
/** | /** | ||||
@@ -380,9 +371,7 @@ public: | |||||
} | } | ||||
/** Multiply by LADDER_ENCODE_RATIO and encode like X25519/X448. */ | /** Multiply by LADDER_ENCODE_RATIO and encode like X25519/X448. */ | ||||
inline void mul_by_ratio_and_encode_like_ladder( | |||||
FixedBuffer<LADDER_BYTES> &out | |||||
) const { | |||||
inline void mul_by_ratio_and_encode_like_ladder(FixedBuffer<LADDER_BYTES> &out) const { | |||||
$(c_ns)_point_mul_by_ratio_and_encode_like_x$(gf_shortname)(out.data(),p); | $(c_ns)_point_mul_by_ratio_and_encode_like_x$(gf_shortname)(out.data(),p); | ||||
} | } | ||||
@@ -418,9 +407,7 @@ public: | |||||
} | } | ||||
} | } | ||||
/** | |||||
* Encode to string. The identity encodes to the all-zero string. | |||||
*/ | |||||
/** Encode to string. The identity encodes to the all-zero string. */ | |||||
inline operator SecureBuffer() const { | inline operator SecureBuffer() const { | ||||
SecureBuffer buffer(SER_BYTES); | SecureBuffer buffer(SER_BYTES); | ||||
$(c_ns)_point_encode(buffer.data(), p); | $(c_ns)_point_encode(buffer.data(), p); | ||||
@@ -570,10 +557,10 @@ public: | |||||
return out; | return out; | ||||
} | } | ||||
/** Return the base point */ | |||||
/** Return the base point of the curve. */ | |||||
static inline const Point base() DECAF_NOEXCEPT { return Point($(c_ns)_point_base); } | static inline const Point base() DECAF_NOEXCEPT { return Point($(c_ns)_point_base); } | ||||
/** Return the identity point */ | |||||
/** Return the identity point of the curve. */ | |||||
static inline const Point identity() DECAF_NOEXCEPT { return Point($(c_ns)_point_identity); } | static inline const Point identity() DECAF_NOEXCEPT { return Point($(c_ns)_point_identity); } | ||||
}; | }; | ||||
@@ -671,6 +658,7 @@ public: | |||||
/** @endcond */ | /** @endcond */ | ||||
}; | }; | ||||
/** X-only Diffie-Hellman ladder functions */ | |||||
struct DhLadder { | struct DhLadder { | ||||
public: | public: | ||||
/** Bytes in an X$(gf_shortname) public key. */ | /** Bytes in an X$(gf_shortname) public key. */ | ||||
@@ -745,7 +733,8 @@ public: | |||||
* equivalent to shared_secret(base_point(),scalar) but possibly faster. | * equivalent to shared_secret(base_point(),scalar) but possibly faster. | ||||
* @deprecated Renamed to derive_public_key_noexcept. | * @deprecated Renamed to derive_public_key_noexcept. | ||||
*/ | */ | ||||
static inline void DECAF_DEPRECATED("Renamed to derive_public_key_noexcept") | |||||
static inline void | |||||
DECAF_DEPRECATED("Renamed to derive_public_key_noexcept") | |||||
generate_key_noexcept ( | generate_key_noexcept ( | ||||
FixedBuffer<PUBLIC_BYTES> &out, | FixedBuffer<PUBLIC_BYTES> &out, | ||||
const FixedBlock<PRIVATE_BYTES> &scalar | const FixedBlock<PRIVATE_BYTES> &scalar | ||||
@@ -781,7 +770,7 @@ inline decaf_error_t $(cxx_ns)::Scalar::direct_scalarmul_noexcept ( | |||||
} | } | ||||
/** @endcond */ | /** @endcond */ | ||||
$("typedef %s %s;\n" % (cxx_ns,altname) if altname else "") | |||||
$("/** Alternative name for %s, for backwards compatibility */\ntypedef %s %s;\n" % (cxx_ns,cxx_ns,altname) if altname else "") | |||||
#undef DECAF_NOEXCEPT | #undef DECAF_NOEXCEPT | ||||
} /* namespace decaf */ | } /* namespace decaf */ |
@@ -4,7 +4,9 @@ $("\n".join([ | |||||
"#include <decaf/point_%s.hxx>" % g for g in sorted([c["bits"] for _,c in curve.items()]) | "#include <decaf/point_%s.hxx>" % g for g in sorted([c["bits"] for _,c in curve.items()]) | ||||
])) | ])) | ||||
/** Namespace for all C++ decaf objects. */ | |||||
namespace decaf { | namespace decaf { | ||||
/** Given a template with a "run" function, run it for all curves */ | |||||
template <template<typename Group> class Run> | template <template<typename Group> class Run> | ||||
void run_for_all_curves() { | void run_for_all_curves() { | ||||
$("\n".join([ | $("\n".join([ | ||||
@@ -21,8 +21,9 @@ extern "C" { | |||||
/* Goldilocks' build flags default to hidden and stripping executables. */ | /* Goldilocks' build flags default to hidden and stripping executables. */ | ||||
/** @cond internal */ | /** @cond internal */ | ||||
#if defined(DOXYGEN) && !defined(__attribute__) | |||||
#define __attribute__((x)) | |||||
#if DOXYGEN || defined(__attribute__) | |||||
#define __attribute__(x) | |||||
#define NOINLINE | |||||
#endif | #endif | ||||
#define DECAF_API_VIS __attribute__((visibility("default"))) | #define DECAF_API_VIS __attribute__((visibility("default"))) | ||||
#define DECAF_NOINLINE __attribute__((noinline)) | #define DECAF_NOINLINE __attribute__((noinline)) | ||||
@@ -2,7 +2,15 @@ | |||||
* EdDSA crypto routines, metaheader. | * EdDSA crypto routines, metaheader. | ||||
*/ | */ | ||||
namespace decaf { enum Prehashed { PURE, PREHASHED }; } | |||||
/** Namespace for all libdecaf C++ objects. */ | |||||
namespace decaf { | |||||
/** How signatures handle hashing. */ | |||||
enum Prehashed { | |||||
PURE, /**< Sign the message itself. This can't be done in one pass. */ | |||||
PREHASHED /**< Sign the hash of the message. */ | |||||
}; | |||||
} | |||||
$("\n".join([ | $("\n".join([ | ||||
"#include <decaf/ed%s.hxx>" % g for g in sorted([c["bits"] for _,c in curve.items()]) | "#include <decaf/ed%s.hxx>" % g for g in sorted([c["bits"] for _,c in curve.items()]) | ||||
])) | ])) |
@@ -18,21 +18,39 @@ | |||||
extern "C" { | extern "C" { | ||||
#endif | #endif | ||||
/** Hash context for SHA-512 */ | |||||
typedef struct decaf_sha512_ctx_s { | typedef struct decaf_sha512_ctx_s { | ||||
/** @cond internal */ | |||||
uint64_t state[8]; | uint64_t state[8]; | ||||
uint8_t block[128]; | uint8_t block[128]; | ||||
uint64_t bytes_processed; | uint64_t bytes_processed; | ||||
/* @endcond */ | |||||
} decaf_sha512_ctx_s, decaf_sha512_ctx_t[1]; | } decaf_sha512_ctx_s, decaf_sha512_ctx_t[1]; | ||||
/** Initialize a SHA-512 context. */ | |||||
void decaf_sha512_init(decaf_sha512_ctx_t ctx) DECAF_NONNULL DECAF_API_VIS; | void decaf_sha512_init(decaf_sha512_ctx_t ctx) DECAF_NONNULL DECAF_API_VIS; | ||||
void decaf_sha512_update(decaf_sha512_ctx_t ctx, const uint8_t *message, size_t length) DECAF_NONNULL DECAF_API_VIS; | |||||
void decaf_sha512_final(decaf_sha512_ctx_t ctx, uint8_t *out, size_t length) DECAF_NONNULL DECAF_API_VIS; | |||||
/** Update context by hashing part of a message. */ | |||||
void decaf_sha512_update(decaf_sha512_ctx_t ctx, const uint8_t *message, size_t message_len) DECAF_NONNULL DECAF_API_VIS; | |||||
/** Finalize context and write out hash. | |||||
* @param [inout] ctx The context. Will be destroyed and re-initialized on return. | |||||
* @param [out] output Place to store the output hash. | |||||
* @param [in] output_len Length in bytes of the output hash. Must between 0 and 64, inclusive. | |||||
*/ | |||||
void decaf_sha512_final(decaf_sha512_ctx_t ctx, uint8_t *output, size_t output_len) DECAF_NONNULL DECAF_API_VIS; | |||||
/** Securely destroy a SHA512 context. */ | |||||
static inline void decaf_sha512_destroy(decaf_sha512_ctx_t ctx) { | static inline void decaf_sha512_destroy(decaf_sha512_ctx_t ctx) { | ||||
decaf_bzero(ctx,sizeof(*ctx)); | decaf_bzero(ctx,sizeof(*ctx)); | ||||
} | } | ||||
/** Hash a message. | |||||
* @param [out] output Place to store the output hash. | |||||
* @param [in] output_len Length in bytes of the output hash. Must between 0 and 64, inclusive. | |||||
* @param [in] message A message to hash. | |||||
* @param [in] message_len Length in bytes of the input message. | |||||
*/ | |||||
static inline void decaf_sha512_hash( | static inline void decaf_sha512_hash( | ||||
uint8_t *output, | uint8_t *output, | ||||
size_t output_len, | size_t output_len, | ||||
@@ -31,9 +31,9 @@ protected: | |||||
/** @cond internal */ | /** @cond internal */ | ||||
/** The C-wrapper sponge state */ | /** The C-wrapper sponge state */ | ||||
decaf_sha512_ctx_t wrapped; | decaf_sha512_ctx_t wrapped; | ||||
/** @endcond */ | |||||
public: | public: | ||||
/** Number of bytes ouf output */ | /** Number of bytes ouf output */ | ||||
static const size_t OUTPUT_BYTES = 64; | static const size_t OUTPUT_BYTES = 64; | ||||
@@ -1,7 +1,5 @@ | |||||
/** | /** | ||||
* @file decaf/strobe.hxx | |||||
* @file decaf/spongerng.hxx | |||||
* @copyright | * @copyright | ||||
* Based on CC0 code by David Leon Gil, 2015 \n | * Based on CC0 code by David Leon Gil, 2015 \n | ||||
* Copyright (c) 2015 Cryptography Research, Inc. \n | * Copyright (c) 2015 Cryptography Research, Inc. \n | ||||