@@ -1040,7 +1040,7 @@ decaf_error_t API_NS(direct_scalarmul) ( | |||||
return succ; | return succ; | ||||
} | } | ||||
void API_NS(point_mul_by_cofactor_and_encode_like_eddsa) ( | |||||
void API_NS(point_mul_by_ratio_and_encode_like_eddsa) ( | |||||
uint8_t enc[DECAF_EDDSA_25519_PUBLIC_BYTES], | uint8_t enc[DECAF_EDDSA_25519_PUBLIC_BYTES], | ||||
const point_t p | const point_t p | ||||
) { | ) { | ||||
@@ -1133,7 +1133,7 @@ void API_NS(point_mul_by_cofactor_and_encode_like_eddsa) ( | |||||
} | } | ||||
decaf_error_t API_NS(point_decode_like_eddsa_and_ignore_cofactor) ( | |||||
decaf_error_t API_NS(point_decode_like_eddsa_and_mul_by_ratio) ( | |||||
point_t p, | point_t p, | ||||
const uint8_t enc[DECAF_EDDSA_25519_PUBLIC_BYTES] | const uint8_t enc[DECAF_EDDSA_25519_PUBLIC_BYTES] | ||||
) { | ) { | ||||
@@ -1352,13 +1352,16 @@ void decaf_x25519_generate_key ( | |||||
decaf_x25519_derive_public_key(out,scalar); | decaf_x25519_derive_public_key(out,scalar); | ||||
} | } | ||||
void API_NS(point_mul_by_cofactor_and_encode_like_x25519) ( | |||||
void API_NS(point_mul_by_ratio_and_encode_like_x25519) ( | |||||
uint8_t out[X_PUBLIC_BYTES], | uint8_t out[X_PUBLIC_BYTES], | ||||
const point_t p | const point_t p | ||||
) { | ) { | ||||
point_t q; | point_t q; | ||||
#if COFACTOR == 8 | |||||
point_double_internal(q,p,1); | point_double_internal(q,p,1); | ||||
for (unsigned i=1; i<COFACTOR/4; i<<=1) point_double_internal(q,q,1); | |||||
#else | |||||
API_NS(point_copy)(q,p); | |||||
#endif | |||||
gf_invert(q->t,q->x,0); /* 1/x */ | gf_invert(q->t,q->x,0); /* 1/x */ | ||||
gf_mul(q->z,q->t,q->y); /* y/x */ | gf_mul(q->z,q->t,q->y); /* y/x */ | ||||
gf_sqr(q->y,q->z); /* (y/x)^2 */ | gf_sqr(q->y,q->z); /* (y/x)^2 */ | ||||
@@ -1384,24 +1387,13 @@ void decaf_x25519_derive_public_key ( | |||||
scalar_t the_scalar; | scalar_t the_scalar; | ||||
API_NS(scalar_decode_long)(the_scalar,scalar2,sizeof(scalar2)); | API_NS(scalar_decode_long)(the_scalar,scalar2,sizeof(scalar2)); | ||||
/* We're gonna isogenize by 2, so divide by 2. | |||||
* | |||||
* Why by 2, even though it's a 4-isogeny? | |||||
* | |||||
* The isogeny map looks like | |||||
* Montgomery <-2-> Jacobi <-2-> Edwards | |||||
* | |||||
* Since the Jacobi base point is the PREimage of the iso to | |||||
* the Montgomery curve, and we're going | |||||
* Jacobi -> Edwards -> Jacobi -> Montgomery, | |||||
* we pick up only a factor of 2 over Jacobi -> Montgomery. | |||||
*/ | |||||
for (unsigned i=1; i<COFACTOR; i<<=1) { | |||||
/* Compensate for the encoding ratio */ | |||||
for (unsigned i=1; i<DECAF_X25519_ENCODE_RATIO; i<<=1) { | |||||
API_NS(scalar_halve)(the_scalar,the_scalar); | API_NS(scalar_halve)(the_scalar,the_scalar); | ||||
} | } | ||||
point_t p; | point_t p; | ||||
API_NS(precomputed_scalarmul)(p,API_NS(precomputed_base),the_scalar); | API_NS(precomputed_scalarmul)(p,API_NS(precomputed_base),the_scalar); | ||||
API_NS(point_mul_by_cofactor_and_encode_like_x25519)(out,p); | |||||
API_NS(point_mul_by_ratio_and_encode_like_x25519)(out,p); | |||||
API_NS(point_destroy)(p); | API_NS(point_destroy)(p); | ||||
} | } | ||||
@@ -31,6 +31,7 @@ | |||||
#define NO_CONTEXT DECAF_EDDSA_25519_SUPPORTS_CONTEXTLESS_SIGS | #define NO_CONTEXT DECAF_EDDSA_25519_SUPPORTS_CONTEXTLESS_SIGS | ||||
#define EDDSA_USE_SIGMA_ISOGENY 1 | #define EDDSA_USE_SIGMA_ISOGENY 1 | ||||
#define COFACTOR 8 | #define COFACTOR 8 | ||||
#define EDDSA_PREHASH_BYTES 64 | |||||
#if NO_CONTEXT | #if NO_CONTEXT | ||||
const uint8_t NO_CONTEXT_POINTS_HERE = 0; | const uint8_t NO_CONTEXT_POINTS_HERE = 0; | ||||
@@ -41,7 +42,7 @@ const uint8_t * const DECAF_ED25519_NO_CONTEXT = &NO_CONTEXT_POINTS_HERE; | |||||
* Because EdDSA25519 is not on E_d but on the isogenous E_sigma_d, | * Because EdDSA25519 is not on E_d but on the isogenous E_sigma_d, | ||||
* its base point is twice ours. | * its base point is twice ours. | ||||
*/ | */ | ||||
#define EDDSA_BASE_POINT_RATIO (1+EDDSA_USE_SIGMA_ISOGENY) | |||||
#define EDDSA_BASE_POINT_RATIO (1+EDDSA_USE_SIGMA_ISOGENY) /* TODO: remove */ | |||||
static void clamp ( | static void clamp ( | ||||
uint8_t secret_scalar_ser[DECAF_EDDSA_25519_PRIVATE_BYTES] | uint8_t secret_scalar_ser[DECAF_EDDSA_25519_PRIVATE_BYTES] | ||||
@@ -128,14 +129,14 @@ void decaf_ed25519_derive_public_key ( | |||||
* the decaf base point is on Etwist_d, and when converted it effectively | * the decaf base point is on Etwist_d, and when converted it effectively | ||||
* picks up a factor of 2 from the isogenies. So we might start at 2 instead of 1. | * picks up a factor of 2 from the isogenies. So we might start at 2 instead of 1. | ||||
*/ | */ | ||||
for (unsigned int c = EDDSA_BASE_POINT_RATIO; c < COFACTOR; c <<= 1) { | |||||
for (unsigned int c=1; c<DECAF_255_EDDSA_ENCODE_RATIO; c <<= 1) { | |||||
API_NS(scalar_halve)(secret_scalar,secret_scalar); | API_NS(scalar_halve)(secret_scalar,secret_scalar); | ||||
} | } | ||||
API_NS(point_t) p; | API_NS(point_t) p; | ||||
API_NS(precomputed_scalarmul)(p,API_NS(precomputed_base),secret_scalar); | API_NS(precomputed_scalarmul)(p,API_NS(precomputed_base),secret_scalar); | ||||
API_NS(point_mul_by_cofactor_and_encode_like_eddsa)(pubkey, p); | |||||
API_NS(point_mul_by_ratio_and_encode_like_eddsa)(pubkey, p); | |||||
/* Cleanup */ | /* Cleanup */ | ||||
API_NS(scalar_destroy)(secret_scalar); | API_NS(scalar_destroy)(secret_scalar); | ||||
@@ -191,13 +192,13 @@ void decaf_ed25519_sign ( | |||||
/* Scalarmul to create the nonce-point */ | /* Scalarmul to create the nonce-point */ | ||||
API_NS(scalar_t) nonce_scalar_2; | API_NS(scalar_t) nonce_scalar_2; | ||||
API_NS(scalar_halve)(nonce_scalar_2,nonce_scalar); | API_NS(scalar_halve)(nonce_scalar_2,nonce_scalar); | ||||
for (unsigned int c = 2*EDDSA_BASE_POINT_RATIO; c < COFACTOR; c <<= 1) { | |||||
for (unsigned int c = 2; c < DECAF_255_EDDSA_ENCODE_RATIO; c <<= 1) { | |||||
API_NS(scalar_halve)(nonce_scalar_2,nonce_scalar_2); | API_NS(scalar_halve)(nonce_scalar_2,nonce_scalar_2); | ||||
} | } | ||||
API_NS(point_t) p; | API_NS(point_t) p; | ||||
API_NS(precomputed_scalarmul)(p,API_NS(precomputed_base),nonce_scalar_2); | API_NS(precomputed_scalarmul)(p,API_NS(precomputed_base),nonce_scalar_2); | ||||
API_NS(point_mul_by_cofactor_and_encode_like_eddsa)(nonce_point, p); | |||||
API_NS(point_mul_by_ratio_and_encode_like_eddsa)(nonce_point, p); | |||||
API_NS(point_destroy)(p); | API_NS(point_destroy)(p); | ||||
API_NS(scalar_destroy)(nonce_scalar_2); | API_NS(scalar_destroy)(nonce_scalar_2); | ||||
} | } | ||||
@@ -237,7 +238,7 @@ void decaf_ed25519_sign_prehash ( | |||||
const uint8_t *context, | const uint8_t *context, | ||||
uint8_t context_len | uint8_t context_len | ||||
) { | ) { | ||||
uint8_t hash_output[64]; /* MAGIC but true for all existing schemes */ | |||||
uint8_t hash_output[EDDSA_PREHASH_BYTES]; | |||||
{ | { | ||||
decaf_ed25519_prehash_ctx_t hash_too; | decaf_ed25519_prehash_ctx_t hash_too; | ||||
memcpy(hash_too,hash,sizeof(hash_too)); | memcpy(hash_too,hash,sizeof(hash_too)); | ||||
@@ -259,10 +260,10 @@ decaf_error_t decaf_ed25519_verify ( | |||||
uint8_t context_len | uint8_t context_len | ||||
) { | ) { | ||||
API_NS(point_t) pk_point, r_point; | API_NS(point_t) pk_point, r_point; | ||||
decaf_error_t error = API_NS(point_decode_like_eddsa_and_ignore_cofactor)(pk_point,pubkey); | |||||
decaf_error_t error = API_NS(point_decode_like_eddsa_and_mul_by_ratio)(pk_point,pubkey); | |||||
if (DECAF_SUCCESS != error) { return error; } | if (DECAF_SUCCESS != error) { return error; } | ||||
error = API_NS(point_decode_like_eddsa_and_ignore_cofactor)(r_point,signature); | |||||
error = API_NS(point_decode_like_eddsa_and_mul_by_ratio)(r_point,signature); | |||||
if (DECAF_SUCCESS != error) { return error; } | if (DECAF_SUCCESS != error) { return error; } | ||||
API_NS(scalar_t) challenge_scalar; | API_NS(scalar_t) challenge_scalar; | ||||
@@ -287,9 +288,10 @@ decaf_error_t decaf_ed25519_verify ( | |||||
&signature[DECAF_EDDSA_25519_PUBLIC_BYTES], | &signature[DECAF_EDDSA_25519_PUBLIC_BYTES], | ||||
DECAF_EDDSA_25519_PRIVATE_BYTES | DECAF_EDDSA_25519_PRIVATE_BYTES | ||||
); | ); | ||||
#if EDDSA_BASE_POINT_RATIO == 2 | |||||
API_NS(scalar_add)(response_scalar,response_scalar,response_scalar); | |||||
#endif | |||||
for (unsigned c=1; c<DECAF_255_EDDSA_DECODE_RATIO; c<<=1) { | |||||
API_NS(scalar_add)(response_scalar,response_scalar,response_scalar); | |||||
} | |||||
/* pk_point = -c(x(P)) + (cx + k)G = kG */ | /* pk_point = -c(x(P)) + (cx + k)G = kG */ | ||||
@@ -312,7 +314,7 @@ decaf_error_t decaf_ed25519_verify_prehash ( | |||||
) { | ) { | ||||
decaf_error_t ret; | decaf_error_t ret; | ||||
uint8_t hash_output[64]; /* MAGIC but true for all existing schemes */ | |||||
uint8_t hash_output[EDDSA_PREHASH_BYTES]; | |||||
{ | { | ||||
decaf_ed25519_prehash_ctx_t hash_too; | decaf_ed25519_prehash_ctx_t hash_too; | ||||
memcpy(hash_too,hash,sizeof(hash_too)); | memcpy(hash_too,hash,sizeof(hash_too)); | ||||
@@ -1040,7 +1040,7 @@ decaf_error_t API_NS(direct_scalarmul) ( | |||||
return succ; | return succ; | ||||
} | } | ||||
void API_NS(point_mul_by_cofactor_and_encode_like_eddsa) ( | |||||
void API_NS(point_mul_by_ratio_and_encode_like_eddsa) ( | |||||
uint8_t enc[DECAF_EDDSA_448_PUBLIC_BYTES], | uint8_t enc[DECAF_EDDSA_448_PUBLIC_BYTES], | ||||
const point_t p | const point_t p | ||||
) { | ) { | ||||
@@ -1133,7 +1133,7 @@ void API_NS(point_mul_by_cofactor_and_encode_like_eddsa) ( | |||||
} | } | ||||
decaf_error_t API_NS(point_decode_like_eddsa_and_ignore_cofactor) ( | |||||
decaf_error_t API_NS(point_decode_like_eddsa_and_mul_by_ratio) ( | |||||
point_t p, | point_t p, | ||||
const uint8_t enc[DECAF_EDDSA_448_PUBLIC_BYTES] | const uint8_t enc[DECAF_EDDSA_448_PUBLIC_BYTES] | ||||
) { | ) { | ||||
@@ -1352,13 +1352,16 @@ void decaf_x448_generate_key ( | |||||
decaf_x448_derive_public_key(out,scalar); | decaf_x448_derive_public_key(out,scalar); | ||||
} | } | ||||
void API_NS(point_mul_by_cofactor_and_encode_like_x448) ( | |||||
void API_NS(point_mul_by_ratio_and_encode_like_x448) ( | |||||
uint8_t out[X_PUBLIC_BYTES], | uint8_t out[X_PUBLIC_BYTES], | ||||
const point_t p | const point_t p | ||||
) { | ) { | ||||
point_t q; | point_t q; | ||||
#if COFACTOR == 8 | |||||
point_double_internal(q,p,1); | point_double_internal(q,p,1); | ||||
for (unsigned i=1; i<COFACTOR/4; i<<=1) point_double_internal(q,q,1); | |||||
#else | |||||
API_NS(point_copy)(q,p); | |||||
#endif | |||||
gf_invert(q->t,q->x,0); /* 1/x */ | gf_invert(q->t,q->x,0); /* 1/x */ | ||||
gf_mul(q->z,q->t,q->y); /* y/x */ | gf_mul(q->z,q->t,q->y); /* y/x */ | ||||
gf_sqr(q->y,q->z); /* (y/x)^2 */ | gf_sqr(q->y,q->z); /* (y/x)^2 */ | ||||
@@ -1384,24 +1387,13 @@ void decaf_x448_derive_public_key ( | |||||
scalar_t the_scalar; | scalar_t the_scalar; | ||||
API_NS(scalar_decode_long)(the_scalar,scalar2,sizeof(scalar2)); | API_NS(scalar_decode_long)(the_scalar,scalar2,sizeof(scalar2)); | ||||
/* We're gonna isogenize by 2, so divide by 2. | |||||
* | |||||
* Why by 2, even though it's a 4-isogeny? | |||||
* | |||||
* The isogeny map looks like | |||||
* Montgomery <-2-> Jacobi <-2-> Edwards | |||||
* | |||||
* Since the Jacobi base point is the PREimage of the iso to | |||||
* the Montgomery curve, and we're going | |||||
* Jacobi -> Edwards -> Jacobi -> Montgomery, | |||||
* we pick up only a factor of 2 over Jacobi -> Montgomery. | |||||
*/ | |||||
for (unsigned i=1; i<COFACTOR; i<<=1) { | |||||
/* Compensate for the encoding ratio */ | |||||
for (unsigned i=1; i<DECAF_X448_ENCODE_RATIO; i<<=1) { | |||||
API_NS(scalar_halve)(the_scalar,the_scalar); | API_NS(scalar_halve)(the_scalar,the_scalar); | ||||
} | } | ||||
point_t p; | point_t p; | ||||
API_NS(precomputed_scalarmul)(p,API_NS(precomputed_base),the_scalar); | API_NS(precomputed_scalarmul)(p,API_NS(precomputed_base),the_scalar); | ||||
API_NS(point_mul_by_cofactor_and_encode_like_x448)(out,p); | |||||
API_NS(point_mul_by_ratio_and_encode_like_x448)(out,p); | |||||
API_NS(point_destroy)(p); | API_NS(point_destroy)(p); | ||||
} | } | ||||
@@ -31,6 +31,7 @@ | |||||
#define NO_CONTEXT DECAF_EDDSA_448_SUPPORTS_CONTEXTLESS_SIGS | #define NO_CONTEXT DECAF_EDDSA_448_SUPPORTS_CONTEXTLESS_SIGS | ||||
#define EDDSA_USE_SIGMA_ISOGENY 0 | #define EDDSA_USE_SIGMA_ISOGENY 0 | ||||
#define COFACTOR 4 | #define COFACTOR 4 | ||||
#define EDDSA_PREHASH_BYTES 64 | |||||
#if NO_CONTEXT | #if NO_CONTEXT | ||||
const uint8_t NO_CONTEXT_POINTS_HERE = 0; | const uint8_t NO_CONTEXT_POINTS_HERE = 0; | ||||
@@ -41,7 +42,7 @@ const uint8_t * const DECAF_ED448_NO_CONTEXT = &NO_CONTEXT_POINTS_HERE; | |||||
* Because EdDSA25519 is not on E_d but on the isogenous E_sigma_d, | * Because EdDSA25519 is not on E_d but on the isogenous E_sigma_d, | ||||
* its base point is twice ours. | * its base point is twice ours. | ||||
*/ | */ | ||||
#define EDDSA_BASE_POINT_RATIO (1+EDDSA_USE_SIGMA_ISOGENY) | |||||
#define EDDSA_BASE_POINT_RATIO (1+EDDSA_USE_SIGMA_ISOGENY) /* TODO: remove */ | |||||
static void clamp ( | static void clamp ( | ||||
uint8_t secret_scalar_ser[DECAF_EDDSA_448_PRIVATE_BYTES] | uint8_t secret_scalar_ser[DECAF_EDDSA_448_PRIVATE_BYTES] | ||||
@@ -128,14 +129,14 @@ void decaf_ed448_derive_public_key ( | |||||
* the decaf base point is on Etwist_d, and when converted it effectively | * the decaf base point is on Etwist_d, and when converted it effectively | ||||
* picks up a factor of 2 from the isogenies. So we might start at 2 instead of 1. | * picks up a factor of 2 from the isogenies. So we might start at 2 instead of 1. | ||||
*/ | */ | ||||
for (unsigned int c = EDDSA_BASE_POINT_RATIO; c < COFACTOR; c <<= 1) { | |||||
for (unsigned int c=1; c<DECAF_448_EDDSA_ENCODE_RATIO; c <<= 1) { | |||||
API_NS(scalar_halve)(secret_scalar,secret_scalar); | API_NS(scalar_halve)(secret_scalar,secret_scalar); | ||||
} | } | ||||
API_NS(point_t) p; | API_NS(point_t) p; | ||||
API_NS(precomputed_scalarmul)(p,API_NS(precomputed_base),secret_scalar); | API_NS(precomputed_scalarmul)(p,API_NS(precomputed_base),secret_scalar); | ||||
API_NS(point_mul_by_cofactor_and_encode_like_eddsa)(pubkey, p); | |||||
API_NS(point_mul_by_ratio_and_encode_like_eddsa)(pubkey, p); | |||||
/* Cleanup */ | /* Cleanup */ | ||||
API_NS(scalar_destroy)(secret_scalar); | API_NS(scalar_destroy)(secret_scalar); | ||||
@@ -191,13 +192,13 @@ void decaf_ed448_sign ( | |||||
/* Scalarmul to create the nonce-point */ | /* Scalarmul to create the nonce-point */ | ||||
API_NS(scalar_t) nonce_scalar_2; | API_NS(scalar_t) nonce_scalar_2; | ||||
API_NS(scalar_halve)(nonce_scalar_2,nonce_scalar); | API_NS(scalar_halve)(nonce_scalar_2,nonce_scalar); | ||||
for (unsigned int c = 2*EDDSA_BASE_POINT_RATIO; c < COFACTOR; c <<= 1) { | |||||
for (unsigned int c = 2; c < DECAF_448_EDDSA_ENCODE_RATIO; c <<= 1) { | |||||
API_NS(scalar_halve)(nonce_scalar_2,nonce_scalar_2); | API_NS(scalar_halve)(nonce_scalar_2,nonce_scalar_2); | ||||
} | } | ||||
API_NS(point_t) p; | API_NS(point_t) p; | ||||
API_NS(precomputed_scalarmul)(p,API_NS(precomputed_base),nonce_scalar_2); | API_NS(precomputed_scalarmul)(p,API_NS(precomputed_base),nonce_scalar_2); | ||||
API_NS(point_mul_by_cofactor_and_encode_like_eddsa)(nonce_point, p); | |||||
API_NS(point_mul_by_ratio_and_encode_like_eddsa)(nonce_point, p); | |||||
API_NS(point_destroy)(p); | API_NS(point_destroy)(p); | ||||
API_NS(scalar_destroy)(nonce_scalar_2); | API_NS(scalar_destroy)(nonce_scalar_2); | ||||
} | } | ||||
@@ -237,7 +238,7 @@ void decaf_ed448_sign_prehash ( | |||||
const uint8_t *context, | const uint8_t *context, | ||||
uint8_t context_len | uint8_t context_len | ||||
) { | ) { | ||||
uint8_t hash_output[64]; /* MAGIC but true for all existing schemes */ | |||||
uint8_t hash_output[EDDSA_PREHASH_BYTES]; | |||||
{ | { | ||||
decaf_ed448_prehash_ctx_t hash_too; | decaf_ed448_prehash_ctx_t hash_too; | ||||
memcpy(hash_too,hash,sizeof(hash_too)); | memcpy(hash_too,hash,sizeof(hash_too)); | ||||
@@ -259,10 +260,10 @@ decaf_error_t decaf_ed448_verify ( | |||||
uint8_t context_len | uint8_t context_len | ||||
) { | ) { | ||||
API_NS(point_t) pk_point, r_point; | API_NS(point_t) pk_point, r_point; | ||||
decaf_error_t error = API_NS(point_decode_like_eddsa_and_ignore_cofactor)(pk_point,pubkey); | |||||
decaf_error_t error = API_NS(point_decode_like_eddsa_and_mul_by_ratio)(pk_point,pubkey); | |||||
if (DECAF_SUCCESS != error) { return error; } | if (DECAF_SUCCESS != error) { return error; } | ||||
error = API_NS(point_decode_like_eddsa_and_ignore_cofactor)(r_point,signature); | |||||
error = API_NS(point_decode_like_eddsa_and_mul_by_ratio)(r_point,signature); | |||||
if (DECAF_SUCCESS != error) { return error; } | if (DECAF_SUCCESS != error) { return error; } | ||||
API_NS(scalar_t) challenge_scalar; | API_NS(scalar_t) challenge_scalar; | ||||
@@ -287,9 +288,10 @@ decaf_error_t decaf_ed448_verify ( | |||||
&signature[DECAF_EDDSA_448_PUBLIC_BYTES], | &signature[DECAF_EDDSA_448_PUBLIC_BYTES], | ||||
DECAF_EDDSA_448_PRIVATE_BYTES | DECAF_EDDSA_448_PRIVATE_BYTES | ||||
); | ); | ||||
#if EDDSA_BASE_POINT_RATIO == 2 | |||||
API_NS(scalar_add)(response_scalar,response_scalar,response_scalar); | |||||
#endif | |||||
for (unsigned c=1; c<DECAF_448_EDDSA_DECODE_RATIO; c<<=1) { | |||||
API_NS(scalar_add)(response_scalar,response_scalar,response_scalar); | |||||
} | |||||
/* pk_point = -c(x(P)) + (cx + k)G = kG */ | /* pk_point = -c(x(P)) + (cx + k)G = kG */ | ||||
@@ -312,7 +314,7 @@ decaf_error_t decaf_ed448_verify_prehash ( | |||||
) { | ) { | ||||
decaf_error_t ret; | decaf_error_t ret; | ||||
uint8_t hash_output[64]; /* MAGIC but true for all existing schemes */ | |||||
uint8_t hash_output[EDDSA_PREHASH_BYTES]; | |||||
{ | { | ||||
decaf_ed448_prehash_ctx_t hash_too; | decaf_ed448_prehash_ctx_t hash_too; | ||||
memcpy(hash_too,hash,sizeof(hash_too)); | memcpy(hash_too,hash,sizeof(hash_too)); | ||||
@@ -42,6 +42,12 @@ extern const uint8_t * const DECAF_ED25519_NO_CONTEXT DECAF_API_VIS; | |||||
#define decaf_ed25519_prehash_update decaf_sha512_update | #define decaf_ed25519_prehash_update decaf_sha512_update | ||||
#define decaf_ed25519_prehash_destroy decaf_sha512_destroy | #define decaf_ed25519_prehash_destroy decaf_sha512_destroy | ||||
/** EdDSA encoding ratio. */ | |||||
#define DECAF_255_EDDSA_ENCODE_RATIO 4 | |||||
/** EdDSA decoding ratio. */ | |||||
#define DECAF_255_EDDSA_DECODE_RATIO (8 / 4) | |||||
/** | /** | ||||
* @brief EdDSA key generation. This function uses a different (non-Decaf) | * @brief EdDSA key generation. This function uses a different (non-Decaf) | ||||
* encoding. | * encoding. | ||||
@@ -169,25 +175,43 @@ decaf_error_t decaf_ed25519_verify_prehash ( | |||||
/** | /** | ||||
* @brief EdDSA point encoding. Used internally, exposed externally. | * @brief EdDSA point encoding. Used internally, exposed externally. | ||||
* Multiplies the point by the current cofactor first. | |||||
* Multiplies by DECAF_255_EDDSA_ENCODE_RATIO first. | |||||
* | |||||
* The multiplication is required because the EdDSA encoding represents | |||||
* the cofactor information, but the Decaf encoding ignores it (which | |||||
* is the whole point). So if you decode from EdDSA and re-encode to | |||||
* EdDSA, the cofactor info must get cleared, because the intermediate | |||||
* representation doesn't track it. | |||||
* | |||||
* The way libdecaf handles this is to multiply by | |||||
* DECAF_255_EDDSA_DECODE_RATIO when decoding, and by | |||||
* DECAF_255_EDDSA_ENCODE_RATIO when encoding. The product of these | |||||
* ratios is always exactly the cofactor 8, so the cofactor | |||||
* ends up cleared one way or another. But exactly how that shakes | |||||
* out depends on the base points specified in RFC 8032. | |||||
* | |||||
* The upshot is that if you pass the Decaf/Ristretto base point to | |||||
* this function, you will get DECAF_255_EDDSA_ENCODE_RATIO times the | |||||
* EdDSA base point. | |||||
* | * | ||||
* @param [out] enc The encoded point. | * @param [out] enc The encoded point. | ||||
* @param [in] p The point. | * @param [in] p The point. | ||||
*/ | */ | ||||
void decaf_255_point_mul_by_cofactor_and_encode_like_eddsa ( | |||||
void decaf_255_point_mul_by_ratio_and_encode_like_eddsa ( | |||||
uint8_t enc[DECAF_EDDSA_25519_PUBLIC_BYTES], | uint8_t enc[DECAF_EDDSA_25519_PUBLIC_BYTES], | ||||
const decaf_255_point_t p | const decaf_255_point_t p | ||||
) DECAF_API_VIS DECAF_NONNULL DECAF_NOINLINE; | ) DECAF_API_VIS DECAF_NONNULL DECAF_NOINLINE; | ||||
/** | /** | ||||
* @brief EdDSA point decoding. Remember that while points on the | |||||
* EdDSA curves have cofactor information, Decaf ignores (quotients | |||||
* out) all cofactor information. | |||||
* @brief EdDSA point decoding. Multiplies by DECAF_255_EDDSA_DECODE_RATIO, | |||||
* and ignores cofactor information. | |||||
* | |||||
* See notes on decaf_255_point_mul_by_ratio_and_encode_like_eddsa | |||||
* | * | ||||
* @param [out] enc The encoded point. | * @param [out] enc The encoded point. | ||||
* @param [in] p The point. | * @param [in] p The point. | ||||
*/ | */ | ||||
decaf_error_t decaf_255_point_decode_like_eddsa_and_ignore_cofactor ( | |||||
decaf_error_t decaf_255_point_decode_like_eddsa_and_mul_by_ratio ( | |||||
decaf_255_point_t p, | decaf_255_point_t p, | ||||
const uint8_t enc[DECAF_EDDSA_25519_PUBLIC_BYTES] | const uint8_t enc[DECAF_EDDSA_25519_PUBLIC_BYTES] | ||||
) DECAF_API_VIS DECAF_NONNULL DECAF_NOINLINE; | ) DECAF_API_VIS DECAF_NONNULL DECAF_NOINLINE; | ||||
@@ -41,6 +41,12 @@ extern "C" { | |||||
#define decaf_ed448_prehash_update decaf_shake256_update | #define decaf_ed448_prehash_update decaf_shake256_update | ||||
#define decaf_ed448_prehash_destroy decaf_shake256_destroy | #define decaf_ed448_prehash_destroy decaf_shake256_destroy | ||||
/** EdDSA encoding ratio. */ | |||||
#define DECAF_448_EDDSA_ENCODE_RATIO 4 | |||||
/** EdDSA decoding ratio. */ | |||||
#define DECAF_448_EDDSA_DECODE_RATIO (4 / 4) | |||||
/** | /** | ||||
* @brief EdDSA key generation. This function uses a different (non-Decaf) | * @brief EdDSA key generation. This function uses a different (non-Decaf) | ||||
* encoding. | * encoding. | ||||
@@ -168,25 +174,43 @@ decaf_error_t decaf_ed448_verify_prehash ( | |||||
/** | /** | ||||
* @brief EdDSA point encoding. Used internally, exposed externally. | * @brief EdDSA point encoding. Used internally, exposed externally. | ||||
* Multiplies the point by the current cofactor first. | |||||
* Multiplies by DECAF_448_EDDSA_ENCODE_RATIO first. | |||||
* | |||||
* The multiplication is required because the EdDSA encoding represents | |||||
* the cofactor information, but the Decaf encoding ignores it (which | |||||
* is the whole point). So if you decode from EdDSA and re-encode to | |||||
* EdDSA, the cofactor info must get cleared, because the intermediate | |||||
* representation doesn't track it. | |||||
* | |||||
* The way libdecaf handles this is to multiply by | |||||
* DECAF_448_EDDSA_DECODE_RATIO when decoding, and by | |||||
* DECAF_448_EDDSA_ENCODE_RATIO when encoding. The product of these | |||||
* ratios is always exactly the cofactor 4, so the cofactor | |||||
* ends up cleared one way or another. But exactly how that shakes | |||||
* out depends on the base points specified in RFC 8032. | |||||
* | |||||
* The upshot is that if you pass the Decaf/Ristretto base point to | |||||
* this function, you will get DECAF_448_EDDSA_ENCODE_RATIO times the | |||||
* EdDSA base point. | |||||
* | * | ||||
* @param [out] enc The encoded point. | * @param [out] enc The encoded point. | ||||
* @param [in] p The point. | * @param [in] p The point. | ||||
*/ | */ | ||||
void decaf_448_point_mul_by_cofactor_and_encode_like_eddsa ( | |||||
void decaf_448_point_mul_by_ratio_and_encode_like_eddsa ( | |||||
uint8_t enc[DECAF_EDDSA_448_PUBLIC_BYTES], | uint8_t enc[DECAF_EDDSA_448_PUBLIC_BYTES], | ||||
const decaf_448_point_t p | const decaf_448_point_t p | ||||
) DECAF_API_VIS DECAF_NONNULL DECAF_NOINLINE; | ) DECAF_API_VIS DECAF_NONNULL DECAF_NOINLINE; | ||||
/** | /** | ||||
* @brief EdDSA point decoding. Remember that while points on the | |||||
* EdDSA curves have cofactor information, Decaf ignores (quotients | |||||
* out) all cofactor information. | |||||
* @brief EdDSA point decoding. Multiplies by DECAF_448_EDDSA_DECODE_RATIO, | |||||
* and ignores cofactor information. | |||||
* | |||||
* See notes on decaf_448_point_mul_by_ratio_and_encode_like_eddsa | |||||
* | * | ||||
* @param [out] enc The encoded point. | * @param [out] enc The encoded point. | ||||
* @param [in] p The point. | * @param [in] p The point. | ||||
*/ | */ | ||||
decaf_error_t decaf_448_point_decode_like_eddsa_and_ignore_cofactor ( | |||||
decaf_error_t decaf_448_point_decode_like_eddsa_and_mul_by_ratio ( | |||||
decaf_448_point_t p, | decaf_448_point_t p, | ||||
const uint8_t enc[DECAF_EDDSA_448_PUBLIC_BYTES] | const uint8_t enc[DECAF_EDDSA_448_PUBLIC_BYTES] | ||||
) DECAF_API_VIS DECAF_NONNULL DECAF_NOINLINE; | ) DECAF_API_VIS DECAF_NONNULL DECAF_NOINLINE; | ||||
@@ -55,6 +55,9 @@ typedef struct gf_25519_s { | |||||
/** The cofactor the curve would have, if we hadn't removed it */ | /** The cofactor the curve would have, if we hadn't removed it */ | ||||
#define DECAF_255_REMOVED_COFACTOR 8 | #define DECAF_255_REMOVED_COFACTOR 8 | ||||
/** X25519 encoding ratio. */ | |||||
#define DECAF_X25519_ENCODE_RATIO 4 | |||||
/** Number of bytes in an x25519 public key */ | /** Number of bytes in an x25519 public key */ | ||||
#define DECAF_X25519_PUBLIC_BYTES 32 | #define DECAF_X25519_PUBLIC_BYTES 32 | ||||
@@ -401,12 +404,26 @@ decaf_error_t decaf_x25519 ( | |||||
) DECAF_API_VIS DECAF_NONNULL DECAF_WARN_UNUSED DECAF_NOINLINE; | ) DECAF_API_VIS DECAF_NONNULL DECAF_WARN_UNUSED DECAF_NOINLINE; | ||||
/** | /** | ||||
* @brief Multiply a point by the cofactor, then encode it like RFC 7748 | |||||
* @brief Multiply a point by DECAF_X25519_ENCODE_RATIO, | |||||
* then encode it like RFC 7748. | |||||
* | |||||
* This function is mainly used internally, but is exported in case | |||||
* it will be useful. | |||||
* | |||||
* The ratio is necessary because the internal representation doesn't | |||||
* track the cofactor information, so on output we must clear the cofactor. | |||||
* This would multiply by the cofactor, but in fact internally libdecaf's | |||||
* points are always even, so it multiplies by half the cofactor instead. | |||||
* | |||||
* As it happens, this aligns with the base point definitions; that is, | |||||
* if you pass the Decaf/Ristretto base point to this function, the result | |||||
* will be DECAF_X25519_ENCODE_RATIO times the X25519 | |||||
* base point. | |||||
* | * | ||||
* @param [out] out The scaled and encoded point. | * @param [out] out The scaled and encoded point. | ||||
* @param [in] p The point to be scaled and encoded. | * @param [in] p The point to be scaled and encoded. | ||||
*/ | */ | ||||
void decaf_255_point_mul_by_cofactor_and_encode_like_x25519 ( | |||||
void decaf_255_point_mul_by_ratio_and_encode_like_x25519 ( | |||||
uint8_t out[DECAF_X25519_PUBLIC_BYTES], | uint8_t out[DECAF_X25519_PUBLIC_BYTES], | ||||
const decaf_255_point_t p | const decaf_255_point_t p | ||||
) DECAF_API_VIS DECAF_NONNULL; | ) DECAF_API_VIS DECAF_NONNULL; | ||||
@@ -64,9 +64,6 @@ static inline int bits() { return 255; } | |||||
/** The curve's cofactor (removed, but useful for testing) */ | /** The curve's cofactor (removed, but useful for testing) */ | ||||
static const int REMOVED_COFACTOR = 8; | static const int REMOVED_COFACTOR = 8; | ||||
/** The curve's cofactor (removed, but useful for testing) */ | |||||
static const int EDDSA_RATIO = 4; | |||||
/** Residue class of field modulus: p == this mod 2*(this-1) */ | /** Residue class of field modulus: p == this mod 2*(this-1) */ | ||||
static const int FIELD_MODULUS_TYPE = 5; | static const int FIELD_MODULUS_TYPE = 5; | ||||
@@ -263,6 +260,15 @@ public: | |||||
/** Bytes required for EdDSA encoding */ | /** Bytes required for EdDSA encoding */ | ||||
static const size_t LADDER_BYTES = DECAF_X25519_PUBLIC_BYTES; | static const size_t LADDER_BYTES = DECAF_X25519_PUBLIC_BYTES; | ||||
/** Ratio due to EdDSA encoding */ | |||||
static const int EDDSA_ENCODE_RATIO = DECAF_255_EDDSA_ENCODE_RATIO; | |||||
/** Ratio due to EdDSA decoding */ | |||||
static const int EDDSA_DECODE_RATIO = DECAF_255_EDDSA_DECODE_RATIO; | |||||
/** Ratio due to ladder decoding */ | |||||
static const int LADDER_ENCODE_RATIO = DECAF_X25519_ENCODE_RATIO; | |||||
/** | /** | ||||
* Size of a stegged element. | * Size of a stegged element. | ||||
@@ -348,44 +354,49 @@ public: | |||||
* @return DECAF_FAILURE the string was the wrong length, or wasn't the encoding of a point. | * @return DECAF_FAILURE the string was the wrong length, or wasn't the encoding of a point. | ||||
* Contents of the point are undefined. | * Contents of the point are undefined. | ||||
*/ | */ | ||||
inline decaf_error_t DECAF_WARN_UNUSED decode_like_eddsa_and_ignore_cofactor_noexcept ( | |||||
inline decaf_error_t DECAF_WARN_UNUSED decode_like_eddsa_and_mul_by_ratio_noexcept ( | |||||
const FixedBlock<DECAF_EDDSA_25519_PUBLIC_BYTES> &buffer | const FixedBlock<DECAF_EDDSA_25519_PUBLIC_BYTES> &buffer | ||||
) DECAF_NOEXCEPT { | ) DECAF_NOEXCEPT { | ||||
return decaf_255_point_decode_like_eddsa_and_ignore_cofactor(p,buffer.data()); | |||||
return decaf_255_point_decode_like_eddsa_and_mul_by_ratio(p,buffer.data()); | |||||
} | } | ||||
inline void decode_like_eddsa_and_ignore_cofactor ( | |||||
/** | |||||
* Decode from EDDSA, multiply by EDDSA_DECODE_RATIO, and ignore any | |||||
* remaining cofactor information. | |||||
* @throw CryptoException if the input point was invalid. | |||||
*/ | |||||
inline void decode_like_eddsa_and_mul_by_ratio( | |||||
const FixedBlock<DECAF_EDDSA_25519_PUBLIC_BYTES> &buffer | const FixedBlock<DECAF_EDDSA_25519_PUBLIC_BYTES> &buffer | ||||
) /*throw(CryptoException)*/ { | ) /*throw(CryptoException)*/ { | ||||
if (DECAF_SUCCESS != decode_like_eddsa_and_ignore_cofactor_noexcept(buffer)) throw(CryptoException()); | |||||
if (DECAF_SUCCESS != decode_like_eddsa_and_mul_by_ratio_noexcept(buffer)) throw(CryptoException()); | |||||
} | } | ||||
/** Multiply out cofactor and encode like EdDSA. */ | |||||
inline SecureBuffer mul_by_cofactor_and_encode_like_eddsa() const { | |||||
/** Multiply by EDDSA_ENCODE_RATIO and encode like EdDSA. */ | |||||
inline SecureBuffer mul_by_ratio_and_encode_like_eddsa() const { | |||||
SecureBuffer ret(DECAF_EDDSA_25519_PUBLIC_BYTES); | SecureBuffer ret(DECAF_EDDSA_25519_PUBLIC_BYTES); | ||||
decaf_255_point_mul_by_cofactor_and_encode_like_eddsa(ret.data(),p); | |||||
decaf_255_point_mul_by_ratio_and_encode_like_eddsa(ret.data(),p); | |||||
return ret; | return ret; | ||||
} | } | ||||
/** Multiply out cofactor and encode like X25519/X448. */ | |||||
inline SecureBuffer mul_by_cofactor_and_encode_like_ladder() const { | |||||
SecureBuffer ret(LADDER_BYTES); | |||||
decaf_255_point_mul_by_cofactor_and_encode_like_x25519(ret.data(),p); | |||||
return ret; | |||||
} | |||||
/** Multiply out cofactor and encode like EdDSA. */ | |||||
inline void mul_by_cofactor_and_encode_like_eddsa( | |||||
/** Multiply by EDDSA_ENCODE_RATIO and encode like EdDSA. */ | |||||
inline void mul_by_ratio_and_encode_like_eddsa( | |||||
FixedBuffer<DECAF_EDDSA_25519_PUBLIC_BYTES> &out | FixedBuffer<DECAF_EDDSA_25519_PUBLIC_BYTES> &out | ||||
) const { | ) const { | ||||
decaf_255_point_mul_by_cofactor_and_encode_like_eddsa(out.data(),p); | |||||
decaf_255_point_mul_by_ratio_and_encode_like_eddsa(out.data(),p); | |||||
} | |||||
/** Multiply by LADDER_ENCODE_RATIO and encode like X25519/X448. */ | |||||
inline SecureBuffer mul_by_ratio_and_encode_like_ladder() const { | |||||
SecureBuffer ret(LADDER_BYTES); | |||||
decaf_255_point_mul_by_ratio_and_encode_like_x25519(ret.data(),p); | |||||
return ret; | |||||
} | } | ||||
/** Multiply out cofactor and encode like X25519/X448. */ | |||||
inline void mul_by_cofactor_and_encode_like_ladder( | |||||
/** Multiply by LADDER_ENCODE_RATIO and encode like X25519/X448. */ | |||||
inline void mul_by_ratio_and_encode_like_ladder( | |||||
FixedBuffer<LADDER_BYTES> &out | FixedBuffer<LADDER_BYTES> &out | ||||
) const { | ) const { | ||||
decaf_255_point_mul_by_cofactor_and_encode_like_x25519(out.data(),p); | |||||
decaf_255_point_mul_by_ratio_and_encode_like_x25519(out.data(),p); | |||||
} | } | ||||
/** | /** | ||||
@@ -55,6 +55,9 @@ typedef struct gf_448_s { | |||||
/** The cofactor the curve would have, if we hadn't removed it */ | /** The cofactor the curve would have, if we hadn't removed it */ | ||||
#define DECAF_448_REMOVED_COFACTOR 4 | #define DECAF_448_REMOVED_COFACTOR 4 | ||||
/** X448 encoding ratio. */ | |||||
#define DECAF_X448_ENCODE_RATIO 2 | |||||
/** Number of bytes in an x448 public key */ | /** Number of bytes in an x448 public key */ | ||||
#define DECAF_X448_PUBLIC_BYTES 56 | #define DECAF_X448_PUBLIC_BYTES 56 | ||||
@@ -401,12 +404,26 @@ decaf_error_t decaf_x448 ( | |||||
) DECAF_API_VIS DECAF_NONNULL DECAF_WARN_UNUSED DECAF_NOINLINE; | ) DECAF_API_VIS DECAF_NONNULL DECAF_WARN_UNUSED DECAF_NOINLINE; | ||||
/** | /** | ||||
* @brief Multiply a point by the cofactor, then encode it like RFC 7748 | |||||
* @brief Multiply a point by DECAF_X448_ENCODE_RATIO, | |||||
* then encode it like RFC 7748. | |||||
* | |||||
* This function is mainly used internally, but is exported in case | |||||
* it will be useful. | |||||
* | |||||
* The ratio is necessary because the internal representation doesn't | |||||
* track the cofactor information, so on output we must clear the cofactor. | |||||
* This would multiply by the cofactor, but in fact internally libdecaf's | |||||
* points are always even, so it multiplies by half the cofactor instead. | |||||
* | |||||
* As it happens, this aligns with the base point definitions; that is, | |||||
* if you pass the Decaf/Ristretto base point to this function, the result | |||||
* will be DECAF_X448_ENCODE_RATIO times the X448 | |||||
* base point. | |||||
* | * | ||||
* @param [out] out The scaled and encoded point. | * @param [out] out The scaled and encoded point. | ||||
* @param [in] p The point to be scaled and encoded. | * @param [in] p The point to be scaled and encoded. | ||||
*/ | */ | ||||
void decaf_448_point_mul_by_cofactor_and_encode_like_x448 ( | |||||
void decaf_448_point_mul_by_ratio_and_encode_like_x448 ( | |||||
uint8_t out[DECAF_X448_PUBLIC_BYTES], | uint8_t out[DECAF_X448_PUBLIC_BYTES], | ||||
const decaf_448_point_t p | const decaf_448_point_t p | ||||
) DECAF_API_VIS DECAF_NONNULL; | ) DECAF_API_VIS DECAF_NONNULL; | ||||
@@ -64,9 +64,6 @@ static inline int bits() { return 448; } | |||||
/** The curve's cofactor (removed, but useful for testing) */ | /** The curve's cofactor (removed, but useful for testing) */ | ||||
static const int REMOVED_COFACTOR = 4; | static const int REMOVED_COFACTOR = 4; | ||||
/** The curve's cofactor (removed, but useful for testing) */ | |||||
static const int EDDSA_RATIO = 4; | |||||
/** Residue class of field modulus: p == this mod 2*(this-1) */ | /** Residue class of field modulus: p == this mod 2*(this-1) */ | ||||
static const int FIELD_MODULUS_TYPE = 3; | static const int FIELD_MODULUS_TYPE = 3; | ||||
@@ -263,6 +260,15 @@ public: | |||||
/** Bytes required for EdDSA encoding */ | /** Bytes required for EdDSA encoding */ | ||||
static const size_t LADDER_BYTES = DECAF_X448_PUBLIC_BYTES; | static const size_t LADDER_BYTES = DECAF_X448_PUBLIC_BYTES; | ||||
/** Ratio due to EdDSA encoding */ | |||||
static const int EDDSA_ENCODE_RATIO = DECAF_448_EDDSA_ENCODE_RATIO; | |||||
/** Ratio due to EdDSA decoding */ | |||||
static const int EDDSA_DECODE_RATIO = DECAF_448_EDDSA_DECODE_RATIO; | |||||
/** Ratio due to ladder decoding */ | |||||
static const int LADDER_ENCODE_RATIO = DECAF_X448_ENCODE_RATIO; | |||||
/** | /** | ||||
* Size of a stegged element. | * Size of a stegged element. | ||||
@@ -348,44 +354,49 @@ public: | |||||
* @return DECAF_FAILURE the string was the wrong length, or wasn't the encoding of a point. | * @return DECAF_FAILURE the string was the wrong length, or wasn't the encoding of a point. | ||||
* Contents of the point are undefined. | * Contents of the point are undefined. | ||||
*/ | */ | ||||
inline decaf_error_t DECAF_WARN_UNUSED decode_like_eddsa_and_ignore_cofactor_noexcept ( | |||||
inline decaf_error_t DECAF_WARN_UNUSED decode_like_eddsa_and_mul_by_ratio_noexcept ( | |||||
const FixedBlock<DECAF_EDDSA_448_PUBLIC_BYTES> &buffer | const FixedBlock<DECAF_EDDSA_448_PUBLIC_BYTES> &buffer | ||||
) DECAF_NOEXCEPT { | ) DECAF_NOEXCEPT { | ||||
return decaf_448_point_decode_like_eddsa_and_ignore_cofactor(p,buffer.data()); | |||||
return decaf_448_point_decode_like_eddsa_and_mul_by_ratio(p,buffer.data()); | |||||
} | } | ||||
inline void decode_like_eddsa_and_ignore_cofactor ( | |||||
/** | |||||
* Decode from EDDSA, multiply by EDDSA_DECODE_RATIO, and ignore any | |||||
* remaining cofactor information. | |||||
* @throw CryptoException if the input point was invalid. | |||||
*/ | |||||
inline void decode_like_eddsa_and_mul_by_ratio( | |||||
const FixedBlock<DECAF_EDDSA_448_PUBLIC_BYTES> &buffer | const FixedBlock<DECAF_EDDSA_448_PUBLIC_BYTES> &buffer | ||||
) /*throw(CryptoException)*/ { | ) /*throw(CryptoException)*/ { | ||||
if (DECAF_SUCCESS != decode_like_eddsa_and_ignore_cofactor_noexcept(buffer)) throw(CryptoException()); | |||||
if (DECAF_SUCCESS != decode_like_eddsa_and_mul_by_ratio_noexcept(buffer)) throw(CryptoException()); | |||||
} | } | ||||
/** Multiply out cofactor and encode like EdDSA. */ | |||||
inline SecureBuffer mul_by_cofactor_and_encode_like_eddsa() const { | |||||
/** Multiply by EDDSA_ENCODE_RATIO and encode like EdDSA. */ | |||||
inline SecureBuffer mul_by_ratio_and_encode_like_eddsa() const { | |||||
SecureBuffer ret(DECAF_EDDSA_448_PUBLIC_BYTES); | SecureBuffer ret(DECAF_EDDSA_448_PUBLIC_BYTES); | ||||
decaf_448_point_mul_by_cofactor_and_encode_like_eddsa(ret.data(),p); | |||||
decaf_448_point_mul_by_ratio_and_encode_like_eddsa(ret.data(),p); | |||||
return ret; | return ret; | ||||
} | } | ||||
/** Multiply out cofactor and encode like X25519/X448. */ | |||||
inline SecureBuffer mul_by_cofactor_and_encode_like_ladder() const { | |||||
SecureBuffer ret(LADDER_BYTES); | |||||
decaf_448_point_mul_by_cofactor_and_encode_like_x448(ret.data(),p); | |||||
return ret; | |||||
} | |||||
/** Multiply out cofactor and encode like EdDSA. */ | |||||
inline void mul_by_cofactor_and_encode_like_eddsa( | |||||
/** Multiply by EDDSA_ENCODE_RATIO and encode like EdDSA. */ | |||||
inline void mul_by_ratio_and_encode_like_eddsa( | |||||
FixedBuffer<DECAF_EDDSA_448_PUBLIC_BYTES> &out | FixedBuffer<DECAF_EDDSA_448_PUBLIC_BYTES> &out | ||||
) const { | ) const { | ||||
decaf_448_point_mul_by_cofactor_and_encode_like_eddsa(out.data(),p); | |||||
decaf_448_point_mul_by_ratio_and_encode_like_eddsa(out.data(),p); | |||||
} | |||||
/** Multiply by LADDER_ENCODE_RATIO and encode like X25519/X448. */ | |||||
inline SecureBuffer mul_by_ratio_and_encode_like_ladder() const { | |||||
SecureBuffer ret(LADDER_BYTES); | |||||
decaf_448_point_mul_by_ratio_and_encode_like_x448(ret.data(),p); | |||||
return ret; | |||||
} | } | ||||
/** Multiply out cofactor and encode like X25519/X448. */ | |||||
inline void mul_by_cofactor_and_encode_like_ladder( | |||||
/** Multiply by LADDER_ENCODE_RATIO and encode like X25519/X448. */ | |||||
inline void mul_by_ratio_and_encode_like_ladder( | |||||
FixedBuffer<LADDER_BYTES> &out | FixedBuffer<LADDER_BYTES> &out | ||||
) const { | ) const { | ||||
decaf_448_point_mul_by_cofactor_and_encode_like_x448(out.data(),p); | |||||
decaf_448_point_mul_by_ratio_and_encode_like_x448(out.data(),p); | |||||
} | } | ||||
/** | /** | ||||
@@ -33,6 +33,8 @@ curve_data = { | |||||
"trace": -0xa6f7cef517bce6b2c09318d2e7ae9f7a, | "trace": -0xa6f7cef517bce6b2c09318d2e7ae9f7a, | ||||
"mont_base": 9, | "mont_base": 9, | ||||
"rist_base": "e2f2ae0a6abc4e71a884a961c500515f58e30b6aa582dd8db6a65945e08d2d76", | "rist_base": "e2f2ae0a6abc4e71a884a961c500515f58e30b6aa582dd8db6a65945e08d2d76", | ||||
"eddsa_encode_ratio": 4, | |||||
"x_encode_ratio": 4, | |||||
"combs":comb_config(3,5,17), | "combs":comb_config(3,5,17), | ||||
"wnaf":wnaf_config(5,3), | "wnaf":wnaf_config(5,3), | ||||
@@ -44,6 +46,8 @@ curve_data = { | |||||
"eddsa_sigma_iso": 1 | "eddsa_sigma_iso": 1 | ||||
}, | }, | ||||
"ed448goldilocks" : { | "ed448goldilocks" : { | ||||
"eddsa_encode_ratio": 4, | |||||
"x_encode_ratio": 2, | |||||
"altname": None, | "altname": None, | ||||
"name" : "Ed448-Goldilocks", | "name" : "Ed448-Goldilocks", | ||||
"cofactor" : 4, | "cofactor" : 4, | ||||
@@ -1029,7 +1029,7 @@ decaf_error_t API_NS(direct_scalarmul) ( | |||||
return succ; | return succ; | ||||
} | } | ||||
void API_NS(point_mul_by_cofactor_and_encode_like_eddsa) ( | |||||
void API_NS(point_mul_by_ratio_and_encode_like_eddsa) ( | |||||
uint8_t enc[DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES], | uint8_t enc[DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES], | ||||
const point_t p | const point_t p | ||||
) { | ) { | ||||
@@ -1122,7 +1122,7 @@ void API_NS(point_mul_by_cofactor_and_encode_like_eddsa) ( | |||||
} | } | ||||
decaf_error_t API_NS(point_decode_like_eddsa_and_ignore_cofactor) ( | |||||
decaf_error_t API_NS(point_decode_like_eddsa_and_mul_by_ratio) ( | |||||
point_t p, | point_t p, | ||||
const uint8_t enc[DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES] | const uint8_t enc[DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES] | ||||
) { | ) { | ||||
@@ -1341,13 +1341,16 @@ void decaf_x$(gf_shortname)_generate_key ( | |||||
decaf_x$(gf_shortname)_derive_public_key(out,scalar); | decaf_x$(gf_shortname)_derive_public_key(out,scalar); | ||||
} | } | ||||
void API_NS(point_mul_by_cofactor_and_encode_like_x$(gf_shortname)) ( | |||||
void API_NS(point_mul_by_ratio_and_encode_like_x$(gf_shortname)) ( | |||||
uint8_t out[X_PUBLIC_BYTES], | uint8_t out[X_PUBLIC_BYTES], | ||||
const point_t p | const point_t p | ||||
) { | ) { | ||||
point_t q; | point_t q; | ||||
#if COFACTOR == 8 | |||||
point_double_internal(q,p,1); | point_double_internal(q,p,1); | ||||
for (unsigned i=1; i<COFACTOR/4; i<<=1) point_double_internal(q,q,1); | |||||
#else | |||||
API_NS(point_copy)(q,p); | |||||
#endif | |||||
gf_invert(q->t,q->x,0); /* 1/x */ | gf_invert(q->t,q->x,0); /* 1/x */ | ||||
gf_mul(q->z,q->t,q->y); /* y/x */ | gf_mul(q->z,q->t,q->y); /* y/x */ | ||||
gf_sqr(q->y,q->z); /* (y/x)^2 */ | gf_sqr(q->y,q->z); /* (y/x)^2 */ | ||||
@@ -1373,24 +1376,13 @@ void decaf_x$(gf_shortname)_derive_public_key ( | |||||
scalar_t the_scalar; | scalar_t the_scalar; | ||||
API_NS(scalar_decode_long)(the_scalar,scalar2,sizeof(scalar2)); | API_NS(scalar_decode_long)(the_scalar,scalar2,sizeof(scalar2)); | ||||
/* We're gonna isogenize by 2, so divide by 2. | |||||
* | |||||
* Why by 2, even though it's a 4-isogeny? | |||||
* | |||||
* The isogeny map looks like | |||||
* Montgomery <-2-> Jacobi <-2-> Edwards | |||||
* | |||||
* Since the Jacobi base point is the PREimage of the iso to | |||||
* the Montgomery curve, and we're going | |||||
* Jacobi -> Edwards -> Jacobi -> Montgomery, | |||||
* we pick up only a factor of 2 over Jacobi -> Montgomery. | |||||
*/ | |||||
for (unsigned i=1; i<COFACTOR; i<<=1) { | |||||
/* Compensate for the encoding ratio */ | |||||
for (unsigned i=1; i<DECAF_X$(gf_shortname)_ENCODE_RATIO; i<<=1) { | |||||
API_NS(scalar_halve)(the_scalar,the_scalar); | API_NS(scalar_halve)(the_scalar,the_scalar); | ||||
} | } | ||||
point_t p; | point_t p; | ||||
API_NS(precomputed_scalarmul)(p,API_NS(precomputed_base),the_scalar); | API_NS(precomputed_scalarmul)(p,API_NS(precomputed_base),the_scalar); | ||||
API_NS(point_mul_by_cofactor_and_encode_like_x$(gf_shortname))(out,p); | |||||
API_NS(point_mul_by_ratio_and_encode_like_x$(gf_shortname))(out,p); | |||||
API_NS(point_destroy)(p); | API_NS(point_destroy)(p); | ||||
} | } | ||||
@@ -29,12 +29,6 @@ const uint8_t NO_CONTEXT_POINTS_HERE = 0; | |||||
const uint8_t * const DECAF_ED$(gf_shortname)_NO_CONTEXT = &NO_CONTEXT_POINTS_HERE; | const uint8_t * const DECAF_ED$(gf_shortname)_NO_CONTEXT = &NO_CONTEXT_POINTS_HERE; | ||||
#endif | #endif | ||||
/* EDDSA_BASE_POINT_RATIO = 1 or 2 | |||||
* Because EdDSA25519 is not on E_d but on the isogenous E_sigma_d, | |||||
* its base point is twice ours. | |||||
*/ | |||||
#define EDDSA_BASE_POINT_RATIO (1+EDDSA_USE_SIGMA_ISOGENY) | |||||
static void clamp ( | static void clamp ( | ||||
uint8_t secret_scalar_ser[DECAF_EDDSA_$(gf_shortname)_PRIVATE_BYTES] | uint8_t secret_scalar_ser[DECAF_EDDSA_$(gf_shortname)_PRIVATE_BYTES] | ||||
) { | ) { | ||||
@@ -120,14 +114,14 @@ void decaf_ed$(gf_shortname)_derive_public_key ( | |||||
* the decaf base point is on Etwist_d, and when converted it effectively | * the decaf base point is on Etwist_d, and when converted it effectively | ||||
* picks up a factor of 2 from the isogenies. So we might start at 2 instead of 1. | * picks up a factor of 2 from the isogenies. So we might start at 2 instead of 1. | ||||
*/ | */ | ||||
for (unsigned int c = EDDSA_BASE_POINT_RATIO; c < COFACTOR; c <<= 1) { | |||||
for (unsigned int c=1; c<$(C_NS)_EDDSA_ENCODE_RATIO; c <<= 1) { | |||||
API_NS(scalar_halve)(secret_scalar,secret_scalar); | API_NS(scalar_halve)(secret_scalar,secret_scalar); | ||||
} | } | ||||
API_NS(point_t) p; | API_NS(point_t) p; | ||||
API_NS(precomputed_scalarmul)(p,API_NS(precomputed_base),secret_scalar); | API_NS(precomputed_scalarmul)(p,API_NS(precomputed_base),secret_scalar); | ||||
API_NS(point_mul_by_cofactor_and_encode_like_eddsa)(pubkey, p); | |||||
API_NS(point_mul_by_ratio_and_encode_like_eddsa)(pubkey, p); | |||||
/* Cleanup */ | /* Cleanup */ | ||||
API_NS(scalar_destroy)(secret_scalar); | API_NS(scalar_destroy)(secret_scalar); | ||||
@@ -183,13 +177,13 @@ void decaf_ed$(gf_shortname)_sign ( | |||||
/* Scalarmul to create the nonce-point */ | /* Scalarmul to create the nonce-point */ | ||||
API_NS(scalar_t) nonce_scalar_2; | API_NS(scalar_t) nonce_scalar_2; | ||||
API_NS(scalar_halve)(nonce_scalar_2,nonce_scalar); | API_NS(scalar_halve)(nonce_scalar_2,nonce_scalar); | ||||
for (unsigned int c = 2*EDDSA_BASE_POINT_RATIO; c < COFACTOR; c <<= 1) { | |||||
for (unsigned int c = 2; c < $(C_NS)_EDDSA_ENCODE_RATIO; c <<= 1) { | |||||
API_NS(scalar_halve)(nonce_scalar_2,nonce_scalar_2); | API_NS(scalar_halve)(nonce_scalar_2,nonce_scalar_2); | ||||
} | } | ||||
API_NS(point_t) p; | API_NS(point_t) p; | ||||
API_NS(precomputed_scalarmul)(p,API_NS(precomputed_base),nonce_scalar_2); | API_NS(precomputed_scalarmul)(p,API_NS(precomputed_base),nonce_scalar_2); | ||||
API_NS(point_mul_by_cofactor_and_encode_like_eddsa)(nonce_point, p); | |||||
API_NS(point_mul_by_ratio_and_encode_like_eddsa)(nonce_point, p); | |||||
API_NS(point_destroy)(p); | API_NS(point_destroy)(p); | ||||
API_NS(scalar_destroy)(nonce_scalar_2); | API_NS(scalar_destroy)(nonce_scalar_2); | ||||
} | } | ||||
@@ -251,10 +245,10 @@ decaf_error_t decaf_ed$(gf_shortname)_verify ( | |||||
uint8_t context_len | uint8_t context_len | ||||
) { | ) { | ||||
API_NS(point_t) pk_point, r_point; | API_NS(point_t) pk_point, r_point; | ||||
decaf_error_t error = API_NS(point_decode_like_eddsa_and_ignore_cofactor)(pk_point,pubkey); | |||||
decaf_error_t error = API_NS(point_decode_like_eddsa_and_mul_by_ratio)(pk_point,pubkey); | |||||
if (DECAF_SUCCESS != error) { return error; } | if (DECAF_SUCCESS != error) { return error; } | ||||
error = API_NS(point_decode_like_eddsa_and_ignore_cofactor)(r_point,signature); | |||||
error = API_NS(point_decode_like_eddsa_and_mul_by_ratio)(r_point,signature); | |||||
if (DECAF_SUCCESS != error) { return error; } | if (DECAF_SUCCESS != error) { return error; } | ||||
API_NS(scalar_t) challenge_scalar; | API_NS(scalar_t) challenge_scalar; | ||||
@@ -279,9 +273,10 @@ decaf_error_t decaf_ed$(gf_shortname)_verify ( | |||||
&signature[DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES], | &signature[DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES], | ||||
DECAF_EDDSA_$(gf_shortname)_PRIVATE_BYTES | DECAF_EDDSA_$(gf_shortname)_PRIVATE_BYTES | ||||
); | ); | ||||
#if EDDSA_BASE_POINT_RATIO == 2 | |||||
API_NS(scalar_add)(response_scalar,response_scalar,response_scalar); | |||||
#endif | |||||
for (unsigned c=1; c<$(C_NS)_EDDSA_DECODE_RATIO; c<<=1) { | |||||
API_NS(scalar_add)(response_scalar,response_scalar,response_scalar); | |||||
} | |||||
/* pk_point = -c(x(P)) + (cx + k)G = kG */ | /* pk_point = -c(x(P)) + (cx + k)G = kG */ | ||||
@@ -26,6 +26,12 @@ $("extern const uint8_t * const DECAF_ED" + gf_shortname + "_NO_CONTEXT DECAF_AP | |||||
#define decaf_ed$(gf_shortname)_prehash_update decaf_$(eddsa_hash)_update | #define decaf_ed$(gf_shortname)_prehash_update decaf_$(eddsa_hash)_update | ||||
#define decaf_ed$(gf_shortname)_prehash_destroy decaf_$(eddsa_hash)_destroy | #define decaf_ed$(gf_shortname)_prehash_destroy decaf_$(eddsa_hash)_destroy | ||||
/** EdDSA encoding ratio. */ | |||||
#define $(C_NS)_EDDSA_ENCODE_RATIO $(eddsa_encode_ratio) | |||||
/** EdDSA decoding ratio. */ | |||||
#define $(C_NS)_EDDSA_DECODE_RATIO ($(cofactor) / $(eddsa_encode_ratio)) | |||||
/** | /** | ||||
* @brief EdDSA key generation. This function uses a different (non-Decaf) | * @brief EdDSA key generation. This function uses a different (non-Decaf) | ||||
* encoding. | * encoding. | ||||
@@ -153,25 +159,43 @@ decaf_error_t decaf_ed$(gf_shortname)_verify_prehash ( | |||||
/** | /** | ||||
* @brief EdDSA point encoding. Used internally, exposed externally. | * @brief EdDSA point encoding. Used internally, exposed externally. | ||||
* Multiplies the point by the current cofactor first. | |||||
* Multiplies by $(C_NS)_EDDSA_ENCODE_RATIO first. | |||||
* | |||||
* The multiplication is required because the EdDSA encoding represents | |||||
* the cofactor information, but the Decaf encoding ignores it (which | |||||
* is the whole point). So if you decode from EdDSA and re-encode to | |||||
* EdDSA, the cofactor info must get cleared, because the intermediate | |||||
* representation doesn't track it. | |||||
* | |||||
* The way libdecaf handles this is to multiply by | |||||
* $(C_NS)_EDDSA_DECODE_RATIO when decoding, and by | |||||
* $(C_NS)_EDDSA_ENCODE_RATIO when encoding. The product of these | |||||
* ratios is always exactly the cofactor $(cofactor), so the cofactor | |||||
* ends up cleared one way or another. But exactly how that shakes | |||||
* out depends on the base points specified in RFC 8032. | |||||
* | |||||
* The upshot is that if you pass the Decaf/Ristretto base point to | |||||
* this function, you will get $(C_NS)_EDDSA_ENCODE_RATIO times the | |||||
* EdDSA base point. | |||||
* | * | ||||
* @param [out] enc The encoded point. | * @param [out] enc The encoded point. | ||||
* @param [in] p The point. | * @param [in] p The point. | ||||
*/ | */ | ||||
void $(c_ns)_point_mul_by_cofactor_and_encode_like_eddsa ( | |||||
void $(c_ns)_point_mul_by_ratio_and_encode_like_eddsa ( | |||||
uint8_t enc[DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES], | uint8_t enc[DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES], | ||||
const $(c_ns)_point_t p | const $(c_ns)_point_t p | ||||
) DECAF_API_VIS DECAF_NONNULL DECAF_NOINLINE; | ) DECAF_API_VIS DECAF_NONNULL DECAF_NOINLINE; | ||||
/** | /** | ||||
* @brief EdDSA point decoding. Remember that while points on the | |||||
* EdDSA curves have cofactor information, Decaf ignores (quotients | |||||
* out) all cofactor information. | |||||
* @brief EdDSA point decoding. Multiplies by $(C_NS)_EDDSA_DECODE_RATIO, | |||||
* and ignores cofactor information. | |||||
* | |||||
* See notes on $(c_ns)_point_mul_by_ratio_and_encode_like_eddsa | |||||
* | * | ||||
* @param [out] enc The encoded point. | * @param [out] enc The encoded point. | ||||
* @param [in] p The point. | * @param [in] p The point. | ||||
*/ | */ | ||||
decaf_error_t $(c_ns)_point_decode_like_eddsa_and_ignore_cofactor ( | |||||
decaf_error_t $(c_ns)_point_decode_like_eddsa_and_mul_by_ratio ( | |||||
$(c_ns)_point_t p, | $(c_ns)_point_t p, | ||||
const uint8_t enc[DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES] | const uint8_t enc[DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES] | ||||
) DECAF_API_VIS DECAF_NONNULL DECAF_NOINLINE; | ) DECAF_API_VIS DECAF_NONNULL DECAF_NOINLINE; | ||||
@@ -40,6 +40,9 @@ typedef struct gf_$(gf_shortname)_s { | |||||
/** The cofactor the curve would have, if we hadn't removed it */ | /** The cofactor the curve would have, if we hadn't removed it */ | ||||
#define $(C_NS)_REMOVED_COFACTOR $(cofactor) | #define $(C_NS)_REMOVED_COFACTOR $(cofactor) | ||||
/** X$(gf_shortname) encoding ratio. */ | |||||
#define DECAF_X$(gf_shortname)_ENCODE_RATIO $(x_encode_ratio) | |||||
/** Number of bytes in an x$(gf_shortname) public key */ | /** Number of bytes in an x$(gf_shortname) public key */ | ||||
#define DECAF_X$(gf_shortname)_PUBLIC_BYTES $((gf_bits-1)//8 + 1) | #define DECAF_X$(gf_shortname)_PUBLIC_BYTES $((gf_bits-1)//8 + 1) | ||||
@@ -386,12 +389,26 @@ decaf_error_t decaf_x$(gf_shortname) ( | |||||
) DECAF_API_VIS DECAF_NONNULL DECAF_WARN_UNUSED DECAF_NOINLINE; | ) DECAF_API_VIS DECAF_NONNULL DECAF_WARN_UNUSED DECAF_NOINLINE; | ||||
/** | /** | ||||
* @brief Multiply a point by the cofactor, then encode it like RFC 7748 | |||||
* @brief Multiply a point by DECAF_X$(gf_shortname)_ENCODE_RATIO, | |||||
* then encode it like RFC 7748. | |||||
* | |||||
* This function is mainly used internally, but is exported in case | |||||
* it will be useful. | |||||
* | |||||
* The ratio is necessary because the internal representation doesn't | |||||
* track the cofactor information, so on output we must clear the cofactor. | |||||
* This would multiply by the cofactor, but in fact internally libdecaf's | |||||
* points are always even, so it multiplies by half the cofactor instead. | |||||
* | |||||
* As it happens, this aligns with the base point definitions; that is, | |||||
* if you pass the Decaf/Ristretto base point to this function, the result | |||||
* will be DECAF_X$(gf_shortname)_ENCODE_RATIO times the X$(gf_shortname) | |||||
* base point. | |||||
* | * | ||||
* @param [out] out The scaled and encoded point. | * @param [out] out The scaled and encoded point. | ||||
* @param [in] p The point to be scaled and encoded. | * @param [in] p The point to be scaled and encoded. | ||||
*/ | */ | ||||
void $(c_ns)_point_mul_by_cofactor_and_encode_like_x$(gf_shortname) ( | |||||
void $(c_ns)_point_mul_by_ratio_and_encode_like_x$(gf_shortname) ( | |||||
uint8_t out[DECAF_X$(gf_shortname)_PUBLIC_BYTES], | uint8_t out[DECAF_X$(gf_shortname)_PUBLIC_BYTES], | ||||
const $(c_ns)_point_t p | const $(c_ns)_point_t p | ||||
) DECAF_API_VIS DECAF_NONNULL; | ) DECAF_API_VIS DECAF_NONNULL; | ||||
@@ -51,9 +51,6 @@ static inline int bits() { return $(gf_bits); } | |||||
/** The curve's cofactor (removed, but useful for testing) */ | /** The curve's cofactor (removed, but useful for testing) */ | ||||
static const int REMOVED_COFACTOR = $(cofactor); | static const int REMOVED_COFACTOR = $(cofactor); | ||||
/** The curve's cofactor (removed, but useful for testing) */ | |||||
static const int EDDSA_RATIO = $(cofactor/2 if eddsa_sigma_iso else cofactor); | |||||
/** Residue class of field modulus: p == this mod 2*(this-1) */ | /** Residue class of field modulus: p == this mod 2*(this-1) */ | ||||
static const int FIELD_MODULUS_TYPE = $(modulus &~ (modulus-3)); | static const int FIELD_MODULUS_TYPE = $(modulus &~ (modulus-3)); | ||||
@@ -250,6 +247,15 @@ public: | |||||
/** Bytes required for EdDSA encoding */ | /** Bytes required for EdDSA encoding */ | ||||
static const size_t LADDER_BYTES = DECAF_X$(gf_shortname)_PUBLIC_BYTES; | static const size_t LADDER_BYTES = DECAF_X$(gf_shortname)_PUBLIC_BYTES; | ||||
/** Ratio due to EdDSA encoding */ | |||||
static const int EDDSA_ENCODE_RATIO = $(C_NS)_EDDSA_ENCODE_RATIO; | |||||
/** Ratio due to EdDSA decoding */ | |||||
static const int EDDSA_DECODE_RATIO = $(C_NS)_EDDSA_DECODE_RATIO; | |||||
/** Ratio due to ladder decoding */ | |||||
static const int LADDER_ENCODE_RATIO = DECAF_X$(gf_shortname)_ENCODE_RATIO; | |||||
/** | /** | ||||
* Size of a stegged element. | * Size of a stegged element. | ||||
@@ -335,44 +341,49 @@ public: | |||||
* @return DECAF_FAILURE the string was the wrong length, or wasn't the encoding of a point. | * @return DECAF_FAILURE the string was the wrong length, or wasn't the encoding of a point. | ||||
* Contents of the point are undefined. | * Contents of the point are undefined. | ||||
*/ | */ | ||||
inline decaf_error_t DECAF_WARN_UNUSED decode_like_eddsa_and_ignore_cofactor_noexcept ( | |||||
inline decaf_error_t DECAF_WARN_UNUSED decode_like_eddsa_and_mul_by_ratio_noexcept ( | |||||
const FixedBlock<DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES> &buffer | const FixedBlock<DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES> &buffer | ||||
) DECAF_NOEXCEPT { | ) DECAF_NOEXCEPT { | ||||
return $(c_ns)_point_decode_like_eddsa_and_ignore_cofactor(p,buffer.data()); | |||||
return $(c_ns)_point_decode_like_eddsa_and_mul_by_ratio(p,buffer.data()); | |||||
} | } | ||||
inline void decode_like_eddsa_and_ignore_cofactor ( | |||||
/** | |||||
* Decode from EDDSA, multiply by EDDSA_DECODE_RATIO, and ignore any | |||||
* remaining cofactor information. | |||||
* @throw CryptoException if the input point was invalid. | |||||
*/ | |||||
inline void decode_like_eddsa_and_mul_by_ratio( | |||||
const FixedBlock<DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES> &buffer | const FixedBlock<DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES> &buffer | ||||
) /*throw(CryptoException)*/ { | ) /*throw(CryptoException)*/ { | ||||
if (DECAF_SUCCESS != decode_like_eddsa_and_ignore_cofactor_noexcept(buffer)) throw(CryptoException()); | |||||
if (DECAF_SUCCESS != decode_like_eddsa_and_mul_by_ratio_noexcept(buffer)) throw(CryptoException()); | |||||
} | } | ||||
/** Multiply out cofactor and encode like EdDSA. */ | |||||
inline SecureBuffer mul_by_cofactor_and_encode_like_eddsa() const { | |||||
/** Multiply by EDDSA_ENCODE_RATIO and encode like EdDSA. */ | |||||
inline SecureBuffer mul_by_ratio_and_encode_like_eddsa() const { | |||||
SecureBuffer ret(DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES); | SecureBuffer ret(DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES); | ||||
$(c_ns)_point_mul_by_cofactor_and_encode_like_eddsa(ret.data(),p); | |||||
$(c_ns)_point_mul_by_ratio_and_encode_like_eddsa(ret.data(),p); | |||||
return ret; | return ret; | ||||
} | } | ||||
/** Multiply out cofactor and encode like X25519/X448. */ | |||||
inline SecureBuffer mul_by_cofactor_and_encode_like_ladder() const { | |||||
SecureBuffer ret(LADDER_BYTES); | |||||
$(c_ns)_point_mul_by_cofactor_and_encode_like_x$(gf_shortname)(ret.data(),p); | |||||
return ret; | |||||
} | |||||
/** Multiply out cofactor and encode like EdDSA. */ | |||||
inline void mul_by_cofactor_and_encode_like_eddsa( | |||||
/** Multiply by EDDSA_ENCODE_RATIO and encode like EdDSA. */ | |||||
inline void mul_by_ratio_and_encode_like_eddsa( | |||||
FixedBuffer<DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES> &out | FixedBuffer<DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES> &out | ||||
) const { | ) const { | ||||
$(c_ns)_point_mul_by_cofactor_and_encode_like_eddsa(out.data(),p); | |||||
$(c_ns)_point_mul_by_ratio_and_encode_like_eddsa(out.data(),p); | |||||
} | |||||
/** Multiply by LADDER_ENCODE_RATIO and encode like X25519/X448. */ | |||||
inline SecureBuffer mul_by_ratio_and_encode_like_ladder() const { | |||||
SecureBuffer ret(LADDER_BYTES); | |||||
$(c_ns)_point_mul_by_ratio_and_encode_like_x$(gf_shortname)(ret.data(),p); | |||||
return ret; | |||||
} | } | ||||
/** Multiply out cofactor and encode like X25519/X448. */ | |||||
inline void mul_by_cofactor_and_encode_like_ladder( | |||||
/** Multiply by LADDER_ENCODE_RATIO and encode like X25519/X448. */ | |||||
inline void mul_by_ratio_and_encode_like_ladder( | |||||
FixedBuffer<LADDER_BYTES> &out | FixedBuffer<LADDER_BYTES> &out | ||||
) const { | ) const { | ||||
$(c_ns)_point_mul_by_cofactor_and_encode_like_x$(gf_shortname)(out.data(),p); | |||||
$(c_ns)_point_mul_by_ratio_and_encode_like_x$(gf_shortname)(out.data(),p); | |||||
} | } | ||||
/** | /** | ||||
@@ -70,7 +70,7 @@ void usage() { | |||||
fprintf(stderr," -D: Display output in EdDSA format (times clearing ratio)\n"); | fprintf(stderr," -D: Display output in EdDSA format (times clearing ratio)\n"); | ||||
fprintf(stderr," -R: Display raw xyzt\n"); | fprintf(stderr," -R: Display raw xyzt\n"); | ||||
fprintf(stderr," -C: Display output in X[25519|448] format\n"); | fprintf(stderr," -C: Display output in X[25519|448] format\n"); | ||||
fprintf(stderr," -H: ... divide by clearing ratio first\n"); | |||||
fprintf(stderr," -H: ... divide by encoding ratio first\n"); | |||||
fprintf(stderr,"\n"); | fprintf(stderr,"\n"); | ||||
fprintf(stderr," Ways to create points:\n"); | fprintf(stderr," Ways to create points:\n"); | ||||
fprintf(stderr," [hex]: Point from point data as hex\n"); | fprintf(stderr," [hex]: Point from point data as hex\n"); | ||||
@@ -97,7 +97,7 @@ public: | |||||
uint8_t tmp[Group::Point::SER_BYTES]; | uint8_t tmp[Group::Point::SER_BYTES]; | ||||
typename Group::Point a,b; | typename Group::Point a,b; | ||||
typename Group::Scalar s; | typename Group::Scalar s; | ||||
bool plus=false, empty=true, elligator=false, mul=false, scalar=false, | |||||
bool plus=false, empty=true, elligator=false, mul=false, scalar=false, div=false, torque=false, | |||||
scalarempty=true, neg=false, einv=false, like_eddsa=false, like_x=false, decoeff=false, raw=false; | scalarempty=true, neg=false, einv=false, like_eddsa=false, like_x=false, decoeff=false, raw=false; | ||||
if (done || error) return; | if (done || error) return; | ||||
for (int i=1; i<g_argc && !error; i++) { | for (int i=1; i<g_argc && !error; i++) { | ||||
@@ -121,9 +121,14 @@ public: | |||||
like_x = true; | like_x = true; | ||||
} else if (!strcmp(g_argv[i],"-H")) { | } else if (!strcmp(g_argv[i],"-H")) { | ||||
decoeff = true; | decoeff = true; | ||||
} else if (!strcmp(g_argv[i],"-T")) { | |||||
torque = true; | |||||
} else if (!strcmp(g_argv[i],"*")) { | } else if (!strcmp(g_argv[i],"*")) { | ||||
if (elligator || scalar || scalarempty) usage(); | |||||
if (elligator || scalar || scalarempty || div) usage(); | |||||
mul = true; | mul = true; | ||||
} else if (!strcmp(g_argv[i],"/")) { | |||||
if (elligator || scalar || scalarempty || mul) usage(); | |||||
div = true; | |||||
} else if (!strcmp(g_argv[i],"-s")) { | } else if (!strcmp(g_argv[i],"-s")) { | ||||
if (elligator || scalar || !scalarempty) usage(); | if (elligator || scalar || !scalarempty) usage(); | ||||
scalar = true; | scalar = true; | ||||
@@ -156,6 +161,8 @@ public: | |||||
if (point) { | if (point) { | ||||
if (neg) { b = -b; neg = false; } | if (neg) { b = -b; neg = false; } | ||||
if (div) { b /= s; div=false; } | |||||
if (torque) { b = b.debugging_torque(); torque=false; } | |||||
if (mul) { b *= s; mul=false; } | if (mul) { b *= s; mul=false; } | ||||
if (empty) { a = b; empty=false; } | if (empty) { a = b; empty=false; } | ||||
else if (plus) { a += b; plus=false; } | else if (plus) { a += b; plus=false; } | ||||
@@ -164,7 +171,6 @@ public: | |||||
} | } | ||||
if (!error && !empty) { | if (!error && !empty) { | ||||
if (decoeff) a /= (Group::EDDSA_RATIO); | |||||
if (einv) { | if (einv) { | ||||
uint8_t buffer[Group::Point::HASH_BYTES]; | uint8_t buffer[Group::Point::HASH_BYTES]; | ||||
for (int h=0; h<1<<Group::Point::INVERT_ELLIGATOR_WHICH_BITS; h++) { | for (int h=0; h<1<<Group::Point::INVERT_ELLIGATOR_WHICH_BITS; h++) { | ||||
@@ -179,11 +185,13 @@ public: | |||||
printhex((const uint8_t *)&a, sizeof(a)); | printhex((const uint8_t *)&a, sizeof(a)); | ||||
printf("\n"); | printf("\n"); | ||||
} else if (like_eddsa) { | } else if (like_eddsa) { | ||||
SecureBuffer b = a.mul_by_cofactor_and_encode_like_eddsa(); | |||||
if (decoeff) a /= (Group::Point::EDDSA_ENCODE_RATIO); | |||||
SecureBuffer b = a.mul_by_ratio_and_encode_like_eddsa(); | |||||
printhex(b.data(),b.size()); | printhex(b.data(),b.size()); | ||||
printf("\n"); | printf("\n"); | ||||
} else if (like_x) { | } else if (like_x) { | ||||
SecureBuffer b = a.mul_by_cofactor_and_encode_like_ladder(); | |||||
if (decoeff) a /= (Group::Point::LADDER_ENCODE_RATIO); | |||||
SecureBuffer b = a.mul_by_ratio_and_encode_like_ladder(); | |||||
printhex(b.data(),b.size()); | printhex(b.data(),b.size()); | ||||
printf("\n"); | printf("\n"); | ||||
} else { | } else { | ||||
@@ -415,8 +415,8 @@ static void test_ec() { | |||||
q=p; | q=p; | ||||
for (int j=1; j<Group::REMOVED_COFACTOR; j<<=1) q = q.times_two(); | for (int j=1; j<Group::REMOVED_COFACTOR; j<<=1) q = q.times_two(); | ||||
decaf_error_t error = r.decode_like_eddsa_and_ignore_cofactor_noexcept( | |||||
p.mul_by_cofactor_and_encode_like_eddsa() | |||||
decaf_error_t error = r.decode_like_eddsa_and_mul_by_ratio_noexcept( | |||||
p.mul_by_ratio_and_encode_like_eddsa() | |||||
); | ); | ||||
if (error != DECAF_SUCCESS) { | if (error != DECAF_SUCCESS) { | ||||
test.fail(); | test.fail(); | ||||
@@ -552,7 +552,6 @@ static void test_eddsa() { | |||||
SpongeRng rng(Block("test_eddsa"),SpongeRng::DETERMINISTIC); | SpongeRng rng(Block("test_eddsa"),SpongeRng::DETERMINISTIC); | ||||
for (int i=0; i<NTESTS && test.passing_now; i++) { | for (int i=0; i<NTESTS && test.passing_now; i++) { | ||||
typename EdDSA<Group>::PrivateKey priv(rng); | typename EdDSA<Group>::PrivateKey priv(rng); | ||||
typename EdDSA<Group>::PublicKey pub(priv); | typename EdDSA<Group>::PublicKey pub(priv); | ||||
@@ -569,7 +568,22 @@ static void test_eddsa() { | |||||
} catch(CryptoException) { | } catch(CryptoException) { | ||||
test.fail(); | test.fail(); | ||||
printf(" Signature validation failed on sig %d\n", i); | printf(" Signature validation failed on sig %d\n", i); | ||||
} | |||||
} | |||||
/* Test encode_like and torque */ | |||||
Point p(rng); | |||||
SecureBuffer p1 = p.mul_by_ratio_and_encode_like_eddsa(); | |||||
SecureBuffer p2 = p.debugging_torque().mul_by_ratio_and_encode_like_eddsa(); | |||||
if (!memeq(p1,p2)) { | |||||
test.fail(); | |||||
printf(" Torque and encode like EdDSA failed\n"); | |||||
} | |||||
SecureBuffer p3 = p.mul_by_ratio_and_encode_like_ladder(); | |||||
SecureBuffer p4 = p.debugging_torque().mul_by_ratio_and_encode_like_ladder(); | |||||
if (!memeq(p3,p4)) { | |||||
test.fail(); | |||||
printf(" Torque and encode like ladder failed\n"); | |||||
} | |||||
} | } | ||||
} | } | ||||