Browse Source

Update EdDSA operations to match draft 07 from CFRG.

master
Andrew Bennett 8 years ago
parent
commit
ef6e74bdec
No known key found for this signature in database GPG Key ID: 4FBD353257AD0DCA
12 changed files with 395 additions and 569 deletions
  1. +34
    -62
      src/GENERATED/c/curve25519/eddsa.c
  2. +33
    -61
      src/GENERATED/c/ed448goldilocks/eddsa.c
  3. +22
    -34
      src/GENERATED/include/decaf/ed255.h
  4. +48
    -81
      src/GENERATED/include/decaf/ed255.hxx
  5. +22
    -34
      src/GENERATED/include/decaf/ed448.h
  6. +28
    -63
      src/GENERATED/include/decaf/ed448.hxx
  7. +4
    -4
      src/generator/curve_data.py
  8. +33
    -61
      src/per_curve/eddsa.tmpl.c
  9. +22
    -34
      src/per_curve/eddsa.tmpl.h
  10. +28
    -93
      src/per_curve/eddsa.tmpl.hxx
  11. +4
    -12
      test/test_decaf.cxx
  12. +117
    -30
      test/vectors.inc.cxx

+ 34
- 62
src/GENERATED/c/curve25519/eddsa.c View File

@@ -28,7 +28,7 @@
#define hash_destroy decaf_sha512_destroy #define hash_destroy decaf_sha512_destroy
#define hash_hash decaf_sha512_hash #define hash_hash decaf_sha512_hash


#define SUPPORTS_CONTEXTS DECAF_EDDSA_25519_SUPPORTS_CONTEXTS
#define NO_CONTEXT DECAF_EDDSA_25519_NO_CONTEXT
#define EDDSA_USE_SIGMA_ISOGENY 1 #define EDDSA_USE_SIGMA_ISOGENY 1
#define COFACTOR 8 #define COFACTOR 8


@@ -58,38 +58,33 @@ 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 context_len,
uint8_t no_context
) { ) {
hash_init(hash); hash_init(hash);
#if SUPPORTS_CONTEXTS
const char *dom_s = "";
#if NO_CONTEXT
if (no_context) {
(void)prehashed;
(void)for_prehash;
(void)context;
(void)context_len;
return;
}
#else
(void)no_context;
#endif
const char *dom_s = "SigEd25519 no Ed25519 collisions";
const uint8_t dom[2] = {2+word_is_zero(prehashed)+word_is_zero(for_prehash), context_len}; 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
(void)prehashed;
(void)for_prehash;
(void)context;
assert(context==NULL);
(void)context_len;
assert(context_len == 0);
#endif
} }


void decaf_ed25519_prehash_init ( void decaf_ed25519_prehash_init (
hash_ctx_t hash hash_ctx_t hash
#if DECAF_EDDSA_25519_SUPPORTS_CONTEXTS
, const uint8_t *context,
uint8_t context_len
#endif
) { ) {
#if DECAF_EDDSA_25519_SUPPORTS_CONTEXTS
hash_init_with_dom(hash,1,1,context,context_len);
#else
hash_init_with_dom(hash,1,1,NULL,0);
#endif
hash_init(hash);
} }


void decaf_ed25519_derive_public_key ( void decaf_ed25519_derive_public_key (
@@ -137,16 +132,11 @@ void decaf_ed25519_sign (
const uint8_t pubkey[DECAF_EDDSA_25519_PUBLIC_BYTES], const uint8_t pubkey[DECAF_EDDSA_25519_PUBLIC_BYTES],
const uint8_t *message, const uint8_t *message,
size_t message_len, size_t message_len,
uint8_t prehashed
#if SUPPORTS_CONTEXTS
, const uint8_t *context,
uint8_t context_len
#endif
uint8_t prehashed,
const uint8_t *context,
uint8_t context_len,
uint8_t no_context
) { ) {
#if !SUPPORTS_CONTEXTS
const uint8_t *const context = NULL;
const uint8_t context_len = 0;
#endif
API_NS(scalar_t) secret_scalar; API_NS(scalar_t) secret_scalar;
hash_ctx_t hash; hash_ctx_t hash;
{ {
@@ -165,7 +155,7 @@ void decaf_ed25519_sign (
API_NS(scalar_decode_long)(secret_scalar, expanded.secret_scalar_ser, sizeof(expanded.secret_scalar_ser)); 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);
hash_init_with_dom(hash,prehashed,0,context,context_len,no_context);
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));
@@ -199,7 +189,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);
hash_init_with_dom(hash,prehashed,0,context,context_len,no_context);
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);
@@ -227,11 +217,9 @@ void decaf_ed25519_sign_prehash (
uint8_t signature[DECAF_EDDSA_25519_SIGNATURE_BYTES], uint8_t signature[DECAF_EDDSA_25519_SIGNATURE_BYTES],
const uint8_t privkey[DECAF_EDDSA_25519_PRIVATE_BYTES], const uint8_t privkey[DECAF_EDDSA_25519_PRIVATE_BYTES],
const uint8_t pubkey[DECAF_EDDSA_25519_PUBLIC_BYTES], const uint8_t pubkey[DECAF_EDDSA_25519_PUBLIC_BYTES],
const decaf_ed25519_prehash_ctx_t hash
#if DECAF_EDDSA_25519_SUPPORTS_CONTEXTS
, const uint8_t *context,
const decaf_ed25519_prehash_ctx_t hash,
const uint8_t *context,
uint8_t context_len uint8_t context_len
#endif
) { ) {
uint8_t hash_output[64]; /* MAGIC but true for all existing schemes */ uint8_t hash_output[64]; /* MAGIC but true for all existing schemes */
{ {
@@ -240,13 +228,8 @@ void decaf_ed25519_sign_prehash (
hash_final(hash_too,hash_output,sizeof(hash_output)); hash_final(hash_too,hash_output,sizeof(hash_output));
hash_destroy(hash_too); hash_destroy(hash_too);
} }
#if DECAF_EDDSA_25519_SUPPORTS_CONTEXTS
decaf_ed25519_sign(signature,privkey,pubkey,hash_output,sizeof(hash_output),1,context,context_len);
#else
decaf_ed25519_sign(signature,privkey,pubkey,hash_output,sizeof(hash_output),1);
#endif

decaf_ed25519_sign(signature,privkey,pubkey,hash_output,sizeof(hash_output),1,context,context_len,0);
decaf_bzero(hash_output,sizeof(hash_output)); decaf_bzero(hash_output,sizeof(hash_output));
} }


@@ -255,16 +238,11 @@ decaf_error_t decaf_ed25519_verify (
const uint8_t pubkey[DECAF_EDDSA_25519_PUBLIC_BYTES], const uint8_t pubkey[DECAF_EDDSA_25519_PUBLIC_BYTES],
const uint8_t *message, const uint8_t *message,
size_t message_len, size_t message_len,
uint8_t prehashed
#if SUPPORTS_CONTEXTS
, const uint8_t *context,
uint8_t context_len
#endif
uint8_t prehashed,
const uint8_t *context,
uint8_t context_len,
uint8_t no_context
) { ) {
#if !SUPPORTS_CONTEXTS
const uint8_t *const context = NULL;
const uint8_t context_len = 0;
#endif
API_NS(point_t) pk_point, r_point; 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);
if (DECAF_SUCCESS != error) { return error; } if (DECAF_SUCCESS != error) { return error; }
@@ -276,7 +254,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);
hash_init_with_dom(hash,prehashed,0,context,context_len,no_context);
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);
@@ -313,11 +291,9 @@ decaf_error_t decaf_ed25519_verify (
decaf_error_t decaf_ed25519_verify_prehash ( decaf_error_t decaf_ed25519_verify_prehash (
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],
const decaf_ed25519_prehash_ctx_t hash
#if DECAF_EDDSA_25519_SUPPORTS_CONTEXTS
, const uint8_t *context,
const decaf_ed25519_prehash_ctx_t hash,
const uint8_t *context,
uint8_t context_len uint8_t context_len
#endif
) { ) {
decaf_error_t ret; decaf_error_t ret;
@@ -329,11 +305,7 @@ decaf_error_t decaf_ed25519_verify_prehash (
hash_destroy(hash_too); hash_destroy(hash_too);
} }
#if DECAF_EDDSA_25519_SUPPORTS_CONTEXTS
ret = decaf_ed25519_verify(signature,pubkey,hash_output,sizeof(hash_output),1,context,context_len);
#else
ret = decaf_ed25519_verify(signature,pubkey,hash_output,sizeof(hash_output),1);
#endif
ret = decaf_ed25519_verify(signature,pubkey,hash_output,sizeof(hash_output),1,context,context_len,0);
return ret; return ret;
} }

+ 33
- 61
src/GENERATED/c/ed448goldilocks/eddsa.c View File

@@ -28,7 +28,7 @@
#define hash_destroy decaf_shake256_destroy #define hash_destroy decaf_shake256_destroy
#define hash_hash decaf_shake256_hash #define hash_hash decaf_shake256_hash


#define SUPPORTS_CONTEXTS DECAF_EDDSA_448_SUPPORTS_CONTEXTS
#define NO_CONTEXT DECAF_EDDSA_448_NO_CONTEXT
#define EDDSA_USE_SIGMA_ISOGENY 0 #define EDDSA_USE_SIGMA_ISOGENY 0
#define COFACTOR 4 #define COFACTOR 4


@@ -58,38 +58,33 @@ 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 context_len,
uint8_t no_context
) { ) {
hash_init(hash); hash_init(hash);
#if SUPPORTS_CONTEXTS
#if NO_CONTEXT
if (no_context) {
(void)prehashed;
(void)for_prehash;
(void)context;
(void)context_len;
return;
}
#else
(void)no_context;
#endif
const char *dom_s = "SigEd448"; const 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};
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
(void)prehashed;
(void)for_prehash;
(void)context;
assert(context==NULL);
(void)context_len;
assert(context_len == 0);
#endif
} }


void decaf_ed448_prehash_init ( void decaf_ed448_prehash_init (
hash_ctx_t hash hash_ctx_t hash
#if DECAF_EDDSA_448_SUPPORTS_CONTEXTS
, const uint8_t *context,
uint8_t context_len
#endif
) { ) {
#if DECAF_EDDSA_448_SUPPORTS_CONTEXTS
hash_init_with_dom(hash,1,1,context,context_len);
#else
hash_init_with_dom(hash,1,1,NULL,0);
#endif
hash_init(hash);
} }


