| #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; |
| } |