1 | #include "ed25519.h" |
2 | #include "sha512.h" |
3 | #include "ge.h" |
4 | #include "sc.h" |
5 | |
6 | static int consttime_equal(const unsigned char *x, const unsigned char *y) { |
7 | unsigned char r = 0; |
8 | |
9 | r = x[0] ^ y[0]; |
10 | #define F(i) r |= x[i] ^ y[i] |
11 | F(1); |
12 | F(2); |
13 | F(3); |
14 | F(4); |
15 | F(5); |
16 | F(6); |
17 | F(7); |
18 | F(8); |
19 | F(9); |
20 | F(10); |
21 | F(11); |
22 | F(12); |
23 | F(13); |
24 | F(14); |
25 | F(15); |
26 | F(16); |
27 | F(17); |
28 | F(18); |
29 | F(19); |
30 | F(20); |
31 | F(21); |
32 | F(22); |
33 | F(23); |
34 | F(24); |
35 | F(25); |
36 | F(26); |
37 | F(27); |
38 | F(28); |
39 | F(29); |
40 | F(30); |
41 | F(31); |
42 | #undef F |
43 | |
44 | return !r; |
45 | } |
46 | |
47 | int ed25519_verify(const unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key) { |
48 | unsigned char h[64]; |
49 | unsigned char checker[32]; |
50 | sha512_context hash; |
51 | ge_p3 A; |
52 | ge_p2 R; |
53 | |
54 | if (signature[63] & 224) { |
55 | return 0; |
56 | } |
57 | |
58 | if (ge_frombytes_negate_vartime(h: &A, s: public_key) != 0) { |
59 | return 0; |
60 | } |
61 | |
62 | sha512_init(md: &hash); |
63 | sha512_update(md: &hash, in: signature, inlen: 32); |
64 | sha512_update(md: &hash, in: public_key, inlen: 32); |
65 | sha512_update(md: &hash, in: message, inlen: message_len); |
66 | sha512_final(md: &hash, out: h); |
67 | |
68 | sc_reduce(s: h); |
69 | ge_double_scalarmult_vartime(r: &R, a: h, A: &A, b: signature + 32); |
70 | ge_tobytes(s: checker, h: &R); |
71 | |
72 | if (!consttime_equal(x: checker, y: signature)) { |
73 | return 0; |
74 | } |
75 | |
76 | return 1; |
77 | } |
78 | |