void decaf_ed448_derive_public_key ( void decaf_ed448_derive_public_key (
@@ -137,16 +132,11 @@ void decaf_ed448_sign (
const uint8_t pubkey[DECAF_EDDSA_448_PUBLIC_BYTES], const uint8_t pubkey[DECAF_EDDSA_448_PUBLIC_BYTES],
const uint8_t *message, const uint8_t *message,
size_t message_len, size_t message_len,
uint8_t prehashed
#if SUPPORTS_CONTEXTS
, const uint8_t *context,
uint8_t context_len
#endif
uint8_t prehashed,
const uint8_t *context,
uint8_t context_len,
uint8_t no_context
) { ) {
#if !SUPPORTS_CONTEXTS
const uint8_t *const context = NULL;
const uint8_t context_len = 0;
#endif
API_NS(scalar_t) secret_scalar; API_NS(scalar_t) secret_scalar;
hash_ctx_t hash; hash_ctx_t hash;
{ {
@@ -165,7 +155,7 @@ void decaf_ed448_sign (
API_NS(scalar_decode_long)(secret_scalar, expanded.secret_scalar_ser, sizeof(expanded.secret_scalar_ser)); 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);
hash_init_with_dom(hash,prehashed,0,context,context_len,no_context);
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));
@@ -199,7 +189,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);
hash_init_with_dom(hash,prehashed,0,context,context_len,no_context);
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);
@@ -227,11 +217,9 @@ void decaf_ed448_sign_prehash (
uint8_t signature[DECAF_EDDSA_448_SIGNATURE_BYTES], uint8_t signature[DECAF_EDDSA_448_SIGNATURE_BYTES],
const uint8_t privkey[DECAF_EDDSA_448_PRIVATE_BYTES], const uint8_t privkey[DECAF_EDDSA_448_PRIVATE_BYTES],
const uint8_t pubkey[DECAF_EDDSA_448_PUBLIC_BYTES], const uint8_t pubkey[DECAF_EDDSA_448_PUBLIC_BYTES],
const decaf_ed448_prehash_ctx_t hash
#if DECAF_EDDSA_448_SUPPORTS_CONTEXTS
, const uint8_t *context,
const decaf_ed448_prehash_ctx_t hash,
const uint8_t *context,
uint8_t context_len uint8_t context_len
#endif
) { ) {
uint8_t hash_output[64]; /* MAGIC but true for all existing schemes */ uint8_t hash_output[64]; /* MAGIC but true for all existing schemes */
{ {
@@ -240,13 +228,8 @@ void decaf_ed448_sign_prehash (
hash_final(hash_too,hash_output,sizeof(hash_output)); hash_final(hash_too,hash_output,sizeof(hash_output));
hash_destroy(hash_too); hash_destroy(hash_too);
} }
#if DECAF_EDDSA_448_SUPPORTS_CONTEXTS
decaf_ed448_sign(signature,privkey,pubkey,hash_output,sizeof(hash_output),1,context,context_len);
#else
decaf_ed448_sign(signature,privkey,pubkey,hash_output,sizeof(hash_output),1);
#endif

decaf_ed448_sign(signature,privkey,pubkey,hash_output,sizeof(hash_output),1,context,context_len,0);
decaf_bzero(hash_output,sizeof(hash_output)); decaf_bzero(hash_output,sizeof(hash_output));
} }


@@ -255,16 +238,11 @@ decaf_error_t decaf_ed448_verify (
const uint8_t pubkey[DECAF_EDDSA_448_PUBLIC_BYTES], const uint8_t pubkey[DECAF_EDDSA_448_PUBLIC_BYTES],
const uint8_t *message, const uint8_t *message,
size_t message_len, size_t message_len,
uint8_t prehashed
#if SUPPORTS_CONTEXTS
, const uint8_t *context,
uint8_t context_len
#endif
uint8_t prehashed,
const uint8_t *context,
uint8_t context_len,
uint8_t no_context
) { ) {
#if !SUPPORTS_CONTEXTS
const uint8_t *const context = NULL;
const uint8_t context_len = 0;
#endif
API_NS(point_t) pk_point, r_point; 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);
if (DECAF_SUCCESS != error) { return error; } if (DECAF_SUCCESS != error) { return error; }
@@ -276,7 +254,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);
hash_init_with_dom(hash,prehashed,0,context,context_len,no_context);
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);
@@ -313,11 +291,9 @@ decaf_error_t decaf_ed448_verify (
decaf_error_t decaf_ed448_verify_prehash ( decaf_error_t decaf_ed448_verify_prehash (
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],
const decaf_ed448_prehash_ctx_t hash
#if DECAF_EDDSA_448_SUPPORTS_CONTEXTS
, const uint8_t *context,
const decaf_ed448_prehash_ctx_t hash,
const uint8_t *context,
uint8_t context_len uint8_t context_len
#endif
) { ) {
decaf_error_t ret; decaf_error_t ret;
@@ -329,11 +305,7 @@ decaf_error_t decaf_ed448_verify_prehash (
hash_destroy(hash_too); hash_destroy(hash_too);
} }
#if DECAF_EDDSA_448_SUPPORTS_CONTEXTS
ret = decaf_ed448_verify(signature,pubkey,hash_output,sizeof(hash_output),1,context,context_len);
#else
ret = decaf_ed448_verify(signature,pubkey,hash_output,sizeof(hash_output),1);
#endif
ret = decaf_ed448_verify(signature,pubkey,hash_output,sizeof(hash_output),1,context,context_len,0);
return ret; return ret;
} }

+ 22
- 34
src/GENERATED/include/decaf/ed255.h View File

@@ -32,8 +32,8 @@ extern "C" {
/** Number of bytes in an EdDSA private key. */ /** Number of bytes in an EdDSA private key. */
#define DECAF_EDDSA_25519_SIGNATURE_BYTES (DECAF_EDDSA_25519_PUBLIC_BYTES + DECAF_EDDSA_25519_PRIVATE_BYTES) #define DECAF_EDDSA_25519_SIGNATURE_BYTES (DECAF_EDDSA_25519_PUBLIC_BYTES + DECAF_EDDSA_25519_PRIVATE_BYTES)


/** Does EdDSA support contexts? */
#define DECAF_EDDSA_25519_SUPPORTS_CONTEXTS 0
/** Does EdDSA support non-contextual signatures? */
#define DECAF_EDDSA_25519_NO_CONTEXT 1
/** Prehash context renaming macros. */ /** Prehash context renaming macros. */
#define decaf_ed25519_prehash_ctx_s decaf_sha512_ctx_s #define decaf_ed25519_prehash_ctx_s decaf_sha512_ctx_s
@@ -59,11 +59,12 @@ void decaf_ed25519_derive_public_key (
* @param [out] signature The signature. * @param [out] signature The signature.
* @param [in] privkey The private key. * @param [in] privkey The private key.
* @param [in] pubkey The public key. * @param [in] pubkey The public key.
* @param [in] context A "context" for this signature of up to 255 bytes.
* @param [in] context_len Length of the context.
* @param [in] message The message to sign. * @param [in] message The message to sign.
* @param [in] message_len The length of the message. * @param [in] message_len The length of the message.
* @param [in] prehashed Nonzero if the message is actually the hash of something you want to sign. * @param [in] prehashed Nonzero if the message is actually the hash of something you want to sign.
* @param [in] context A "context" for this signature of up to 255 bytes.
* @param [in] context_len Length of the context.
* @param [in] no_context Nonzero if no context should be used (only Ed25519 supported).
* *
* @warning For Ed25519, it is unsafe to use the same key for both prehashed and non-prehashed * @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
@@ -76,11 +77,10 @@ void decaf_ed25519_sign (
const uint8_t pubkey[DECAF_EDDSA_25519_PUBLIC_BYTES], const uint8_t pubkey[DECAF_EDDSA_25519_PUBLIC_BYTES],
const uint8_t *message, const uint8_t *message,
size_t message_len, size_t message_len,
uint8_t prehashed
#if DECAF_EDDSA_25519_SUPPORTS_CONTEXTS
, const uint8_t *context,
uint8_t context_len
#endif
uint8_t prehashed,
const uint8_t *context,
uint8_t context_len,
uint8_t no_context
) API_VIS __attribute__((nonnull(1,2,3))) NOINLINE; ) API_VIS __attribute__((nonnull(1,2,3))) NOINLINE;


/** /**
@@ -89,10 +89,9 @@ void decaf_ed25519_sign (
* @param [out] signature The signature. * @param [out] signature The signature.
* @param [in] privkey The private key. * @param [in] privkey The private key.
* @param [in] pubkey The public key. * @param [in] pubkey The public key.
* @param [in] hash The hash of the message. This object will not be modified by the call.
* @param [in] context A "context" for this signature of up to 255 bytes. Must be the same as what was used for the prehash. * @param [in] context 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] 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 * @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
@@ -103,26 +102,18 @@ void decaf_ed25519_sign_prehash (
uint8_t signature[DECAF_EDDSA_25519_SIGNATURE_BYTES], uint8_t signature[DECAF_EDDSA_25519_SIGNATURE_BYTES],
const uint8_t privkey[DECAF_EDDSA_25519_PRIVATE_BYTES], const uint8_t privkey[DECAF_EDDSA_25519_PRIVATE_BYTES],
const uint8_t pubkey[DECAF_EDDSA_25519_PUBLIC_BYTES], const uint8_t pubkey[DECAF_EDDSA_25519_PUBLIC_BYTES],
const decaf_ed25519_prehash_ctx_t hash
#if DECAF_EDDSA_25519_SUPPORTS_CONTEXTS
, const uint8_t *context,
const decaf_ed25519_prehash_ctx_t hash,
const uint8_t *context,
uint8_t context_len uint8_t context_len
#endif
) API_VIS __attribute__((nonnull(1,2,3,4))) NOINLINE; ) API_VIS __attribute__((nonnull(1,2,3,4))) NOINLINE;
/** /**
* @brief Prehash initialization, with contexts if supported. * @brief Prehash initialization, with contexts if supported.
* *
* @param [out] hash The hash object to be initialized. * @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 ( void decaf_ed25519_prehash_init (
decaf_ed25519_prehash_ctx_t hash 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; ) API_VIS __attribute__((nonnull(1))) NOINLINE;


/** /**
@@ -132,11 +123,12 @@ void decaf_ed25519_prehash_init (
* *
* @param [in] signature The signature. * @param [in] signature The signature.
* @param [in] pubkey The public key. * @param [in] pubkey The public key.
* @param [in] context A "context" for this signature of up to 255 bytes.
* @param [in] context_len Length of the context.
* @param [in] message The message to verify. * @param [in] message The message to verify.
* @param [in] message_len The length of the message. * @param [in] message_len The length of the message.
* @param [in] prehashed Nonzero if the message is actually the hash of something you want to verify. * @param [in] prehashed Nonzero if the message is actually the hash of something you want to verify.
* @param [in] context A "context" for this signature of up to 255 bytes.
* @param [in] context_len Length of the context.
* @param [in] no_context Nonzero if no context should be used (only Ed25519 supported).
* *
* @warning For Ed25519, it is unsafe to use the same key for both prehashed and non-prehashed * @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
@@ -148,11 +140,10 @@ decaf_error_t decaf_ed25519_verify (
const uint8_t pubkey[DECAF_EDDSA_25519_PUBLIC_BYTES], const uint8_t pubkey[DECAF_EDDSA_25519_PUBLIC_BYTES],
const uint8_t *message, const uint8_t *message,
size_t message_len, size_t message_len,
uint8_t prehashed
#if DECAF_EDDSA_25519_SUPPORTS_CONTEXTS
, const uint8_t *context,
uint8_t context_len
#endif
uint8_t prehashed,
const uint8_t *context,
uint8_t context_len,
uint8_t no_context
) API_VIS __attribute__((nonnull(1,2))) NOINLINE; ) API_VIS __attribute__((nonnull(1,2))) NOINLINE;


/** /**
@@ -162,10 +153,9 @@ decaf_error_t decaf_ed25519_verify (
* *
* @param [in] signature The signature. * @param [in] signature The signature.
* @param [in] pubkey The public key. * @param [in] pubkey The public key.
* @param [in] hash The hash of the message. This object will not be modified by the call.
* @param [in] context A "context" for this signature of up to 255 bytes. Must be the same as what was used for the prehash. * @param [in] context 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] 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 * @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
@@ -175,11 +165,9 @@ decaf_error_t decaf_ed25519_verify (
decaf_error_t decaf_ed25519_verify_prehash ( decaf_error_t decaf_ed25519_verify_prehash (
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],
const decaf_ed25519_prehash_ctx_t hash
#if DECAF_EDDSA_25519_SUPPORTS_CONTEXTS
, const uint8_t *context,
const decaf_ed25519_prehash_ctx_t hash,
const uint8_t *context,
uint8_t context_len uint8_t context_len
#endif
) API_VIS __attribute__((nonnull(1,2))) NOINLINE; ) API_VIS __attribute__((nonnull(1,2))) NOINLINE;


/** /**


+ 48
- 81
src/GENERATED/include/decaf/ed255.hxx View File

@@ -49,22 +49,14 @@ template<> struct EdDSA<IsoEd25519> {
/** @cond internal */ /** @cond internal */
template<class CRTP, Prehashed> class Signing; template<class CRTP, Prehashed> class Signing;
template<class CRTP, Prehashed> class Verification; template<class CRTP, Prehashed> class Verification;

template<Prehashed=PURE> class PublicKeyBase;
template<Prehashed=PURE> class PrivateKeyBase;
typedef class PublicKeyBase<PURE> PublicKey, PublicKeyPure;
typedef class PublicKeyBase<PREHASHED> PublicKeyPh;
typedef class PrivateKeyBase<PURE> PrivateKey, PrivateKeyPure;
typedef class PrivateKeyBase<PREHASHED> PrivateKeyPh;

class PublicKeyBase;
class PrivateKeyBase;
typedef class PrivateKeyBase PrivateKey, PrivateKeyPure, PrivateKeyPh;
typedef class PublicKeyBase PublicKey, PublicKeyPure, PublicKeyPh;
/** @endcond */ /** @endcond */


/** Prehash context for EdDSA. */ /** Prehash context for EdDSA. */
class Prehash : public SHA512 { class Prehash : public SHA512 {
public:
/** Do we support contexts for signatures? If not, they must always be NULL */
static const bool SUPPORTS_CONTEXTS = DECAF_EDDSA_25519_SUPPORTS_CONTEXTS;
private: private:
typedef SHA512 Super; typedef SHA512 Super;
SecureBuffer context_; SecureBuffer context_;
@@ -74,17 +66,11 @@ private:
void init() throw(LengthException) { void init() throw(LengthException) {
Super::reset(); Super::reset();
if (context_.size() > 255
|| (context_.size() != 0 && !SUPPORTS_CONTEXTS)
) {
if (context_.size() > 255) {
throw LengthException(); throw LengthException();
} }


#if DECAF_EDDSA_25519_SUPPORTS_CONTEXTS
decaf_ed25519_prehash_init((decaf_sha512_ctx_s *)wrapped,context_.data(),context_.size());
#else
decaf_ed25519_prehash_init(wrapped);
#endif
decaf_ed25519_prehash_init((decaf_sha512_ctx_s *)wrapped);
} }
public: public:
@@ -126,11 +112,9 @@ public:
out.data(), out.data(),
((const CRTP*)this)->priv_.data(), ((const CRTP*)this)->priv_.data(),
((const CRTP*)this)->pub_.data(), ((const CRTP*)this)->pub_.data(),
(const decaf_ed25519_prehash_ctx_s*)ph.wrapped
#if DECAF_EDDSA_25519_SUPPORTS_CONTEXTS
, ph.context_.data(),
(const decaf_ed25519_prehash_ctx_s*)ph.wrapped,
ph.context_.data(),
ph.context_.size() ph.context_.size()
#endif
); );
return out; return out;
} }
@@ -151,20 +135,18 @@ public:
/** /**
* Sign a message. * Sign a message.
* @param [in] message The message to be signed. * @param [in] message The message to be signed.
* @param [in] context A context for the signature; must be at most 255 bytes;
* must be absent if SUPPORTS_CONTEXTS == false.
* @param [in] context A context for the signature; must be at most 255 bytes.
* *
* @warning It is generally unsafe to use Ed25519 with both prehashed and non-prehashed messages. * @warning It is generally unsafe to use Ed25519 with both prehashed and non-prehashed messages.
*/ */
inline SecureBuffer sign ( inline SecureBuffer sign (
const Block &message, const Block &message,
const Block &context = Block(NULL,0)
const Block &context = Block(NULL,0),
const bool no_context = false
) const /* TODO: this exn spec tickles a Clang bug? ) const /* TODO: this exn spec tickles a Clang bug?
* throw(LengthException, std::bad_alloc) * throw(LengthException, std::bad_alloc)
*/ { */ {
if (context.size() > 255
|| (context.size() != 0 && !CRTP::SUPPORTS_CONTEXTS)
) {
if (context.size() > 255) {
throw LengthException(); throw LengthException();
} }
@@ -175,28 +157,27 @@ public:
((const CRTP*)this)->pub_.data(), ((const CRTP*)this)->pub_.data(),
message.data(), message.data(),
message.size(), message.size(),
0
#if DECAF_EDDSA_25519_SUPPORTS_CONTEXTS
, context.data(),
context.size()
#endif
0,
context.data(),
context.size(),
no_context
); );
return out; return out;
} }
}; };


