Line data Source code
1 : #ifndef HEADER_fd_src_ballet_ed25519_fd_ristretto255_h
2 : #define HEADER_fd_src_ballet_ed25519_fd_ristretto255_h
3 :
4 : /* fd_ristretto255.h provides the public ristretto255 group element
5 : API.
6 :
7 : This API is specifically only provided for the Solana virtual machine
8 : syscall sol_curve_group_op (slow!). It is guaranteed to be stable
9 : irrespective of underlying backend chosen (ref, avx, etc...)
10 :
11 : All operations in this API should be assumed to take a variable
12 : amount of time depending on inputs. (And thus should not be exposed
13 : to secret data) */
14 :
15 : #include "fd_curve25519.h"
16 :
17 : /* fd_ristretto255 provides APIs for the ristretto255 prime order group */
18 :
19 : static const uchar fd_ristretto255_compressed_zero[ 32 ] = {
20 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
21 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
22 : };
23 :
24 : /* fd_ristretto255_point_t is a opaque handle to a ristretto255 group
25 : element. Although it is the same type as an Ed25519 group element,
26 : it is unsafe to mix Ed25519 point and ristretto point APIs. */
27 :
28 : typedef fd_ed25519_point_t fd_ristretto255_point_t;
29 :
30 9 : #define fd_ristretto255_point_set_zero fd_ed25519_point_set_zero
31 978 : #define fd_ristretto255_point_set fd_ed25519_point_set
32 3030348 : #define fd_ristretto255_point_add fd_ed25519_point_add
33 3000330 : #define fd_ristretto255_point_sub fd_ed25519_point_sub
34 3000000 : #define fd_ristretto255_scalar_validate fd_ed25519_scalar_validate
35 30018 : #define fd_ristretto255_scalar_mul fd_ed25519_scalar_mul
36 2346 : #define fd_ristretto255_multi_scalar_mul fd_ed25519_multi_scalar_mul
37 301392 : #define fd_ristretto255_point_decompress fd_ristretto255_point_frombytes
38 300099 : #define fd_ristretto255_point_compress fd_ristretto255_point_tobytes
39 :
40 : FD_PROTOTYPES_BEGIN
41 :
42 : uchar *
43 : fd_ristretto255_point_tobytes( uchar buf[ 32 ],
44 : fd_ristretto255_point_t const * p );
45 :
46 : /* fd_ristretto255_point_frombytes decompresses a 32-byte array into
47 : an element of the ristretto group h.
48 : It returns p on success, NULL on failure. */
49 :
50 : fd_ristretto255_point_t *
51 : fd_ristretto255_point_frombytes( fd_ristretto255_point_t * p,
52 : uchar const buf[ 32 ] );
53 :
54 : /* fd_ristretto255_point_validate checks if a 32-byte array represents
55 : a valid element of the ristretto group h.
56 : It returns 1 on success, 0 on failure. */
57 :
58 : static inline int
59 6 : fd_ristretto255_point_validate( uchar const buf[ 32 ] ) {
60 6 : fd_ristretto255_point_t t[1];
61 6 : return !!fd_ristretto255_point_frombytes( t, buf );
62 6 : }
63 :
64 : /* fd_ristretto255_point_eq checks if two elements of the ristretto group
65 : p and q are equal.
66 : It returns 1 on success, 0 on failure. */
67 :
68 : static inline int
69 : fd_ristretto255_point_eq( fd_ristretto255_point_t * const p,
70 1041 : fd_ristretto255_point_t * const q ) {
71 : // https://ristretto.group/details/equality.html
72 1041 : fd_f25519_t cmp[2];
73 1041 : fd_f25519_t x[2], y[2], _z[2], _t[2];
74 1041 : fd_ed25519_point_to( &x[0], &y[0], &_z[0], &_t[0], p );
75 1041 : fd_ed25519_point_to( &x[1], &y[1], &_z[1], &_t[1], q );
76 :
77 1041 : fd_f25519_mul( &cmp[ 0 ], &x[0], &y[1] );
78 1041 : fd_f25519_mul( &cmp[ 1 ], &x[1], &y[0] );
79 1041 : int xx = fd_f25519_eq( &cmp[ 0 ], &cmp[ 1 ] );
80 :
81 1041 : fd_f25519_mul( &cmp[ 0 ], &x[0], &x[1] );
82 1041 : fd_f25519_mul( &cmp[ 1 ], &y[0], &y[1] );
83 1041 : int yy = fd_f25519_eq( &cmp[ 0 ], &cmp[ 1 ] );
84 :
85 1041 : return xx | yy;
86 1041 : }
87 :
88 : /* fd_ristretto255_point_eq_neg checks if two elements of the ristretto group
89 : p and q are such that -p == q. This uses just 1 extra neg.
90 : It returns 1 on success, 0 on failure. */
91 :
92 : static inline int
93 : fd_ristretto255_point_eq_neg( fd_ristretto255_point_t * const p,
94 123 : fd_ristretto255_point_t * const q ) {
95 : // https://ristretto.group/details/equality.html
96 123 : fd_f25519_t neg[1];
97 123 : fd_f25519_t cmp[2];
98 123 : fd_f25519_t x[2], y[2], _z[2], _t[2];
99 123 : fd_ed25519_point_to( &x[0], &y[0], &_z[0], &_t[0], p );
100 123 : fd_ed25519_point_to( &x[1], &y[1], &_z[1], &_t[1], q );
101 :
102 123 : fd_f25519_neg( neg, &x[0] );
103 123 : fd_f25519_mul( &cmp[ 0 ], neg, &y[1] );
104 123 : fd_f25519_mul( &cmp[ 1 ], &x[1], &y[0] );
105 123 : int xx = fd_f25519_eq( &cmp[ 0 ], &cmp[ 1 ] );
106 :
107 123 : fd_f25519_mul( &cmp[ 0 ], neg, &x[1] );
108 123 : fd_f25519_mul( &cmp[ 1 ], &y[0], &y[1] );
109 123 : int yy = fd_f25519_eq( &cmp[ 0 ], &cmp[ 1 ] );
110 :
111 123 : return xx | yy;
112 123 : }
113 :
114 : /* fd_ristretto255_hash_to_curve computes an element h of the ristretto group
115 : given an array s of 64-byte of uniformly random input (e.g., the output of a
116 : hash function).
117 : This function behaves like a random oracle.
118 : It returns h. */
119 :
120 : fd_ristretto255_point_t *
121 : fd_ristretto255_hash_to_curve( fd_ristretto255_point_t * h,
122 : uchar const s[ 64 ] );
123 :
124 : /* fd_ristretto255_map_to_curve implements the elligato2 map for curve25519,
125 : and computes an element h of the ristretto group given an array s of 32-byte
126 : of uniformly random input (e.g., the output of a hash function).
127 : This function does NOT behave like a random oracle, and is intended for
128 : internal use.
129 : It returns h. */
130 :
131 : fd_ristretto255_point_t *
132 : fd_ristretto255_map_to_curve( fd_ristretto255_point_t * h,
133 : uchar const s[ 32 ] );
134 :
135 : FD_PROTOTYPES_END
136 :
137 : #endif /* HEADER_fd_src_ballet_ed25519_fd_ristretto255_h */
|