Update EdDSA operations to match draft 07 from CFRG.

parent 80c0bd5d
......@@ -28,7 +28,7 @@
#define hash_destroy decaf_sha512_destroy
#define hash_hash decaf_sha512_hash
#define SUPPORTS_CONTEXTS DECAF_EDDSA_25519_SUPPORTS_CONTEXTS
#define NO_CONTEXT DECAF_EDDSA_25519_NO_CONTEXT
#define EDDSA_USE_SIGMA_ISOGENY 1
#define COFACTOR 8
......@@ -58,38 +58,33 @@ static void hash_init_with_dom(
uint8_t prehashed,
uint8_t for_prehash,
const uint8_t *context,
uint8_t context_len
uint8_t context_len,
uint8_t no_context
) {
hash_init(hash);
#if SUPPORTS_CONTEXTS
const char *dom_s = "";
#if NO_CONTEXT
if (no_context) {
(void)prehashed;
(void)for_prehash;
(void)context;
(void)context_len;
return;
}
#else
(void)no_context;
#endif
const char *dom_s = "SigEd25519 no Ed25519 collisions";
const uint8_t dom[2] = {2+word_is_zero(prehashed)+word_is_zero(for_prehash), context_len};
hash_update(hash,(const unsigned char *)dom_s, strlen(dom_s));
hash_update(hash,dom,2);
hash_update(hash,context,context_len);
#else
(void)prehashed;
(void)for_prehash;
(void)context;
assert(context==NULL);
(void)context_len;
assert(context_len == 0);
#endif
}
void decaf_ed25519_prehash_init (
hash_ctx_t hash
#if DECAF_EDDSA_25519_SUPPORTS_CONTEXTS
, const uint8_t *context,
uint8_t context_len
#endif
) {
#if DECAF_EDDSA_25519_SUPPORTS_CONTEXTS
hash_init_with_dom(hash,1,1,context,context_len);
#else
hash_init_with_dom(hash,1,1,NULL,0);
#endif
hash_init(hash);
}
void decaf_ed25519_derive_public_key (
......@@ -137,16 +132,11 @@ void decaf_ed25519_sign (
const uint8_t pubkey[DECAF_EDDSA_25519_PUBLIC_BYTES],
const uint8_t *message,
size_t message_len,
uint8_t prehashed
#if SUPPORTS_CONTEXTS
, const uint8_t *context,
uint8_t context_len
#endif
uint8_t prehashed,
const uint8_t *context,
uint8_t context_len,
uint8_t no_context
) {
#if !SUPPORTS_CONTEXTS
const uint8_t *const context = NULL;
const uint8_t context_len = 0;
#endif
API_NS(scalar_t) secret_scalar;
hash_ctx_t hash;
{
......@@ -165,7 +155,7 @@ void decaf_ed25519_sign (
API_NS(scalar_decode_long)(secret_scalar, expanded.secret_scalar_ser, sizeof(expanded.secret_scalar_ser));
/* Hash to create the nonce */
hash_init_with_dom(hash,prehashed,0,context,context_len);
hash_init_with_dom(hash,prehashed,0,context,context_len,no_context);
hash_update(hash,expanded.seed,sizeof(expanded.seed));
hash_update(hash,message,message_len);
decaf_bzero(&expanded, sizeof(expanded));
......@@ -199,7 +189,7 @@ void decaf_ed25519_sign (
API_NS(scalar_t) challenge_scalar;
{
/* Compute the challenge */
hash_init_with_dom(hash,prehashed,0,context,context_len);
hash_init_with_dom(hash,prehashed,0,context,context_len,no_context);
hash_update(hash,nonce_point,sizeof(nonce_point));
hash_update(hash,pubkey,DECAF_EDDSA_25519_PUBLIC_BYTES);
hash_update(hash,message,message_len);
......@@ -227,11 +217,9 @@ void decaf_ed25519_sign_prehash (
uint8_t signature[DECAF_EDDSA_25519_SIGNATURE_BYTES],
const uint8_t privkey[DECAF_EDDSA_25519_PRIVATE_BYTES],
const uint8_t pubkey[DECAF_EDDSA_25519_PUBLIC_BYTES],
const decaf_ed25519_prehash_ctx_t hash
#if DECAF_EDDSA_25519_SUPPORTS_CONTEXTS
, const uint8_t *context,
const decaf_ed25519_prehash_ctx_t hash,
const uint8_t *context,
uint8_t context_len
#endif
) {
uint8_t hash_output[64]; /* MAGIC but true for all existing schemes */
{
......@@ -240,13 +228,8 @@ void decaf_ed25519_sign_prehash (
hash_final(hash_too,hash_output,sizeof(hash_output));
hash_destroy(hash_too);
}
#if DECAF_EDDSA_25519_SUPPORTS_CONTEXTS
decaf_ed25519_sign(signature,privkey,pubkey,hash_output,sizeof(hash_output),1,context,context_len);
#else
decaf_ed25519_sign(signature,privkey,pubkey,hash_output,sizeof(hash_output),1);
#endif
decaf_ed25519_sign(signature,privkey,pubkey,hash_output,sizeof(hash_output),1,context,context_len,0);
decaf_bzero(hash_output,sizeof(hash_output));
}
......@@ -255,16 +238,11 @@ decaf_error_t decaf_ed25519_verify (
const uint8_t pubkey[DECAF_EDDSA_25519_PUBLIC_BYTES],
const uint8_t *message,
size_t message_len,
uint8_t prehashed
#if SUPPORTS_CONTEXTS
, const uint8_t *context,
uint8_t context_len
#endif
uint8_t prehashed,
const uint8_t *context,
uint8_t context_len,
uint8_t no_context
) {
#if !SUPPORTS_CONTEXTS
const uint8_t *const context = NULL;
const uint8_t context_len = 0;
#endif
API_NS(point_t) pk_point, r_point;
decaf_error_t error = API_NS(point_decode_like_eddsa_and_ignore_cofactor)(pk_point,pubkey);
if (DECAF_SUCCESS != error) { return error; }
......@@ -276,7 +254,7 @@ decaf_error_t decaf_ed25519_verify (
{
/* Compute the challenge */
hash_ctx_t hash;
hash_init_with_dom(hash,prehashed,0,context,context_len);
hash_init_with_dom(hash,prehashed,0,context,context_len,no_context);
hash_update(hash,signature,DECAF_EDDSA_25519_PUBLIC_BYTES);
hash_update(hash,pubkey,DECAF_EDDSA_25519_PUBLIC_BYTES);
hash_update(hash,message,message_len);
......@@ -313,11 +291,9 @@ decaf_error_t decaf_ed25519_verify (
decaf_error_t decaf_ed25519_verify_prehash (
const uint8_t signature[DECAF_EDDSA_25519_SIGNATURE_BYTES],
const uint8_t pubkey[DECAF_EDDSA_25519_PUBLIC_BYTES],
const decaf_ed25519_prehash_ctx_t hash
#if DECAF_EDDSA_25519_SUPPORTS_CONTEXTS
, const uint8_t *context,
const decaf_ed25519_prehash_ctx_t hash,
const uint8_t *context,
uint8_t context_len
#endif
) {
decaf_error_t ret;
......@@ -329,11 +305,7 @@ decaf_error_t decaf_ed25519_verify_prehash (
hash_destroy(hash_too);
}
#if DECAF_EDDSA_25519_SUPPORTS_CONTEXTS
ret = decaf_ed25519_verify(signature,pubkey,hash_output,sizeof(hash_output),1,context,context_len);
#else
ret = decaf_ed25519_verify(signature,pubkey,hash_output,sizeof(hash_output),1);
#endif
ret = decaf_ed25519_verify(signature,pubkey,hash_output,sizeof(hash_output),1,context,context_len,0);
return ret;
}
......@@ -28,7 +28,7 @@
#define hash_destroy decaf_shake256_destroy
#define hash_hash decaf_shake256_hash
#define SUPPORTS_CONTEXTS DECAF_EDDSA_448_SUPPORTS_CONTEXTS
#define NO_CONTEXT DECAF_EDDSA_448_NO_CONTEXT
#define EDDSA_USE_SIGMA_ISOGENY 0
#define COFACTOR 4
......@@ -58,38 +58,33 @@ static void hash_init_with_dom(
uint8_t prehashed,
uint8_t for_prehash,
const uint8_t *context,
uint8_t context_len
uint8_t context_len,
uint8_t no_context
) {
hash_init(hash);
#if SUPPORTS_CONTEXTS
#if NO_CONTEXT
if (no_context) {
(void)prehashed;
(void)for_prehash;
(void)context;
(void)context_len;
return;
}
#else
(void)no_context;
#endif
const char *dom_s = "SigEd448";
const uint8_t dom[2] = {2+word_is_zero(prehashed)+word_is_zero(for_prehash), context_len};
hash_update(hash,(const unsigned char *)dom_s, strlen(dom_s));
hash_update(hash,dom,2);
hash_update(hash,context,context_len);
#else
(void)prehashed;
(void)for_prehash;
(void)context;
assert(context==NULL);
(void)context_len;
assert(context_len == 0);
#endif
}
void decaf_ed448_prehash_init (
hash_ctx_t hash
#if DECAF_EDDSA_448_SUPPORTS_CONTEXTS
, const uint8_t *context,
uint8_t context_len
#endif
) {
#if DECAF_EDDSA_448_SUPPORTS_CONTEXTS
hash_init_with_dom(hash,1,1,context,context_len);
#else
hash_init_with_dom(hash,1,1,NULL,0);
#endif
hash_init(hash);
}
void decaf_ed448_derive_public_key (
......@@ -137,16 +132,11 @@ void decaf_ed448_sign (
const uint8_t pubkey[DECAF_EDDSA_448_PUBLIC_BYTES],
const uint8_t *message,
size_t message_len,
uint8_t prehashed
#if SUPPORTS_CONTEXTS
, const uint8_t *context,
uint8_t context_len
#endif
uint8_t prehashed,
const uint8_t *context,
uint8_t context_len,
uint8_t no_context
) {
#if !SUPPORTS_CONTEXTS
const uint8_t *const context = NULL;
const uint8_t context_len = 0;
#endif
API_NS(scalar_t) secret_scalar;
hash_ctx_t hash;
{
......@@ -165,7 +155,7 @@ void decaf_ed448_sign (
API_NS(scalar_decode_long)(secret_scalar, expanded.secret_scalar_ser, sizeof(expanded.secret_scalar_ser));
/* Hash to create the nonce */
hash_init_with_dom(hash,prehashed,0,context,context_len);
hash_init_with_dom(hash,prehashed,0,context,context_len,no_context);
hash_update(hash,expanded.seed,sizeof(expanded.seed));
hash_update(hash,message,message_len);
decaf_bzero(&expanded, sizeof(expanded));
......@@ -199,7 +189,7 @@ void decaf_ed448_sign (
API_NS(scalar_t) challenge_scalar;
{
/* Compute the challenge */
hash_init_with_dom(hash,prehashed,0,context,context_len);
hash_init_with_dom(hash,prehashed,0,context,context_len,no_context);
hash_update(hash,nonce_point,sizeof(nonce_point));
hash_update(hash,pubkey,DECAF_EDDSA_448_PUBLIC_BYTES);
hash_update(hash,message,message_len);
......@@ -227,11 +217,9 @@ void decaf_ed448_sign_prehash (
uint8_t signature[DECAF_EDDSA_448_SIGNATURE_BYTES],
const uint8_t privkey[DECAF_EDDSA_448_PRIVATE_BYTES],
const uint8_t pubkey[DECAF_EDDSA_448_PUBLIC_BYTES],
const decaf_ed448_prehash_ctx_t hash
#if DECAF_EDDSA_448_SUPPORTS_CONTEXTS
, const uint8_t *context,
const decaf_ed448_prehash_ctx_t hash,
const uint8_t *context,
uint8_t context_len
#endif
) {
uint8_t hash_output[64]; /* MAGIC but true for all existing schemes */
{
......@@ -240,13 +228,8 @@ void decaf_ed448_sign_prehash (
hash_final(hash_too,hash_output,sizeof(hash_output));
hash_destroy(hash_too);
}
#if DECAF_EDDSA_448_SUPPORTS_CONTEXTS
decaf_ed448_sign(signature,privkey,pubkey,hash_output,sizeof(hash_output),1,context,context_len);
#else
decaf_ed448_sign(signature,privkey,pubkey,hash_output,sizeof(hash_output),1);
#endif
decaf_ed448_sign(signature,privkey,pubkey,hash_output,sizeof(hash_output),1,context,context_len,0);
decaf_bzero(hash_output,sizeof(hash_output));
}
......@@ -255,16 +238,11 @@ decaf_error_t decaf_ed448_verify (
const uint8_t pubkey[DECAF_EDDSA_448_PUBLIC_BYTES],
const uint8_t *message,
size_t message_len,
uint8_t prehashed
#if SUPPORTS_CONTEXTS
, const uint8_t *context,
uint8_t context_len
#endif
uint8_t prehashed,
const uint8_t *context,
uint8_t context_len,
uint8_t no_context
) {
#if !SUPPORTS_CONTEXTS
const uint8_t *const context = NULL;
const uint8_t context_len = 0;
#endif
API_NS(point_t) pk_point, r_point;
decaf_error_t error = API_NS(point_decode_like_eddsa_and_ignore_cofactor)(pk_point,pubkey);
if (DECAF_SUCCESS != error) { return error; }
......@@ -276,7 +254,7 @@ decaf_error_t decaf_ed448_verify (
{
/* Compute the challenge */
hash_ctx_t hash;
hash_init_with_dom(hash,prehashed,0,context,context_len);
hash_init_with_dom(hash,prehashed,0,context,context_len,no_context);
hash_update(hash,signature,DECAF_EDDSA_448_PUBLIC_BYTES);
hash_update(hash,pubkey,DECAF_EDDSA_448_PUBLIC_BYTES);
hash_update(hash,message,message_len);
......@@ -313,11 +291,9 @@ decaf_error_t decaf_ed448_verify (
decaf_error_t decaf_ed448_verify_prehash (
const uint8_t signature[DECAF_EDDSA_448_SIGNATURE_BYTES],
const uint8_t pubkey[DECAF_EDDSA_448_PUBLIC_BYTES],
const decaf_ed448_prehash_ctx_t hash
#if DECAF_EDDSA_448_SUPPORTS_CONTEXTS
, const uint8_t *context,
const decaf_ed448_prehash_ctx_t hash,
const uint8_t *context,
uint8_t context_len
#endif
) {
decaf_error_t ret;
......@@ -329,11 +305,7 @@ decaf_error_t decaf_ed448_verify_prehash (
hash_destroy(hash_too);
}
#if DECAF_EDDSA_448_SUPPORTS_CONTEXTS
ret = decaf_ed448_verify(signature,pubkey,hash_output,sizeof(hash_output),1,context,context_len);
#else
ret = decaf_ed448_verify(signature,pubkey,hash_output,sizeof(hash_output),1);
#endif
ret = decaf_ed448_verify(signature,pubkey,hash_output,sizeof(hash_output),1,context,context_len,0);
return ret;
}
......@@ -32,8 +32,8 @@ extern "C" {
/** Number of bytes in an EdDSA private key. */
#define DECAF_EDDSA_25519_SIGNATURE_BYTES (DECAF_EDDSA_25519_PUBLIC_BYTES + DECAF_EDDSA_25519_PRIVATE_BYTES)
/** Does EdDSA support contexts? */
#define DECAF_EDDSA_25519_SUPPORTS_CONTEXTS 0
/** Does EdDSA support non-contextual signatures? */
#define DECAF_EDDSA_25519_NO_CONTEXT 1
/** Prehash context renaming macros. */
#define decaf_ed25519_prehash_ctx_s decaf_sha512_ctx_s
......@@ -59,11 +59,12 @@ void decaf_ed25519_derive_public_key (
* @param [out] signature The signature.
* @param [in] privkey The private key.
* @param [in] pubkey The public key.
* @param [in] context A "context" for this signature of up to 255 bytes.
* @param [in] context_len Length of the context.
* @param [in] message The message to sign.
* @param [in] message_len The length of the message.
* @param [in] prehashed Nonzero if the message is actually the hash of something you want to sign.
* @param [in] context A "context" for this signature of up to 255 bytes.
* @param [in] context_len Length of the context.
* @param [in] no_context Nonzero if no context should be used (only Ed25519 supported).
*
* @warning For Ed25519, it is unsafe to use the same key for both prehashed and non-prehashed
* messages, at least without some very careful protocol-level disambiguation. For Ed448 it is
......@@ -76,11 +77,10 @@ void decaf_ed25519_sign (
const uint8_t pubkey[DECAF_EDDSA_25519_PUBLIC_BYTES],
const uint8_t *message,
size_t message_len,
uint8_t prehashed
#if DECAF_EDDSA_25519_SUPPORTS_CONTEXTS
, const uint8_t *context,
uint8_t context_len
#endif
uint8_t prehashed,
const uint8_t *context,
uint8_t context_len,
uint8_t no_context
) API_VIS __attribute__((nonnull(1,2,3))) NOINLINE;
/**
......@@ -89,10 +89,9 @@ void decaf_ed25519_sign (
* @param [out] signature The signature.
* @param [in] privkey The private key.
* @param [in] pubkey The public key.
* @param [in] hash The hash of the message. This object will not be modified by the call.
* @param [in] context A "context" for this signature of up to 255 bytes. Must be the same as what was used for the prehash.
* @param [in] context_len Length of the context.
* @param [in] hash The hash of the message. This object will not be modified by the call.
* @param [in] prehashed Nonzero if the message is actually the hash of something you want to sign.
*
* @warning For Ed25519, it is unsafe to use the same key for both prehashed and non-prehashed
* messages, at least without some very careful protocol-level disambiguation. For Ed448 it is
......@@ -103,26 +102,18 @@ void decaf_ed25519_sign_prehash (
uint8_t signature[DECAF_EDDSA_25519_SIGNATURE_BYTES],
const uint8_t privkey[DECAF_EDDSA_25519_PRIVATE_BYTES],
const uint8_t pubkey[DECAF_EDDSA_25519_PUBLIC_BYTES],
const decaf_ed25519_prehash_ctx_t hash
#if DECAF_EDDSA_25519_SUPPORTS_CONTEXTS
, const uint8_t *context,
const decaf_ed25519_prehash_ctx_t hash,
const uint8_t *context,
uint8_t context_len
#endif
) API_VIS __attribute__((nonnull(1,2,3,4))) NOINLINE;
/**
* @brief Prehash initialization, with contexts if supported.
*
* @param [out] hash The hash object to be initialized.
* @param [in] context A "context" for this signature of up to 255 bytes.
* @param [in] context_len Length of the context.
*/
void decaf_ed25519_prehash_init (
decaf_ed25519_prehash_ctx_t hash
#if DECAF_EDDSA_25519_SUPPORTS_CONTEXTS
, const uint8_t *context,
uint8_t context_len
#endif
) API_VIS __attribute__((nonnull(1))) NOINLINE;
/**
......@@ -132,11 +123,12 @@ void decaf_ed25519_prehash_init (
*
* @param [in] signature The signature.
* @param [in] pubkey The public key.
* @param [in] context A "context" for this signature of up to 255 bytes.
* @param [in] context_len Length of the context.
* @param [in] message The message to verify.
* @param [in] message_len The length of the message.
* @param [in] prehashed Nonzero if the message is actually the hash of something you want to verify.
* @param [in] context A "context" for this signature of up to 255 bytes.
* @param [in] context_len Length of the context.
* @param [in] no_context Nonzero if no context should be used (only Ed25519 supported).
*
* @warning For Ed25519, it is unsafe to use the same key for both prehashed and non-prehashed
* messages, at least without some very careful protocol-level disambiguation. For Ed448 it is
......@@ -148,11 +140,10 @@ decaf_error_t decaf_ed25519_verify (
const uint8_t pubkey[DECAF_EDDSA_25519_PUBLIC_BYTES],
const uint8_t *message,
size_t message_len,
uint8_t prehashed
#if DECAF_EDDSA_25519_SUPPORTS_CONTEXTS
, const uint8_t *context,
uint8_t context_len
#endif
uint8_t prehashed,
const uint8_t *context,
uint8_t context_len,
uint8_t no_context
) API_VIS __attribute__((nonnull(1,2))) NOINLINE;
/**
......@@ -162,10 +153,9 @@ decaf_error_t decaf_ed25519_verify (
*
* @param [in] signature The signature.
* @param [in] pubkey The public key.
* @param [in] hash The hash of the message. This object will not be modified by the call.
* @param [in] context A "context" for this signature of up to 255 bytes. Must be the same as what was used for the prehash.
* @param [in] context_len Length of the context.
* @param [in] hash The hash of the message. This object will not be modified by the call.
* @param [in] prehashed Nonzero if the message is actually the hash of something you want to verify.
*
* @warning For Ed25519, it is unsafe to use the same key for both prehashed and non-prehashed
* messages, at least without some very careful protocol-level disambiguation. For Ed448 it is
......@@ -175,11 +165,9 @@ decaf_error_t decaf_ed25519_verify (
decaf_error_t decaf_ed25519_verify_prehash (
const uint8_t signature[DECAF_EDDSA_25519_SIGNATURE_BYTES],
const uint8_t pubkey[DECAF_EDDSA_25519_PUBLIC_BYTES],
const decaf_ed25519_prehash_ctx_t hash
#if DECAF_EDDSA_25519_SUPPORTS_CONTEXTS
, const uint8_t *context,
const decaf_ed25519_prehash_ctx_t hash,
const uint8_t *context,
uint8_t context_len
#endif
) API_VIS __attribute__((nonnull(1,2))) NOINLINE;
/**
......
......@@ -49,22 +49,14 @@ template<> struct EdDSA<IsoEd25519> {
/** @cond internal */
template<class CRTP, Prehashed> class Signing;
template<class CRTP, Prehashed> class Verification;
template<Prehashed=PURE> class PublicKeyBase;
template<Prehashed=PURE> class PrivateKeyBase;
typedef class PublicKeyBase<PURE> PublicKey, PublicKeyPure;
typedef class PublicKeyBase<PREHASHED> PublicKeyPh;
typedef class PrivateKeyBase<PURE> PrivateKey, PrivateKeyPure;
typedef class PrivateKeyBase<PREHASHED> PrivateKeyPh;
class PublicKeyBase;
class PrivateKeyBase;
typedef class PrivateKeyBase PrivateKey, PrivateKeyPure, PrivateKeyPh;
typedef class PublicKeyBase PublicKey, PublicKeyPure, PublicKeyPh;
/** @endcond */
/** Prehash context for EdDSA. */
class Prehash : public SHA512 {
public:
/** Do we support contexts for signatures? If not, they must always be NULL */
static const bool SUPPORTS_CONTEXTS = DECAF_EDDSA_25519_SUPPORTS_CONTEXTS;
private:
typedef SHA512 Super;
SecureBuffer context_;
......@@ -74,17 +66,11 @@ private:
void init() throw(LengthException) {
Super::reset();
if (context_.size() > 255
|| (context_.size() != 0 && !SUPPORTS_CONTEXTS)
) {
if (context_.size() > 255) {
throw LengthException();
}
#if DECAF_EDDSA_25519_SUPPORTS_CONTEXTS
decaf_ed25519_prehash_init((decaf_sha512_ctx_s *)wrapped,context_.data(),context_.size());
#else
decaf_ed25519_prehash_init(wrapped);
#endif
decaf_ed25519_prehash_init((decaf_sha512_ctx_s *)wrapped);
}
public:
......@@ -126,11 +112,9 @@ public:
out.data(),
((const CRTP*)this)->priv_.data(),
((const CRTP*)this)->pub_.data(),
(const decaf_ed25519_prehash_ctx_s*)ph.wrapped
#if DECAF_EDDSA_25519_SUPPORTS_CONTEXTS
, ph.context_.data(),
(const decaf_ed25519_prehash_ctx_s*)ph.wrapped,
ph.context_.data(),
ph.context_.size()
#endif
);
return out;
}
......@@ -151,20 +135,18 @@ public:
/**
* Sign a message.
* @param [in] message The message to be signed.
* @param [in] context A context for the signature; must be at most 255 bytes;
* must be absent if SUPPORTS_CONTEXTS == false.
* @param [in] context A context for the signature; must be at most 255 bytes.
*
* @warning It is generally unsafe to use Ed25519 with both prehashed and non-prehashed messages.
*/
inline SecureBuffer sign (
const Block &message,
const Block &context = Block(NULL,0)
const Block &context = Block(NULL,0),
const bool no_context = false
) const /* TODO: this exn spec tickles a Clang bug?
* throw(LengthException, std::bad_alloc)
*/ {
if (context.size() > 255
|| (context.size() != 0 && !CRTP::SUPPORTS_CONTEXTS)
) {
if (context.size() > 255) {
throw LengthException();
}
......@@ -175,28 +157,27 @@ public:
((const CRTP*)this)->pub_.data(),
message.data(),
message.size(),
0
#if DECAF_EDDSA_25519_SUPPORTS_CONTEXTS
, context.data(),
context.size()
#endif
0,
context.data(),
context.size(),
no_context
);
return out;
}
};
template<Prehashed ph> class PrivateKeyBase
: public Serializable<PrivateKeyBase<ph> >
, public Signing<PrivateKeyBase<ph>,ph> {
class PrivateKeyBase
: public Serializable<PrivateKeyBase>
, public Signing<PrivateKeyBase,PURE>
, public Signing<PrivateKeyBase,PREHASHED> {
public:
typedef class PublicKeyBase<ph> MyPublicKey;
typedef class PublicKeyBase MyPublicKey;
private:
/** @cond internal */
friend class PublicKeyBase<ph>;
friend class Signing<PrivateKeyBase<ph>, ph>;
friend class PublicKeyBase;
friend class Signing<PrivateKey,PURE>;
friend class Signing<PrivateKey,PREHASHED>;
/** @endcond */
/** The pre-expansion form of the signing key. */
FixedArrayBuffer<DECAF_EDDSA_25519_PRIVATE_BYTES> priv_;
......@@ -214,9 +195,6 @@ public:
/** Serialization size. */
static const size_t SER_BYTES = DECAF_EDDSA_25519_PRIVATE_BYTES;
/** Do we support contexts for signatures? If not, they must always be NULL */
static const bool SUPPORTS_CONTEXTS = DECAF_EDDSA_25519_SUPPORTS_CONTEXTS;
/** Create but don't initialize */
inline explicit PrivateKeyBase(const NOINIT&) NOEXCEPT : priv_((NOINIT())), pub_((NOINIT())) { }
......@@ -269,11 +247,10 @@ public:
inline decaf_error_t WARN_UNUSED verify_noexcept (
const FixedBlock<DECAF_EDDSA_25519_SIGNATURE_BYTES> &sig,
const Block &message,
const Block &context = Block(NULL,0)
const Block &context = Block(NULL,0),
const bool no_context = false
) const /*NOEXCEPT*/ {
if (context.size() > 255
|| (context.size() != 0 && !CRTP::SUPPORTS_CONTEXTS)
) {
if (context.size() > 255) {
return DECAF_FAILURE;
}
......@@ -282,34 +259,31 @@ public:
((const CRTP*)this)->pub_.data(),
message.data(),
message.size(),
0
#if DECAF_EDDSA_25519_SUPPORTS_CONTEXTS
, context.data(),
context.size()
#endif
0,
context.data(),
context.size(),
no_context
);
}
/** Verify a signature, throwing an exception if verification fails
* @param [in] sig The signature.
* @param [in] message The signed message.
* @param [in] context A context for the signature; must be at most 255 bytes;
* must be absent if SUPPORTS_CONTEXTS == false.
* @param [in] context A context for the signature; must be at most 255 bytes.
*
* @warning It is generally unsafe to use Ed25519 with both prehashed and non-prehashed messages.
*/
inline void verify (
const FixedBlock<DECAF_EDDSA_25519_SIGNATURE_BYTES> &sig,
const Block &message,
const Block &context = Block(NULL,0)
const Block &context = Block(NULL,0),
const bool no_context = false
) const /*throw(LengthException,CryptoException)*/ {
if (context.size() > 255
|| (context.size() != 0 && !CRTP::SUPPORTS_CONTEXTS)
) {
if (context.size() > 255) {
throw LengthException();
}
if (DECAF_SUCCESS != verify_noexcept( sig, message, context )) {
if (DECAF_SUCCESS != verify_noexcept( sig, message, context, no_context )) {
throw CryptoException();
}
}
......@@ -326,11 +300,9 @@ public:
return decaf_ed25519_verify_prehash (
sig.data(),
((const CRTP*)this)->pub_.data(),
(const decaf_ed25519_prehash_ctx_s*)ph.wrapped
#if DECAF_EDDSA_25519_SUPPORTS_CONTEXTS
, ph.context_.data(),
(const decaf_ed25519_prehash_ctx_s*)ph.wrapped,
ph.context_.data(),
ph.context_.size()
#endif
);
}
......@@ -342,11 +314,9 @@ public:
if (DECAF_SUCCESS != decaf_ed25519_verify_prehash (
sig.data(),
((const CRTP*)this)->pub_.data(),
(const decaf_ed25519_prehash_ctx_s*)ph.wrapped
#if DECAF_EDDSA_25519_SUPPORTS_CONTEXTS
, ph.context_.data(),
(const decaf_ed25519_prehash_ctx_s*)ph.wrapped,
ph.context_.data(),
ph.context_.size()
#endif
)) {
throw CryptoException();
}
......@@ -365,20 +335,20 @@ public:
};
template<Prehashed ph> class PublicKeyBase
: public Serializable<PublicKeyBase<ph> >
, public Verification<PublicKeyBase<ph>,ph> {
class PublicKeyBase