template<Prehashed ph> class PrivateKeyBase
: public Serializable<PrivateKeyBase<ph> >
, public Signing<PrivateKeyBase<ph>,ph> {
class PrivateKeyBase
: public Serializable<PrivateKeyBase>
, public Signing<PrivateKeyBase,PURE>
, public Signing<PrivateKeyBase,PREHASHED> {
public: public:
typedef class PublicKeyBase<ph> MyPublicKey;
typedef class PublicKeyBase MyPublicKey;
private: private:
/** @cond internal */ /** @cond internal */
friend class PublicKeyBase<ph>;
friend class Signing<PrivateKeyBase<ph>, ph>;
friend class PublicKeyBase;
friend class Signing<PrivateKey,PURE>;
friend class Signing<PrivateKey,PREHASHED>;
/** @endcond */ /** @endcond */

/** The pre-expansion form of the signing key. */ /** The pre-expansion form of the signing key. */
FixedArrayBuffer<DECAF_EDDSA_25519_PRIVATE_BYTES> priv_; FixedArrayBuffer<DECAF_EDDSA_25519_PRIVATE_BYTES> priv_;
@@ -214,9 +195,6 @@ public:
/** Serialization size. */ /** Serialization size. */
static const size_t SER_BYTES = DECAF_EDDSA_25519_PRIVATE_BYTES; static const size_t SER_BYTES = DECAF_EDDSA_25519_PRIVATE_BYTES;
/** Do we support contexts for signatures? If not, they must always be NULL */
static const bool SUPPORTS_CONTEXTS = DECAF_EDDSA_25519_SUPPORTS_CONTEXTS;
/** Create but don't initialize */ /** Create but don't initialize */
inline explicit PrivateKeyBase(const NOINIT&) NOEXCEPT : priv_((NOINIT())), pub_((NOINIT())) { } inline explicit PrivateKeyBase(const NOINIT&) NOEXCEPT : priv_((NOINIT())), pub_((NOINIT())) { }
@@ -269,11 +247,10 @@ 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 Block &context = Block(NULL,0),
const bool no_context = false
) const /*NOEXCEPT*/ { ) const /*NOEXCEPT*/ {
if (context.size() > 255
|| (context.size() != 0 && !CRTP::SUPPORTS_CONTEXTS)
) {
if (context.size() > 255) {
return DECAF_FAILURE; return DECAF_FAILURE;
} }
@@ -282,34 +259,31 @@ public:
((const CRTP*)this)->pub_.data(), ((const CRTP*)this)->pub_.data(),
message.data(), message.data(),
message.size(), message.size(),
0
#if DECAF_EDDSA_25519_SUPPORTS_CONTEXTS
, context.data(),
context.size()
#endif
0,
context.data(),
context.size(),
no_context
); );
} }
/** Verify a signature, throwing an exception if verification fails /** Verify a signature, throwing an exception if verification fails
* @param [in] sig The signature. * @param [in] sig The signature.
* @param [in] message The signed message. * @param [in] message The signed message.
* @param [in] context A context for the signature; must be at most 255 bytes;
* must be absent if SUPPORTS_CONTEXTS == false.
* @param [in] context A context for the signature; must be at most 255 bytes.
* *
* @warning It is generally unsafe to use Ed25519 with both prehashed and non-prehashed messages. * @warning It is generally unsafe to use Ed25519 with both prehashed and non-prehashed messages.
*/ */
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 Block &context = Block(NULL,0),
const bool no_context = false
) const /*throw(LengthException,CryptoException)*/ { ) const /*throw(LengthException,CryptoException)*/ {
if (context.size() > 255
|| (context.size() != 0 && !CRTP::SUPPORTS_CONTEXTS)
) {
if (context.size() > 255) {
throw LengthException(); throw LengthException();
} }
if (DECAF_SUCCESS != verify_noexcept( sig, message, context )) {
if (DECAF_SUCCESS != verify_noexcept( sig, message, context, no_context )) {
throw CryptoException(); throw CryptoException();
} }
} }
@@ -326,11 +300,9 @@ public:
return decaf_ed25519_verify_prehash ( return decaf_ed25519_verify_prehash (
sig.data(), sig.data(),
((const CRTP*)this)->pub_.data(), ((const CRTP*)this)->pub_.data(),
(const decaf_ed25519_prehash_ctx_s*)ph.wrapped
#if DECAF_EDDSA_25519_SUPPORTS_CONTEXTS
, ph.context_.data(),
(const decaf_ed25519_prehash_ctx_s*)ph.wrapped,
ph.context_.data(),
ph.context_.size() ph.context_.size()
#endif
); );
} }
@@ -342,11 +314,9 @@ public:
if (DECAF_SUCCESS != decaf_ed25519_verify_prehash ( if (DECAF_SUCCESS != decaf_ed25519_verify_prehash (
sig.data(), sig.data(),
((const CRTP*)this)->pub_.data(), ((const CRTP*)this)->pub_.data(),
(const decaf_ed25519_prehash_ctx_s*)ph.wrapped
#if DECAF_EDDSA_25519_SUPPORTS_CONTEXTS
, ph.context_.data(),
(const decaf_ed25519_prehash_ctx_s*)ph.wrapped,
ph.context_.data(),
ph.context_.size() ph.context_.size()
#endif
)) { )) {
throw CryptoException(); throw CryptoException();
} }
@@ -365,20 +335,20 @@ public:
}; };




