Browse Source

Update EdDSA operations to match draft 07 from CFRG.

master
Andrew Bennett 10 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