@@ -56,6 +56,7 @@ static void clamp ( | |||||
static void hash_init_with_dom( | static void hash_init_with_dom( | ||||
hash_ctx_t hash, | hash_ctx_t hash, | ||||
uint8_t prehashed, | uint8_t prehashed, | ||||
uint8_t for_prehash, | |||||
const uint8_t *context, | const uint8_t *context, | ||||
uint8_t context_len | uint8_t context_len | ||||
) { | ) { | ||||
@@ -63,12 +64,13 @@ static void hash_init_with_dom( | |||||
#if SUPPORTS_CONTEXTS | #if SUPPORTS_CONTEXTS | ||||
const char *dom_s = ""; | const char *dom_s = ""; | ||||
const uint8_t dom[2] = {1+word_is_zero(prehashed), context_len}; | |||||
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,(const unsigned char *)dom_s, strlen(dom_s)); | ||||
hash_update(hash,dom,2); | hash_update(hash,dom,2); | ||||
hash_update(hash,context,context_len); | hash_update(hash,context,context_len); | ||||
#else | #else | ||||
(void)prehashed; | (void)prehashed; | ||||
(void)for_prehash; | |||||
(void)context; | (void)context; | ||||
assert(context==NULL); | assert(context==NULL); | ||||
(void)context_len; | (void)context_len; | ||||
@@ -76,6 +78,20 @@ static void hash_init_with_dom( | |||||
#endif | #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 | |||||
} | |||||
void decaf_ed25519_derive_public_key ( | void decaf_ed25519_derive_public_key ( | ||||
uint8_t pubkey[DECAF_EDDSA_25519_PUBLIC_BYTES], | uint8_t pubkey[DECAF_EDDSA_25519_PUBLIC_BYTES], | ||||
const uint8_t privkey[DECAF_EDDSA_25519_PRIVATE_BYTES] | const uint8_t privkey[DECAF_EDDSA_25519_PRIVATE_BYTES] | ||||
@@ -149,7 +165,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,context,context_len); | |||||
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)); | ||||
@@ -183,7 +199,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,context,context_len); | |||||
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); | ||||
@@ -207,6 +223,33 @@ void decaf_ed25519_sign ( | |||||
} | } | ||||
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, | |||||
uint8_t context_len | |||||
#endif | |||||
) { | |||||
uint8_t hash_output[64]; /* MAGIC but true for all existing schemes */ | |||||
{ | |||||
decaf_ed25519_prehash_ctx_t hash_too; | |||||
memcpy(hash_too,hash,sizeof(hash_too)); | |||||
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_bzero(hash_output,sizeof(hash_output)); | |||||
} | |||||
decaf_error_t decaf_ed25519_verify ( | decaf_error_t decaf_ed25519_verify ( | ||||
const uint8_t signature[DECAF_EDDSA_25519_SIGNATURE_BYTES], | const uint8_t signature[DECAF_EDDSA_25519_SIGNATURE_BYTES], | ||||
const uint8_t pubkey[DECAF_EDDSA_25519_PUBLIC_BYTES], | const uint8_t pubkey[DECAF_EDDSA_25519_PUBLIC_BYTES], | ||||
@@ -233,7 +276,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,context,context_len); | |||||
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); | ||||
@@ -265,3 +308,32 @@ decaf_error_t decaf_ed25519_verify ( | |||||
); | ); | ||||
return decaf_succeed_if(API_NS(point_eq(pk_point,r_point))); | return decaf_succeed_if(API_NS(point_eq(pk_point,r_point))); | ||||
} | } | ||||
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, | |||||
uint8_t context_len | |||||
#endif | |||||
) { | |||||
decaf_error_t ret; | |||||
uint8_t hash_output[64]; /* MAGIC but true for all existing schemes */ | |||||
{ | |||||
decaf_ed25519_prehash_ctx_t hash_too; | |||||
memcpy(hash_too,hash,sizeof(hash_too)); | |||||
hash_final(hash_too,hash_output,sizeof(hash_output)); | |||||
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 | |||||
return ret; | |||||
} |
@@ -56,6 +56,7 @@ static void clamp ( | |||||
static void hash_init_with_dom( | static void hash_init_with_dom( | ||||
hash_ctx_t hash, | hash_ctx_t hash, | ||||
uint8_t prehashed, | uint8_t prehashed, | ||||
uint8_t for_prehash, | |||||
const uint8_t *context, | const uint8_t *context, | ||||
uint8_t context_len | uint8_t context_len | ||||
) { | ) { | ||||
@@ -63,12 +64,13 @@ static void hash_init_with_dom( | |||||
#if SUPPORTS_CONTEXTS | #if SUPPORTS_CONTEXTS | ||||
const char *dom_s = "SigEd448"; | const char *dom_s = "SigEd448"; | ||||
const uint8_t dom[2] = {1+word_is_zero(prehashed), context_len}; | |||||
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,(const unsigned char *)dom_s, strlen(dom_s)); | ||||
hash_update(hash,dom,2); | hash_update(hash,dom,2); | ||||
hash_update(hash,context,context_len); | hash_update(hash,context,context_len); | ||||
#else | #else | ||||
(void)prehashed; | (void)prehashed; | ||||
(void)for_prehash; | |||||
(void)context; | (void)context; | ||||
assert(context==NULL); | assert(context==NULL); | ||||
(void)context_len; | (void)context_len; | ||||
@@ -76,6 +78,20 @@ static void hash_init_with_dom( | |||||
#endif | #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 | |||||
} | |||||
void decaf_ed448_derive_public_key ( | void decaf_ed448_derive_public_key ( | ||||
uint8_t pubkey[DECAF_EDDSA_448_PUBLIC_BYTES], | uint8_t pubkey[DECAF_EDDSA_448_PUBLIC_BYTES], | ||||
const uint8_t privkey[DECAF_EDDSA_448_PRIVATE_BYTES] | const uint8_t privkey[DECAF_EDDSA_448_PRIVATE_BYTES] | ||||
@@ -149,7 +165,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,context,context_len); | |||||
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)); | ||||
@@ -183,7 +199,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,context,context_len); | |||||
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); | ||||
@@ -207,6 +223,33 @@ void decaf_ed448_sign ( | |||||
} | } | ||||
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, | |||||
uint8_t context_len | |||||
#endif | |||||
) { | |||||
uint8_t hash_output[64]; /* MAGIC but true for all existing schemes */ | |||||
{ | |||||
decaf_ed448_prehash_ctx_t hash_too; | |||||
memcpy(hash_too,hash,sizeof(hash_too)); | |||||
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_bzero(hash_output,sizeof(hash_output)); | |||||
} | |||||
decaf_error_t decaf_ed448_verify ( | decaf_error_t decaf_ed448_verify ( | ||||
const uint8_t signature[DECAF_EDDSA_448_SIGNATURE_BYTES], | const uint8_t signature[DECAF_EDDSA_448_SIGNATURE_BYTES], | ||||
const uint8_t pubkey[DECAF_EDDSA_448_PUBLIC_BYTES], | const uint8_t pubkey[DECAF_EDDSA_448_PUBLIC_BYTES], | ||||
@@ -233,7 +276,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,context,context_len); | |||||
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); | ||||
@@ -265,3 +308,32 @@ decaf_error_t decaf_ed448_verify ( | |||||
); | ); | ||||
return decaf_succeed_if(API_NS(point_eq(pk_point,r_point))); | return decaf_succeed_if(API_NS(point_eq(pk_point,r_point))); | ||||
} | } | ||||
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, | |||||
uint8_t context_len | |||||
#endif | |||||
) { | |||||
decaf_error_t ret; | |||||
uint8_t hash_output[64]; /* MAGIC but true for all existing schemes */ | |||||
{ | |||||
decaf_ed448_prehash_ctx_t hash_too; | |||||
memcpy(hash_too,hash,sizeof(hash_too)); | |||||
hash_final(hash_too,hash_output,sizeof(hash_output)); | |||||
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 | |||||
return ret; | |||||
} |
@@ -16,6 +16,8 @@ | |||||
#define __DECAF_ED255_H__ 1 | #define __DECAF_ED255_H__ 1 | ||||
#include <decaf/decaf_255.h> | #include <decaf/decaf_255.h> | ||||
#include <decaf/shake.h> | |||||
#include <decaf/sha512.h> | |||||
#ifdef __cplusplus | #ifdef __cplusplus | ||||
extern "C" { | extern "C" { | ||||
@@ -32,6 +34,12 @@ extern "C" { | |||||
/** Does EdDSA support contexts? */ | /** Does EdDSA support contexts? */ | ||||
#define DECAF_EDDSA_25519_SUPPORTS_CONTEXTS 0 | #define DECAF_EDDSA_25519_SUPPORTS_CONTEXTS 0 | ||||
/** Prehash context renaming macros. */ | |||||
#define decaf_ed25519_prehash_ctx_s decaf_sha512_ctx_s | |||||
#define decaf_ed25519_prehash_ctx_t decaf_sha512_ctx_t | |||||
#define decaf_ed25519_prehash_update decaf_sha512_update | |||||
#define decaf_ed25519_prehash_destroy decaf_sha512_destroy | |||||
/** | /** | ||||
* @brief EdDSA key generation. This function uses a different (non-Decaf) | * @brief EdDSA key generation. This function uses a different (non-Decaf) | ||||
@@ -75,6 +83,48 @@ void decaf_ed25519_sign ( | |||||
#endif | #endif | ||||
) API_VIS __attribute__((nonnull(1,2,3))) NOINLINE; | ) API_VIS __attribute__((nonnull(1,2,3))) NOINLINE; | ||||
/** | |||||
* @brief EdDSA signing with prehash. | |||||
* | |||||
* @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. 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 | |||||
* safe. The C++ wrapper is designed to make it harder to screw this up, but this C code gives | |||||
* you no seat belt. | |||||
*/ | |||||
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, | |||||
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; | |||||
/** | /** | ||||
* @brief EdDSA signature verification. | * @brief EdDSA signature verification. | ||||
* | * | ||||
@@ -105,7 +155,32 @@ decaf_error_t decaf_ed25519_verify ( | |||||
#endif | #endif | ||||
) API_VIS __attribute__((nonnull(1,2))) NOINLINE; | ) API_VIS __attribute__((nonnull(1,2))) NOINLINE; | ||||
/** | |||||
* @brief EdDSA signature verification. | |||||
* | |||||
* Uses the standard (i.e. less-strict) verification formula. | |||||
* | |||||
* @param [in] signature The signature. | |||||
* @param [in] pubkey The public key. | |||||
* @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 | |||||
* safe. The C++ wrapper is designed to make it harder to screw this up, but this C code gives | |||||
* you no seat belt. | |||||
*/ | |||||
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, | |||||
uint8_t context_len | |||||
#endif | |||||
) API_VIS __attribute__((nonnull(1,2))) NOINLINE; | |||||
/** | /** | ||||
* @brief EdDSA point encoding. Used internally, exposed externally. | * @brief EdDSA point encoding. Used internally, exposed externally. | ||||
@@ -79,14 +79,12 @@ private: | |||||
) { | ) { | ||||
throw LengthException(); | throw LengthException(); | ||||
} | } | ||||
if (SUPPORTS_CONTEXTS) { | |||||
const char pfx[] = ""; | |||||
uint8_t dom[2] = {2, (uint8_t)context_.size() }; | |||||
update((const unsigned char*)pfx,strlen(pfx)); | |||||
update(dom,2); | |||||
update(context_); | |||||
} | |||||
#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 | |||||
} | } | ||||
public: | public: | ||||
@@ -122,17 +120,13 @@ template<class CRTP, Prehashed ph> class Signing; | |||||
template<class CRTP> class Signing<CRTP,PREHASHED> { | template<class CRTP> class Signing<CRTP,PREHASHED> { | ||||
public: | public: | ||||
/* Sign a prehash context, and reset the context */ | /* Sign a prehash context, and reset the context */ | ||||
inline SecureBuffer sign_prehashed ( Prehash &ph ) const /*throw(std::bad_alloc)*/ { | |||||
inline SecureBuffer sign_prehashed ( const Prehash &ph ) const /*throw(std::bad_alloc)*/ { | |||||
SecureBuffer out(CRTP::SIG_BYTES); | SecureBuffer out(CRTP::SIG_BYTES); | ||||
FixedArrayBuffer<Prehash::OUTPUT_BYTES> tmp; | |||||
ph.final(tmp); | |||||
decaf_ed25519_sign ( | |||||
decaf_ed25519_sign_prehash ( | |||||
out.data(), | out.data(), | ||||
((const CRTP*)this)->priv_.data(), | ((const CRTP*)this)->priv_.data(), | ||||
((const CRTP*)this)->pub_.data(), | ((const CRTP*)this)->pub_.data(), | ||||
tmp.data(), | |||||
tmp.size(), | |||||
1 | |||||
(const decaf_ed25519_prehash_ctx_s*)ph.wrapped | |||||
#if DECAF_EDDSA_25519_SUPPORTS_CONTEXTS | #if DECAF_EDDSA_25519_SUPPORTS_CONTEXTS | ||||
, ph.context_.data(), | , ph.context_.data(), | ||||
ph.context_.size() | ph.context_.size() | ||||
@@ -324,19 +318,15 @@ public: | |||||
template<class CRTP> class Verification<CRTP,PREHASHED> { | template<class CRTP> class Verification<CRTP,PREHASHED> { | ||||
public: | public: | ||||
/* Verify a prehash context, and reset the context */ | |||||
/* Verify a prehash context. */ | |||||
inline decaf_error_t WARN_UNUSED verify_prehashed_noexcept ( | inline decaf_error_t WARN_UNUSED verify_prehashed_noexcept ( | ||||
const FixedBlock<DECAF_EDDSA_25519_SIGNATURE_BYTES> &sig, | const FixedBlock<DECAF_EDDSA_25519_SIGNATURE_BYTES> &sig, | ||||
Prehash &ph | |||||
const Prehash &ph | |||||
) const /*NOEXCEPT*/ { | ) const /*NOEXCEPT*/ { | ||||
FixedArrayBuffer<Prehash::OUTPUT_BYTES> m; | |||||
ph.final(m); | |||||
return decaf_ed25519_verify ( | |||||
return decaf_ed25519_verify_prehash ( | |||||
sig.data(), | sig.data(), | ||||
((const CRTP*)this)->pub_.data(), | ((const CRTP*)this)->pub_.data(), | ||||
m.data(), | |||||
m.size(), | |||||
1 | |||||
(const decaf_ed25519_prehash_ctx_s*)ph.wrapped | |||||
#if DECAF_EDDSA_25519_SUPPORTS_CONTEXTS | #if DECAF_EDDSA_25519_SUPPORTS_CONTEXTS | ||||
, ph.context_.data(), | , ph.context_.data(), | ||||
ph.context_.size() | ph.context_.size() | ||||
@@ -344,19 +334,15 @@ public: | |||||
); | ); | ||||
} | } | ||||
/* Verify a prehash context, and reset the context */ | |||||
/* Verify a prehash 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, | ||||
Prehash &ph | |||||
const Prehash &ph | |||||
) const /*throw(CryptoException)*/ { | ) const /*throw(CryptoException)*/ { | ||||
FixedArrayBuffer<Prehash::OUTPUT_BYTES> m; | |||||
ph.final(m); | |||||
if (DECAF_SUCCESS != decaf_ed25519_verify ( | |||||
if (DECAF_SUCCESS != decaf_ed25519_verify_prehash ( | |||||
sig.data(), | sig.data(), | ||||
((const CRTP*)this)->pub_.data(), | ((const CRTP*)this)->pub_.data(), | ||||
m.data(), | |||||
m.size(), | |||||
1 | |||||
(const decaf_ed25519_prehash_ctx_s*)ph.wrapped | |||||
#if DECAF_EDDSA_25519_SUPPORTS_CONTEXTS | #if DECAF_EDDSA_25519_SUPPORTS_CONTEXTS | ||||
, ph.context_.data(), | , ph.context_.data(), | ||||
ph.context_.size() | ph.context_.size() | ||||
@@ -16,6 +16,8 @@ | |||||
#define __DECAF_ED448_H__ 1 | #define __DECAF_ED448_H__ 1 | ||||
#include <decaf/decaf_448.h> | #include <decaf/decaf_448.h> | ||||
#include <decaf/shake.h> | |||||
#include <decaf/sha512.h> | |||||
#ifdef __cplusplus | #ifdef __cplusplus | ||||
extern "C" { | extern "C" { | ||||
@@ -32,6 +34,12 @@ extern "C" { | |||||
/** Does EdDSA support contexts? */ | /** Does EdDSA support contexts? */ | ||||
#define DECAF_EDDSA_448_SUPPORTS_CONTEXTS 1 | #define DECAF_EDDSA_448_SUPPORTS_CONTEXTS 1 | ||||
/** Prehash context renaming macros. */ | |||||
#define decaf_ed448_prehash_ctx_s decaf_shake256_ctx_s | |||||
#define decaf_ed448_prehash_ctx_t decaf_shake256_ctx_t | |||||
#define decaf_ed448_prehash_update decaf_shake256_update | |||||
#define decaf_ed448_prehash_destroy decaf_shake256_destroy | |||||
/** | /** | ||||
* @brief EdDSA key generation. This function uses a different (non-Decaf) | * @brief EdDSA key generation. This function uses a different (non-Decaf) | ||||
@@ -75,6 +83,48 @@ void decaf_ed448_sign ( | |||||
#endif | #endif | ||||
) API_VIS __attribute__((nonnull(1,2,3))) NOINLINE; | ) API_VIS __attribute__((nonnull(1,2,3))) NOINLINE; | ||||
/** | |||||
* @brief EdDSA signing with prehash. | |||||
* | |||||
* @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. 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 | |||||
* safe. The C++ wrapper is designed to make it harder to screw this up, but this C code gives | |||||
* you no seat belt. | |||||
*/ | |||||
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, | |||||
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_ed448_prehash_init ( | |||||
decaf_ed448_prehash_ctx_t hash | |||||
#if DECAF_EDDSA_448_SUPPORTS_CONTEXTS | |||||
, const uint8_t *context, | |||||
uint8_t context_len | |||||
#endif | |||||
) API_VIS __attribute__((nonnull(1))) NOINLINE; | |||||
/** | /** | ||||
* @brief EdDSA signature verification. | * @brief EdDSA signature verification. | ||||
* | * | ||||
@@ -105,7 +155,32 @@ decaf_error_t decaf_ed448_verify ( | |||||
#endif | #endif | ||||
) API_VIS __attribute__((nonnull(1,2))) NOINLINE; | ) API_VIS __attribute__((nonnull(1,2))) NOINLINE; | ||||
/** | |||||
* @brief EdDSA signature verification. | |||||
* | |||||
* Uses the standard (i.e. less-strict) verification formula. | |||||
* | |||||
* @param [in] signature The signature. | |||||
* @param [in] pubkey The public key. | |||||
* @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 | |||||
* safe. The C++ wrapper is designed to make it harder to screw this up, but this C code gives | |||||
* you no seat belt. | |||||
*/ | |||||
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, | |||||
uint8_t context_len | |||||
#endif | |||||
) API_VIS __attribute__((nonnull(1,2))) NOINLINE; | |||||
/** | /** | ||||
* @brief EdDSA point encoding. Used internally, exposed externally. | * @brief EdDSA point encoding. Used internally, exposed externally. | ||||
@@ -77,14 +77,12 @@ private: | |||||
) { | ) { | ||||
throw LengthException(); | throw LengthException(); | ||||
} | } | ||||
if (SUPPORTS_CONTEXTS) { | |||||
const char pfx[] = "SigEd448"; | |||||
uint8_t dom[2] = {2, (uint8_t)context_.size() }; | |||||
update((const unsigned char*)pfx,strlen(pfx)); | |||||
update(dom,2); | |||||
update(context_); | |||||
} | |||||
#if DECAF_EDDSA_448_SUPPORTS_CONTEXTS | |||||
decaf_ed448_prehash_init((decaf_shake256_ctx_s *)wrapped,context_.data(),context_.size()); | |||||
#else | |||||
decaf_ed448_prehash_init(wrapped); | |||||
#endif | |||||
} | } | ||||
public: | public: | ||||
@@ -120,17 +118,13 @@ template<class CRTP, Prehashed ph> class Signing; | |||||
template<class CRTP> class Signing<CRTP,PREHASHED> { | template<class CRTP> class Signing<CRTP,PREHASHED> { | ||||
public: | public: | ||||
/* Sign a prehash context, and reset the context */ | /* Sign a prehash context, and reset the context */ | ||||
inline SecureBuffer sign_prehashed ( Prehash &ph ) const /*throw(std::bad_alloc)*/ { | |||||
inline SecureBuffer sign_prehashed ( const Prehash &ph ) const /*throw(std::bad_alloc)*/ { | |||||
SecureBuffer out(CRTP::SIG_BYTES); | SecureBuffer out(CRTP::SIG_BYTES); | ||||
FixedArrayBuffer<Prehash::OUTPUT_BYTES> tmp; | |||||
ph.final(tmp); | |||||
decaf_ed448_sign ( | |||||
decaf_ed448_sign_prehash ( | |||||
out.data(), | out.data(), | ||||
((const CRTP*)this)->priv_.data(), | ((const CRTP*)this)->priv_.data(), | ||||
((const CRTP*)this)->pub_.data(), | ((const CRTP*)this)->pub_.data(), | ||||
tmp.data(), | |||||
tmp.size(), | |||||
1 | |||||
(const decaf_ed448_prehash_ctx_s*)ph.wrapped | |||||
#if DECAF_EDDSA_448_SUPPORTS_CONTEXTS | #if DECAF_EDDSA_448_SUPPORTS_CONTEXTS | ||||
, ph.context_.data(), | , ph.context_.data(), | ||||
ph.context_.size() | ph.context_.size() | ||||
@@ -324,19 +318,15 @@ public: | |||||
template<class CRTP> class Verification<CRTP,PREHASHED> { | template<class CRTP> class Verification<CRTP,PREHASHED> { | ||||
public: | public: | ||||
/* Verify a prehash context, and reset the context */ | |||||
/* Verify a prehash context. */ | |||||
inline decaf_error_t WARN_UNUSED verify_prehashed_noexcept ( | inline decaf_error_t WARN_UNUSED verify_prehashed_noexcept ( | ||||
const FixedBlock<DECAF_EDDSA_448_SIGNATURE_BYTES> &sig, | const FixedBlock<DECAF_EDDSA_448_SIGNATURE_BYTES> &sig, | ||||
Prehash &ph | |||||
const Prehash &ph | |||||
) const /*NOEXCEPT*/ { | ) const /*NOEXCEPT*/ { | ||||
FixedArrayBuffer<Prehash::OUTPUT_BYTES> m; | |||||
ph.final(m); | |||||
return decaf_ed448_verify ( | |||||
return decaf_ed448_verify_prehash ( | |||||
sig.data(), | sig.data(), | ||||
((const CRTP*)this)->pub_.data(), | ((const CRTP*)this)->pub_.data(), | ||||
m.data(), | |||||
m.size(), | |||||
1 | |||||
(const decaf_ed448_prehash_ctx_s*)ph.wrapped | |||||
#if DECAF_EDDSA_448_SUPPORTS_CONTEXTS | #if DECAF_EDDSA_448_SUPPORTS_CONTEXTS | ||||
, ph.context_.data(), | , ph.context_.data(), | ||||
ph.context_.size() | ph.context_.size() | ||||
@@ -344,19 +334,15 @@ public: | |||||
); | ); | ||||
} | } | ||||
/* Verify a prehash context, and reset the context */ | |||||
/* Verify a prehash 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, | ||||
Prehash &ph | |||||
const Prehash &ph | |||||
) const /*throw(CryptoException)*/ { | ) const /*throw(CryptoException)*/ { | ||||
FixedArrayBuffer<Prehash::OUTPUT_BYTES> m; | |||||
ph.final(m); | |||||
if (DECAF_SUCCESS != decaf_ed448_verify ( | |||||
if (DECAF_SUCCESS != decaf_ed448_verify_prehash ( | |||||
sig.data(), | sig.data(), | ||||
((const CRTP*)this)->pub_.data(), | ((const CRTP*)this)->pub_.data(), | ||||
m.data(), | |||||
m.size(), | |||||
1 | |||||
(const decaf_ed448_prehash_ctx_s*)ph.wrapped | |||||
#if DECAF_EDDSA_448_SUPPORTS_CONTEXTS | #if DECAF_EDDSA_448_SUPPORTS_CONTEXTS | ||||
, ph.context_.data(), | , ph.context_.data(), | ||||
ph.context_.size() | ph.context_.size() | ||||
@@ -30,7 +30,7 @@ class SHA512 { | |||||
protected: | protected: | ||||
/** @cond internal */ | /** @cond internal */ | ||||
/** The C-wrapper sponge state */ | /** The C-wrapper sponge state */ | ||||
decaf_sha512_ctx_t sha; | |||||
decaf_sha512_ctx_t wrapped; | |||||
public: | public: | ||||
@@ -44,10 +44,10 @@ public: | |||||
static const size_t DEFAULT_OUTPUT_BYTES = OUTPUT_BYTES; | static const size_t DEFAULT_OUTPUT_BYTES = OUTPUT_BYTES; | ||||
/** Constructor */ | /** Constructor */ | ||||
inline SHA512() NOEXCEPT { decaf_sha512_init(sha); } | |||||
inline SHA512() NOEXCEPT { decaf_sha512_init(wrapped); } | |||||
/** Add more data to running hash */ | /** Add more data to running hash */ | ||||
inline void update(const uint8_t *__restrict__ in, size_t len) NOEXCEPT { decaf_sha512_update(sha,in,len); } | |||||
inline void update(const uint8_t *__restrict__ in, size_t len) NOEXCEPT { decaf_sha512_update(wrapped,in,len); } | |||||
/** Add more data to running hash, C++ version. */ | /** Add more data to running hash, C++ version. */ | ||||
inline void update(const Block &s) NOEXCEPT { update(s.data(),s.size()); } | inline void update(const Block &s) NOEXCEPT { update(s.data(),s.size()); } | ||||
@@ -61,17 +61,17 @@ public: | |||||
/** @brief Output bytes from the SHA context, and resets it. */ | /** @brief Output bytes from the SHA context, and resets it. */ | ||||
inline void final(Buffer b) throw(LengthException) { | inline void final(Buffer b) throw(LengthException) { | ||||
if (b.size() > OUTPUT_BYTES) throw LengthException(); | if (b.size() > OUTPUT_BYTES) throw LengthException(); | ||||
decaf_sha512_final(sha,b.data(),b.size()); | |||||
decaf_sha512_final(wrapped,b.data(),b.size()); | |||||
} | } | ||||
/** Resets the SHA context */ | /** Resets the SHA context */ | ||||
inline void reset() NOEXCEPT { decaf_sha512_init(sha); } | |||||
inline void reset() NOEXCEPT { decaf_sha512_init(wrapped); } | |||||
/** @brief Output bytes from the sponge. */ | /** @brief Output bytes from the sponge. */ | ||||
inline SecureBuffer final(size_t len = OUTPUT_BYTES) throw(LengthException) { | inline SecureBuffer final(size_t len = OUTPUT_BYTES) throw(LengthException) { | ||||
if (len > OUTPUT_BYTES) throw LengthException(); | if (len > OUTPUT_BYTES) throw LengthException(); | ||||
SecureBuffer buffer(len); | SecureBuffer buffer(len); | ||||
decaf_sha512_final(sha,buffer.data(),len); | |||||
decaf_sha512_final(wrapped,buffer.data(),len); | |||||
return buffer; | return buffer; | ||||
} | } | ||||
@@ -93,7 +93,7 @@ public: | |||||
} | } | ||||
/** Destructor zeroizes state */ | /** Destructor zeroizes state */ | ||||
inline ~SHA512() NOEXCEPT { decaf_sha512_destroy(sha); } | |||||
inline ~SHA512() NOEXCEPT { decaf_sha512_destroy(wrapped); } | |||||
}; | }; | ||||
} /* namespace decaf */ | } /* namespace decaf */ | ||||
@@ -35,18 +35,18 @@ class KeccakHash { | |||||
protected: | protected: | ||||
/** @cond internal */ | /** @cond internal */ | ||||
/** The C-wrapper sponge state */ | /** The C-wrapper sponge state */ | ||||
decaf_keccak_sponge_t sp; | |||||
decaf_keccak_sponge_t wrapped; | |||||
/** Initialize from parameters */ | /** Initialize from parameters */ | ||||
inline KeccakHash(const decaf_kparams_s *params) NOEXCEPT { decaf_sponge_init(sp, params); } | |||||
inline KeccakHash(const decaf_kparams_s *params) NOEXCEPT { decaf_sponge_init(wrapped, params); } | |||||
/** @endcond */ | /** @endcond */ | ||||
public: | public: | ||||
/** Add more data to running hash */ | /** Add more data to running hash */ | ||||
inline void update(const uint8_t *__restrict__ in, size_t len) NOEXCEPT { decaf_sha3_update(sp,in,len); } | |||||
inline void update(const uint8_t *__restrict__ in, size_t len) NOEXCEPT { decaf_sha3_update(wrapped,in,len); } | |||||
/** Add more data to running hash, C++ version. */ | /** Add more data to running hash, C++ version. */ | ||||
inline void update(const Block &s) NOEXCEPT { decaf_sha3_update(sp,s.data(),s.size()); } | |||||
inline void update(const Block &s) NOEXCEPT { decaf_sha3_update(wrapped,s.data(),s.size()); } | |||||
/** Add more data, stream version. */ | /** Add more data, stream version. */ | ||||
inline KeccakHash &operator<<(const Block &s) NOEXCEPT { update(s); return *this; } | inline KeccakHash &operator<<(const Block &s) NOEXCEPT { update(s); return *this; } | ||||
@@ -58,7 +58,7 @@ public: | |||||
inline SecureBuffer output(size_t len) throw(std::bad_alloc, LengthException) { | inline SecureBuffer output(size_t len) throw(std::bad_alloc, LengthException) { | ||||
if (len > max_output_size()) throw LengthException(); | if (len > max_output_size()) throw LengthException(); | ||||
SecureBuffer buffer(len); | SecureBuffer buffer(len); | ||||
if (DECAF_SUCCESS != decaf_sha3_output(sp,buffer.data(),len)) { | |||||
if (DECAF_SUCCESS != decaf_sha3_output(wrapped,buffer.data(),len)) { | |||||
throw LengthException(); | throw LengthException(); | ||||
} | } | ||||
return buffer; | return buffer; | ||||
@@ -68,7 +68,7 @@ public: | |||||
inline SecureBuffer final(size_t len) throw(std::bad_alloc, LengthException) { | inline SecureBuffer final(size_t len) throw(std::bad_alloc, LengthException) { | ||||
if (len > max_output_size()) throw LengthException(); | if (len > max_output_size()) throw LengthException(); | ||||
SecureBuffer buffer(len); | SecureBuffer buffer(len); | ||||
if (DECAF_SUCCESS != decaf_sha3_final(sp,buffer.data(),len)) { | |||||
if (DECAF_SUCCESS != decaf_sha3_final(wrapped,buffer.data(),len)) { | |||||
throw LengthException(); | throw LengthException(); | ||||
} | } | ||||
return buffer; | return buffer; | ||||
@@ -78,7 +78,7 @@ public: | |||||
* output too many bytes from a SHA-3 instance. | * output too many bytes from a SHA-3 instance. | ||||
*/ | */ | ||||
inline void output(Buffer b) throw(LengthException) { | inline void output(Buffer b) throw(LengthException) { | ||||
if (DECAF_SUCCESS != decaf_sha3_output(sp,b.data(),b.size())) { | |||||
if (DECAF_SUCCESS != decaf_sha3_output(wrapped,b.data(),b.size())) { | |||||
throw LengthException(); | throw LengthException(); | ||||
} | } | ||||
} | } | ||||
@@ -87,19 +87,19 @@ public: | |||||
* LengthException if you've output too many bytes from a SHA3 instance. | * LengthException if you've output too many bytes from a SHA3 instance. | ||||
*/ | */ | ||||
inline void final(Buffer b) throw(LengthException) { | inline void final(Buffer b) throw(LengthException) { | ||||
if (DECAF_SUCCESS != decaf_sha3_final(sp,b.data(),b.size())) { | |||||
if (DECAF_SUCCESS != decaf_sha3_final(wrapped,b.data(),b.size())) { | |||||
throw LengthException(); | throw LengthException(); | ||||
} | } | ||||
} | } | ||||
/** @brief Return the sponge's default output size. */ | /** @brief Return the sponge's default output size. */ | ||||
inline size_t default_output_size() const NOEXCEPT { | inline size_t default_output_size() const NOEXCEPT { | ||||
return decaf_sponge_default_output_bytes(sp); | |||||
return decaf_sponge_default_output_bytes(wrapped); | |||||
} | } | ||||
/** @brief Return the sponge's maximum output size. */ | /** @brief Return the sponge's maximum output size. */ | ||||
inline size_t max_output_size() const NOEXCEPT { | inline size_t max_output_size() const NOEXCEPT { | ||||
return decaf_sponge_max_output_bytes(sp); | |||||
return decaf_sponge_max_output_bytes(wrapped); | |||||
} | } | ||||
/** Output the default number of bytes. */ | /** Output the default number of bytes. */ | ||||
@@ -113,10 +113,10 @@ public: | |||||
} | } | ||||
/** Reset the hash to the empty string */ | /** Reset the hash to the empty string */ | ||||
inline void reset() NOEXCEPT { decaf_sha3_reset(sp); } | |||||
inline void reset() NOEXCEPT { decaf_sha3_reset(wrapped); } | |||||
/** Destructor zeroizes state */ | /** Destructor zeroizes state */ | ||||
inline ~KeccakHash() NOEXCEPT { decaf_sponge_destroy(sp); } | |||||
inline ~KeccakHash() NOEXCEPT { decaf_sponge_destroy(wrapped); } | |||||
}; | }; | ||||
/** Fixed-output-length SHA3 */ | /** Fixed-output-length SHA3 */ | ||||
@@ -47,6 +47,7 @@ static void clamp ( | |||||
static void hash_init_with_dom( | static void hash_init_with_dom( | ||||
hash_ctx_t hash, | hash_ctx_t hash, | ||||
uint8_t prehashed, | uint8_t prehashed, | ||||
uint8_t for_prehash, | |||||
const uint8_t *context, | const uint8_t *context, | ||||
uint8_t context_len | uint8_t context_len | ||||
) { | ) { | ||||
@@ -54,12 +55,13 @@ static void hash_init_with_dom( | |||||
#if SUPPORTS_CONTEXTS | #if SUPPORTS_CONTEXTS | ||||
const char *dom_s = "$(eddsa_dom)"; | const char *dom_s = "$(eddsa_dom)"; | ||||
const uint8_t dom[2] = {1+word_is_zero(prehashed), context_len}; | |||||
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,(const unsigned char *)dom_s, strlen(dom_s)); | ||||
hash_update(hash,dom,2); | hash_update(hash,dom,2); | ||||
hash_update(hash,context,context_len); | hash_update(hash,context,context_len); | ||||
#else | #else | ||||
(void)prehashed; | (void)prehashed; | ||||
(void)for_prehash; | |||||
(void)context; | (void)context; | ||||
assert(context==NULL); | assert(context==NULL); | ||||
(void)context_len; | (void)context_len; | ||||
@@ -67,6 +69,20 @@ static void hash_init_with_dom( | |||||
#endif | #endif | ||||
} | } | ||||
void decaf_ed$(gf_shortname)_prehash_init ( | |||||
hash_ctx_t hash | |||||
#if DECAF_EDDSA_$(gf_shortname)_SUPPORTS_CONTEXTS | |||||
, const uint8_t *context, | |||||
uint8_t context_len | |||||
#endif | |||||
) { | |||||
#if DECAF_EDDSA_$(gf_shortname)_SUPPORTS_CONTEXTS | |||||
hash_init_with_dom(hash,1,1,context,context_len); | |||||
#else | |||||
hash_init_with_dom(hash,1,1,NULL,0); | |||||
#endif | |||||
} | |||||
void decaf_ed$(gf_shortname)_derive_public_key ( | void decaf_ed$(gf_shortname)_derive_public_key ( | ||||
uint8_t pubkey[DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES], | uint8_t pubkey[DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES], | ||||
const uint8_t privkey[DECAF_EDDSA_$(gf_shortname)_PRIVATE_BYTES] | const uint8_t privkey[DECAF_EDDSA_$(gf_shortname)_PRIVATE_BYTES] | ||||
@@ -140,7 +156,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,context,context_len); | |||||
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)); | ||||
@@ -174,7 +190,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,context,context_len); | |||||
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); | ||||
@@ -198,6 +214,33 @@ void decaf_ed$(gf_shortname)_sign ( | |||||
} | } | ||||
void decaf_ed$(gf_shortname)_sign_prehash ( | |||||
uint8_t signature[DECAF_EDDSA_$(gf_shortname)_SIGNATURE_BYTES], | |||||
const uint8_t privkey[DECAF_EDDSA_$(gf_shortname)_PRIVATE_BYTES], | |||||
const uint8_t pubkey[DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES], | |||||
const decaf_ed$(gf_shortname)_prehash_ctx_t hash | |||||
#if DECAF_EDDSA_$(gf_shortname)_SUPPORTS_CONTEXTS | |||||
, const uint8_t *context, | |||||
uint8_t context_len | |||||
#endif | |||||
) { | |||||
uint8_t hash_output[64]; /* MAGIC but true for all existing schemes */ | |||||
{ | |||||
decaf_ed$(gf_shortname)_prehash_ctx_t hash_too; | |||||
memcpy(hash_too,hash,sizeof(hash_too)); | |||||
hash_final(hash_too,hash_output,sizeof(hash_output)); | |||||
hash_destroy(hash_too); | |||||
} | |||||
#if DECAF_EDDSA_$(gf_shortname)_SUPPORTS_CONTEXTS | |||||
decaf_ed$(gf_shortname)_sign(signature,privkey,pubkey,hash_output,sizeof(hash_output),1,context,context_len); | |||||
#else | |||||
decaf_ed$(gf_shortname)_sign(signature,privkey,pubkey,hash_output,sizeof(hash_output),1); | |||||
#endif | |||||
decaf_bzero(hash_output,sizeof(hash_output)); | |||||
} | |||||
decaf_error_t decaf_ed$(gf_shortname)_verify ( | decaf_error_t decaf_ed$(gf_shortname)_verify ( | ||||
const uint8_t signature[DECAF_EDDSA_$(gf_shortname)_SIGNATURE_BYTES], | const uint8_t signature[DECAF_EDDSA_$(gf_shortname)_SIGNATURE_BYTES], | ||||
const uint8_t pubkey[DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES], | const uint8_t pubkey[DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES], | ||||
@@ -224,7 +267,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,context,context_len); | |||||
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); | ||||
@@ -256,3 +299,32 @@ decaf_error_t decaf_ed$(gf_shortname)_verify ( | |||||
); | ); | ||||
return decaf_succeed_if(API_NS(point_eq(pk_point,r_point))); | return decaf_succeed_if(API_NS(point_eq(pk_point,r_point))); | ||||
} | } | ||||
decaf_error_t decaf_ed$(gf_shortname)_verify_prehash ( | |||||
const uint8_t signature[DECAF_EDDSA_$(gf_shortname)_SIGNATURE_BYTES], | |||||
const uint8_t pubkey[DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES], | |||||
const decaf_ed$(gf_shortname)_prehash_ctx_t hash | |||||
#if DECAF_EDDSA_$(gf_shortname)_SUPPORTS_CONTEXTS | |||||
, const uint8_t *context, | |||||
uint8_t context_len | |||||
#endif | |||||
) { | |||||
decaf_error_t ret; | |||||
uint8_t hash_output[64]; /* MAGIC but true for all existing schemes */ | |||||
{ | |||||
decaf_ed$(gf_shortname)_prehash_ctx_t hash_too; | |||||
memcpy(hash_too,hash,sizeof(hash_too)); | |||||
hash_final(hash_too,hash_output,sizeof(hash_output)); | |||||
hash_destroy(hash_too); | |||||
} | |||||
#if DECAF_EDDSA_$(gf_shortname)_SUPPORTS_CONTEXTS | |||||
ret = decaf_ed$(gf_shortname)_verify(signature,pubkey,hash_output,sizeof(hash_output),1,context,context_len); | |||||
#else | |||||
ret = decaf_ed$(gf_shortname)_verify(signature,pubkey,hash_output,sizeof(hash_output),1); | |||||
#endif | |||||
return ret; | |||||
} |
@@ -1,6 +1,8 @@ | |||||
/** @brief A group of prime order p, based on $(iso_to). */ | /** @brief A group of prime order p, based on $(iso_to). */ | ||||
#include <decaf/decaf_$(gf_bits).h> | #include <decaf/decaf_$(gf_bits).h> | ||||
#include <decaf/shake.h> | |||||
#include <decaf/sha512.h> | |||||
#ifdef __cplusplus | #ifdef __cplusplus | ||||
extern "C" { | extern "C" { | ||||
@@ -17,6 +19,12 @@ extern "C" { | |||||
/** Does EdDSA support contexts? */ | /** Does EdDSA support contexts? */ | ||||
#define DECAF_EDDSA_$(gf_shortname)_SUPPORTS_CONTEXTS $(eddsa_supports_contexts) | #define DECAF_EDDSA_$(gf_shortname)_SUPPORTS_CONTEXTS $(eddsa_supports_contexts) | ||||
/** Prehash context renaming macros. */ | |||||
#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_update decaf_$(eddsa_hash)_update | |||||
#define decaf_ed$(gf_shortname)_prehash_destroy decaf_$(eddsa_hash)_destroy | |||||
/** | /** | ||||
* @brief EdDSA key generation. This function uses a different (non-Decaf) | * @brief EdDSA key generation. This function uses a different (non-Decaf) | ||||
@@ -60,6 +68,48 @@ void decaf_ed$(gf_shortname)_sign ( | |||||
#endif | #endif | ||||
) API_VIS __attribute__((nonnull(1,2,3))) NOINLINE; | ) API_VIS __attribute__((nonnull(1,2,3))) NOINLINE; | ||||
/** | |||||
* @brief EdDSA signing with prehash. | |||||
* | |||||
* @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. 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 | |||||
* safe. The C++ wrapper is designed to make it harder to screw this up, but this C code gives | |||||
* you no seat belt. | |||||
*/ | |||||
void decaf_ed$(gf_shortname)_sign_prehash ( | |||||
uint8_t signature[DECAF_EDDSA_$(gf_shortname)_SIGNATURE_BYTES], | |||||
const uint8_t privkey[DECAF_EDDSA_$(gf_shortname)_PRIVATE_BYTES], | |||||
const uint8_t pubkey[DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES], | |||||
const decaf_ed$(gf_shortname)_prehash_ctx_t hash | |||||
#if DECAF_EDDSA_$(gf_shortname)_SUPPORTS_CONTEXTS | |||||
, 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_ed$(gf_shortname)_prehash_init ( | |||||
decaf_ed$(gf_shortname)_prehash_ctx_t hash | |||||
#if DECAF_EDDSA_$(gf_shortname)_SUPPORTS_CONTEXTS | |||||
, const uint8_t *context, | |||||
uint8_t context_len | |||||
#endif | |||||
) API_VIS __attribute__((nonnull(1))) NOINLINE; | |||||
/** | /** | ||||
* @brief EdDSA signature verification. | * @brief EdDSA signature verification. | ||||
* | * | ||||
@@ -90,7 +140,32 @@ decaf_error_t decaf_ed$(gf_shortname)_verify ( | |||||
#endif | #endif | ||||
) API_VIS __attribute__((nonnull(1,2))) NOINLINE; | ) API_VIS __attribute__((nonnull(1,2))) NOINLINE; | ||||
/** | |||||
* @brief EdDSA signature verification. | |||||
* | |||||
* Uses the standard (i.e. less-strict) verification formula. | |||||
* | |||||
* @param [in] signature The signature. | |||||
* @param [in] pubkey The public key. | |||||
* @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 | |||||
* safe. The C++ wrapper is designed to make it harder to screw this up, but this C code gives | |||||
* you no seat belt. | |||||
*/ | |||||
decaf_error_t decaf_ed$(gf_shortname)_verify_prehash ( | |||||
const uint8_t signature[DECAF_EDDSA_$(gf_shortname)_SIGNATURE_BYTES], | |||||
const uint8_t pubkey[DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES], | |||||
const decaf_ed$(gf_shortname)_prehash_ctx_t hash | |||||
#if DECAF_EDDSA_$(gf_shortname)_SUPPORTS_CONTEXTS | |||||
, const uint8_t *context, | |||||
uint8_t context_len | |||||
#endif | |||||
) API_VIS __attribute__((nonnull(1,2))) NOINLINE; | |||||
/** | /** | ||||
* @brief EdDSA point encoding. Used internally, exposed externally. | * @brief EdDSA point encoding. Used internally, exposed externally. | ||||
@@ -68,14 +68,12 @@ private: | |||||
) { | ) { | ||||
throw LengthException(); | throw LengthException(); | ||||
} | } | ||||
if (SUPPORTS_CONTEXTS) { | |||||
const char pfx[] = "$(eddsa_dom)"; | |||||
uint8_t dom[2] = {2, (uint8_t)context_.size() }; | |||||
update((const unsigned char*)pfx,strlen(pfx)); | |||||
update(dom,2); | |||||
update(context_); | |||||
} | |||||
#if DECAF_EDDSA_$(gf_shortname)_SUPPORTS_CONTEXTS | |||||
decaf_ed$(gf_shortname)_prehash_init((decaf_$(eddsa_hash)_ctx_s *)wrapped,context_.data(),context_.size()); | |||||
#else | |||||
decaf_ed$(gf_shortname)_prehash_init(wrapped); | |||||
#endif | |||||
} | } | ||||
public: | public: | ||||
@@ -111,17 +109,13 @@ template<class CRTP, Prehashed ph> class Signing; | |||||
template<class CRTP> class Signing<CRTP,PREHASHED> { | template<class CRTP> class Signing<CRTP,PREHASHED> { | ||||
public: | public: | ||||
/* Sign a prehash context, and reset the context */ | /* Sign a prehash context, and reset the context */ | ||||
inline SecureBuffer sign_prehashed ( Prehash &ph ) const /*throw(std::bad_alloc)*/ { | |||||
inline SecureBuffer sign_prehashed ( const Prehash &ph ) const /*throw(std::bad_alloc)*/ { | |||||
SecureBuffer out(CRTP::SIG_BYTES); | SecureBuffer out(CRTP::SIG_BYTES); | ||||
FixedArrayBuffer<Prehash::OUTPUT_BYTES> tmp; | |||||
ph.final(tmp); | |||||
decaf_ed$(gf_shortname)_sign ( | |||||
decaf_ed$(gf_shortname)_sign_prehash ( | |||||
out.data(), | out.data(), | ||||
((const CRTP*)this)->priv_.data(), | ((const CRTP*)this)->priv_.data(), | ||||
((const CRTP*)this)->pub_.data(), | ((const CRTP*)this)->pub_.data(), | ||||
tmp.data(), | |||||
tmp.size(), | |||||
1 | |||||
(const decaf_ed$(gf_shortname)_prehash_ctx_s*)ph.wrapped | |||||
#if DECAF_EDDSA_$(gf_shortname)_SUPPORTS_CONTEXTS | #if DECAF_EDDSA_$(gf_shortname)_SUPPORTS_CONTEXTS | ||||
, ph.context_.data(), | , ph.context_.data(), | ||||
ph.context_.size() | ph.context_.size() | ||||
@@ -326,19 +320,15 @@ public: | |||||
template<class CRTP> class Verification<CRTP,PREHASHED> { | template<class CRTP> class Verification<CRTP,PREHASHED> { | ||||
public: | public: | ||||
/* Verify a prehash context, and reset the context */ | |||||
/* Verify a prehash context. */ | |||||
inline decaf_error_t WARN_UNUSED verify_prehashed_noexcept ( | inline decaf_error_t WARN_UNUSED verify_prehashed_noexcept ( | ||||
const FixedBlock<DECAF_EDDSA_$(gf_shortname)_SIGNATURE_BYTES> &sig, | const FixedBlock<DECAF_EDDSA_$(gf_shortname)_SIGNATURE_BYTES> &sig, | ||||
Prehash &ph | |||||
const Prehash &ph | |||||
) const /*NOEXCEPT*/ { | ) const /*NOEXCEPT*/ { | ||||
FixedArrayBuffer<Prehash::OUTPUT_BYTES> m; | |||||
ph.final(m); | |||||
return decaf_ed$(gf_shortname)_verify ( | |||||
return decaf_ed$(gf_shortname)_verify_prehash ( | |||||
sig.data(), | sig.data(), | ||||
((const CRTP*)this)->pub_.data(), | ((const CRTP*)this)->pub_.data(), | ||||
m.data(), | |||||
m.size(), | |||||
1 | |||||
(const decaf_ed$(gf_shortname)_prehash_ctx_s*)ph.wrapped | |||||
#if DECAF_EDDSA_$(gf_shortname)_SUPPORTS_CONTEXTS | #if DECAF_EDDSA_$(gf_shortname)_SUPPORTS_CONTEXTS | ||||
, ph.context_.data(), | , ph.context_.data(), | ||||
ph.context_.size() | ph.context_.size() | ||||
@@ -346,19 +336,15 @@ public: | |||||
); | ); | ||||
} | } | ||||
/* Verify a prehash context, and reset the context */ | |||||
/* Verify a prehash 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, | ||||
Prehash &ph | |||||
const Prehash &ph | |||||
) const /*throw(CryptoException)*/ { | ) const /*throw(CryptoException)*/ { | ||||
FixedArrayBuffer<Prehash::OUTPUT_BYTES> m; | |||||
ph.final(m); | |||||
if (DECAF_SUCCESS != decaf_ed$(gf_shortname)_verify ( | |||||
if (DECAF_SUCCESS != decaf_ed$(gf_shortname)_verify_prehash ( | |||||
sig.data(), | sig.data(), | ||||
((const CRTP*)this)->pub_.data(), | ((const CRTP*)this)->pub_.data(), | ||||
m.data(), | |||||
m.size(), | |||||
1 | |||||
(const decaf_ed$(gf_shortname)_prehash_ctx_s*)ph.wrapped | |||||
#if DECAF_EDDSA_$(gf_shortname)_SUPPORTS_CONTEXTS | #if DECAF_EDDSA_$(gf_shortname)_SUPPORTS_CONTEXTS | ||||
, ph.context_.data(), | , ph.context_.data(), | ||||
ph.context_.size() | ph.context_.size() | ||||
@@ -30,7 +30,7 @@ class SHA512 { | |||||
protected: | protected: | ||||
/** @cond internal */ | /** @cond internal */ | ||||
/** The C-wrapper sponge state */ | /** The C-wrapper sponge state */ | ||||
decaf_sha512_ctx_t sha; | |||||
decaf_sha512_ctx_t wrapped; | |||||
public: | public: | ||||
@@ -44,10 +44,10 @@ public: | |||||
static const size_t DEFAULT_OUTPUT_BYTES = OUTPUT_BYTES; | static const size_t DEFAULT_OUTPUT_BYTES = OUTPUT_BYTES; | ||||
/** Constructor */ | /** Constructor */ | ||||
inline SHA512() NOEXCEPT { decaf_sha512_init(sha); } | |||||
inline SHA512() NOEXCEPT { decaf_sha512_init(wrapped); } | |||||
/** Add more data to running hash */ | /** Add more data to running hash */ | ||||
inline void update(const uint8_t *__restrict__ in, size_t len) NOEXCEPT { decaf_sha512_update(sha,in,len); } | |||||
inline void update(const uint8_t *__restrict__ in, size_t len) NOEXCEPT { decaf_sha512_update(wrapped,in,len); } | |||||
/** Add more data to running hash, C++ version. */ | /** Add more data to running hash, C++ version. */ | ||||
inline void update(const Block &s) NOEXCEPT { update(s.data(),s.size()); } | inline void update(const Block &s) NOEXCEPT { update(s.data(),s.size()); } | ||||
@@ -61,17 +61,17 @@ public: | |||||
/** @brief Output bytes from the SHA context, and resets it. */ | /** @brief Output bytes from the SHA context, and resets it. */ | ||||
inline void final(Buffer b) throw(LengthException) { | inline void final(Buffer b) throw(LengthException) { | ||||
if (b.size() > OUTPUT_BYTES) throw LengthException(); | if (b.size() > OUTPUT_BYTES) throw LengthException(); | ||||
decaf_sha512_final(sha,b.data(),b.size()); | |||||
decaf_sha512_final(wrapped,b.data(),b.size()); | |||||
} | } | ||||
/** Resets the SHA context */ | /** Resets the SHA context */ | ||||
inline void reset() NOEXCEPT { decaf_sha512_init(sha); } | |||||
inline void reset() NOEXCEPT { decaf_sha512_init(wrapped); } | |||||
/** @brief Output bytes from the sponge. */ | /** @brief Output bytes from the sponge. */ | ||||
inline SecureBuffer final(size_t len = OUTPUT_BYTES) throw(LengthException) { | inline SecureBuffer final(size_t len = OUTPUT_BYTES) throw(LengthException) { | ||||
if (len > OUTPUT_BYTES) throw LengthException(); | if (len > OUTPUT_BYTES) throw LengthException(); | ||||
SecureBuffer buffer(len); | SecureBuffer buffer(len); | ||||
decaf_sha512_final(sha,buffer.data(),len); | |||||
decaf_sha512_final(wrapped,buffer.data(),len); | |||||
return buffer; | return buffer; | ||||
} | } | ||||
@@ -93,7 +93,7 @@ public: | |||||
} | } | ||||
/** Destructor zeroizes state */ | /** Destructor zeroizes state */ | ||||
inline ~SHA512() NOEXCEPT { decaf_sha512_destroy(sha); } | |||||
inline ~SHA512() NOEXCEPT { decaf_sha512_destroy(wrapped); } | |||||
}; | }; | ||||
} /* namespace decaf */ | } /* namespace decaf */ | ||||
@@ -35,18 +35,18 @@ class KeccakHash { | |||||
protected: | protected: | ||||
/** @cond internal */ | /** @cond internal */ | ||||
/** The C-wrapper sponge state */ | /** The C-wrapper sponge state */ | ||||
decaf_keccak_sponge_t sp; | |||||
decaf_keccak_sponge_t wrapped; | |||||
/** Initialize from parameters */ | /** Initialize from parameters */ | ||||
inline KeccakHash(const decaf_kparams_s *params) NOEXCEPT { decaf_sponge_init(sp, params); } | |||||
inline KeccakHash(const decaf_kparams_s *params) NOEXCEPT { decaf_sponge_init(wrapped, params); } | |||||
/** @endcond */ | /** @endcond */ | ||||
public: | public: | ||||
/** Add more data to running hash */ | /** Add more data to running hash */ | ||||
inline void update(const uint8_t *__restrict__ in, size_t len) NOEXCEPT { decaf_sha3_update(sp,in,len); } | |||||
inline void update(const uint8_t *__restrict__ in, size_t len) NOEXCEPT { decaf_sha3_update(wrapped,in,len); } | |||||
/** Add more data to running hash, C++ version. */ | /** Add more data to running hash, C++ version. */ | ||||
inline void update(const Block &s) NOEXCEPT { decaf_sha3_update(sp,s.data(),s.size()); } | |||||
inline void update(const Block &s) NOEXCEPT { decaf_sha3_update(wrapped,s.data(),s.size()); } | |||||
/** Add more data, stream version. */ | /** Add more data, stream version. */ | ||||
inline KeccakHash &operator<<(const Block &s) NOEXCEPT { update(s); return *this; } | inline KeccakHash &operator<<(const Block &s) NOEXCEPT { update(s); return *this; } | ||||
@@ -58,7 +58,7 @@ public: | |||||
inline SecureBuffer output(size_t len) throw(std::bad_alloc, LengthException) { | inline SecureBuffer output(size_t len) throw(std::bad_alloc, LengthException) { | ||||
if (len > max_output_size()) throw LengthException(); | if (len > max_output_size()) throw LengthException(); | ||||
SecureBuffer buffer(len); | SecureBuffer buffer(len); | ||||
if (DECAF_SUCCESS != decaf_sha3_output(sp,buffer.data(),len)) { | |||||
if (DECAF_SUCCESS != decaf_sha3_output(wrapped,buffer.data(),len)) { | |||||
throw LengthException(); | throw LengthException(); | ||||
} | } | ||||
return buffer; | return buffer; | ||||
@@ -68,7 +68,7 @@ public: | |||||
inline SecureBuffer final(size_t len) throw(std::bad_alloc, LengthException) { | inline SecureBuffer final(size_t len) throw(std::bad_alloc, LengthException) { | ||||
if (len > max_output_size()) throw LengthException(); | if (len > max_output_size()) throw LengthException(); | ||||
SecureBuffer buffer(len); | SecureBuffer buffer(len); | ||||
if (DECAF_SUCCESS != decaf_sha3_final(sp,buffer.data(),len)) { | |||||
if (DECAF_SUCCESS != decaf_sha3_final(wrapped,buffer.data(),len)) { | |||||
throw LengthException(); | throw LengthException(); | ||||
} | } | ||||
return buffer; | return buffer; | ||||
@@ -78,7 +78,7 @@ public: | |||||
* output too many bytes from a SHA-3 instance. | * output too many bytes from a SHA-3 instance. | ||||
*/ | */ | ||||
inline void output(Buffer b) throw(LengthException) { | inline void output(Buffer b) throw(LengthException) { | ||||
if (DECAF_SUCCESS != decaf_sha3_output(sp,b.data(),b.size())) { | |||||
if (DECAF_SUCCESS != decaf_sha3_output(wrapped,b.data(),b.size())) { | |||||
throw LengthException(); | throw LengthException(); | ||||
} | } | ||||
} | } | ||||
@@ -87,19 +87,19 @@ public: | |||||
* LengthException if you've output too many bytes from a SHA3 instance. | * LengthException if you've output too many bytes from a SHA3 instance. | ||||
*/ | */ | ||||
inline void final(Buffer b) throw(LengthException) { | inline void final(Buffer b) throw(LengthException) { | ||||
if (DECAF_SUCCESS != decaf_sha3_final(sp,b.data(),b.size())) { | |||||
if (DECAF_SUCCESS != decaf_sha3_final(wrapped,b.data(),b.size())) { | |||||
throw LengthException(); | throw LengthException(); | ||||
} | } | ||||
} | } | ||||
/** @brief Return the sponge's default output size. */ | /** @brief Return the sponge's default output size. */ | ||||
inline size_t default_output_size() const NOEXCEPT { | inline size_t default_output_size() const NOEXCEPT { | ||||
return decaf_sponge_default_output_bytes(sp); | |||||
return decaf_sponge_default_output_bytes(wrapped); | |||||
} | } | ||||
/** @brief Return the sponge's maximum output size. */ | /** @brief Return the sponge's maximum output size. */ | ||||
inline size_t max_output_size() const NOEXCEPT { | inline size_t max_output_size() const NOEXCEPT { | ||||
return decaf_sponge_max_output_bytes(sp); | |||||
return decaf_sponge_max_output_bytes(wrapped); | |||||
} | } | ||||
/** Output the default number of bytes. */ | /** Output the default number of bytes. */ | ||||
@@ -113,10 +113,10 @@ public: | |||||
} | } | ||||
/** Reset the hash to the empty string */ | /** Reset the hash to the empty string */ | ||||
inline void reset() NOEXCEPT { decaf_sha3_reset(sp); } | |||||
inline void reset() NOEXCEPT { decaf_sha3_reset(wrapped); } | |||||
/** Destructor zeroizes state */ | /** Destructor zeroizes state */ | ||||
inline ~KeccakHash() NOEXCEPT { decaf_sponge_destroy(sp); } | |||||
inline ~KeccakHash() NOEXCEPT { decaf_sponge_destroy(wrapped); } | |||||
}; | }; | ||||
/** Fixed-output-length SHA3 */ | /** Fixed-output-length SHA3 */ | ||||