template<Prehashed ph> class PublicKeyBase
: public Serializable<PublicKeyBase<ph> >
, public Verification<PublicKeyBase<ph>,ph> {
class PublicKeyBase
: public Serializable<PublicKeyBase>
, public Verification<PublicKeyBase,PURE>
, public Verification<PublicKeyBase,PREHASHED> {
public: public:
typedef class PrivateKeyBase<ph> MyPrivateKey;
typedef class PrivateKeyBase MyPrivateKey;
private: private:
/** @cond internal */ /** @cond internal */
friend class PrivateKeyBase<ph>;
friend class Verification<PublicKeyBase<ph>, ph>;
friend class PrivateKeyBase;
friend class Verification<PublicKey,PURE>;
friend class Verification<PublicKey,PREHASHED>;
/** @endcond */ /** @endcond */



private: private:
/** The pre-expansion form of the signature */ /** The pre-expansion form of the signature */
FixedArrayBuffer<DECAF_EDDSA_25519_PUBLIC_BYTES> pub_; FixedArrayBuffer<DECAF_EDDSA_25519_PUBLIC_BYTES> pub_;
@@ -395,9 +365,6 @@ public:
/** Serialization size. */ /** Serialization size. */
static const size_t SER_BYTES = DECAF_EDDSA_25519_PRIVATE_BYTES; static const size_t SER_BYTES = DECAF_EDDSA_25519_PRIVATE_BYTES;
/** Do we support contexts for signatures? If not, they must always be NULL */
static const bool SUPPORTS_CONTEXTS = DECAF_EDDSA_25519_SUPPORTS_CONTEXTS;
/** Create but don't initialize */ /** Create but don't initialize */
inline explicit PublicKeyBase(const NOINIT&) NOEXCEPT : pub_((NOINIT())) { } inline explicit PublicKeyBase(const NOINIT&) NOEXCEPT : pub_((NOINIT())) { }


+ 22
- 34
src/GENERATED/include/decaf/ed448.h View File

@@ -32,8 +32,8 @@ extern "C" {
/** Number of bytes in an EdDSA private key. */ /** Number of bytes in an EdDSA private key. */
#define DECAF_EDDSA_448_SIGNATURE_BYTES (DECAF_EDDSA_448_PUBLIC_BYTES + DECAF_EDDSA_448_PRIVATE_BYTES) #define DECAF_EDDSA_448_SIGNATURE_BYTES (DECAF_EDDSA_448_PUBLIC_BYTES + DECAF_EDDSA_448_PRIVATE_BYTES)


/** Does EdDSA support contexts? */
#define DECAF_EDDSA_448_SUPPORTS_CONTEXTS 1
/** Does EdDSA support non-contextual signatures? */
#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
@@ -59,11 +59,12 @@ void decaf_ed448_derive_public_key (
* @param [out] signature The signature. * @param [out] signature The signature.
* @param [in] privkey The private key. * @param [in] privkey The private key.
* @param [in] pubkey The public key. * @param [in] pubkey The public key.
* @param [in] context A "context" for this signature of up to 255 bytes.
* @param [in] context_len Length of the context.
* @param [in] message The message to sign. * @param [in] message The message to sign.
* @param [in] message_len The length of the message. * @param [in] message_len The length of the message.
* @param [in] prehashed Nonzero if the message is actually the hash of something you want to sign. * @param [in] prehashed Nonzero if the message is actually the hash of something you want to sign.
* @param [in] context A "context" for this signature of up to 255 bytes.
* @param [in] context_len Length of the context.
* @param [in] no_context Nonzero if no context should be used (only Ed25519 supported).
* *
* @warning For Ed25519, it is unsafe to use the same key for both prehashed and non-prehashed * @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
@@ -76,11 +77,10 @@ void decaf_ed448_sign (
const uint8_t pubkey[DECAF_EDDSA_448_PUBLIC_BYTES], const uint8_t pubkey[DECAF_EDDSA_448_PUBLIC_BYTES],
const uint8_t *message, const uint8_t *message,
size_t message_len, size_t message_len,
uint8_t prehashed
#if DECAF_EDDSA_448_SUPPORTS_CONTEXTS
, const uint8_t *context,
uint8_t context_len
#endif
uint8_t prehashed,
const uint8_t *context,
uint8_t context_len,
uint8_t no_context
) API_VIS __attribute__((nonnull(1,2,3))) NOINLINE; ) API_VIS __attribute__((nonnull(1,2,3))) NOINLINE;


/** /**
@@ -89,10 +89,9 @@ void decaf_ed448_sign (
* @param [out] signature The signature. * @param [out] signature The signature.
* @param [in] privkey The private key. * @param [in] privkey The private key.
* @param [in] pubkey The public key. * @param [in] pubkey The public key.
* @param [in] hash The hash of the message. This object will not be modified by the call.
* @param [in] context A "context" for this signature of up to 255 bytes. Must be the same as what was used for the prehash. * @param [in] context 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] 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 * @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
@@ -103,26 +102,18 @@ void decaf_ed448_sign_prehash (
uint8_t signature[DECAF_EDDSA_448_SIGNATURE_BYTES], uint8_t signature[DECAF_EDDSA_448_SIGNATURE_BYTES],
const uint8_t privkey[DECAF_EDDSA_448_PRIVATE_BYTES], const uint8_t privkey[DECAF_EDDSA_448_PRIVATE_BYTES],
const uint8_t pubkey[DECAF_EDDSA_448_PUBLIC_BYTES], const uint8_t pubkey[DECAF_EDDSA_448_PUBLIC_BYTES],
const decaf_ed448_prehash_ctx_t hash
#if DECAF_EDDSA_448_SUPPORTS_CONTEXTS
, const uint8_t *context,
const decaf_ed448_prehash_ctx_t hash,
const uint8_t *context,
uint8_t context_len uint8_t context_len
#endif
) API_VIS __attribute__((nonnull(1,2,3,4))) NOINLINE; ) API_VIS __attribute__((nonnull(1,2,3,4))) NOINLINE;
/** /**
* @brief Prehash initialization, with contexts if supported. * @brief Prehash initialization, with contexts if supported.
* *
* @param [out] hash The hash object to be initialized. * @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 ( void decaf_ed448_prehash_init (
decaf_ed448_prehash_ctx_t hash 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; ) API_VIS __attribute__((nonnull(1))) NOINLINE;


/** /**
@@ -132,11 +123,12 @@ void decaf_ed448_prehash_init (
* *
* @param [in] signature The signature. * @param [in] signature The signature.
* @param [in] pubkey The public key. * @param [in] pubkey The public key.
* @param [in] context A "context" for this signature of up to 255 bytes.
* @param [in] context_len Length of the context.
* @param [in] message The message to verify. * @param [in] message The message to verify.
* @param [in] message_len The length of the message. * @param [in] message_len The length of the message.
* @param [in] prehashed Nonzero if the message is actually the hash of something you want to verify. * @param [in] prehashed Nonzero if the message is actually the hash of something you want to verify.
* @param [in] context A "context" for this signature of up to 255 bytes.
* @param [in] context_len Length of the context.
* @param [in] no_context Nonzero if no context should be used (only Ed25519 supported).
* *
* @warning For Ed25519, it is unsafe to use the same key for both prehashed and non-prehashed * @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
@@ -148,11 +140,10 @@ decaf_error_t decaf_ed448_verify (
const uint8_t pubkey[DECAF_EDDSA_448_PUBLIC_BYTES], const uint8_t pubkey[DECAF_EDDSA_448_PUBLIC_BYTES],
const uint8_t *message, const uint8_t *message,
size_t message_len, size_t message_len,
uint8_t prehashed
#if DECAF_EDDSA_448_SUPPORTS_CONTEXTS
, const uint8_t *context,
uint8_t context_len
#endif
uint8_t prehashed,
const uint8_t *context,
uint8_t context_len,
uint8_t no_context
) API_VIS __attribute__((nonnull(1,2))) NOINLINE; ) API_VIS __attribute__((nonnull(1,2))) NOINLINE;


/** /**
@@ -162,10 +153,9 @@ decaf_error_t decaf_ed448_verify (
* *
* @param [in] signature The signature. * @param [in] signature The signature.
* @param [in] pubkey The public key. * @param [in] pubkey The public key.
* @param [in] hash The hash of the message. This object will not be modified by the call.
* @param [in] context A "context" for this signature of up to 255 bytes. Must be the same as what was used for the prehash. * @param [in] context 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] 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 * @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
@@ -175,11 +165,9 @@ decaf_error_t decaf_ed448_verify (
decaf_error_t decaf_ed448_verify_prehash ( decaf_error_t decaf_ed448_verify_prehash (
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],
const decaf_ed448_prehash_ctx_t hash
#if DECAF_EDDSA_448_SUPPORTS_CONTEXTS
, const uint8_t *context,
const decaf_ed448_prehash_ctx_t hash,
const uint8_t *context,
uint8_t context_len uint8_t context_len
#endif
) API_VIS __attribute__((nonnull(1,2))) NOINLINE; ) API_VIS __attribute__((nonnull(1,2))) NOINLINE;


/** /**


+ 28
- 63
src/GENERATED/include/decaf/ed448.hxx View File

@@ -49,20 +49,14 @@ template<> struct EdDSA<Ed448Goldilocks> {
/** @cond internal */ /** @cond internal */
template<class CRTP, Prehashed> class Signing; template<class CRTP, Prehashed> class Signing;
template<class CRTP, Prehashed> class Verification; template<class CRTP, Prehashed> class Verification;

class PublicKeyBase; class PublicKeyBase;
class PrivateKeyBase; class PrivateKeyBase;
typedef class PrivateKeyBase PrivateKey, PrivateKeyPure, PrivateKeyPh; typedef class PrivateKeyBase PrivateKey, PrivateKeyPure, PrivateKeyPh;
typedef class PublicKeyBase PublicKey, PublicKeyPure, PublicKeyPh; typedef class PublicKeyBase PublicKey, PublicKeyPure, PublicKeyPh;
/** @endcond */ /** @endcond */


/** Prehash context for EdDSA. */ /** Prehash context for EdDSA. */
class Prehash : public SHAKE<256> { class Prehash : public SHAKE<256> {
public:
/** Do we support contexts for signatures? If not, they must always be NULL */
static const bool SUPPORTS_CONTEXTS = DECAF_EDDSA_448_SUPPORTS_CONTEXTS;
private: private:
typedef SHAKE<256> Super; typedef SHAKE<256> Super;
SecureBuffer context_; SecureBuffer context_;
@@ -72,17 +66,11 @@ private:
void init() throw(LengthException) { void init() throw(LengthException) {
Super::reset(); Super::reset();
if (context_.size() > 255
|| (context_.size() != 0 && !SUPPORTS_CONTEXTS)
) {
if (context_.size() > 255) {
throw LengthException(); throw LengthException();
} }


#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
decaf_ed448_prehash_init((decaf_shake256_ctx_s *)wrapped);
} }
public: public:
@@ -124,11 +112,9 @@ public:
out.data(), out.data(),
((const CRTP*)this)->priv_.data(), ((const CRTP*)this)->priv_.data(),
((const CRTP*)this)->pub_.data(), ((const CRTP*)this)->pub_.data(),
(const decaf_ed448_prehash_ctx_s*)ph.wrapped
#if DECAF_EDDSA_448_SUPPORTS_CONTEXTS
, ph.context_.data(),
(const decaf_ed448_prehash_ctx_s*)ph.wrapped,
ph.context_.data(),
ph.context_.size() ph.context_.size()
#endif
); );
return out; return out;
} }
@@ -149,20 +135,18 @@ public:
/** /**
* Sign a message. * Sign a message.
* @param [in] message The message to be signed. * @param [in] message The message to be signed.
* @param [in] context A context for the signature; must be at most 255 bytes;
* must be absent if SUPPORTS_CONTEXTS == false.
* @param [in] context A context for the signature; must be at most 255 bytes.
* *
* @warning It is generally unsafe to use Ed25519 with both prehashed and non-prehashed messages. * @warning It is generally unsafe to use Ed25519 with both prehashed and non-prehashed messages.
*/ */
inline SecureBuffer sign ( inline SecureBuffer sign (
const Block &message, const Block &message,
const Block &context = Block(NULL,0)
const Block &context = Block(NULL,0),
const bool no_context = false
) const /* TODO: this exn spec tickles a Clang bug? ) const /* TODO: this exn spec tickles a Clang bug?
* throw(LengthException, std::bad_alloc) * throw(LengthException, std::bad_alloc)
*/ { */ {
if (context.size() > 255
|| (context.size() != 0 && !CRTP::SUPPORTS_CONTEXTS)
) {
if (context.size() > 255) {
throw LengthException(); throw LengthException();
} }
@@ -173,17 +157,15 @@ public:
((const CRTP*)this)->pub_.data(), ((const CRTP*)this)->pub_.data(),
message.data(), message.data(),
message.size(), message.size(),
0
#if DECAF_EDDSA_448_SUPPORTS_CONTEXTS
, context.data(),
context.size()
#endif
0,
context.data(),
context.size(),
no_context
); );
return out; return out;
} }
}; };



class PrivateKeyBase class PrivateKeyBase
: public Serializable<PrivateKeyBase> : public Serializable<PrivateKeyBase>
, public Signing<PrivateKeyBase,PURE> , public Signing<PrivateKeyBase,PURE>
@@ -196,7 +178,6 @@ private:
friend class Signing<PrivateKey,PURE>; friend class Signing<PrivateKey,PURE>;
friend class Signing<PrivateKey,PREHASHED>; friend class Signing<PrivateKey,PREHASHED>;
/** @endcond */ /** @endcond */

/** The pre-expansion form of the signing key. */ /** The pre-expansion form of the signing key. */
FixedArrayBuffer<DECAF_EDDSA_448_PRIVATE_BYTES> priv_; FixedArrayBuffer<DECAF_EDDSA_448_PRIVATE_BYTES> priv_;
@@ -214,9 +195,6 @@ public:
/** Serialization size. */ /** Serialization size. */
static const size_t SER_BYTES = DECAF_EDDSA_448_PRIVATE_BYTES; static const size_t SER_BYTES = DECAF_EDDSA_448_PRIVATE_BYTES;
/** Do we support contexts for signatures? If not, they must always be NULL */
static const bool SUPPORTS_CONTEXTS = DECAF_EDDSA_448_SUPPORTS_CONTEXTS;
/** Create but don't initialize */ /** Create but don't initialize */
inline explicit PrivateKeyBase(const NOINIT&) NOEXCEPT : priv_((NOINIT())), pub_((NOINIT())) { } inline explicit PrivateKeyBase(const NOINIT&) NOEXCEPT : priv_((NOINIT())), pub_((NOINIT())) { }
@@ -269,11 +247,10 @@ 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 Block &context = Block(NULL,0),
const bool no_context = false
) const /*NOEXCEPT*/ { ) const /*NOEXCEPT*/ {
if (context.size() > 255
|| (context.size() != 0 && !CRTP::SUPPORTS_CONTEXTS)
) {
if (context.size() > 255) {
return DECAF_FAILURE; return DECAF_FAILURE;
} }
@@ -282,34 +259,31 @@ public:
((const CRTP*)this)->pub_.data(), ((const CRTP*)this)->pub_.data(),
message.data(), message.data(),
message.size(), message.size(),
0
#if DECAF_EDDSA_448_SUPPORTS_CONTEXTS
, context.data(),
context.size()
#endif
0,
context.data(),
context.size(),
no_context
); );
} }
/** Verify a signature, throwing an exception if verification fails /** Verify a signature, throwing an exception if verification fails
* @param [in] sig The signature. * @param [in] sig The signature.
* @param [in] message The signed message. * @param [in] message The signed message.
* @param [in] context A context for the signature; must be at most 255 bytes;
* must be absent if SUPPORTS_CONTEXTS == false.
* @param [in] context A context for the signature; must be at most 255 bytes.
* *
* @warning It is generally unsafe to use Ed25519 with both prehashed and non-prehashed messages. * @warning It is generally unsafe to use Ed25519 with both prehashed and non-prehashed messages.
*/ */
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 Block &context = Block(NULL,0),
const bool no_context = false
) const /*throw(LengthException,CryptoException)*/ { ) const /*throw(LengthException,CryptoException)*/ {
if (context.size() > 255
|| (context.size() != 0 && !CRTP::SUPPORTS_CONTEXTS)
) {
if (context.size() > 255) {
throw LengthException(); throw LengthException();
} }
if (DECAF_SUCCESS != verify_noexcept( sig, message, context )) {
if (DECAF_SUCCESS != verify_noexcept( sig, message, context, no_context )) {
throw CryptoException(); throw CryptoException();
} }
} }
@@ -326,11 +300,9 @@ public:
return decaf_ed448_verify_prehash ( return decaf_ed448_verify_prehash (
sig.data(), sig.data(),
((const CRTP*)this)->pub_.data(), ((const CRTP*)this)->pub_.data(),
(const decaf_ed448_prehash_ctx_s*)ph.wrapped
#if DECAF_EDDSA_448_SUPPORTS_CONTEXTS
, ph.context_.data(),
(const decaf_ed448_prehash_ctx_s*)ph.wrapped,
ph.context_.data(),
ph.context_.size() ph.context_.size()
#endif
); );
} }
@@ -342,11 +314,9 @@ public:
if (DECAF_SUCCESS != decaf_ed448_verify_prehash ( if (DECAF_SUCCESS != decaf_ed448_verify_prehash (
sig.data(), sig.data(),
((const CRTP*)this)->pub_.data(), ((const CRTP*)this)->pub_.data(),
(const decaf_ed448_prehash_ctx_s*)ph.wrapped
#if DECAF_EDDSA_448_SUPPORTS_CONTEXTS
, ph.context_.data(),
(const decaf_ed448_prehash_ctx_s*)ph.wrapped,
ph.context_.data(),
ph.context_.size() ph.context_.size()
#endif
)) { )) {
throw CryptoException(); throw CryptoException();
} }
@@ -365,7 +335,6 @@ public:
}; };





