| @@ -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"); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||