| @@ -1040,7 +1040,7 @@ decaf_error_t API_NS(direct_scalarmul) ( | |||
| 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], | |||
| 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, | |||
| 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); | |||
| } | |||
| 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], | |||
| const point_t p | |||
| ) { | |||
| point_t q; | |||
| #if COFACTOR == 8 | |||
| 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_mul(q->z,q->t,q->y); /* y/x */ | |||
| gf_sqr(q->y,q->z); /* (y/x)^2 */ | |||
| @@ -1384,24 +1387,13 @@ void decaf_x25519_derive_public_key ( | |||
| scalar_t the_scalar; | |||
| 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); | |||
| } | |||
| point_t p; | |||
| 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); | |||
| } | |||
| @@ -31,6 +31,7 @@ | |||
| #define NO_CONTEXT DECAF_EDDSA_25519_SUPPORTS_CONTEXTLESS_SIGS | |||
| #define EDDSA_USE_SIGMA_ISOGENY 1 | |||
| #define COFACTOR 8 | |||
| #define EDDSA_PREHASH_BYTES 64 | |||
| #if NO_CONTEXT | |||
| 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, | |||
| * 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 ( | |||
| 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 | |||
| * 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(point_t) p; | |||
| 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 */ | |||
| API_NS(scalar_destroy)(secret_scalar); | |||
| @@ -191,13 +192,13 @@ void decaf_ed25519_sign ( | |||
| /* Scalarmul to create the nonce-point */ | |||
| API_NS(scalar_t) nonce_scalar_2; | |||
| 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(point_t) p; | |||
| 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(scalar_destroy)(nonce_scalar_2); | |||
| } | |||
| @@ -237,7 +238,7 @@ void decaf_ed25519_sign_prehash ( | |||
| const uint8_t *context, | |||
| 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; | |||
| memcpy(hash_too,hash,sizeof(hash_too)); | |||
| @@ -259,10 +260,10 @@ decaf_error_t decaf_ed25519_verify ( | |||
| uint8_t context_len | |||
| ) { | |||
| 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; } | |||
| 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; } | |||
| API_NS(scalar_t) challenge_scalar; | |||
| @@ -287,9 +288,10 @@ decaf_error_t decaf_ed25519_verify ( | |||
| &signature[DECAF_EDDSA_25519_PUBLIC_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 */ | |||
| @@ -312,7 +314,7 @@ decaf_error_t decaf_ed25519_verify_prehash ( | |||
| ) { | |||
| 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; | |||
| memcpy(hash_too,hash,sizeof(hash_too)); | |||
| @@ -1040,7 +1040,7 @@ decaf_error_t API_NS(direct_scalarmul) ( | |||
| 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], | |||
| 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, | |||
| 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); | |||
| } | |||
| 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], | |||
| const point_t p | |||
| ) { | |||
| point_t q; | |||
| #if COFACTOR == 8 | |||
| 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_mul(q->z,q->t,q->y); /* y/x */ | |||
| gf_sqr(q->y,q->z); /* (y/x)^2 */ | |||
| @@ -1384,24 +1387,13 @@ void decaf_x448_derive_public_key ( | |||
| scalar_t the_scalar; | |||
| 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); | |||
| } | |||
| point_t p; | |||
| 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); | |||
| } | |||
| @@ -31,6 +31,7 @@ | |||
| #define NO_CONTEXT DECAF_EDDSA_448_SUPPORTS_CONTEXTLESS_SIGS | |||
| #define EDDSA_USE_SIGMA_ISOGENY 0 | |||
| #define COFACTOR 4 | |||
| #define EDDSA_PREHASH_BYTES 64 | |||
| #if NO_CONTEXT | |||
| 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, | |||
| * 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 ( | |||
| 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 | |||
| * 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(point_t) p; | |||
| 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 */ | |||
| API_NS(scalar_destroy)(secret_scalar); | |||
| @@ -191,13 +192,13 @@ void decaf_ed448_sign ( | |||
| /* Scalarmul to create the nonce-point */ | |||
| API_NS(scalar_t) nonce_scalar_2; | |||
| 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(point_t) p; | |||
| 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(scalar_destroy)(nonce_scalar_2); | |||
| } | |||
| @@ -237,7 +238,7 @@ void decaf_ed448_sign_prehash ( | |||
| const uint8_t *context, | |||
| 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; | |||
| memcpy(hash_too,hash,sizeof(hash_too)); | |||
| @@ -259,10 +260,10 @@ decaf_error_t decaf_ed448_verify ( | |||
| uint8_t context_len | |||
| ) { | |||
| 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; } | |||
| 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; } | |||
| API_NS(scalar_t) challenge_scalar; | |||
| @@ -287,9 +288,10 @@ decaf_error_t decaf_ed448_verify ( | |||
| &signature[DECAF_EDDSA_448_PUBLIC_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 */ | |||
| @@ -312,7 +314,7 @@ decaf_error_t decaf_ed448_verify_prehash ( | |||
| ) { | |||
| 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; | |||
| 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_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) | |||
| * encoding. | |||
| @@ -169,25 +175,43 @@ decaf_error_t decaf_ed25519_verify_prehash ( | |||
| /** | |||
| * @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 [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], | |||
| const decaf_255_point_t p | |||
| ) 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 [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, | |||
| const uint8_t enc[DECAF_EDDSA_25519_PUBLIC_BYTES] | |||
| ) 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_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) | |||
| * encoding. | |||
| @@ -168,25 +174,43 @@ decaf_error_t decaf_ed448_verify_prehash ( | |||
| /** | |||
| * @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 [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], | |||
| const decaf_448_point_t p | |||
| ) 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 [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, | |||
| const uint8_t enc[DECAF_EDDSA_448_PUBLIC_BYTES] | |||
| ) 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 */ | |||
| #define DECAF_255_REMOVED_COFACTOR 8 | |||
| /** X25519 encoding ratio. */ | |||
| #define DECAF_X25519_ENCODE_RATIO 4 | |||
| /** Number of bytes in an x25519 public key */ | |||
| #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; | |||
| /** | |||
| * @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 [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], | |||
| const decaf_255_point_t p | |||
| ) DECAF_API_VIS DECAF_NONNULL; | |||
| @@ -64,9 +64,6 @@ static inline int bits() { return 255; } | |||
| /** The curve's cofactor (removed, but useful for testing) */ | |||
| 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) */ | |||
| static const int FIELD_MODULUS_TYPE = 5; | |||
| @@ -263,6 +260,15 @@ public: | |||
| /** Bytes required for EdDSA encoding */ | |||
| 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. | |||
| @@ -348,44 +354,49 @@ public: | |||
| * @return DECAF_FAILURE the string was the wrong length, or wasn't the encoding of a point. | |||
| * 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 | |||
| ) 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 | |||
| ) /*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); | |||
| 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; | |||
| } | |||
| /** 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 | |||
| ) 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 | |||
| ) 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 */ | |||
| #define DECAF_448_REMOVED_COFACTOR 4 | |||
| /** X448 encoding ratio. */ | |||
| #define DECAF_X448_ENCODE_RATIO 2 | |||
| /** Number of bytes in an x448 public key */ | |||
| #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; | |||
| /** | |||
| * @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 [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], | |||
| const decaf_448_point_t p | |||
| ) DECAF_API_VIS DECAF_NONNULL; | |||
| @@ -64,9 +64,6 @@ static inline int bits() { return 448; } | |||
| /** The curve's cofactor (removed, but useful for testing) */ | |||
| 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) */ | |||
| static const int FIELD_MODULUS_TYPE = 3; | |||
| @@ -263,6 +260,15 @@ public: | |||
| /** Bytes required for EdDSA encoding */ | |||
| 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. | |||
| @@ -348,44 +354,49 @@ public: | |||
| * @return DECAF_FAILURE the string was the wrong length, or wasn't the encoding of a point. | |||
| * 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 | |||
| ) 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 | |||
| ) /*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); | |||
| 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; | |||
| } | |||
| /** 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 | |||
| ) 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 | |||
| ) 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, | |||
| "mont_base": 9, | |||
| "rist_base": "e2f2ae0a6abc4e71a884a961c500515f58e30b6aa582dd8db6a65945e08d2d76", | |||
| "eddsa_encode_ratio": 4, | |||
| "x_encode_ratio": 4, | |||
| "combs":comb_config(3,5,17), | |||
| "wnaf":wnaf_config(5,3), | |||
| @@ -44,6 +46,8 @@ curve_data = { | |||
| "eddsa_sigma_iso": 1 | |||
| }, | |||
| "ed448goldilocks" : { | |||
| "eddsa_encode_ratio": 4, | |||
| "x_encode_ratio": 2, | |||
| "altname": None, | |||
| "name" : "Ed448-Goldilocks", | |||
| "cofactor" : 4, | |||
| @@ -1029,7 +1029,7 @@ decaf_error_t API_NS(direct_scalarmul) ( | |||
| 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], | |||
| 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, | |||
| 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); | |||
| } | |||
| 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], | |||
| const point_t p | |||
| ) { | |||
| point_t q; | |||
| #if COFACTOR == 8 | |||
| 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_mul(q->z,q->t,q->y); /* y/x */ | |||
| 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; | |||
| 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); | |||
| } | |||
| point_t p; | |||
| 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); | |||
| } | |||
| @@ -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; | |||
| #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 ( | |||
| 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 | |||
| * 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(point_t) p; | |||
| 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 */ | |||
| API_NS(scalar_destroy)(secret_scalar); | |||
| @@ -183,13 +177,13 @@ void decaf_ed$(gf_shortname)_sign ( | |||
| /* Scalarmul to create the nonce-point */ | |||
| API_NS(scalar_t) nonce_scalar_2; | |||
| 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(point_t) p; | |||
| 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(scalar_destroy)(nonce_scalar_2); | |||
| } | |||
| @@ -251,10 +245,10 @@ decaf_error_t decaf_ed$(gf_shortname)_verify ( | |||
| uint8_t context_len | |||
| ) { | |||
| 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; } | |||
| 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; } | |||
| 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], | |||
| 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 */ | |||
| @@ -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_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) | |||
| * encoding. | |||
| @@ -153,25 +159,43 @@ decaf_error_t decaf_ed$(gf_shortname)_verify_prehash ( | |||
| /** | |||
| * @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 [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], | |||
| const $(c_ns)_point_t p | |||
| ) 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 [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, | |||
| const uint8_t enc[DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES] | |||
| ) 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 */ | |||
| #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 */ | |||
| #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; | |||
| /** | |||
| * @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 [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], | |||
| const $(c_ns)_point_t p | |||
| ) 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) */ | |||
| 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) */ | |||
| static const int FIELD_MODULUS_TYPE = $(modulus &~ (modulus-3)); | |||
| @@ -250,6 +247,15 @@ public: | |||
| /** Bytes required for EdDSA encoding */ | |||
| 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. | |||
| @@ -335,44 +341,49 @@ public: | |||
| * @return DECAF_FAILURE the string was the wrong length, or wasn't the encoding of a point. | |||
| * 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 | |||
| ) 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 | |||
| ) /*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); | |||
| $(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; | |||
| } | |||
| /** 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 | |||
| ) 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 | |||
| ) 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," -R: Display raw xyzt\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," Ways to create points:\n"); | |||
| fprintf(stderr," [hex]: Point from point data as hex\n"); | |||
| @@ -97,7 +97,7 @@ public: | |||
| uint8_t tmp[Group::Point::SER_BYTES]; | |||
| typename Group::Point a,b; | |||
| 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; | |||
| if (done || error) return; | |||
| for (int i=1; i<g_argc && !error; i++) { | |||
| @@ -121,9 +121,14 @@ public: | |||
| like_x = true; | |||
| } else if (!strcmp(g_argv[i],"-H")) { | |||
| decoeff = true; | |||
| } else if (!strcmp(g_argv[i],"-T")) { | |||
| torque = true; | |||
| } else if (!strcmp(g_argv[i],"*")) { | |||
| if (elligator || scalar || scalarempty) usage(); | |||
| if (elligator || scalar || scalarempty || div) usage(); | |||
| mul = true; | |||
| } else if (!strcmp(g_argv[i],"/")) { | |||
| if (elligator || scalar || scalarempty || mul) usage(); | |||
| div = true; | |||
| } else if (!strcmp(g_argv[i],"-s")) { | |||
| if (elligator || scalar || !scalarempty) usage(); | |||
| scalar = true; | |||
| @@ -156,6 +161,8 @@ public: | |||
| if (point) { | |||
| 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 (empty) { a = b; empty=false; } | |||
| else if (plus) { a += b; plus=false; } | |||
| @@ -164,7 +171,6 @@ public: | |||
| } | |||
| if (!error && !empty) { | |||
| if (decoeff) a /= (Group::EDDSA_RATIO); | |||
| if (einv) { | |||
| uint8_t buffer[Group::Point::HASH_BYTES]; | |||
| 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)); | |||
| printf("\n"); | |||
| } 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()); | |||
| printf("\n"); | |||
| } 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()); | |||
| printf("\n"); | |||
| } else { | |||
| @@ -415,8 +415,8 @@ static void test_ec() { | |||
| q=p; | |||
| 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) { | |||
| test.fail(); | |||
| @@ -552,7 +552,6 @@ static void test_eddsa() { | |||
| SpongeRng rng(Block("test_eddsa"),SpongeRng::DETERMINISTIC); | |||
| for (int i=0; i<NTESTS && test.passing_now; i++) { | |||
| typename EdDSA<Group>::PrivateKey priv(rng); | |||
| typename EdDSA<Group>::PublicKey pub(priv); | |||
| @@ -569,7 +568,22 @@ static void test_eddsa() { | |||
| } catch(CryptoException) { | |||
| test.fail(); | |||
| 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"); | |||
| } | |||
| } | |||
| } | |||