class PublicKeyBase class PublicKeyBase
: public Serializable<PublicKeyBase> : public Serializable<PublicKeyBase>
, public Verification<PublicKeyBase,PURE> , public Verification<PublicKeyBase,PURE>
@@ -380,7 +349,6 @@ private:
friend class Verification<PublicKey,PREHASHED>; friend class Verification<PublicKey,PREHASHED>;
/** @endcond */ /** @endcond */



private: private:
/** The pre-expansion form of the signature */ /** The pre-expansion form of the signature */
FixedArrayBuffer<DECAF_EDDSA_448_PUBLIC_BYTES> pub_; FixedArrayBuffer<DECAF_EDDSA_448_PUBLIC_BYTES> pub_;
@@ -397,9 +365,6 @@ public:
/** Serialization size. */ /** Serialization size. */
static const size_t SER_BYTES = DECAF_EDDSA_448_PRIVATE_BYTES; static const size_t SER_BYTES = DECAF_EDDSA_448_PRIVATE_BYTES;
/** Do we support contexts for signatures? If not, they must always be NULL */
static const bool SUPPORTS_CONTEXTS = DECAF_EDDSA_448_SUPPORTS_CONTEXTS;
/** Create but don't initialize */ /** Create but don't initialize */
inline explicit PublicKeyBase(const NOINIT&) NOEXCEPT : pub_((NOINIT())) { } inline explicit PublicKeyBase(const NOINIT&) NOEXCEPT : pub_((NOINIT())) { }


+ 4
- 4
src/generator/curve_data.py View File

@@ -36,8 +36,8 @@ curve_data = {
"window_bits":4, "window_bits":4,
"eddsa_hash": "sha512", "eddsa_hash": "sha512",
"eddsa_supports_contexts": 0,
"eddsa_dom": "",
"eddsa_no_context": 1,
"eddsa_dom": "SigEd25519 no Ed25519 collisions",
"eddsa_sigma_iso": 1 "eddsa_sigma_iso": 1
}, },
"ed448goldilocks" : { "ed448goldilocks" : {
@@ -112,8 +112,8 @@ for curve,data in curve_data.iteritems():
if "eddsa_hash" not in data: if "eddsa_hash" not in data:
data["eddsa_hash"] = "shake256" data["eddsa_hash"] = "shake256"
if "eddsa_supports_contexts" not in data:
data["eddsa_supports_contexts"] = 1
if "eddsa_no_context" not in data:
data["eddsa_no_context"] = 0
if "cxx_ns" not in data: if "cxx_ns" not in data:
data["cxx_ns"] = data["name"].replace("-","") data["cxx_ns"] = data["name"].replace("-","")


+ 33
- 61
src/per_curve/eddsa.tmpl.c View File

@@ -19,7 +19,7 @@
#define hash_destroy decaf_$(eddsa_hash)_destroy #define hash_destroy decaf_$(eddsa_hash)_destroy
#define hash_hash decaf_$(eddsa_hash)_hash #define hash_hash decaf_$(eddsa_hash)_hash


#define SUPPORTS_CONTEXTS DECAF_EDDSA_$(gf_shortname)_SUPPORTS_CONTEXTS
#define NO_CONTEXT DECAF_EDDSA_$(gf_shortname)_NO_CONTEXT
#define EDDSA_USE_SIGMA_ISOGENY $(eddsa_sigma_iso) #define EDDSA_USE_SIGMA_ISOGENY $(eddsa_sigma_iso)
#define COFACTOR $(cofactor) #define COFACTOR $(cofactor)


@@ -49,38 +49,33 @@ 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 context_len,
uint8_t no_context
) { ) {
hash_init(hash); hash_init(hash);
#if SUPPORTS_CONTEXTS
#if NO_CONTEXT
if (no_context) {
(void)prehashed;
(void)for_prehash;
(void)context;
(void)context_len;
return;
}
#else
(void)no_context;
#endif
const char *dom_s = "$(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};
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
(void)prehashed;
(void)for_prehash;
(void)context;
assert(context==NULL);
(void)context_len;
assert(context_len == 0);
#endif
} }


void decaf_ed$(gf_shortname)_prehash_init ( void decaf_ed$(gf_shortname)_prehash_init (
hash_ctx_t hash 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
hash_init(hash);
} }


