Commit 559658ff authored by George Kadianakis's avatar George Kadianakis Committed by Nick Mathewson
Browse files

ed25519: Add func that checks for torsion component in pubkeys.

See https://lists.torproject.org/pipermail/tor-dev/2017-April/012213.html .
parent 39b5dca7
o Minor features (ed25519):
- Add validation function that checks for torsion components in ed25119
public keys. Currently unused but will be used by prop224 client-side
code. Addresses ticket #22006. Math help by Ian Goldberg.
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "crypto_format.h" #include "crypto_format.h"
#include "torlog.h" #include "torlog.h"
#include "util.h" #include "util.h"
#include "util_format.h"
#include "ed25519/ref10/ed25519_ref10.h" #include "ed25519/ref10/ed25519_ref10.h"
#include "ed25519/donna/ed25519_donna_tor.h" #include "ed25519/donna/ed25519_donna_tor.h"
...@@ -57,6 +58,9 @@ typedef struct { ...@@ -57,6 +58,9 @@ typedef struct {
int (*pubkey_from_curve25519_pubkey)(unsigned char *, const unsigned char *, int (*pubkey_from_curve25519_pubkey)(unsigned char *, const unsigned char *,
int); int);
int (*ed25519_scalarmult_with_group_order)(unsigned char *,
const unsigned char *);
} ed25519_impl_t; } ed25519_impl_t;
/** The Ref10 Ed25519 implementation. This one is pure C and lightly /** The Ref10 Ed25519 implementation. This one is pure C and lightly
...@@ -77,6 +81,7 @@ static const ed25519_impl_t impl_ref10 = { ...@@ -77,6 +81,7 @@ static const ed25519_impl_t impl_ref10 = {
ed25519_ref10_blind_public_key, ed25519_ref10_blind_public_key,
ed25519_ref10_pubkey_from_curve25519_pubkey, ed25519_ref10_pubkey_from_curve25519_pubkey,
ed25519_ref10_scalarmult_with_group_order,
}; };
/** The Ref10 Ed25519 implementation. This one is heavily optimized, but still /** The Ref10 Ed25519 implementation. This one is heavily optimized, but still
...@@ -97,6 +102,7 @@ static const ed25519_impl_t impl_donna = { ...@@ -97,6 +102,7 @@ static const ed25519_impl_t impl_donna = {
ed25519_donna_blind_public_key, ed25519_donna_blind_public_key,
ed25519_donna_pubkey_from_curve25519_pubkey, ed25519_donna_pubkey_from_curve25519_pubkey,
ed25519_donna_scalarmult_with_group_order,
}; };
/** Which Ed25519 implementation are we using? NULL if we haven't decided /** Which Ed25519 implementation are we using? NULL if we haven't decided
...@@ -754,3 +760,47 @@ ed25519_init(void) ...@@ -754,3 +760,47 @@ ed25519_init(void)
pick_ed25519_impl(); pick_ed25519_impl();
} }
/* Return true if <b>point</b> is the identity element of the ed25519 group. */
static int
ed25519_point_is_identity_element(const uint8_t *point)
{
/* The identity element in ed25159 is the point with coordinates (0,1). */
static const uint8_t ed25519_identity[32] = {
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
tor_assert(sizeof(ed25519_identity) == ED25519_PUBKEY_LEN);
return tor_memeq(point, ed25519_identity, sizeof(ed25519_identity));
}
/** Validate <b>pubkey</b> to ensure that it has no torsion component.
* Return 0 if <b>pubkey</b> is valid, else return -1. */
int
ed25519_validate_pubkey(const ed25519_public_key_t *pubkey)
{
uint8_t result[32] = {9};
/* First check that we were not given the identity element */
if (ed25519_point_is_identity_element(pubkey->pubkey)) {
log_warn(LD_CRYPTO, "ed25519 pubkey is the identity\n");
return -1;
}
/* For any point on the curve, doing l*point should give the identity element
* (where l is the group order). Do the computation and check that the
* identity element is returned. */
if (get_ed_impl()->ed25519_scalarmult_with_group_order(result,
pubkey->pubkey) < 0) {
log_warn(LD_CRYPTO, "ed25519 group order scalarmult failed\n");
return -1;
}
if (!ed25519_point_is_identity_element(result)) {
log_warn(LD_CRYPTO, "ed25519 validation failed\n");
return -1;
}
return 0;
}
...@@ -127,6 +127,8 @@ void ed25519_pubkey_copy(ed25519_public_key_t *dest, ...@@ -127,6 +127,8 @@ void ed25519_pubkey_copy(ed25519_public_key_t *dest,
void ed25519_set_impl_params(int use_donna); void ed25519_set_impl_params(int use_donna);
void ed25519_init(void); void ed25519_init(void);
int ed25519_validate_pubkey(const ed25519_public_key_t *pubkey);
#ifdef TOR_UNIT_TESTS #ifdef TOR_UNIT_TESTS
void crypto_ed25519_testing_force_impl(const char *name); void crypto_ed25519_testing_force_impl(const char *name);
void crypto_ed25519_testing_restore_impl(void); void crypto_ed25519_testing_restore_impl(void);
......
...@@ -30,4 +30,9 @@ int ed25519_donna_blind_public_key(unsigned char *out, const unsigned char *inp, ...@@ -30,4 +30,9 @@ int ed25519_donna_blind_public_key(unsigned char *out, const unsigned char *inp,
int ed25519_donna_pubkey_from_curve25519_pubkey(unsigned char *out, int ed25519_donna_pubkey_from_curve25519_pubkey(unsigned char *out,
const unsigned char *inp, int signbit); const unsigned char *inp, int signbit);
int
ed25519_donna_scalarmult_with_group_order(unsigned char *out,
const unsigned char *pubkey);
#endif #endif
...@@ -340,5 +340,32 @@ ed25519_donna_pubkey_from_curve25519_pubkey(unsigned char *out, ...@@ -340,5 +340,32 @@ ed25519_donna_pubkey_from_curve25519_pubkey(unsigned char *out,
return 0; return 0;
} }
/* Do the scalar multiplication of <b>pubkey</b> with the group order
* <b>modm_m</b>. Place the result in <b>out</b> which must be at least 32
* bytes long. */
int
ed25519_donna_scalarmult_with_group_order(unsigned char *out,
const unsigned char *pubkey)
{
static const bignum256modm ALIGN(16) zero = { 0 };
unsigned char pkcopy[32];
ge25519 ALIGN(16) Point, Result;
/* No "ge25519_unpack", negate the public key and unpack it back.
* See ed25519_donna_blind_public_key() */
memcpy(pkcopy, pubkey, 32);
pkcopy[31] ^= (1<<7);
if (!ge25519_unpack_negative_vartime(&Point, pkcopy)) {
return -1; /* error: bail out */
}
/* There is no regular scalarmult function so we have to do:
* Result = l*P + 0*B */
ge25519_double_scalarmult_vartime(&Result, &Point, modm_m, zero);
ge25519_pack(out, &Result);
return 0;
}
#include "test-internals.c" #include "test-internals.c"
...@@ -74,3 +74,40 @@ int ed25519_ref10_blind_public_key(unsigned char *out, ...@@ -74,3 +74,40 @@ int ed25519_ref10_blind_public_key(unsigned char *out,
return 0; return 0;
} }
/* This is the group order encoded in a format that
* ge_double_scalarmult_vartime() understands. The group order m is:
* m = 2^252 + 27742317777372353535851937790883648493 =
* 0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed
*/
static const uint8_t modm_m[32] = {0xed,0xd3,0xf5,0x5c,0x1a,0x63,0x12,0x58,
0xd6,0x9c,0xf7,0xa2,0xde,0xf9,0xde,0x14,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10};
/* Do the scalar multiplication of <b>pubkey</b> with the group order
* <b>modm_m</b>. Place the result in <b>out</b> which must be at least 32
* bytes long. */
int
ed25519_ref10_scalarmult_with_group_order(unsigned char *out,
const unsigned char *pubkey)
{
unsigned char pkcopy[32];
unsigned char zero[32] = {0};
ge_p3 Point;
ge_p2 Result;
/* All this is done to fit 'pubkey' in 'Point' so that it can be used by
* ed25519 ref code. Same thing as in blinding function */
memcpy(pkcopy, pubkey, 32);
pkcopy[31] ^= (1<<7);
if (ge_frombytes_negate_vartime(&Point, pkcopy) != 0) {
return -1; /* error: bail out */
}
/* There isn't a regular scalarmult -- we have to do r = l*P + 0*B */
ge_double_scalarmult_vartime(&Result, modm_m, &Point, zero);
ge_tobytes(out, &Result);
return 0;
}
...@@ -27,4 +27,8 @@ int ed25519_ref10_blind_public_key(unsigned char *out, ...@@ -27,4 +27,8 @@ int ed25519_ref10_blind_public_key(unsigned char *out,
const unsigned char *inp, const unsigned char *inp,
const unsigned char *param); const unsigned char *param);
int
ed25519_ref10_scalarmult_with_group_order(unsigned char *out,
const unsigned char *pubkey);
#endif #endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment