/src/libtorrent/src/ed25519/verify.cpp
Line | Count | Source |
1 | | // ignore warnings in this file |
2 | | #include "libtorrent/aux_/disable_warnings_push.hpp" |
3 | | |
4 | | #include "libtorrent/aux_/ed25519.hpp" |
5 | | #include "libtorrent/aux_/hasher512.hpp" |
6 | | #include "ge.h" |
7 | | #include "sc.h" |
8 | | |
9 | | namespace libtorrent { |
10 | | namespace aux { |
11 | | |
12 | 0 | static int consttime_equal(const unsigned char *x, const unsigned char *y) { |
13 | 0 | unsigned char r = 0; |
14 | |
|
15 | 0 | r = x[0] ^ y[0]; |
16 | 0 | #define F(i) r |= x[i] ^ y[i] |
17 | 0 | F(1); |
18 | 0 | F(2); |
19 | 0 | F(3); |
20 | 0 | F(4); |
21 | 0 | F(5); |
22 | 0 | F(6); |
23 | 0 | F(7); |
24 | 0 | F(8); |
25 | 0 | F(9); |
26 | 0 | F(10); |
27 | 0 | F(11); |
28 | 0 | F(12); |
29 | 0 | F(13); |
30 | 0 | F(14); |
31 | 0 | F(15); |
32 | 0 | F(16); |
33 | 0 | F(17); |
34 | 0 | F(18); |
35 | 0 | F(19); |
36 | 0 | F(20); |
37 | 0 | F(21); |
38 | 0 | F(22); |
39 | 0 | F(23); |
40 | 0 | F(24); |
41 | 0 | F(25); |
42 | 0 | F(26); |
43 | 0 | F(27); |
44 | 0 | F(28); |
45 | 0 | F(29); |
46 | 0 | F(30); |
47 | 0 | F(31); |
48 | 0 | #undef F |
49 | |
|
50 | 0 | return !r; |
51 | 0 | } |
52 | | |
53 | 0 | int ed25519_verify(const unsigned char *signature, const unsigned char *message, std::ptrdiff_t message_len, const unsigned char *public_key) { |
54 | 0 | unsigned char checker[32]; |
55 | 0 | ge_p3 A; |
56 | 0 | ge_p2 R; |
57 | |
|
58 | 0 | if (signature[63] & 224) { |
59 | 0 | return 0; |
60 | 0 | } |
61 | | |
62 | 0 | if (ge_frombytes_negate_vartime(&A, public_key) != 0) { |
63 | 0 | return 0; |
64 | 0 | } |
65 | | |
66 | 0 | hasher512 hash; |
67 | 0 | hash.update({reinterpret_cast<char const*>(signature), 32}); |
68 | 0 | hash.update({reinterpret_cast<char const*>(public_key), 32}); |
69 | 0 | hash.update({reinterpret_cast<char const*>(message), message_len}); |
70 | 0 | sha512_hash h = hash.final(); |
71 | | |
72 | 0 | sc_reduce(reinterpret_cast<unsigned char*>(h.data())); |
73 | 0 | ge_double_scalarmult_vartime(&R, reinterpret_cast<unsigned char*>(h.data()) |
74 | 0 | , &A, signature + 32); |
75 | 0 | ge_tobytes(checker, &R); |
76 | |
|
77 | 0 | if (!consttime_equal(checker, signature)) { |
78 | 0 | return 0; |
79 | 0 | } |
80 | | |
81 | 0 | return 1; |
82 | 0 | } |
83 | | |
84 | | } } |