void decaf_ed$(gf_shortname)_derive_public_key ( void decaf_ed$(gf_shortname)_derive_public_key (
@@ -128,16 +123,11 @@ void decaf_ed$(gf_shortname)_sign (
const uint8_t pubkey[DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES], const uint8_t pubkey[DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES],
const uint8_t *message, const uint8_t *message,
size_t message_len, size_t message_len,
uint8_t prehashed
#if SUPPORTS_CONTEXTS
, const uint8_t *context,
uint8_t context_len
#endif
uint8_t prehashed,
const uint8_t *context,
uint8_t context_len,
uint8_t no_context
) { ) {
#if !SUPPORTS_CONTEXTS
const uint8_t *const context = NULL;
const uint8_t context_len = 0;
#endif
API_NS(scalar_t) secret_scalar; API_NS(scalar_t) secret_scalar;
hash_ctx_t hash; hash_ctx_t hash;
{ {
@@ -156,7 +146,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);
hash_init_with_dom(hash,prehashed,0,context,context_len,no_context);
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));
@@ -190,7 +180,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);
hash_init_with_dom(hash,prehashed,0,context,context_len,no_context);
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);
@@ -218,11 +208,9 @@ void decaf_ed$(gf_shortname)_sign_prehash (
uint8_t signature[DECAF_EDDSA_$(gf_shortname)_SIGNATURE_BYTES], uint8_t signature[DECAF_EDDSA_$(gf_shortname)_SIGNATURE_BYTES],
const uint8_t privkey[DECAF_EDDSA_$(gf_shortname)_PRIVATE_BYTES], const uint8_t privkey[DECAF_EDDSA_$(gf_shortname)_PRIVATE_BYTES],
const uint8_t pubkey[DECAF_EDDSA_$(gf_shortname)_PUBLIC_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,
const decaf_ed$(gf_shortname)_prehash_ctx_t hash,
const uint8_t *context,
uint8_t context_len uint8_t context_len
#endif
) { ) {
uint8_t hash_output[64]; /* MAGIC but true for all existing schemes */ uint8_t hash_output[64]; /* MAGIC but true for all existing schemes */
{ {
@@ -231,13 +219,8 @@ void decaf_ed$(gf_shortname)_sign_prehash (
hash_final(hash_too,hash_output,sizeof(hash_output)); hash_final(hash_too,hash_output,sizeof(hash_output));
hash_destroy(hash_too); 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_ed$(gf_shortname)_sign(signature,privkey,pubkey,hash_output,sizeof(hash_output),1,context,context_len,0);
decaf_bzero(hash_output,sizeof(hash_output)); decaf_bzero(hash_output,sizeof(hash_output));
} }


@@ -246,16 +229,11 @@ decaf_error_t decaf_ed$(gf_shortname)_verify (
const uint8_t pubkey[DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES], const uint8_t pubkey[DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES],
const uint8_t *message, const uint8_t *message,
size_t message_len, size_t message_len,
uint8_t prehashed
#if SUPPORTS_CONTEXTS
, const uint8_t *context,
uint8_t context_len
#endif
uint8_t prehashed,
const uint8_t *context,
uint8_t context_len,
uint8_t no_context
) { ) {
#if !SUPPORTS_CONTEXTS
const uint8_t *const context = NULL;
const uint8_t context_len = 0;
#endif
API_NS(point_t) pk_point, r_point; 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);
if (DECAF_SUCCESS != error) { return error; } if (DECAF_SUCCESS != error) { return error; }
@@ -267,7 +245,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);
hash_init_with_dom(hash,prehashed,0,context,context_len,no_context);
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);
@@ -304,11 +282,9 @@ decaf_error_t decaf_ed$(gf_shortname)_verify (
decaf_error_t decaf_ed$(gf_shortname)_verify_prehash ( decaf_error_t decaf_ed$(gf_shortname)_verify_prehash (
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],
const decaf_ed$(gf_shortname)_prehash_ctx_t hash
#if DECAF_EDDSA_$(gf_shortname)_SUPPORTS_CONTEXTS
, const uint8_t *context,
const decaf_ed$(gf_shortname)_prehash_ctx_t hash,
const uint8_t *context,
uint8_t context_len uint8_t context_len
#endif
) { ) {
decaf_error_t ret; decaf_error_t ret;
@@ -320,11 +296,7 @@ decaf_error_t decaf_ed$(gf_shortname)_verify_prehash (
hash_destroy(hash_too); 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
ret = decaf_ed$(gf_shortname)_verify(signature,pubkey,hash_output,sizeof(hash_output),1,context,context_len,0);
return ret; return ret;
} }

+ 22
- 34
src/per_curve/eddsa.tmpl.h View File

@@ -17,8 +17,8 @@ extern "C" {
/** Number of bytes in an EdDSA private key. */ /** Number of bytes in an EdDSA private key. */
#define DECAF_EDDSA_$(gf_shortname)_SIGNATURE_BYTES (DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES + DECAF_EDDSA_$(gf_shortname)_PRIVATE_BYTES) #define DECAF_EDDSA_$(gf_shortname)_SIGNATURE_BYTES (DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES + DECAF_EDDSA_$(gf_shortname)_PRIVATE_BYTES)


/** Does EdDSA support contexts? */
#define DECAF_EDDSA_$(gf_shortname)_SUPPORTS_CONTEXTS $(eddsa_supports_contexts)
/** Does EdDSA support non-contextual signatures? */
#define DECAF_EDDSA_$(gf_shortname)_NO_CONTEXT $(eddsa_no_context)
/** 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
@@ -44,11 +44,12 @@ void decaf_ed$(gf_shortname)_derive_public_key (
* @param [out] signature The signature. * @param [out] signature The signature.
* @param [in] privkey The private key. * @param [in] privkey The private key.
* @param [in] pubkey The public key. * @param [in] pubkey The public key.
* @param [in] context A "context" for this signature of up to 255 bytes.
* @param [in] context_len Length of the context.
* @param [in] message The message to sign. * @param [in] message The message to sign.
* @param [in] message_len The length of the message. * @param [in] message_len The length of the message.
* @param [in] prehashed Nonzero if the message is actually the hash of something you want to sign. * @param [in] prehashed Nonzero if the message is actually the hash of something you want to sign.
* @param [in] context A "context" for this signature of up to 255 bytes.
* @param [in] context_len Length of the context.
* @param [in] no_context Nonzero if no context should be used (only Ed25519 supported).
* *
* @warning For Ed25519, it is unsafe to use the same key for both prehashed and non-prehashed * @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
@@ -61,11 +62,10 @@ void decaf_ed$(gf_shortname)_sign (
const uint8_t pubkey[DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES], const uint8_t pubkey[DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES],
const uint8_t *message, const uint8_t *message,
size_t message_len, size_t message_len,
uint8_t prehashed
#if DECAF_EDDSA_$(gf_shortname)_SUPPORTS_CONTEXTS
, const uint8_t *context,
uint8_t context_len
#endif
uint8_t prehashed,
const uint8_t *context,
uint8_t context_len,
uint8_t no_context
) API_VIS __attribute__((nonnull(1,2,3))) NOINLINE; ) API_VIS __attribute__((nonnull(1,2,3))) NOINLINE;


/** /**
@@ -74,10 +74,9 @@ void decaf_ed$(gf_shortname)_sign (
* @param [out] signature The signature. * @param [out] signature The signature.
* @param [in] privkey The private key. * @param [in] privkey The private key.
* @param [in] pubkey The public key. * @param [in] pubkey The public key.
* @param [in] hash The hash of the message. This object will not be modified by the call.
* @param [in] context A "context" for this signature of up to 255 bytes. Must be the same as what was used for the prehash. * @param [in] context 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] 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 * @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
@@ -88,26 +87,18 @@ void decaf_ed$(gf_shortname)_sign_prehash (
uint8_t signature[DECAF_EDDSA_$(gf_shortname)_SIGNATURE_BYTES], uint8_t signature[DECAF_EDDSA_$(gf_shortname)_SIGNATURE_BYTES],
const uint8_t privkey[DECAF_EDDSA_$(gf_shortname)_PRIVATE_BYTES], const uint8_t privkey[DECAF_EDDSA_$(gf_shortname)_PRIVATE_BYTES],
const uint8_t pubkey[DECAF_EDDSA_$(gf_shortname)_PUBLIC_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,
const decaf_ed$(gf_shortname)_prehash_ctx_t hash,
const uint8_t *context,
uint8_t context_len uint8_t context_len
#endif
) API_VIS __attribute__((nonnull(1,2,3,4))) NOINLINE; ) API_VIS __attribute__((nonnull(1,2,3,4))) NOINLINE;
/** /**
* @brief Prehash initialization, with contexts if supported. * @brief Prehash initialization, with contexts if supported.
* *
* @param [out] hash The hash object to be initialized. * @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 ( void decaf_ed$(gf_shortname)_prehash_init (
decaf_ed$(gf_shortname)_prehash_ctx_t hash 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; ) API_VIS __attribute__((nonnull(1))) NOINLINE;


/** /**
@@ -117,11 +108,12 @@ void decaf_ed$(gf_shortname)_prehash_init (
* *
* @param [in] signature The signature. * @param [in] signature The signature.
* @param [in] pubkey The public key. * @param [in] pubkey The public key.
* @param [in] context A "context" for this signature of up to 255 bytes.
* @param [in] context_len Length of the context.
* @param [in] message The message to verify. * @param [in] message The message to verify.
* @param [in] message_len The length of the message. * @param [in] message_len The length of the message.
* @param [in] prehashed Nonzero if the message is actually the hash of something you want to verify. * @param [in] prehashed Nonzero if the message is actually the hash of something you want to verify.
* @param [in] context A "context" for this signature of up to 255 bytes.
* @param [in] context_len Length of the context.
* @param [in] no_context Nonzero if no context should be used (only Ed25519 supported).
* *
* @warning For Ed25519, it is unsafe to use the same key for both prehashed and non-prehashed * @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
@@ -133,11 +125,10 @@ decaf_error_t decaf_ed$(gf_shortname)_verify (
const uint8_t pubkey[DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES], const uint8_t pubkey[DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES],
const uint8_t *message, const uint8_t *message,
size_t message_len, size_t message_len,
uint8_t prehashed
#if DECAF_EDDSA_$(gf_shortname)_SUPPORTS_CONTEXTS
, const uint8_t *context,
uint8_t context_len
#endif
uint8_t prehashed,
const uint8_t *context,
uint8_t context_len,
uint8_t no_context
) API_VIS __attribute__((nonnull(1,2))) NOINLINE; ) API_VIS __attribute__((nonnull(1,2))) NOINLINE;


/** /**
@@ -147,10 +138,9 @@ decaf_error_t decaf_ed$(gf_shortname)_verify (
* *
* @param [in] signature The signature. * @param [in] signature The signature.
* @param [in] pubkey The public key. * @param [in] pubkey The public key.
* @param [in] hash The hash of the message. This object will not be modified by the call.
* @param [in] context A "context" for this signature of up to 255 bytes. Must be the same as what was used for the prehash. * @param [in] context 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] 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 * @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
@@ -160,11 +150,9 @@ decaf_error_t decaf_ed$(gf_shortname)_verify (
decaf_error_t decaf_ed$(gf_shortname)_verify_prehash ( decaf_error_t decaf_ed$(gf_shortname)_verify_prehash (
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],
const decaf_ed$(gf_shortname)_prehash_ctx_t hash
#if DECAF_EDDSA_$(gf_shortname)_SUPPORTS_CONTEXTS
, const uint8_t *context,
const decaf_ed$(gf_shortname)_prehash_ctx_t hash,
const uint8_t *context,
uint8_t context_len uint8_t context_len
#endif
) API_VIS __attribute__((nonnull(1,2))) NOINLINE; ) API_VIS __attribute__((nonnull(1,2))) NOINLINE;


/** /**


+ 28
- 93
src/per_curve/eddsa.tmpl.hxx View File

@@ -33,27 +33,14 @@ template<> struct EdDSA<$(cxx_ns)> {
/** @cond internal */ /** @cond internal */
template<class CRTP, Prehashed> class Signing; template<class CRTP, Prehashed> class Signing;
template<class CRTP, Prehashed> class Verification; template<class CRTP, Prehashed> class Verification;
$("""
class PublicKeyBase; class PublicKeyBase;
class PrivateKeyBase; class PrivateKeyBase;
typedef class PrivateKeyBase PrivateKey, PrivateKeyPure, PrivateKeyPh; typedef class PrivateKeyBase PrivateKey, PrivateKeyPure, PrivateKeyPh;
typedef class PublicKeyBase PublicKey, PublicKeyPure, PublicKeyPh; typedef class PublicKeyBase PublicKey, PublicKeyPure, PublicKeyPh;
""" if eddsa_supports_contexts else """
template<Prehashed=PURE> class PublicKeyBase;
template<Prehashed=PURE> class PrivateKeyBase;
typedef class PublicKeyBase<PURE> PublicKey, PublicKeyPure;
typedef class PublicKeyBase<PREHASHED> PublicKeyPh;
typedef class PrivateKeyBase<PURE> PrivateKey, PrivateKeyPure;
typedef class PrivateKeyBase<PREHASHED> PrivateKeyPh;
""")
/** @endcond */ /** @endcond */


/** Prehash context for EdDSA. */ /** Prehash context for EdDSA. */
class Prehash : public $(re.sub(r"SHAKE(\d+)",r"SHAKE<\1>", eddsa_hash.upper())) { class Prehash : public $(re.sub(r"SHAKE(\d+)",r"SHAKE<\1>", eddsa_hash.upper())) {
public:
/** Do we support contexts for signatures? If not, they must always be NULL */
static const bool SUPPORTS_CONTEXTS = DECAF_EDDSA_$(gf_shortname)_SUPPORTS_CONTEXTS;
private: private:
typedef $(re.sub(r"SHAKE(\d+)",r"SHAKE<\1>", eddsa_hash.upper())) Super; typedef $(re.sub(r"SHAKE(\d+)",r"SHAKE<\1>", eddsa_hash.upper())) Super;
SecureBuffer context_; SecureBuffer context_;
@@ -63,17 +50,11 @@ private:
void init() throw(LengthException) { void init() throw(LengthException) {
Super::reset(); Super::reset();
if (context_.size() > 255
|| (context_.size() != 0 && !SUPPORTS_CONTEXTS)
) {
if (context_.size() > 255) {
throw LengthException(); throw LengthException();
} }


#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
decaf_ed$(gf_shortname)_prehash_init((decaf_$(eddsa_hash)_ctx_s *)wrapped);
} }
public: public:
@@ -115,11 +96,9 @@ public:
out.data(), out.data(),
((const CRTP*)this)->priv_.data(), ((const CRTP*)this)->priv_.data(),
((const CRTP*)this)->pub_.data(), ((const CRTP*)this)->pub_.data(),
(const decaf_ed$(gf_shortname)_prehash_ctx_s*)ph.wrapped
#if DECAF_EDDSA_$(gf_shortname)_SUPPORTS_CONTEXTS
, ph.context_.data(),
(const decaf_ed$(gf_shortname)_prehash_ctx_s*)ph.wrapped,
ph.context_.data(),
ph.context_.size() ph.context_.size()
#endif
); );
return out; return out;
} }
@@ -140,20 +119,18 @@ public:
/** /**
* Sign a message. * Sign a message.
* @param [in] message The message to be signed. * @param [in] message The message to be signed.
* @param [in] context A context for the signature; must be at most 255 bytes;
* must be absent if SUPPORTS_CONTEXTS == false.
* @param [in] context A context for the signature; must be at most 255 bytes.
* *
* @warning It is generally unsafe to use Ed25519 with both prehashed and non-prehashed messages. * @warning It is generally unsafe to use Ed25519 with both prehashed and non-prehashed messages.
*/ */
inline SecureBuffer sign ( inline SecureBuffer sign (
const Block &message, const Block &message,
const Block &context = Block(NULL,0)
const Block &context = Block(NULL,0),
const bool no_context = false
) const /* TODO: this exn spec tickles a Clang bug? ) const /* TODO: this exn spec tickles a Clang bug?
* throw(LengthException, std::bad_alloc) * throw(LengthException, std::bad_alloc)
*/ { */ {
if (context.size() > 255
|| (context.size() != 0 && !CRTP::SUPPORTS_CONTEXTS)
) {
if (context.size() > 255) {
throw LengthException(); throw LengthException();
} }
@@ -164,17 +141,15 @@ public:
((const CRTP*)this)->pub_.data(), ((const CRTP*)this)->pub_.data(),
message.data(), message.data(),
message.size(), message.size(),
0
#if DECAF_EDDSA_$(gf_shortname)_SUPPORTS_CONTEXTS
, context.data(),
context.size()
#endif
0,
context.data(),
context.size(),
no_context
); );
return out; return out;
} }
}; };


$("""
class PrivateKeyBase class PrivateKeyBase
: public Serializable<PrivateKeyBase> : public Serializable<PrivateKeyBase>
, public Signing<PrivateKeyBase,PURE> , public Signing<PrivateKeyBase,PURE>
@@ -187,18 +162,6 @@ private:
friend class Signing<PrivateKey,PURE>; friend class Signing<PrivateKey,PURE>;
friend class Signing<PrivateKey,PREHASHED>; friend class Signing<PrivateKey,PREHASHED>;
/** @endcond */ /** @endcond */
""" if eddsa_supports_contexts else """
template<Prehashed ph> class PrivateKeyBase
: public Serializable<PrivateKeyBase<ph> >
, public Signing<PrivateKeyBase<ph>,ph> {
public:
typedef class PublicKeyBase<ph> MyPublicKey;
private:
/** @cond internal */
friend class PublicKeyBase<ph>;
friend class Signing<PrivateKeyBase<ph>, ph>;
/** @endcond */
""")
/** The pre-expansion form of the signing key. */ /** The pre-expansion form of the signing key. */
FixedArrayBuffer<DECAF_EDDSA_$(gf_shortname)_PRIVATE_BYTES> priv_; FixedArrayBuffer<DECAF_EDDSA_$(gf_shortname)_PRIVATE_BYTES> priv_;
@@ -216,9 +179,6 @@ public:
/** Serialization size. */ /** Serialization size. */
static const size_t SER_BYTES = DECAF_EDDSA_$(gf_shortname)_PRIVATE_BYTES; static const size_t SER_BYTES = DECAF_EDDSA_$(gf_shortname)_PRIVATE_BYTES;
/** Do we support contexts for signatures? If not, they must always be NULL */
static const bool SUPPORTS_CONTEXTS = DECAF_EDDSA_$(gf_shortname)_SUPPORTS_CONTEXTS;
/** Create but don't initialize */ /** Create but don't initialize */
inline explicit PrivateKeyBase(const NOINIT&) NOEXCEPT : priv_((NOINIT())), pub_((NOINIT())) { } inline explicit PrivateKeyBase(const NOINIT&) NOEXCEPT : priv_((NOINIT())), pub_((NOINIT())) { }
@@ -271,11 +231,10 @@ 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 Block &context = Block(NULL,0),
const bool no_context = false
) const /*NOEXCEPT*/ { ) const /*NOEXCEPT*/ {
if (context.size() > 255
|| (context.size() != 0 && !CRTP::SUPPORTS_CONTEXTS)
) {
if (context.size() > 255) {
return DECAF_FAILURE; return DECAF_FAILURE;
} }
@@ -284,34 +243,31 @@ public:
((const CRTP*)this)->pub_.data(), ((const CRTP*)this)->pub_.data(),
message.data(), message.data(),
message.size(), message.size(),
0
#if DECAF_EDDSA_$(gf_shortname)_SUPPORTS_CONTEXTS
, context.data(),
context.size()
#endif
0,
context.data(),
context.size(),
no_context
); );
} }
/** Verify a signature, throwing an exception if verification fails /** Verify a signature, throwing an exception if verification fails
* @param [in] sig The signature. * @param [in] sig The signature.
* @param [in] message The signed message. * @param [in] message The signed message.
* @param [in] context A context for the signature; must be at most 255 bytes;
* must be absent if SUPPORTS_CONTEXTS == false.
* @param [in] context A context for the signature; must be at most 255 bytes.
* *
* @warning It is generally unsafe to use Ed25519 with both prehashed and non-prehashed messages. * @warning It is generally unsafe to use Ed25519 with both prehashed and non-prehashed messages.
*/ */
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 Block &context = Block(NULL,0),
const bool no_context = false
) const /*throw(LengthException,CryptoException)*/ { ) const /*throw(LengthException,CryptoException)*/ {
if (context.size() > 255
|| (context.size() != 0 && !CRTP::SUPPORTS_CONTEXTS)
) {
if (context.size() > 255) {
throw LengthException(); throw LengthException();
} }
if (DECAF_SUCCESS != verify_noexcept( sig, message, context )) {
if (DECAF_SUCCESS != verify_noexcept( sig, message, context, no_context )) {
throw CryptoException(); throw CryptoException();
} }
} }
@@ -328,11 +284,9 @@ public:
return decaf_ed$(gf_shortname)_verify_prehash ( return decaf_ed$(gf_shortname)_verify_prehash (
sig.data(), sig.data(),
((const CRTP*)this)->pub_.data(), ((const CRTP*)this)->pub_.data(),
(const decaf_ed$(gf_shortname)_prehash_ctx_s*)ph.wrapped
#if DECAF_EDDSA_$(gf_shortname)_SUPPORTS_CONTEXTS
, ph.context_.data(),
(const decaf_ed$(gf_shortname)_prehash_ctx_s*)ph.wrapped,
ph.context_.data(),
ph.context_.size() ph.context_.size()
#endif
); );
} }
@@ -344,11 +298,9 @@ public:
if (DECAF_SUCCESS != decaf_ed$(gf_shortname)_verify_prehash ( if (DECAF_SUCCESS != decaf_ed$(gf_shortname)_verify_prehash (
sig.data(), sig.data(),
((const CRTP*)this)->pub_.data(), ((const CRTP*)this)->pub_.data(),
(const decaf_ed$(gf_shortname)_prehash_ctx_s*)ph.wrapped
#if DECAF_EDDSA_$(gf_shortname)_SUPPORTS_CONTEXTS
, ph.context_.data(),
(const decaf_ed$(gf_shortname)_prehash_ctx_s*)ph.wrapped,
ph.context_.data(),
ph.context_.size() ph.context_.size()
#endif
)) { )) {
throw CryptoException(); throw CryptoException();
} }
@@ -367,7 +319,6 @@ public:
}; };




$("""
class PublicKeyBase class PublicKeyBase
: public Serializable<PublicKeyBase> : public Serializable<PublicKeyBase>
, public Verification<PublicKeyBase,PURE> , public Verification<PublicKeyBase,PURE>
@@ -381,19 +332,6 @@ private:
friend class Verification<PublicKey,PURE>; friend class Verification<PublicKey,PURE>;
friend class Verification<PublicKey,PREHASHED>; friend class Verification<PublicKey,PREHASHED>;
/** @endcond */ /** @endcond */
""" if eddsa_supports_contexts else """
template<Prehashed ph> class PublicKeyBase
: public Serializable<PublicKeyBase<ph> >
, public Verification<PublicKeyBase<ph>,ph> {
public:
typedef class PrivateKeyBase<ph> MyPrivateKey;
private:
/** @cond internal */
friend class PrivateKeyBase<ph>;
friend class Verification<PublicKeyBase<ph>, ph>;
/** @endcond */
""")


private: private:
/** The pre-expansion form of the signature */ /** The pre-expansion form of the signature */
@@ -411,9 +349,6 @@ public:
/** Serialization size. */ /** Serialization size. */
static const size_t SER_BYTES = DECAF_EDDSA_$(gf_shortname)_PRIVATE_BYTES; static const size_t SER_BYTES = DECAF_EDDSA_$(gf_shortname)_PRIVATE_BYTES;
/** Do we support contexts for signatures? If not, they must always be NULL */
static const bool SUPPORTS_CONTEXTS = DECAF_EDDSA_$(gf_shortname)_SUPPORTS_CONTEXTS;
/** Create but don't initialize */ /** Create but don't initialize */
inline explicit PublicKeyBase(const NOINIT&) NOEXCEPT : pub_((NOINIT())) { } inline explicit PublicKeyBase(const NOINIT&) NOEXCEPT : pub_((NOINIT())) { }


+ 4
- 12
test/test_decaf.cxx View File

@@ -469,7 +469,7 @@ static void test_cfrg_crypto() {
} }
} }


