@@ -169,7 +169,8 @@ LIBCOMPONENTS += $$(BUILD_OBJ)/$(1)/decaf.o $$(BUILD_OBJ)/$(1)/elligator.o $$(BU | |||
$$(BUILD_OBJ)/$(1)/crypto.o $$(BUILD_OBJ)/$(1)/eddsa.o $$(BUILD_OBJ)/$(1)/decaf_tables.o | |||
PER_OBJ_DIRS += $$(BUILD_OBJ)/$(1) | |||
GLOBAL_HEADERS_OF_$(1) = $(BUILD_INC)/decaf/decaf_$(3).h $(BUILD_INC)/decaf/decaf_$(3).hxx \ | |||
$(BUILD_INC)/decaf/crypto_$(3).h $(BUILD_INC)/decaf/crypto_$(3).hxx | |||
$(BUILD_INC)/decaf/crypto_$(3).h $(BUILD_INC)/decaf/crypto_$(3).hxx \ | |||
$(BUILD_INC)/decaf/eddsa_$(3).h | |||
HEADERS_OF_$(1) = $$(HEADERS_OF_$(2)) $$(GLOBAL_HEADERS_OF_$(1)) | |||
HEADERS += $$(GLOBAL_HEADERS_OF_$(1)) | |||
@@ -182,6 +183,9 @@ $$(BUILD_H)/$(1)/%.h: src/per_curve/%.tmpl.h src/gen_headers/* $$(HEADERS_OF_$(2 | |||
$$(BUILD_INC)/decaf/decaf_$(3).%: src/per_curve/decaf.tmpl.% src/gen_headers/* $$(HEADERS_OF_$(2)) | |||
python -B src/gen_headers/template.py --per=curve --item=$(1) --guard=$$(@:$(BUILD_INC)/%=%) -o $$@ $$< | |||
$$(BUILD_INC)/decaf/eddsa_$(3).%: src/per_curve/eddsa.tmpl.% src/gen_headers/* $$(HEADERS_OF_$(2)) | |||
python -B src/gen_headers/template.py --per=curve --item=$(1) --guard=$$(@:$(BUILD_INC)/%=%) -o $$@ $$< | |||
$$(BUILD_INC)/decaf/elligator_$(3).%: src/per_curve/elligator.tmpl.% src/gen_headers/* $$(HEADERS_OF_$(2)) | |||
python -B src/gen_headers/template.py --per=curve --item=$(1) --guard=$$(@:$(BUILD_INC)/%=%) -o $$@ $$< | |||
@@ -33,7 +33,10 @@ curve_data = { | |||
"combs":comb_config(3,5,17), | |||
"wnaf":wnaf_config(5,3), | |||
"window_bits":4 | |||
"window_bits":4, | |||
"eddsa_hash": "sha512", | |||
"eddsa_supports_contexts": 0 | |||
}, | |||
"ed448goldilocks" : { | |||
"name" : "Ed448-Goldilocks", | |||
@@ -101,6 +104,12 @@ for curve,data in curve_data.iteritems(): | |||
if "iso_to" not in data: | |||
data["iso_to"] = data["name"] | |||
if "eddsa_hash" not in data: | |||
data["edddsa"] = "sha512" | |||
if "eddsa_supports_contexts" not in data: | |||
data["eddsa_supports_contexts"] = 1 | |||
if "cxx_ns" not in data: | |||
data["cxx_ns"] = data["name"].replace("-","") | |||
@@ -5,6 +5,7 @@ | |||
#include "field.h" | |||
#include <decaf.h> | |||
#include <decaf/eddsa_$(gf_bits).h> | |||
/* Template stuff */ | |||
#define API_NS(_id) $(c_ns)_##_id | |||
@@ -37,16 +37,6 @@ typedef struct gf_$(gf_shortname)_s { | |||
/** Number of bits in the "which" field of an elligator inverse */ | |||
#define $(C_NS)_INVERT_ELLIGATOR_WHICH_BITS $(ceil_log2(cofactor) + 7 + elligator_onto - ((gf_bits-2) % 8)) | |||
/* TODO: move to a different file? */ | |||
/** Number of bytes in an EdDSA public key. */ | |||
#define $(C_NS)_EDDSA_PUBLIC_BYTES $((gf_bits)/8 + 1) /* TODO: change name? */ | |||
/** Number of bytes in an EdDSA private key. */ | |||
#define $(C_NS)_EDDSA_PRIVATE_BYTES $(C_NS)_EDDSA_PUBLIC_BYTES /* TODO: change name? */ | |||
/** Number of bytes in an EdDSA private key. */ | |||
#define $(C_NS)_EDDSA_SIGNATURE_BYTES ($(C_NS)_EDDSA_PUBLIC_BYTES + $(C_NS)_EDDSA_PRIVATE_BYTES) /* TODO: change name? */ | |||
/** Number of bytes in an x$(gf_shortname) public key */ | |||
#define X$(gf_shortname)_PUBLIC_BYTES $((gf_bits-1)/8 + 1) | |||
@@ -414,90 +404,6 @@ void $(c_ns)_x_base_scalarmul ( | |||
const uint8_t scalar[X$(gf_shortname)_PRIVATE_BYTES] | |||
) API_VIS NONNULL NOINLINE; | |||
/** | |||
* @brief EdDSA key generation. This function uses a different (non-Decaf) | |||
* encoding. | |||
* | |||
* @param [out] pubkey The public key. | |||
* @param [in] privkey The private key. | |||
*/ | |||
void $(c_ns)_eddsa_derive_public_key ( | |||
uint8_t pubkey[$(C_NS)_EDDSA_PUBLIC_BYTES], | |||
const uint8_t privkey[$(C_NS)_EDDSA_PRIVATE_BYTES] | |||
) API_VIS NONNULL NOINLINE; | |||
/** | |||
* @brief EdDSA signing. | |||
* | |||
* @param [out] signature The signature. | |||
* @param [in] privkey The private key. | |||
* @param [in] pubkey The public key. | |||
* @param [in] context A "context" for this signature of up to 255 bytes. | |||
* @param [in] context_len Length of the context. | |||
* @param [in] message The message to sign. | |||
* @param [in] message_len The length of the message. | |||
* @param [in] prehashed Nonzero if the message is actually the hash of something you want to sign. | |||
*/ | |||
void $(c_ns)_eddsa_sign ( | |||
uint8_t signature[$(C_NS)_EDDSA_SIGNATURE_BYTES], | |||
const uint8_t privkey[$(C_NS)_EDDSA_PRIVATE_BYTES], | |||
const uint8_t pubkey[$(C_NS)_EDDSA_PUBLIC_BYTES], | |||
const uint8_t *context, | |||
uint8_t context_len, | |||
const uint8_t *message, | |||
size_t message_len, | |||
uint8_t prehashed | |||
) API_VIS __attribute__((nonnull(1,2,3))) NOINLINE; | |||
/** | |||
* @brief EdDSA signature verification. | |||
* | |||
* Uses the standard (i.e. less-strict) verification formula. | |||
* | |||
* @param [in] signature The signature. | |||
* @param [in] pubkey The public key. | |||
* @param [in] context A "context" for this signature of up to 255 bytes. | |||
* @param [in] context_len Length of the context. | |||
* @param [in] message The message to verify. | |||
* @param [in] message_len The length of the message. | |||
* @param [in] prehashed Nonzero if the message is actually the hash of something you want to verify. | |||
*/ | |||
decaf_error_t $(c_ns)_eddsa_verify ( | |||
const uint8_t signature[$(C_NS)_EDDSA_SIGNATURE_BYTES], | |||
const uint8_t pubkey[$(C_NS)_EDDSA_PUBLIC_BYTES], | |||
const uint8_t *context, | |||
uint8_t context_len, | |||
const uint8_t *message, | |||
size_t message_len, | |||
uint8_t prehashed | |||
) API_VIS __attribute__((nonnull(1,2))) NOINLINE; | |||
/** | |||
* @brief EdDSA point encoding. | |||
* | |||
* @param [out] enc The encoded point. | |||
* @param [in] p The point. | |||
* | |||
* FIXME: encode and decode aren't inverses of each other: they | |||
* multiply by a factor. Rename to reflect this once the base | |||
* point doctrine is worked out. | |||
*/ | |||
void $(c_ns)_point_encode_like_eddsa ( | |||
uint8_t enc[$(C_NS)_EDDSA_PUBLIC_BYTES], | |||
const $(c_ns)_point_t p | |||
) API_VIS NONNULL NOINLINE; | |||
/** | |||
* @brief EdDSA point encoding. | |||
* | |||
* @param [out] enc The encoded point. | |||
* @param [in] p The point. | |||
*/ | |||
decaf_error_t $(c_ns)_point_decode_like_eddsa ( | |||
$(c_ns)_point_t p, | |||
const uint8_t enc[$(C_NS)_EDDSA_PUBLIC_BYTES] | |||
) API_VIS NONNULL NOINLINE; | |||
/** | |||
* @brief Precompute a table for fast scalar multiplication. | |||
* Some implementations do not include precomputed points; for | |||
@@ -21,6 +21,7 @@ | |||
#include <string.h> /* for memcpy */ | |||
#include <decaf/decaf_$(gf_bits).h> | |||
#include <decaf/eddsa_$(gf_bits).h> /* TODO: move eddsa to another file? */ | |||
#include <decaf/secure_buffer.hxx> | |||
#include <string> | |||
#include <sys/types.h> | |||
@@ -685,6 +686,9 @@ public: | |||
/** The size of a private key */ | |||
static const size_t SIGNATURE_BYTES = $(C_NS)_EDDSA_SIGNATURE_BYTES; | |||
/** Do we support contexts for signatures? If not, they must always be NULL */ | |||
static const bool SUPPORTS_CONTEXTS = $(C_NS)_EDDSA_SUPPORTS_CONTEXTS; | |||
static inline SecureBuffer generate_key ( | |||
const FixedBlock<PRIVATE_BYTES> &priv | |||
) { | |||
@@ -696,21 +700,28 @@ public: | |||
static inline SecureBuffer sign ( | |||
const FixedBlock<PRIVATE_BYTES> &priv, | |||
const FixedBlock<PUBLIC_BYTES> &pub, | |||
const Block &context, | |||
const Block &message, | |||
bool prehashed = false | |||
bool prehashed = false, | |||
const Block &context = Block(NULL,0) | |||
) throw(LengthException) { | |||
if (context.size() > 255) { throw LengthException(); } | |||
if (context.size() > 255 | |||
|| (context.size() != 0 && !SUPPORTS_CONTEXTS) | |||
) { | |||
throw LengthException(); | |||
} | |||
SecureBuffer out(SIGNATURE_BYTES); | |||
$(c_ns)_eddsa_sign ( | |||
out.data(), | |||
priv.data(), | |||
pub.data(), | |||
context.data(), | |||
context.size(), | |||
message.data(), | |||
message.size(), | |||
prehashed | |||
#if $(C_NS)_EDDSA_SUPPORTS_CONTEXTS | |||
, context.data(), | |||
context.size() | |||
#endif | |||
); | |||
return out; | |||
} | |||
@@ -718,31 +729,43 @@ public: | |||
static inline decaf_error_t WARN_UNUSED verify_noexcept ( | |||
const FixedBlock<SIGNATURE_BYTES> &sig, | |||
const FixedBlock<PUBLIC_BYTES> &pub, | |||
const Block &context, | |||
const Block &message, | |||
bool prehashed = false | |||
bool prehashed = false, | |||
const Block &context = Block(NULL,0) | |||
) { | |||
if (context.size() > 255) return DECAF_FAILURE; | |||
if (context.size() > 255 | |||
|| (context.size() != 0 && !SUPPORTS_CONTEXTS) | |||
) { | |||
return DECAF_FAILURE; | |||
} | |||
return $(c_ns)_eddsa_verify ( | |||
sig.data(), | |||
pub.data(), | |||
context.data(), | |||
context.size(), | |||
message.data(), | |||
message.size(), | |||
prehashed | |||
#if $(C_NS)_EDDSA_SUPPORTS_CONTEXTS | |||
, context.data(), | |||
context.size() | |||
#endif | |||
); | |||
} | |||
static inline void verify ( | |||
const FixedBlock<SIGNATURE_BYTES> &sig, | |||
const FixedBlock<PUBLIC_BYTES> &pub, | |||
const Block &context, | |||
const Block &message, | |||
bool prehashed = false | |||
bool prehashed = false, | |||
const Block &context = Block(NULL,0) | |||
) throw(LengthException,CryptoException) { | |||
if (context.size() > 255) { throw LengthException(); } | |||
if (DECAF_SUCCESS != verify_noexcept( sig, pub, context, message, prehashed )) { | |||
if (context.size() > 255 | |||
|| (context.size() != 0 && !SUPPORTS_CONTEXTS) | |||
) { | |||
throw LengthException(); | |||
} | |||
if (DECAF_SUCCESS != verify_noexcept( sig, pub, message, prehashed, context )) { | |||
throw CryptoException(); | |||
} | |||
} | |||
@@ -3,7 +3,7 @@ | |||
* @brief EdDSA routines. | |||
*/ | |||
#include "decaf.h" | |||
#include <decaf/eddsa_$(gf_bits).h> | |||
#include "decaf/shake.h" | |||
#include "word.h" | |||
#include <string.h> | |||
@@ -11,6 +11,15 @@ | |||
#define API_NAME "$(c_ns)" | |||
#define API_NS(_id) $(c_ns)_##_id | |||
#define hash_ctx_t shake256_ctx_t | |||
#define hash_init shake256_init | |||
#define hash_update shake256_update | |||
#define hash_final shake256_final | |||
#define hash_destroy shake256_destroy | |||
#define hash_hash shake256_hash | |||
#define SUPPORTS_CONTEXTS $(C_NS)_EDDSA_SUPPORTS_CONTEXTS | |||
static void clamp( | |||
uint8_t secret_scalar_ser[$(C_NS)_EDDSA_PRIVATE_BYTES] | |||
) { | |||
@@ -22,6 +31,21 @@ static void clamp( | |||
if (hibit == 0) secret_scalar_ser[$(C_NS)_EDDSA_PRIVATE_BYTES - 2] |= 0x80; | |||
} | |||
static void hash_init_with_dom( | |||
hash_ctx_t hash, | |||
uint8_t prehashed, | |||
const uint8_t *context, | |||
uint8_t context_len | |||
) { | |||
const char *domS = "SigEd448"; | |||
const uint8_t dom[2] = {1+word_is_zero(prehashed), context_len}; | |||
hash_init(hash); | |||
hash_update(hash,(const unsigned char *)domS, strlen(domS)); | |||
hash_update(hash,dom,2); | |||
hash_update(hash,context,context_len); | |||
} | |||
void API_NS(eddsa_derive_public_key) ( | |||
uint8_t pubkey[$(C_NS)_EDDSA_PUBLIC_BYTES], | |||
const uint8_t privkey[$(C_NS)_EDDSA_PRIVATE_BYTES] | |||
@@ -29,7 +53,7 @@ void API_NS(eddsa_derive_public_key) ( | |||
/* only this much used for keygen */ | |||
uint8_t secret_scalar_ser[$(C_NS)_EDDSA_PRIVATE_BYTES]; | |||
shake256_hash( | |||
hash_hash( | |||
secret_scalar_ser, | |||
sizeof(secret_scalar_ser), | |||
privkey, | |||
@@ -55,30 +79,33 @@ void API_NS(eddsa_derive_public_key) ( | |||
decaf_bzero(secret_scalar_ser, sizeof(secret_scalar_ser)); | |||
} | |||
static const char *domS = "SigEd448"; | |||
void API_NS(eddsa_sign) ( | |||
uint8_t signature[$(C_NS)_EDDSA_SIGNATURE_BYTES], | |||
const uint8_t privkey[$(C_NS)_EDDSA_PRIVATE_BYTES], | |||
const uint8_t pubkey[$(C_NS)_EDDSA_PUBLIC_BYTES], | |||
const uint8_t *context, | |||
uint8_t context_len, | |||
const uint8_t *message, | |||
size_t message_len, | |||
uint8_t prehashed | |||
#if SUPPORTS_CONTEXTS | |||
, const uint8_t *context, | |||
uint8_t context_len | |||
#endif | |||
) { | |||
#if !SUPPORTS_CONTEXTS | |||
const uint8_t *const context = NULL; | |||
const uint8_t context_len = 0; | |||
#endif | |||
/* FIXME: of course, need a different hash for Curve25519 */ | |||
API_NS(scalar_t) secret_scalar; | |||
shake256_ctx_t shake; | |||
const uint8_t dom[2] = {1+word_is_zero(prehashed), context_len}; | |||
hash_ctx_t hash; | |||
{ | |||
/* Schedule the secret key */ | |||
struct { | |||
uint8_t secret_scalar_ser[$(C_NS)_EDDSA_PRIVATE_BYTES]; | |||
uint8_t seed[$(C_NS)_EDDSA_PRIVATE_BYTES]; | |||
} __attribute__((packed)) expanded; | |||
shake256_hash( | |||
hash_hash( | |||
(uint8_t *)&expanded, | |||
sizeof(expanded), | |||
privkey, | |||
@@ -88,12 +115,9 @@ void API_NS(eddsa_sign) ( | |||
API_NS(scalar_decode_long)(secret_scalar, expanded.secret_scalar_ser, sizeof(expanded.secret_scalar_ser)); | |||
/* Hash to create the nonce */ | |||
shake256_init(shake); | |||
shake256_update(shake,(const unsigned char *)domS, strlen(domS)); | |||
shake256_update(shake,dom,2); | |||
shake256_update(shake,context,context_len); | |||
shake256_update(shake,expanded.seed,sizeof(expanded.seed)); | |||
shake256_update(shake,message,message_len); | |||
hash_init_with_dom(hash,prehashed,context,context_len); | |||
hash_update(hash,expanded.seed,sizeof(expanded.seed)); | |||
hash_update(hash,message,message_len); | |||
decaf_bzero(&expanded, sizeof(expanded)); | |||
} | |||
@@ -101,7 +125,7 @@ void API_NS(eddsa_sign) ( | |||
API_NS(scalar_t) nonce_scalar; | |||
{ | |||
uint8_t nonce[2*$(C_NS)_EDDSA_PRIVATE_BYTES]; | |||
shake256_final(shake,nonce,sizeof(nonce)); | |||
hash_final(hash,nonce,sizeof(nonce)); | |||
API_NS(scalar_decode_long)(nonce_scalar, nonce, sizeof(nonce)); | |||
decaf_bzero(nonce, sizeof(nonce)); | |||
} | |||
@@ -123,16 +147,13 @@ void API_NS(eddsa_sign) ( | |||
API_NS(scalar_t) challenge_scalar; | |||
{ | |||
/* Compute the challenge */ | |||
shake256_init(shake); | |||
shake256_update(shake,(const unsigned char *)domS, strlen(domS)); | |||
shake256_update(shake,dom,2); | |||
shake256_update(shake,context,context_len); | |||
shake256_update(shake,nonce_point,sizeof(nonce_point)); | |||
shake256_update(shake,pubkey,$(C_NS)_EDDSA_PUBLIC_BYTES); | |||
shake256_update(shake,message,message_len); | |||
hash_init_with_dom(hash,prehashed,context,context_len); | |||
hash_update(hash,nonce_point,sizeof(nonce_point)); | |||
hash_update(hash,pubkey,$(C_NS)_EDDSA_PUBLIC_BYTES); | |||
hash_update(hash,message,message_len); | |||
uint8_t challenge[2*$(C_NS)_EDDSA_PRIVATE_BYTES]; | |||
shake256_final(shake,challenge,sizeof(challenge)); | |||
shake256_destroy(shake); | |||
hash_final(hash,challenge,sizeof(challenge)); | |||
hash_destroy(hash); | |||
API_NS(scalar_decode_long)(challenge_scalar,challenge,sizeof(challenge)); | |||
decaf_bzero(challenge,sizeof(challenge)); | |||
} | |||
@@ -153,12 +174,18 @@ void API_NS(eddsa_sign) ( | |||
decaf_error_t API_NS(eddsa_verify) ( | |||
const uint8_t signature[$(C_NS)_EDDSA_SIGNATURE_BYTES], | |||
const uint8_t pubkey[$(C_NS)_EDDSA_PUBLIC_BYTES], | |||
const uint8_t *context, | |||
uint8_t context_len, | |||
const uint8_t *message, | |||
size_t message_len, | |||
uint8_t prehashed | |||
#if SUPPORTS_CONTEXTS | |||
, const uint8_t *context, | |||
uint8_t context_len | |||
#endif | |||
) { | |||
#if !SUPPORTS_CONTEXTS | |||
const uint8_t *const context = NULL; | |||
const uint8_t context_len = 0; | |||
#endif | |||
API_NS(point_t) pk_point, r_point; | |||
decaf_error_t error = API_NS(point_decode_like_eddsa)(pk_point,pubkey); | |||
if (DECAF_SUCCESS != error) { return error; } | |||
@@ -169,18 +196,14 @@ decaf_error_t API_NS(eddsa_verify) ( | |||
API_NS(scalar_t) challenge_scalar; | |||
{ | |||
/* Compute the challenge */ | |||
shake256_ctx_t shake; | |||
const uint8_t dom[2] = {1+word_is_zero(prehashed), context_len}; | |||
shake256_init(shake); | |||
shake256_update(shake,(const unsigned char *)domS, strlen(domS)); | |||
shake256_update(shake,dom,2); | |||
shake256_update(shake,context,context_len); | |||
shake256_update(shake,signature,$(C_NS)_EDDSA_PUBLIC_BYTES); | |||
shake256_update(shake,pubkey,$(C_NS)_EDDSA_PUBLIC_BYTES); | |||
shake256_update(shake,message,message_len); | |||
hash_ctx_t hash; | |||
hash_init_with_dom(hash,prehashed,context,context_len); | |||
hash_update(hash,signature,$(C_NS)_EDDSA_PUBLIC_BYTES); | |||
hash_update(hash,pubkey,$(C_NS)_EDDSA_PUBLIC_BYTES); | |||
hash_update(hash,message,message_len); | |||
uint8_t challenge[2*$(C_NS)_EDDSA_PRIVATE_BYTES]; | |||
shake256_final(shake,challenge,sizeof(challenge)); | |||
shake256_destroy(shake); | |||
hash_final(hash,challenge,sizeof(challenge)); | |||
hash_destroy(hash); | |||
API_NS(scalar_decode_long)(challenge_scalar,challenge,sizeof(challenge)); | |||
decaf_bzero(challenge,sizeof(challenge)); | |||
} | |||
@@ -0,0 +1,113 @@ | |||
/** @brief A group of prime order p, based on $(iso_to). */ | |||
#include <decaf/decaf_$(gf_bits).h> | |||
#ifdef __cplusplus | |||
extern "C" { | |||
#endif | |||
/** Number of bytes in an EdDSA public key. */ | |||
#define $(C_NS)_EDDSA_PUBLIC_BYTES $((gf_bits)/8 + 1) /* TODO: change name? */ | |||
/** Number of bytes in an EdDSA private key. */ | |||
#define $(C_NS)_EDDSA_PRIVATE_BYTES $(C_NS)_EDDSA_PUBLIC_BYTES /* TODO: change name? */ | |||
/** Number of bytes in an EdDSA private key. */ | |||
#define $(C_NS)_EDDSA_SIGNATURE_BYTES ($(C_NS)_EDDSA_PUBLIC_BYTES + $(C_NS)_EDDSA_PRIVATE_BYTES) /* TODO: change name? */ | |||
/** Does EdDSA support contexts? */ | |||
#define $(C_NS)_EDDSA_SUPPORTS_CONTEXTS $(eddsa_supports_contexts) | |||
/** | |||
* @brief EdDSA key generation. This function uses a different (non-Decaf) | |||
* encoding. | |||
* | |||
* @param [out] pubkey The public key. | |||
* @param [in] privkey The private key. | |||
*/ | |||
void $(c_ns)_eddsa_derive_public_key ( | |||
uint8_t pubkey[$(C_NS)_EDDSA_PUBLIC_BYTES], | |||
const uint8_t privkey[$(C_NS)_EDDSA_PRIVATE_BYTES] | |||
) API_VIS NONNULL NOINLINE; | |||
/** | |||
* @brief EdDSA signing. | |||
* | |||
* @param [out] signature The signature. | |||
* @param [in] privkey The private key. | |||
* @param [in] pubkey The public key. | |||
* @param [in] context A "context" for this signature of up to 255 bytes. | |||
* @param [in] context_len Length of the context. | |||
* @param [in] message The message to sign. | |||
* @param [in] message_len The length of the message. | |||
* @param [in] prehashed Nonzero if the message is actually the hash of something you want to sign. | |||
*/ | |||
void $(c_ns)_eddsa_sign ( | |||
uint8_t signature[$(C_NS)_EDDSA_SIGNATURE_BYTES], | |||
const uint8_t privkey[$(C_NS)_EDDSA_PRIVATE_BYTES], | |||
const uint8_t pubkey[$(C_NS)_EDDSA_PUBLIC_BYTES], | |||
const uint8_t *message, | |||
size_t message_len, | |||
uint8_t prehashed | |||
#if $(C_NS)_EDDSA_SUPPORTS_CONTEXTS | |||
, const uint8_t *context, | |||
uint8_t context_len | |||
#endif | |||
) API_VIS __attribute__((nonnull(1,2,3))) NOINLINE; | |||
/** | |||
* @brief EdDSA signature verification. | |||
* | |||
* Uses the standard (i.e. less-strict) verification formula. | |||
* | |||
* @param [in] signature The signature. | |||
* @param [in] pubkey The public key. | |||
* @param [in] context A "context" for this signature of up to 255 bytes. | |||
* @param [in] context_len Length of the context. | |||
* @param [in] message The message to verify. | |||
* @param [in] message_len The length of the message. | |||
* @param [in] prehashed Nonzero if the message is actually the hash of something you want to verify. | |||
*/ | |||
decaf_error_t $(c_ns)_eddsa_verify ( | |||
const uint8_t signature[$(C_NS)_EDDSA_SIGNATURE_BYTES], | |||
const uint8_t pubkey[$(C_NS)_EDDSA_PUBLIC_BYTES], | |||
const uint8_t *message, | |||
size_t message_len, | |||
uint8_t prehashed | |||
#if $(C_NS)_EDDSA_SUPPORTS_CONTEXTS | |||
, const uint8_t *context, | |||
uint8_t context_len | |||
#endif | |||
) API_VIS __attribute__((nonnull(1,2))) NOINLINE; | |||
/** | |||
* @brief EdDSA point encoding. Used internally, exposed externally. | |||
* | |||
* @param [out] enc The encoded point. | |||
* @param [in] p The point. | |||
* | |||
* FIXME: encode and decode aren't inverses of each other: they | |||
* multiply by a factor. Rename to reflect this once the base | |||
* point doctrine is worked out. | |||
*/ | |||
void $(c_ns)_point_encode_like_eddsa ( | |||
uint8_t enc[$(C_NS)_EDDSA_PUBLIC_BYTES], | |||
const $(c_ns)_point_t p | |||
) API_VIS NONNULL NOINLINE; | |||
/** | |||
* @brief EdDSA point encoding. | |||
* | |||
* @param [out] enc The encoded point. | |||
* @param [in] p The point. | |||
*/ | |||
decaf_error_t $(c_ns)_point_decode_like_eddsa ( | |||
$(c_ns)_point_t p, | |||
const uint8_t enc[$(C_NS)_EDDSA_PUBLIC_BYTES] | |||
) API_VIS NONNULL NOINLINE; | |||
#ifdef __cplusplus | |||
} /* extern "C" */ | |||
#endif |
@@ -488,7 +488,7 @@ static void test_cfrg_vectors() { | |||
for (unsigned i=0; i<eddsa_pk2.size(); i++) printf("%02x", eddsa_pk2[i]); | |||
printf("\n"); | |||
} | |||
SecureBuffer sig = EdDSA::sign(eddsa_sk,eddsa_pk,Block(NULL,0),Block(NULL,0)); | |||
SecureBuffer sig = EdDSA::sign(eddsa_sk,eddsa_pk,Block(NULL,0)); | |||
if (!memeq(SecureBuffer(eddsa_sig0),sig)) { | |||
test.fail(); | |||
@@ -527,7 +527,7 @@ static void test_cfrg_vectors() { | |||
static void test_eddsa() { | |||
Test test("EdDSA"); | |||
SpongeRng rng(Block("test_cfrg_crypto"),SpongeRng::DETERMINISTIC); | |||
SpongeRng rng(Block("test_eddsa"),SpongeRng::DETERMINISTIC); | |||
for (int i=0; i<NTESTS && test.passing_now; i++) { | |||
@@ -537,13 +537,13 @@ static void test_eddsa() { | |||
SecureBuffer message(i); | |||
rng.read(message); | |||
SecureBuffer context(i%256); | |||
SecureBuffer context(EdDSA::SUPPORTS_CONTEXTS ? i%256 : 0); | |||
rng.read(message); | |||
SecureBuffer sig = EdDSA::sign(priv,pub,context,message,i%2); | |||
SecureBuffer sig = EdDSA::sign(priv,pub,message,i%2,context); | |||
try { | |||
EdDSA::verify(sig,pub,context,message,i%2); | |||
EdDSA::verify(sig,pub,message,i%2,context); | |||
} catch(CryptoException) { | |||
test.fail(); | |||
printf(" Signature validation failed on sig %d\n", i); | |||