aboutsummaryrefslogtreecommitdiff
path: root/src/verify.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/verify.c')
-rw-r--r--src/verify.c77
1 files changed, 77 insertions, 0 deletions
diff --git a/src/verify.c b/src/verify.c
new file mode 100644
index 0000000..32f988e
--- /dev/null
+++ b/src/verify.c
@@ -0,0 +1,77 @@
+#include "ed25519.h"
+#include "sha512.h"
+#include "ge.h"
+#include "sc.h"
+
+static int consttime_equal(const unsigned char *x, const unsigned char *y) {
+ unsigned char r = 0;
+
+ r = x[0] ^ y[0];
+ #define F(i) r |= x[i] ^ y[i]
+ F(1);
+ F(2);
+ F(3);
+ F(4);
+ F(5);
+ F(6);
+ F(7);
+ F(8);
+ F(9);
+ F(10);
+ F(11);
+ F(12);
+ F(13);
+ F(14);
+ F(15);
+ F(16);
+ F(17);
+ F(18);
+ F(19);
+ F(20);
+ F(21);
+ F(22);
+ F(23);
+ F(24);
+ F(25);
+ F(26);
+ F(27);
+ F(28);
+ F(29);
+ F(30);
+ F(31);
+ #undef F
+
+ return !r;
+}
+
+int ed25519_verify(const unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key) {
+ unsigned char h[64];
+ unsigned char checker[32];
+ sha512_context hash;
+ ge_p3 A;
+ ge_p2 R;
+
+ if (signature[63] & 224) {
+ return 0;
+ }
+
+ if (ge_frombytes_negate_vartime(&A, public_key) != 0) {
+ return 0;
+ }
+
+ sha512_init(&hash);
+ sha512_update(&hash, signature, 32);
+ sha512_update(&hash, public_key, 32);
+ sha512_update(&hash, message, message_len);
+ sha512_final(&hash, h);
+
+ sc_reduce(h);
+ ge_double_scalarmult_vartime(&R, h, &A, signature + 32);
+ ge_tobytes(checker, &R);
+
+ if (!consttime_equal(checker, signature)) {
+ return 0;
+ }
+
+ return 1;
+}