static const bool eddsa_prehashed[];
static const bool eddsa_prehashed[], eddsa_no_context[];
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() {
@@ -497,17 +497,9 @@ static void test_cfrg_vectors() {
if (eddsa_prehashed[t]) { if (eddsa_prehashed[t]) {
typename EdDSA<Group>::PrivateKeyPh priv2(eddsa_sk[t]); typename EdDSA<Group>::PrivateKeyPh priv2(eddsa_sk[t]);
if (priv2.SUPPORTS_CONTEXTS) {
sig = priv2.sign_with_prehash(eddsa_message[t],eddsa_context[t]);
} else {
sig = priv2.sign_with_prehash(eddsa_message[t]);
}
sig = priv2.sign_with_prehash(eddsa_message[t],eddsa_context[t]);
} else { } else {
if (priv.SUPPORTS_CONTEXTS) {
sig = priv.sign(eddsa_message[t],eddsa_context[t]);
} else {
sig = priv.sign(eddsa_message[t]);
}
sig = priv.sign(eddsa_message[t],eddsa_context[t],eddsa_no_context[t]);
} }


if (!memeq(SecureBuffer(eddsa_sig[t]),sig)) { if (!memeq(SecureBuffer(eddsa_sig[t]),sig)) {
@@ -557,7 +549,7 @@ static void test_eddsa() {
SecureBuffer message(i); SecureBuffer message(i);
rng.read(message); rng.read(message);
SecureBuffer context(priv.SUPPORTS_CONTEXTS ? i%256 : 0);
SecureBuffer context(i%256);
rng.read(message); rng.read(message);
SecureBuffer sig = priv.sign(message,context); SecureBuffer sig = priv.sign(message,context);


+ 117
- 30
test/vectors.inc.cxx View File

@@ -189,6 +189,7 @@ template<> const bool Tests<Ed448Goldilocks>::eddsa_prehashed[] = {
false, false,
false, false,
false, false,
true,
true true
}; };


@@ -276,21 +277,37 @@ const uint8_t ed448_eddsa_sig[][114] = {{
0xa4,0x91,0x55,0xc1,0x37,0x64,0xe6,0x6c, 0xa4,0x91,0x55,0xc1,0x37,0x64,0xe6,0x6c,
0x3c,0x00 0x3c,0x00
}, { }, {
0x86,0xa6,0xbf,0x52,0xf9,0xe8,0xf8,0x4f,
0x45,0x1b,0x2f,0x39,0x2a,0x8d,0x1c,0x3a,
0x41,0x44,0x25,0xfa,0xc0,0x06,0x8f,0x74,
0xae,0xea,0xd5,0x3b,0x0e,0x6b,0x53,0xd4,
0x55,0x5c,0xea,0x17,0x26,0xda,0x4a,0x65,
0x20,0x28,0x80,0xd4,0x07,0x26,0x70,0x87,
0x9e,0x8e,0x6f,0xa4,0xd9,0x69,0x4c,0x06,
0x00,0x54,0xf2,0x06,0x5d,0xc2,0x06,0xa6,
0xe6,0x15,0xd0,0xd8,0xc9,0x9b,0x95,0x20,
0x9b,0x69,0x6c,0x81,0x25,0xc5,0xfb,0xb9,
0xbc,0x82,0xa0,0xf7,0xed,0x3d,0x99,0xc4,
0xc1,0x1c,0x47,0x79,0x8e,0xf0,0xf7,0xeb,
0x97,0xb3,0xb7,0x2a,0xb4,0xac,0x86,0xea,
0xf8,0xb4,0x34,0x49,0xe8,0xac,0x30,0xff,
0x3f,0x00
0x82,0x2f,0x69,0x01,0xf7,0x48,0x0f,0x3d,
0x5f,0x56,0x2c,0x59,0x29,0x94,0xd9,0x69,
0x36,0x02,0x87,0x56,0x14,0x48,0x32,0x56,
0x50,0x56,0x00,0xbb,0xc2,0x81,0xae,0x38,
0x1f,0x54,0xd6,0xbc,0xe2,0xea,0x91,0x15,
0x74,0x93,0x2f,0x52,0xa4,0xe6,0xca,0xdd,
0x78,0x76,0x93,0x75,0xec,0x3f,0xfd,0x1b,
0x80,0x1a,0x0d,0x9b,0x3f,0x40,0x30,0xcd,
0x43,0x39,0x64,0xb6,0x45,0x7e,0xa3,0x94,
0x76,0x51,0x12,0x14,0xf9,0x74,0x69,0xb5,
0x7d,0xd3,0x2d,0xbc,0x56,0x0a,0x9a,0x94,
0xd0,0x0b,0xff,0x07,0x62,0x04,0x64,0xa3,
0xad,0x20,0x3d,0xf7,0xdc,0x7c,0xe3,0x60,
0xc3,0xcd,0x36,0x96,0xd9,0xd9,0xfa,0xb9,
0x0f,0x00
}, {
0xc3,0x22,0x99,0xd4,0x6e,0xc8,0xff,0x02,
0xb5,0x45,0x40,0x98,0x28,0x14,0xdc,0xe9,
0xa0,0x58,0x12,0xf8,0x19,0x62,0xb6,0x49,
0xd5,0x28,0x09,0x59,0x16,0xa2,0xaa,0x48,
0x10,0x65,0xb1,0x58,0x04,0x23,0xef,0x92,
0x7e,0xcf,0x0a,0xf5,0x88,0x8f,0x90,0xda,
0x0f,0x6a,0x9a,0x85,0xad,0x5d,0xc3,0xf2,
0x80,0xd9,0x12,0x24,0xba,0x99,0x11,0xa3,
0x65,0x3d,0x00,0xe4,0x84,0xe2,0xce,0x23,
0x25,0x21,0x48,0x1c,0x86,0x58,0xdf,0x30,
0x4b,0xb7,0x74,0x5a,0x73,0x51,0x4c,0xdb,
0x9b,0xf3,0xe1,0x57,0x84,0xab,0x71,0x28,
0x4f,0x8d,0x07,0x04,0xa6,0x08,0xc5,0x4a,
0x6b,0x62,0xd9,0x7b,0xeb,0x51,0x1d,0x13,
0x21,0x00
}}; }};
template<> const Block Tests<Ed448Goldilocks>::eddsa_sk[] = { template<> const Block Tests<Ed448Goldilocks>::eddsa_sk[] = {
Block(ed448_eddsa_sk[0],57), Block(ed448_eddsa_sk[0],57),
@@ -299,6 +316,7 @@ template<> const Block Tests<Ed448Goldilocks>::eddsa_sk[] = {
Block(ed448_eddsa_sk[2],57), Block(ed448_eddsa_sk[2],57),
Block(ed448_eddsa_sk[3],57), Block(ed448_eddsa_sk[3],57),
Block(ed448_eddsa_sk[4],57), Block(ed448_eddsa_sk[4],57),
Block(ed448_eddsa_sk[4],57),
Block(NULL,0) Block(NULL,0)
}; };
template<> const Block Tests<Ed448Goldilocks>::eddsa_pk[] = { template<> const Block Tests<Ed448Goldilocks>::eddsa_pk[] = {
@@ -307,6 +325,7 @@ template<> const Block Tests<Ed448Goldilocks>::eddsa_pk[] = {
Block(ed448_eddsa_pk[1],57), Block(ed448_eddsa_pk[1],57),
Block(ed448_eddsa_pk[2],57), Block(ed448_eddsa_pk[2],57),
Block(ed448_eddsa_pk[3],57), Block(ed448_eddsa_pk[3],57),
Block(ed448_eddsa_pk[4],57),
Block(ed448_eddsa_pk[4],57) Block(ed448_eddsa_pk[4],57)
}; };
template<> const Block Tests<Ed448Goldilocks>::eddsa_message[] = { template<> const Block Tests<Ed448Goldilocks>::eddsa_message[] = {
@@ -315,6 +334,7 @@ template<> const Block Tests<Ed448Goldilocks>::eddsa_message[] = {
Block(ed448_eddsa_message[1],1), Block(ed448_eddsa_message[1],1),
Block(ed448_eddsa_message[2],11), Block(ed448_eddsa_message[2],11),
Block(ed448_eddsa_message[3],12), Block(ed448_eddsa_message[3],12),
Block(ed448_eddsa_message[4],3),
Block(ed448_eddsa_message[4],3) Block(ed448_eddsa_message[4],3)
}; };
template<> const Block Tests<Ed448Goldilocks>::eddsa_context[] = { template<> const Block Tests<Ed448Goldilocks>::eddsa_context[] = {
@@ -323,15 +343,26 @@ template<> const Block Tests<Ed448Goldilocks>::eddsa_context[] = {
Block(ed448_eddsa_context[0],3), Block(ed448_eddsa_context[0],3),
Block(NULL,0), Block(NULL,0),
Block(NULL,0), 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),
Block(ed448_eddsa_sig[4],114), Block(ed448_eddsa_sig[4],114),
Block(ed448_eddsa_sig[2],114), Block(ed448_eddsa_sig[2],114),
Block(ed448_eddsa_sig[3],114), Block(ed448_eddsa_sig[3],114),
Block(ed448_eddsa_sig[5],114)
Block(ed448_eddsa_sig[5],114),
Block(ed448_eddsa_sig[6],114)
}; };


const uint8_t ed25519_eddsa_sk[][32] = {{ const uint8_t ed25519_eddsa_sk[][32] = {{
@@ -354,6 +385,11 @@ const uint8_t ed25519_eddsa_sk[][32] = {{
0x62,0xec,0x77,0x58,0x75,0x20,0x91,0x1e, 0x62,0xec,0x77,0x58,0x75,0x20,0x91,0x1e,
0x9a,0x75,0x9c,0xec,0x1d,0x19,0x75,0x5b, 0x9a,0x75,0x9c,0xec,0x1d,0x19,0x75,0x5b,
0x7d,0xa9,0x01,0xb9,0x6d,0xca,0x3d,0x42 0x7d,0xa9,0x01,0xb9,0x6d,0xca,0x3d,0x42
}, {
0x03,0x05,0x33,0x4e,0x38,0x1a,0xf7,0x8f,
0x14,0x1c,0xb6,0x66,0xf6,0x19,0x9f,0x57,
0xbc,0x34,0x95,0x33,0x5a,0x25,0x6a,0x95,
0xbd,0x2a,0x55,0xbf,0x54,0x66,0x63,0xf6
}}; }};
const uint8_t ed25519_eddsa_pk[][32] = {{ const uint8_t ed25519_eddsa_pk[][32] = {{
0xd7,0x5a,0x98,0x01,0x82,0xb1,0x0a,0xb7, 0xd7,0x5a,0x98,0x01,0x82,0xb1,0x0a,0xb7,
@@ -375,8 +411,13 @@ const uint8_t ed25519_eddsa_pk[][32] = {{
0xf4,0x93,0x2c,0x70,0xe1,0x24,0x50,0x34, 0xf4,0x93,0x2c,0x70,0xe1,0x24,0x50,0x34,
0xc3,0x54,0x67,0xef,0x2e,0xfd,0x4d,0x64, 0xc3,0x54,0x67,0xef,0x2e,0xfd,0x4d,0x64,
0xeb,0xf8,0x19,0x68,0x34,0x67,0xe2,0xbf 0xeb,0xf8,0x19,0x68,0x34,0x67,0xe2,0xbf
}, {
0xdf,0xc9,0x42,0x5e,0x4f,0x96,0x8f,0x7f,
0x0c,0x29,0xf0,0x25,0x9c,0xf5,0xf9,0xae,
0xd6,0x85,0x1c,0x2b,0xb4,0xad,0x8b,0xfb,
0x86,0x0c,0xfe,0xe0,0xab,0x24,0x82,0x92
}}; }};
const uint8_t ed25519_eddsa_message[][3] = {{
const uint8_t ed25519_eddsa_message[][16] = {{
0 0
}, { }, {
0x72 0x72
@@ -384,6 +425,14 @@ const uint8_t ed25519_eddsa_message[][3] = {{
0xaf,0x82 0xaf,0x82
}, { }, {
0x61,0x62,0x63 0x61,0x62,0x63
}, {
0xf7,0x26,0x93,0x6d,0x19,0xc8,0x00,0x49,
0x4e,0x3f,0xda,0xff,0x20,0xb2,0x76,0xa8
}};
const uint8_t ed25519_eddsa_context[][3] = {{
0x66,0x6f,0x6f
}, {
0x62,0x61,0x72
}}; }};
const uint8_t ed25519_eddsa_sig[][64] = {{ const uint8_t ed25519_eddsa_sig[][64] = {{
0xe5,0x56,0x43,0x00,0xc3,0x60,0xac,0x72, 0xe5,0x56,0x43,0x00,0xc3,0x60,0xac,0x72,
@@ -413,50 +462,88 @@ const uint8_t ed25519_eddsa_sig[][64] = {{
0x4a,0x7c,0x15,0xe9,0x71,0x6e,0xd2,0x8d, 0x4a,0x7c,0x15,0xe9,0x71,0x6e,0xd2,0x8d,
0xc0,0x27,0xbe,0xce,0xea,0x1e,0xc4,0x0a 0xc0,0x27,0xbe,0xce,0xea,0x1e,0xc4,0x0a
}, { }, {
0xdc,0x2a,0x44,0x59,0xe7,0x36,0x96,0x33,
0xa5,0x2b,0x1b,0xf2,0x77,0x83,0x9a,0x00,
0x20,0x10,0x09,0xa3,0xef,0xbf,0x3e,0xcb,
0x69,0xbe,0xa2,0x18,0x6c,0x26,0xb5,0x89,
0x09,0x35,0x1f,0xc9,0xac,0x90,0xb3,0xec,
0xfd,0xfb,0xc7,0xc6,0x64,0x31,0xe0,0x30,
0x3d,0xca,0x17,0x9c,0x13,0x8a,0xc1,0x7a,
0xd9,0xbe,0xf1,0x17,0x73,0x31,0xa7,0x04
0x98,0xa7,0x02,0x22,0xf0,0xb8,0x12,0x1a,
0xa9,0xd3,0x0f,0x81,0x3d,0x68,0x3f,0x80,
0x9e,0x46,0x2b,0x46,0x9c,0x7f,0xf8,0x76,
0x39,0x49,0x9b,0xb9,0x4e,0x6d,0xae,0x41,
0x31,0xf8,0x50,0x42,0x46,0x3c,0x2a,0x35,
0x5a,0x20,0x03,0xd0,0x62,0xad,0xf5,0xaa,
0xa1,0x0b,0x8c,0x61,0xe6,0x36,0x06,0x2a,
0xaa,0xd1,0x1c,0x2a,0x26,0x08,0x34,0x06
}, {
0x55,0xa4,0xcc,0x2f,0x70,0xa5,0x4e,0x04,
0x28,0x8c,0x5f,0x4c,0xd1,0xe4,0x5a,0x7b,
0xb5,0x20,0xb3,0x62,0x92,0x91,0x18,0x76,
0xca,0xda,0x73,0x23,0x19,0x8d,0xd8,0x7a,
0x8b,0x36,0x95,0x0b,0x95,0x13,0x00,0x22,
0x90,0x7a,0x7f,0xb7,0xc4,0xe9,0xb2,0xd5,
0xf6,0xcc,0xa6,0x85,0xa5,0x87,0xb4,0xb2,
0x1f,0x4b,0x88,0x8e,0x4e,0x7e,0xdb,0x0d
}, {
0xfc,0x60,0xd5,0x87,0x2f,0xc4,0x6b,0x3a,
0xa6,0x9f,0x8b,0x5b,0x43,0x51,0xd5,0x80,
0x8f,0x92,0xbc,0xc0,0x44,0x60,0x6d,0xb0,
0x97,0xab,0xab,0x6d,0xbc,0xb1,0xae,0xe3,
0x21,0x6c,0x48,0xe8,0xb3,0xb6,0x64,0x31,
0xb5,0xb1,0x86,0xd1,0xd2,0x8f,0x8e,0xe1,
0x5a,0x5c,0xa2,0xdf,0x66,0x68,0x34,0x62,
0x91,0xc2,0x04,0x3d,0x4e,0xb3,0xe9,0x0d
}}; }};


template<> const bool Tests<IsoEd25519>::eddsa_prehashed[] = { template<> const bool Tests<IsoEd25519>::eddsa_prehashed[] = {
false, false,
false, false,
false, false,
true
true,
false,
false
}; };
template<> const Block Tests<IsoEd25519>::eddsa_sk[] = { template<> const Block Tests<IsoEd25519>::eddsa_sk[] = {
Block(ed25519_eddsa_sk[0],32), Block(ed25519_eddsa_sk[0],32),
Block(ed25519_eddsa_sk[1],32), Block(ed25519_eddsa_sk[1],32),
Block(ed25519_eddsa_sk[2],32), Block(ed25519_eddsa_sk[2],32),
Block(ed25519_eddsa_sk[3],32), Block(ed25519_eddsa_sk[3],32),
Block(ed25519_eddsa_sk[4],32),
Block(ed25519_eddsa_sk[4],32),
Block(NULL,0) Block(NULL,0)
}; };
template<> const Block Tests<IsoEd25519>::eddsa_pk[] = { template<> const Block Tests<IsoEd25519>::eddsa_pk[] = {
Block(ed25519_eddsa_pk[0],32), Block(ed25519_eddsa_pk[0],32),
Block(ed25519_eddsa_pk[1],32), Block(ed25519_eddsa_pk[1],32),
Block(ed25519_eddsa_pk[2],32), Block(ed25519_eddsa_pk[2],32),
Block(ed25519_eddsa_pk[3],32)
Block(ed25519_eddsa_pk[3],32),
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(NULL,0),
Block(NULL,0), Block(NULL,0),
Block(NULL,0)
Block(NULL,0),
Block(ed25519_eddsa_context[0],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),
Block(ed25519_eddsa_message[2],2), Block(ed25519_eddsa_message[2],2),
Block(ed25519_eddsa_message[3],3)
Block(ed25519_eddsa_message[3],3),
Block(ed25519_eddsa_message[4],16),
Block(ed25519_eddsa_message[4],16)
}; };
template<> const Block Tests<IsoEd25519>::eddsa_sig[] = { template<> const Block Tests<IsoEd25519>::eddsa_sig[] = {
Block(ed25519_eddsa_sig[0],64), Block(ed25519_eddsa_sig[0],64),
Block(ed25519_eddsa_sig[1],64), Block(ed25519_eddsa_sig[1],64),
Block(ed25519_eddsa_sig[2],64), Block(ed25519_eddsa_sig[2],64),
Block(ed25519_eddsa_sig[3],64)
Block(ed25519_eddsa_sig[3],64),
Block(ed25519_eddsa_sig[4],64),
Block(ed25519_eddsa_sig[5],64)
}; };

Loading…
Cancel
Save