|
@@ -28,6 +28,7 @@
|
|
|
#include "crypto_format.h"
|
|
|
#include "torlog.h"
|
|
|
#include "util.h"
|
|
|
+#include "util_format.h"
|
|
|
|
|
|
#include "ed25519/ref10/ed25519_ref10.h"
|
|
|
#include "ed25519/donna/ed25519_donna_tor.h"
|
|
@@ -57,6 +58,9 @@ typedef struct {
|
|
|
|
|
|
int (*pubkey_from_curve25519_pubkey)(unsigned char *, const unsigned char *,
|
|
|
int);
|
|
|
+
|
|
|
+ int (*ed25519_scalarmult_with_group_order)(unsigned char *,
|
|
|
+ const unsigned char *);
|
|
|
} ed25519_impl_t;
|
|
|
|
|
|
/** The Ref10 Ed25519 implementation. This one is pure C and lightly
|
|
@@ -77,6 +81,7 @@ static const ed25519_impl_t impl_ref10 = {
|
|
|
ed25519_ref10_blind_public_key,
|
|
|
|
|
|
ed25519_ref10_pubkey_from_curve25519_pubkey,
|
|
|
+ ed25519_ref10_scalarmult_with_group_order,
|
|
|
};
|
|
|
|
|
|
/** The Ref10 Ed25519 implementation. This one is heavily optimized, but still
|
|
@@ -97,6 +102,7 @@ static const ed25519_impl_t impl_donna = {
|
|
|
ed25519_donna_blind_public_key,
|
|
|
|
|
|
ed25519_donna_pubkey_from_curve25519_pubkey,
|
|
|
+ ed25519_donna_scalarmult_with_group_order,
|
|
|
};
|
|
|
|
|
|
/** Which Ed25519 implementation are we using? NULL if we haven't decided
|
|
@@ -754,3 +760,47 @@ ed25519_init(void)
|
|
|
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;
|
|
|
+}
|
|
|
+
|