@@ -58,21 +58,18 @@ static void hash_init_with_dom( | |||||
uint8_t prehashed, | uint8_t prehashed, | ||||
uint8_t for_prehash, | uint8_t for_prehash, | ||||
const uint8_t *context, | const uint8_t *context, | ||||
uint8_t context_len, | |||||
uint8_t no_context | |||||
uint8_t context_len | |||||
) { | ) { | ||||
hash_init(hash); | hash_init(hash); | ||||
#if NO_CONTEXT | #if NO_CONTEXT | ||||
if (no_context) { | |||||
if (context_len == 0 && context == ED25519_NO_CONTEXT) { | |||||
(void)prehashed; | (void)prehashed; | ||||
(void)for_prehash; | (void)for_prehash; | ||||
(void)context; | (void)context; | ||||
(void)context_len; | (void)context_len; | ||||
return; | return; | ||||
} | } | ||||
#else | |||||
(void)no_context; | |||||
#endif | #endif | ||||
const char *dom_s = "SigEd25519 no Ed25519 collisions"; | 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}; | const uint8_t dom[2] = {2+word_is_zero(prehashed)+word_is_zero(for_prehash), context_len}; | ||||
@@ -134,8 +131,7 @@ void decaf_ed25519_sign ( | |||||
size_t message_len, | size_t message_len, | ||||
uint8_t prehashed, | uint8_t prehashed, | ||||
const uint8_t *context, | const uint8_t *context, | ||||
uint8_t context_len, | |||||
uint8_t no_context | |||||
uint8_t context_len | |||||
) { | ) { | ||||
API_NS(scalar_t) secret_scalar; | API_NS(scalar_t) secret_scalar; | ||||
hash_ctx_t hash; | hash_ctx_t hash; | ||||
@@ -155,7 +151,7 @@ void decaf_ed25519_sign ( | |||||
API_NS(scalar_decode_long)(secret_scalar, expanded.secret_scalar_ser, sizeof(expanded.secret_scalar_ser)); | API_NS(scalar_decode_long)(secret_scalar, expanded.secret_scalar_ser, sizeof(expanded.secret_scalar_ser)); | ||||
/* Hash to create the nonce */ | /* Hash to create the nonce */ | ||||
hash_init_with_dom(hash,prehashed,0,context,context_len,no_context); | |||||
hash_init_with_dom(hash,prehashed,0,context,context_len); | |||||
hash_update(hash,expanded.seed,sizeof(expanded.seed)); | hash_update(hash,expanded.seed,sizeof(expanded.seed)); | ||||
hash_update(hash,message,message_len); | hash_update(hash,message,message_len); | ||||
decaf_bzero(&expanded, sizeof(expanded)); | decaf_bzero(&expanded, sizeof(expanded)); | ||||
@@ -189,7 +185,7 @@ void decaf_ed25519_sign ( | |||||
API_NS(scalar_t) challenge_scalar; | API_NS(scalar_t) challenge_scalar; | ||||
{ | { | ||||
/* Compute the challenge */ | /* Compute the challenge */ | ||||
hash_init_with_dom(hash,prehashed,0,context,context_len,no_context); | |||||
hash_init_with_dom(hash,prehashed,0,context,context_len); | |||||
hash_update(hash,nonce_point,sizeof(nonce_point)); | hash_update(hash,nonce_point,sizeof(nonce_point)); | ||||
hash_update(hash,pubkey,DECAF_EDDSA_25519_PUBLIC_BYTES); | hash_update(hash,pubkey,DECAF_EDDSA_25519_PUBLIC_BYTES); | ||||
hash_update(hash,message,message_len); | hash_update(hash,message,message_len); | ||||
@@ -229,7 +225,7 @@ void decaf_ed25519_sign_prehash ( | |||||
hash_destroy(hash_too); | hash_destroy(hash_too); | ||||
} | } | ||||
decaf_ed25519_sign(signature,privkey,pubkey,hash_output,sizeof(hash_output),1,context,context_len,0); | |||||
decaf_ed25519_sign(signature,privkey,pubkey,hash_output,sizeof(hash_output),1,context,context_len); | |||||
decaf_bzero(hash_output,sizeof(hash_output)); | decaf_bzero(hash_output,sizeof(hash_output)); | ||||
} | } | ||||
@@ -240,8 +236,7 @@ decaf_error_t decaf_ed25519_verify ( | |||||
size_t message_len, | size_t message_len, | ||||
uint8_t prehashed, | uint8_t prehashed, | ||||
const uint8_t *context, | const uint8_t *context, | ||||
uint8_t context_len, | |||||
uint8_t no_context | |||||
uint8_t context_len | |||||
) { | ) { | ||||
API_NS(point_t) pk_point, r_point; | API_NS(point_t) pk_point, r_point; | ||||
decaf_error_t error = API_NS(point_decode_like_eddsa_and_ignore_cofactor)(pk_point,pubkey); | decaf_error_t error = API_NS(point_decode_like_eddsa_and_ignore_cofactor)(pk_point,pubkey); | ||||
@@ -254,7 +249,7 @@ decaf_error_t decaf_ed25519_verify ( | |||||
{ | { | ||||
/* Compute the challenge */ | /* Compute the challenge */ | ||||
hash_ctx_t hash; | hash_ctx_t hash; | ||||
hash_init_with_dom(hash,prehashed,0,context,context_len,no_context); | |||||
hash_init_with_dom(hash,prehashed,0,context,context_len); | |||||
hash_update(hash,signature,DECAF_EDDSA_25519_PUBLIC_BYTES); | hash_update(hash,signature,DECAF_EDDSA_25519_PUBLIC_BYTES); | ||||
hash_update(hash,pubkey,DECAF_EDDSA_25519_PUBLIC_BYTES); | hash_update(hash,pubkey,DECAF_EDDSA_25519_PUBLIC_BYTES); | ||||
hash_update(hash,message,message_len); | hash_update(hash,message,message_len); | ||||
@@ -305,7 +300,7 @@ decaf_error_t decaf_ed25519_verify_prehash ( | |||||
hash_destroy(hash_too); | hash_destroy(hash_too); | ||||
} | } | ||||
ret = decaf_ed25519_verify(signature,pubkey,hash_output,sizeof(hash_output),1,context,context_len,0); | |||||
ret = decaf_ed25519_verify(signature,pubkey,hash_output,sizeof(hash_output),1,context,context_len); | |||||
return ret; | return ret; | ||||
} | } |
@@ -58,21 +58,18 @@ static void hash_init_with_dom( | |||||
uint8_t prehashed, | uint8_t prehashed, | ||||
uint8_t for_prehash, | uint8_t for_prehash, | ||||
const uint8_t *context, | const uint8_t *context, | ||||
uint8_t context_len, | |||||
uint8_t no_context | |||||
uint8_t context_len | |||||
) { | ) { | ||||
hash_init(hash); | hash_init(hash); | ||||
#if NO_CONTEXT | #if NO_CONTEXT | ||||
if (no_context) { | |||||
if (context_len == 0 && context == ED448_NO_CONTEXT) { | |||||
(void)prehashed; | (void)prehashed; | ||||
(void)for_prehash; | (void)for_prehash; | ||||
(void)context; | (void)context; | ||||
(void)context_len; | (void)context_len; | ||||
return; | return; | ||||
} | } | ||||
#else | |||||
(void)no_context; | |||||
#endif | #endif | ||||
const char *dom_s = "SigEd448"; | const char *dom_s = "SigEd448"; | ||||
const uint8_t dom[2] = {2+word_is_zero(prehashed)+word_is_zero(for_prehash), context_len}; | const uint8_t dom[2] = {2+word_is_zero(prehashed)+word_is_zero(for_prehash), context_len}; | ||||
@@ -134,8 +131,7 @@ void decaf_ed448_sign ( | |||||
size_t message_len, | size_t message_len, | ||||
uint8_t prehashed, | uint8_t prehashed, | ||||
const uint8_t *context, | const uint8_t *context, | ||||
uint8_t context_len, | |||||
uint8_t no_context | |||||
uint8_t context_len | |||||
) { | ) { | ||||
API_NS(scalar_t) secret_scalar; | API_NS(scalar_t) secret_scalar; | ||||
hash_ctx_t hash; | hash_ctx_t hash; | ||||
@@ -155,7 +151,7 @@ void decaf_ed448_sign ( | |||||
API_NS(scalar_decode_long)(secret_scalar, expanded.secret_scalar_ser, sizeof(expanded.secret_scalar_ser)); | API_NS(scalar_decode_long)(secret_scalar, expanded.secret_scalar_ser, sizeof(expanded.secret_scalar_ser)); | ||||
/* Hash to create the nonce */ | /* Hash to create the nonce */ | ||||
hash_init_with_dom(hash,prehashed,0,context,context_len,no_context); | |||||
hash_init_with_dom(hash,prehashed,0,context,context_len); | |||||
hash_update(hash,expanded.seed,sizeof(expanded.seed)); | hash_update(hash,expanded.seed,sizeof(expanded.seed)); | ||||
hash_update(hash,message,message_len); | hash_update(hash,message,message_len); | ||||
decaf_bzero(&expanded, sizeof(expanded)); | decaf_bzero(&expanded, sizeof(expanded)); | ||||
@@ -189,7 +185,7 @@ void decaf_ed448_sign ( | |||||
API_NS(scalar_t) challenge_scalar; | API_NS(scalar_t) challenge_scalar; | ||||
{ | { | ||||
/* Compute the challenge */ | /* Compute the challenge */ | ||||
hash_init_with_dom(hash,prehashed,0,context,context_len,no_context); | |||||
hash_init_with_dom(hash,prehashed,0,context,context_len); | |||||
hash_update(hash,nonce_point,sizeof(nonce_point)); | hash_update(hash,nonce_point,sizeof(nonce_point)); | ||||
hash_update(hash,pubkey,DECAF_EDDSA_448_PUBLIC_BYTES); | hash_update(hash,pubkey,DECAF_EDDSA_448_PUBLIC_BYTES); | ||||
hash_update(hash,message,message_len); | hash_update(hash,message,message_len); | ||||
@@ -229,7 +225,7 @@ void decaf_ed448_sign_prehash ( | |||||
hash_destroy(hash_too); | hash_destroy(hash_too); | ||||
} | } | ||||
decaf_ed448_sign(signature,privkey,pubkey,hash_output,sizeof(hash_output),1,context,context_len,0); | |||||
decaf_ed448_sign(signature,privkey,pubkey,hash_output,sizeof(hash_output),1,context,context_len); | |||||
decaf_bzero(hash_output,sizeof(hash_output)); | decaf_bzero(hash_output,sizeof(hash_output)); | ||||
} | } | ||||
@@ -240,8 +236,7 @@ decaf_error_t decaf_ed448_verify ( | |||||
size_t message_len, | size_t message_len, | ||||
uint8_t prehashed, | uint8_t prehashed, | ||||
const uint8_t *context, | const uint8_t *context, | ||||
uint8_t context_len, | |||||
uint8_t no_context | |||||
uint8_t context_len | |||||
) { | ) { | ||||
API_NS(point_t) pk_point, r_point; | API_NS(point_t) pk_point, r_point; | ||||
decaf_error_t error = API_NS(point_decode_like_eddsa_and_ignore_cofactor)(pk_point,pubkey); | decaf_error_t error = API_NS(point_decode_like_eddsa_and_ignore_cofactor)(pk_point,pubkey); | ||||
@@ -254,7 +249,7 @@ decaf_error_t decaf_ed448_verify ( | |||||
{ | { | ||||
/* Compute the challenge */ | /* Compute the challenge */ | ||||
hash_ctx_t hash; | hash_ctx_t hash; | ||||
hash_init_with_dom(hash,prehashed,0,context,context_len,no_context); | |||||
hash_init_with_dom(hash,prehashed,0,context,context_len); | |||||
hash_update(hash,signature,DECAF_EDDSA_448_PUBLIC_BYTES); | hash_update(hash,signature,DECAF_EDDSA_448_PUBLIC_BYTES); | ||||
hash_update(hash,pubkey,DECAF_EDDSA_448_PUBLIC_BYTES); | hash_update(hash,pubkey,DECAF_EDDSA_448_PUBLIC_BYTES); | ||||
hash_update(hash,message,message_len); | hash_update(hash,message,message_len); | ||||
@@ -305,7 +300,7 @@ decaf_error_t decaf_ed448_verify_prehash ( | |||||
hash_destroy(hash_too); | hash_destroy(hash_too); | ||||
} | } | ||||
ret = decaf_ed448_verify(signature,pubkey,hash_output,sizeof(hash_output),1,context,context_len,0); | |||||
ret = decaf_ed448_verify(signature,pubkey,hash_output,sizeof(hash_output),1,context,context_len); | |||||
return ret; | return ret; | ||||
} | } |
@@ -34,7 +34,8 @@ extern "C" { | |||||
/** Does EdDSA support non-contextual signatures? */ | /** Does EdDSA support non-contextual signatures? */ | ||||
#define DECAF_EDDSA_25519_NO_CONTEXT 1 | #define DECAF_EDDSA_25519_NO_CONTEXT 1 | ||||
const uint8_t * const ED25519_NO_CONTEXT = (const uint8_t * const)(25519); | |||||
/** Prehash context renaming macros. */ | /** Prehash context renaming macros. */ | ||||
#define decaf_ed25519_prehash_ctx_s decaf_sha512_ctx_s | #define decaf_ed25519_prehash_ctx_s decaf_sha512_ctx_s | ||||
#define decaf_ed25519_prehash_ctx_t decaf_sha512_ctx_t | #define decaf_ed25519_prehash_ctx_t decaf_sha512_ctx_t | ||||
@@ -64,7 +65,6 @@ void decaf_ed25519_derive_public_key ( | |||||
* @param [in] prehashed Nonzero if the message is actually the hash of something you want to sign. | * @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 A "context" for this signature of up to 255 bytes. | ||||
* @param [in] context_len Length of the context. | * @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 | * @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 | * messages, at least without some very careful protocol-level disambiguation. For Ed448 it is | ||||
@@ -79,8 +79,7 @@ void decaf_ed25519_sign ( | |||||
size_t message_len, | size_t message_len, | ||||
uint8_t prehashed, | uint8_t prehashed, | ||||
const uint8_t *context, | const uint8_t *context, | ||||
uint8_t context_len, | |||||
uint8_t no_context | |||||
uint8_t context_len | |||||
) API_VIS __attribute__((nonnull(1,2,3))) NOINLINE; | ) API_VIS __attribute__((nonnull(1,2,3))) NOINLINE; | ||||
/** | /** | ||||
@@ -128,7 +127,6 @@ void decaf_ed25519_prehash_init ( | |||||
* @param [in] prehashed Nonzero if the message is actually the hash of something you want to verify. | * @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 A "context" for this signature of up to 255 bytes. | ||||
* @param [in] context_len Length of the context. | * @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 | * @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 | * messages, at least without some very careful protocol-level disambiguation. For Ed448 it is | ||||
@@ -142,8 +140,7 @@ decaf_error_t decaf_ed25519_verify ( | |||||
size_t message_len, | size_t message_len, | ||||
uint8_t prehashed, | uint8_t prehashed, | ||||
const uint8_t *context, | const uint8_t *context, | ||||
uint8_t context_len, | |||||
uint8_t no_context | |||||
uint8_t context_len | |||||
) API_VIS __attribute__((nonnull(1,2))) NOINLINE; | ) API_VIS __attribute__((nonnull(1,2))) NOINLINE; | ||||
/** | /** | ||||
@@ -141,8 +141,7 @@ public: | |||||
*/ | */ | ||||
inline SecureBuffer sign ( | inline SecureBuffer sign ( | ||||
const Block &message, | const Block &message, | ||||
const Block &context = Block(NULL,0), | |||||
const bool no_context = false | |||||
const Block &context = Block(NULL,0) | |||||
) const /* TODO: this exn spec tickles a Clang bug? | ) const /* TODO: this exn spec tickles a Clang bug? | ||||
* throw(LengthException, std::bad_alloc) | * throw(LengthException, std::bad_alloc) | ||||
*/ { | */ { | ||||
@@ -159,8 +158,7 @@ public: | |||||
message.size(), | message.size(), | ||||
0, | 0, | ||||
context.data(), | context.data(), | ||||
context.size(), | |||||
no_context | |||||
context.size() | |||||
); | ); | ||||
return out; | return out; | ||||
} | } | ||||
@@ -247,8 +245,7 @@ public: | |||||
inline decaf_error_t WARN_UNUSED verify_noexcept ( | inline decaf_error_t WARN_UNUSED verify_noexcept ( | ||||
const FixedBlock<DECAF_EDDSA_25519_SIGNATURE_BYTES> &sig, | const FixedBlock<DECAF_EDDSA_25519_SIGNATURE_BYTES> &sig, | ||||
const Block &message, | const Block &message, | ||||
const Block &context = Block(NULL,0), | |||||
const bool no_context = false | |||||
const Block &context = Block(NULL,0) | |||||
) const /*NOEXCEPT*/ { | ) const /*NOEXCEPT*/ { | ||||
if (context.size() > 255) { | if (context.size() > 255) { | ||||
return DECAF_FAILURE; | return DECAF_FAILURE; | ||||
@@ -261,8 +258,7 @@ public: | |||||
message.size(), | message.size(), | ||||
0, | 0, | ||||
context.data(), | context.data(), | ||||
context.size(), | |||||
no_context | |||||
context.size() | |||||
); | ); | ||||
} | } | ||||
@@ -276,14 +272,13 @@ public: | |||||
inline void verify ( | inline void verify ( | ||||
const FixedBlock<DECAF_EDDSA_25519_SIGNATURE_BYTES> &sig, | const FixedBlock<DECAF_EDDSA_25519_SIGNATURE_BYTES> &sig, | ||||
const Block &message, | const Block &message, | ||||
const Block &context = Block(NULL,0), | |||||
const bool no_context = false | |||||
const Block &context = Block(NULL,0) | |||||
) const /*throw(LengthException,CryptoException)*/ { | ) const /*throw(LengthException,CryptoException)*/ { | ||||
if (context.size() > 255) { | if (context.size() > 255) { | ||||
throw LengthException(); | throw LengthException(); | ||||
} | } | ||||
if (DECAF_SUCCESS != verify_noexcept( sig, message, context, no_context )) { | |||||
if (DECAF_SUCCESS != verify_noexcept( sig, message, context )) { | |||||
throw CryptoException(); | throw CryptoException(); | ||||
} | } | ||||
} | } | ||||
@@ -34,7 +34,7 @@ extern "C" { | |||||
/** Does EdDSA support non-contextual signatures? */ | /** Does EdDSA support non-contextual signatures? */ | ||||
#define DECAF_EDDSA_448_NO_CONTEXT 0 | #define DECAF_EDDSA_448_NO_CONTEXT 0 | ||||
/** Prehash context renaming macros. */ | /** Prehash context renaming macros. */ | ||||
#define decaf_ed448_prehash_ctx_s decaf_shake256_ctx_s | #define decaf_ed448_prehash_ctx_s decaf_shake256_ctx_s | ||||
#define decaf_ed448_prehash_ctx_t decaf_shake256_ctx_t | #define decaf_ed448_prehash_ctx_t decaf_shake256_ctx_t | ||||
@@ -64,7 +64,6 @@ void decaf_ed448_derive_public_key ( | |||||
* @param [in] prehashed Nonzero if the message is actually the hash of something you want to sign. | * @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 A "context" for this signature of up to 255 bytes. | ||||
* @param [in] context_len Length of the context. | * @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 | * @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 | * messages, at least without some very careful protocol-level disambiguation. For Ed448 it is | ||||
@@ -79,8 +78,7 @@ void decaf_ed448_sign ( | |||||
size_t message_len, | size_t message_len, | ||||
uint8_t prehashed, | uint8_t prehashed, | ||||
const uint8_t *context, | const uint8_t *context, | ||||
uint8_t context_len, | |||||
uint8_t no_context | |||||
uint8_t context_len | |||||
) API_VIS __attribute__((nonnull(1,2,3))) NOINLINE; | ) API_VIS __attribute__((nonnull(1,2,3))) NOINLINE; | ||||
/** | /** | ||||
@@ -128,7 +126,6 @@ void decaf_ed448_prehash_init ( | |||||
* @param [in] prehashed Nonzero if the message is actually the hash of something you want to verify. | * @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 A "context" for this signature of up to 255 bytes. | ||||
* @param [in] context_len Length of the context. | * @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 | * @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 | * messages, at least without some very careful protocol-level disambiguation. For Ed448 it is | ||||
@@ -142,8 +139,7 @@ decaf_error_t decaf_ed448_verify ( | |||||
size_t message_len, | size_t message_len, | ||||
uint8_t prehashed, | uint8_t prehashed, | ||||
const uint8_t *context, | const uint8_t *context, | ||||
uint8_t context_len, | |||||
uint8_t no_context | |||||
uint8_t context_len | |||||
) API_VIS __attribute__((nonnull(1,2))) NOINLINE; | ) API_VIS __attribute__((nonnull(1,2))) NOINLINE; | ||||
/** | /** | ||||
@@ -141,8 +141,7 @@ public: | |||||
*/ | */ | ||||
inline SecureBuffer sign ( | inline SecureBuffer sign ( | ||||
const Block &message, | const Block &message, | ||||
const Block &context = Block(NULL,0), | |||||
const bool no_context = false | |||||
const Block &context = Block(NULL,0) | |||||
) const /* TODO: this exn spec tickles a Clang bug? | ) const /* TODO: this exn spec tickles a Clang bug? | ||||
* throw(LengthException, std::bad_alloc) | * throw(LengthException, std::bad_alloc) | ||||
*/ { | */ { | ||||
@@ -159,8 +158,7 @@ public: | |||||
message.size(), | message.size(), | ||||
0, | 0, | ||||
context.data(), | context.data(), | ||||
context.size(), | |||||
no_context | |||||
context.size() | |||||
); | ); | ||||
return out; | return out; | ||||
} | } | ||||
@@ -247,8 +245,7 @@ public: | |||||
inline decaf_error_t WARN_UNUSED verify_noexcept ( | inline decaf_error_t WARN_UNUSED verify_noexcept ( | ||||
const FixedBlock<DECAF_EDDSA_448_SIGNATURE_BYTES> &sig, | const FixedBlock<DECAF_EDDSA_448_SIGNATURE_BYTES> &sig, | ||||
const Block &message, | const Block &message, | ||||
const Block &context = Block(NULL,0), | |||||
const bool no_context = false | |||||
const Block &context = Block(NULL,0) | |||||
) const /*NOEXCEPT*/ { | ) const /*NOEXCEPT*/ { | ||||
if (context.size() > 255) { | if (context.size() > 255) { | ||||
return DECAF_FAILURE; | return DECAF_FAILURE; | ||||
@@ -261,8 +258,7 @@ public: | |||||
message.size(), | message.size(), | ||||
0, | 0, | ||||
context.data(), | context.data(), | ||||
context.size(), | |||||
no_context | |||||
context.size() | |||||
); | ); | ||||
} | } | ||||
@@ -276,14 +272,13 @@ public: | |||||
inline void verify ( | inline void verify ( | ||||
const FixedBlock<DECAF_EDDSA_448_SIGNATURE_BYTES> &sig, | const FixedBlock<DECAF_EDDSA_448_SIGNATURE_BYTES> &sig, | ||||
const Block &message, | const Block &message, | ||||
const Block &context = Block(NULL,0), | |||||
const bool no_context = false | |||||
const Block &context = Block(NULL,0) | |||||
) const /*throw(LengthException,CryptoException)*/ { | ) const /*throw(LengthException,CryptoException)*/ { | ||||
if (context.size() > 255) { | if (context.size() > 255) { | ||||
throw LengthException(); | throw LengthException(); | ||||
} | } | ||||
if (DECAF_SUCCESS != verify_noexcept( sig, message, context, no_context )) { | |||||
if (DECAF_SUCCESS != verify_noexcept( sig, message, context )) { | |||||
throw CryptoException(); | throw CryptoException(); | ||||
} | } | ||||
} | } | ||||
@@ -49,21 +49,18 @@ static void hash_init_with_dom( | |||||
uint8_t prehashed, | uint8_t prehashed, | ||||
uint8_t for_prehash, | uint8_t for_prehash, | ||||
const uint8_t *context, | const uint8_t *context, | ||||
uint8_t context_len, | |||||
uint8_t no_context | |||||
uint8_t context_len | |||||
) { | ) { | ||||
hash_init(hash); | hash_init(hash); | ||||
#if NO_CONTEXT | #if NO_CONTEXT | ||||
if (no_context) { | |||||
if (context_len == 0 && context == ED$(gf_shortname)_NO_CONTEXT) { | |||||
(void)prehashed; | (void)prehashed; | ||||
(void)for_prehash; | (void)for_prehash; | ||||
(void)context; | (void)context; | ||||
(void)context_len; | (void)context_len; | ||||
return; | return; | ||||
} | } | ||||
#else | |||||
(void)no_context; | |||||
#endif | #endif | ||||
const char *dom_s = "$(eddsa_dom)"; | const char *dom_s = "$(eddsa_dom)"; | ||||
const uint8_t dom[2] = {2+word_is_zero(prehashed)+word_is_zero(for_prehash), context_len}; | const uint8_t dom[2] = {2+word_is_zero(prehashed)+word_is_zero(for_prehash), context_len}; | ||||
@@ -125,8 +122,7 @@ void decaf_ed$(gf_shortname)_sign ( | |||||
size_t message_len, | size_t message_len, | ||||
uint8_t prehashed, | uint8_t prehashed, | ||||
const uint8_t *context, | const uint8_t *context, | ||||
uint8_t context_len, | |||||
uint8_t no_context | |||||
uint8_t context_len | |||||
) { | ) { | ||||
API_NS(scalar_t) secret_scalar; | API_NS(scalar_t) secret_scalar; | ||||
hash_ctx_t hash; | hash_ctx_t hash; | ||||
@@ -146,7 +142,7 @@ void decaf_ed$(gf_shortname)_sign ( | |||||
API_NS(scalar_decode_long)(secret_scalar, expanded.secret_scalar_ser, sizeof(expanded.secret_scalar_ser)); | API_NS(scalar_decode_long)(secret_scalar, expanded.secret_scalar_ser, sizeof(expanded.secret_scalar_ser)); | ||||
/* Hash to create the nonce */ | /* Hash to create the nonce */ | ||||
hash_init_with_dom(hash,prehashed,0,context,context_len,no_context); | |||||
hash_init_with_dom(hash,prehashed,0,context,context_len); | |||||
hash_update(hash,expanded.seed,sizeof(expanded.seed)); | hash_update(hash,expanded.seed,sizeof(expanded.seed)); | ||||
hash_update(hash,message,message_len); | hash_update(hash,message,message_len); | ||||
decaf_bzero(&expanded, sizeof(expanded)); | decaf_bzero(&expanded, sizeof(expanded)); | ||||
@@ -180,7 +176,7 @@ void decaf_ed$(gf_shortname)_sign ( | |||||
API_NS(scalar_t) challenge_scalar; | API_NS(scalar_t) challenge_scalar; | ||||
{ | { | ||||
/* Compute the challenge */ | /* Compute the challenge */ | ||||
hash_init_with_dom(hash,prehashed,0,context,context_len,no_context); | |||||
hash_init_with_dom(hash,prehashed,0,context,context_len); | |||||
hash_update(hash,nonce_point,sizeof(nonce_point)); | hash_update(hash,nonce_point,sizeof(nonce_point)); | ||||
hash_update(hash,pubkey,DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES); | hash_update(hash,pubkey,DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES); | ||||
hash_update(hash,message,message_len); | hash_update(hash,message,message_len); | ||||
@@ -220,7 +216,7 @@ void decaf_ed$(gf_shortname)_sign_prehash ( | |||||
hash_destroy(hash_too); | hash_destroy(hash_too); | ||||
} | } | ||||
decaf_ed$(gf_shortname)_sign(signature,privkey,pubkey,hash_output,sizeof(hash_output),1,context,context_len,0); | |||||
decaf_ed$(gf_shortname)_sign(signature,privkey,pubkey,hash_output,sizeof(hash_output),1,context,context_len); | |||||
decaf_bzero(hash_output,sizeof(hash_output)); | decaf_bzero(hash_output,sizeof(hash_output)); | ||||
} | } | ||||
@@ -231,8 +227,7 @@ decaf_error_t decaf_ed$(gf_shortname)_verify ( | |||||
size_t message_len, | size_t message_len, | ||||
uint8_t prehashed, | uint8_t prehashed, | ||||
const uint8_t *context, | const uint8_t *context, | ||||
uint8_t context_len, | |||||
uint8_t no_context | |||||
uint8_t context_len | |||||
) { | ) { | ||||
API_NS(point_t) pk_point, r_point; | API_NS(point_t) pk_point, r_point; | ||||
decaf_error_t error = API_NS(point_decode_like_eddsa_and_ignore_cofactor)(pk_point,pubkey); | decaf_error_t error = API_NS(point_decode_like_eddsa_and_ignore_cofactor)(pk_point,pubkey); | ||||
@@ -245,7 +240,7 @@ decaf_error_t decaf_ed$(gf_shortname)_verify ( | |||||
{ | { | ||||
/* Compute the challenge */ | /* Compute the challenge */ | ||||
hash_ctx_t hash; | hash_ctx_t hash; | ||||
hash_init_with_dom(hash,prehashed,0,context,context_len,no_context); | |||||
hash_init_with_dom(hash,prehashed,0,context,context_len); | |||||
hash_update(hash,signature,DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES); | hash_update(hash,signature,DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES); | ||||
hash_update(hash,pubkey,DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES); | hash_update(hash,pubkey,DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES); | ||||
hash_update(hash,message,message_len); | hash_update(hash,message,message_len); | ||||
@@ -296,7 +291,7 @@ decaf_error_t decaf_ed$(gf_shortname)_verify_prehash ( | |||||
hash_destroy(hash_too); | hash_destroy(hash_too); | ||||
} | } | ||||
ret = decaf_ed$(gf_shortname)_verify(signature,pubkey,hash_output,sizeof(hash_output),1,context,context_len,0); | |||||
ret = decaf_ed$(gf_shortname)_verify(signature,pubkey,hash_output,sizeof(hash_output),1,context,context_len); | |||||
return ret; | return ret; | ||||
} | } |
@@ -19,7 +19,7 @@ extern "C" { | |||||
/** Does EdDSA support non-contextual signatures? */ | /** Does EdDSA support non-contextual signatures? */ | ||||
#define DECAF_EDDSA_$(gf_shortname)_NO_CONTEXT $(eddsa_no_context) | #define DECAF_EDDSA_$(gf_shortname)_NO_CONTEXT $(eddsa_no_context) | ||||
$("const uint8_t * const ED" + gf_shortname + "_NO_CONTEXT = (const uint8_t * const)(" + gf_shortname + ");\n" if eddsa_no_context else "") | |||||
/** Prehash context renaming macros. */ | /** Prehash context renaming macros. */ | ||||
#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 | ||||
#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 | ||||
@@ -49,7 +49,6 @@ void decaf_ed$(gf_shortname)_derive_public_key ( | |||||
* @param [in] prehashed Nonzero if the message is actually the hash of something you want to sign. | * @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 A "context" for this signature of up to 255 bytes. | ||||
* @param [in] context_len Length of the context. | * @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 | * @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 | * messages, at least without some very careful protocol-level disambiguation. For Ed448 it is | ||||
@@ -64,8 +63,7 @@ void decaf_ed$(gf_shortname)_sign ( | |||||
size_t message_len, | size_t message_len, | ||||
uint8_t prehashed, | uint8_t prehashed, | ||||
const uint8_t *context, | const uint8_t *context, | ||||
uint8_t context_len, | |||||
uint8_t no_context | |||||
uint8_t context_len | |||||
) API_VIS __attribute__((nonnull(1,2,3))) NOINLINE; | ) API_VIS __attribute__((nonnull(1,2,3))) NOINLINE; | ||||
/** | /** | ||||
@@ -113,7 +111,6 @@ void decaf_ed$(gf_shortname)_prehash_init ( | |||||
* @param [in] prehashed Nonzero if the message is actually the hash of something you want to verify. | * @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 A "context" for this signature of up to 255 bytes. | ||||
* @param [in] context_len Length of the context. | * @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 | * @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 | * messages, at least without some very careful protocol-level disambiguation. For Ed448 it is | ||||
@@ -127,8 +124,7 @@ decaf_error_t decaf_ed$(gf_shortname)_verify ( | |||||
size_t message_len, | size_t message_len, | ||||
uint8_t prehashed, | uint8_t prehashed, | ||||
const uint8_t *context, | const uint8_t *context, | ||||
uint8_t context_len, | |||||
uint8_t no_context | |||||
uint8_t context_len | |||||
) API_VIS __attribute__((nonnull(1,2))) NOINLINE; | ) API_VIS __attribute__((nonnull(1,2))) NOINLINE; | ||||
/** | /** | ||||
@@ -125,8 +125,7 @@ public: | |||||
*/ | */ | ||||
inline SecureBuffer sign ( | inline SecureBuffer sign ( | ||||
const Block &message, | const Block &message, | ||||
const Block &context = Block(NULL,0), | |||||
const bool no_context = false | |||||
const Block &context = Block(NULL,0) | |||||
) const /* TODO: this exn spec tickles a Clang bug? | ) const /* TODO: this exn spec tickles a Clang bug? | ||||
* throw(LengthException, std::bad_alloc) | * throw(LengthException, std::bad_alloc) | ||||
*/ { | */ { | ||||
@@ -143,8 +142,7 @@ public: | |||||
message.size(), | message.size(), | ||||
0, | 0, | ||||
context.data(), | context.data(), | ||||
context.size(), | |||||
no_context | |||||
context.size() | |||||
); | ); | ||||
return out; | return out; | ||||
} | } | ||||
@@ -231,8 +229,7 @@ public: | |||||
inline decaf_error_t WARN_UNUSED verify_noexcept ( | inline decaf_error_t WARN_UNUSED verify_noexcept ( | ||||
const FixedBlock<DECAF_EDDSA_$(gf_shortname)_SIGNATURE_BYTES> &sig, | const FixedBlock<DECAF_EDDSA_$(gf_shortname)_SIGNATURE_BYTES> &sig, | ||||
const Block &message, | const Block &message, | ||||
const Block &context = Block(NULL,0), | |||||
const bool no_context = false | |||||
const Block &context = Block(NULL,0) | |||||
) const /*NOEXCEPT*/ { | ) const /*NOEXCEPT*/ { | ||||
if (context.size() > 255) { | if (context.size() > 255) { | ||||
return DECAF_FAILURE; | return DECAF_FAILURE; | ||||
@@ -245,8 +242,7 @@ public: | |||||
message.size(), | message.size(), | ||||
0, | 0, | ||||
context.data(), | context.data(), | ||||
context.size(), | |||||
no_context | |||||
context.size() | |||||
); | ); | ||||
} | } | ||||
@@ -260,14 +256,13 @@ public: | |||||
inline void verify ( | inline void verify ( | ||||
const FixedBlock<DECAF_EDDSA_$(gf_shortname)_SIGNATURE_BYTES> &sig, | const FixedBlock<DECAF_EDDSA_$(gf_shortname)_SIGNATURE_BYTES> &sig, | ||||
const Block &message, | const Block &message, | ||||
const Block &context = Block(NULL,0), | |||||
const bool no_context = false | |||||
const Block &context = Block(NULL,0) | |||||
) const /*throw(LengthException,CryptoException)*/ { | ) const /*throw(LengthException,CryptoException)*/ { | ||||
if (context.size() > 255) { | if (context.size() > 255) { | ||||
throw LengthException(); | throw LengthException(); | ||||
} | } | ||||
if (DECAF_SUCCESS != verify_noexcept( sig, message, context, no_context )) { | |||||
if (DECAF_SUCCESS != verify_noexcept( sig, message, context )) { | |||||
throw CryptoException(); | throw CryptoException(); | ||||
} | } | ||||
} | } | ||||
@@ -469,7 +469,7 @@ static void test_cfrg_crypto() { | |||||
} | } | ||||
} | } | ||||
static const bool eddsa_prehashed[], eddsa_no_context[]; | |||||
static const bool eddsa_prehashed[]; | |||||
static const Block eddsa_sk[], eddsa_pk[], eddsa_message[], eddsa_context[], eddsa_sig[]; | static const Block eddsa_sk[], eddsa_pk[], eddsa_message[], eddsa_context[], eddsa_sig[]; | ||||
static void test_cfrg_vectors() { | static void test_cfrg_vectors() { | ||||
@@ -499,7 +499,7 @@ static void test_cfrg_vectors() { | |||||
typename EdDSA<Group>::PrivateKeyPh priv2(eddsa_sk[t]); | typename EdDSA<Group>::PrivateKeyPh priv2(eddsa_sk[t]); | ||||
sig = priv2.sign_with_prehash(eddsa_message[t],eddsa_context[t]); | sig = priv2.sign_with_prehash(eddsa_message[t],eddsa_context[t]); | ||||
} else { | } else { | ||||
sig = priv.sign(eddsa_message[t],eddsa_context[t],eddsa_no_context[t]); | |||||
sig = priv.sign(eddsa_message[t],eddsa_context[t]); | |||||
} | } | ||||
if (!memeq(SecureBuffer(eddsa_sig[t]),sig)) { | if (!memeq(SecureBuffer(eddsa_sig[t]),sig)) { | ||||
@@ -346,15 +346,6 @@ template<> const Block Tests<Ed448Goldilocks>::eddsa_context[] = { | |||||
Block(NULL,0), | Block(NULL,0), | ||||
Block(ed448_eddsa_context[0],3) | Block(ed448_eddsa_context[0],3) | ||||
}; | }; | ||||
template<> const bool Tests<Ed448Goldilocks>::eddsa_no_context[] = { | |||||
false, | |||||
false, | |||||
false, | |||||
false, | |||||
false, | |||||
false, | |||||
false | |||||
}; | |||||
template<> const Block Tests<Ed448Goldilocks>::eddsa_sig[] = { | template<> const Block Tests<Ed448Goldilocks>::eddsa_sig[] = { | ||||
Block(ed448_eddsa_sig[0],114), | Block(ed448_eddsa_sig[0],114), | ||||
Block(ed448_eddsa_sig[1],114), | Block(ed448_eddsa_sig[1],114), | ||||
@@ -516,21 +507,13 @@ template<> const Block Tests<IsoEd25519>::eddsa_pk[] = { | |||||
Block(ed25519_eddsa_pk[4],32) | Block(ed25519_eddsa_pk[4],32) | ||||
}; | }; | ||||
template<> const Block Tests<IsoEd25519>::eddsa_context[] = { | template<> const Block Tests<IsoEd25519>::eddsa_context[] = { | ||||
Block(NULL,0), | |||||
Block(NULL,0), | |||||
Block(NULL,0), | |||||
Block(ED25519_NO_CONTEXT,0), | |||||
Block(ED25519_NO_CONTEXT,0), | |||||
Block(ED25519_NO_CONTEXT,0), | |||||
Block(NULL,0), | Block(NULL,0), | ||||
Block(ed25519_eddsa_context[0],3), | Block(ed25519_eddsa_context[0],3), | ||||
Block(ed25519_eddsa_context[1],3) | Block(ed25519_eddsa_context[1],3) | ||||
}; | }; | ||||
template<> const bool Tests<IsoEd25519>::eddsa_no_context[] = { | |||||
true, | |||||
true, | |||||
true, | |||||
false, | |||||
false, | |||||
false | |||||
}; | |||||
template<> const Block Tests<IsoEd25519>::eddsa_message[] = { | template<> const Block Tests<IsoEd25519>::eddsa_message[] = { | ||||
Block(ed25519_eddsa_message[0],0), | Block(ed25519_eddsa_message[0],0), | ||||
Block(ed25519_eddsa_message[1],1), | Block(ed25519_eddsa_message[1],1), | ||||