Let us walk on the 3-isogeny graph
Loading...
Searching...
No Matches
random.c
Go to the documentation of this file.
1#include <assert.h>
2
3#include "random.h"
4// #include "randombytes.h"
5#include "../common/rng.h"
6// #include "crypto_declassify.h"
7
8#include "int32_sort.h"
9#include "int32mask.h"
10
11#ifdef ENABLE_CT_TESTING
12#include <valgrind/memcheck.h>
13#endif
14
15void random_wombats(uint8_t *key, const long long numkeys, const long long batch_start, const long long batch_stop, const long long batch_sumykeys)
16{
17 int32_t batch_len = batch_stop - batch_start;
18 int32_t r[4 * batch_len];
19 uint8_t ells[numkeys];
20 for (;;)
21 { /* rejection-sampling loop */
22 randombytes(r, 4 * batch_len);
23 for (long long j = 0; j < batch_len; ++j)
24 r[j] &= ~1;
25 for (long long j = 0; j < numkeys; ++j)
26 r[j] |= 1;
27 int32_sort(r, batch_len);
28
29 long long collision = 0;
30 for (long long j = 1; j < numkeys; ++j)
31 collision |= int32mask_zero((r[j] ^ r[j - 1]) & ~1);
32
33#ifdef ENABLE_CT_TESTING
34 VALGRIND_MAKE_MEM_DEFINED(&collision, sizeof(collision));
35#endif
36 if (collision)
37 continue;
38
39 for (int32_t j = 0; j < numkeys; ++j)
40 ells[j] = 0;
41
42 for (int32_t j = 0; j < batch_len; ++j)
43 r[j] &= 1;
44
45 for (int32_t i = 0; i < numkeys; ++i)
46 {
47 for (int32_t j = i; j < batch_len; ++j)
48 {
49 // r[j] &= 1;
50 int32_t updatemask = int32mask_zero(ells[i]) & int32mask_nonzero(r[j]);
51 r[j] ^= (1 & updatemask);
52 ells[i] |= (updatemask & (j + 1));
53 }
54 }
55
56 for (int32_t i = 0; i < numkeys; ++i)
57 key[batch_sumykeys + i] = batch_start + ells[i] - 1;
58
59 return;
60 }
61}
62
63void random_boundedl1(int8_t *e, const long long w, const long long S)
64{
65 // standard correspondences:
66 // e[0],e[1],...,e[w-1] are w nonnegative integers
67 // with sum at most S
68 // <=> 1+e[0],1+e[1],...,1+e[w-1] are w positive integers
69 // with sum at most S+w
70 // <=> 1+e[0],1+e[0]+1+e[1],... are w integers
71 // in strictly increasing order
72 // between 1 and S+w
73 // <=> e[0],1+e[0]+e[1],... are w integers
74 // in strictly increasing order
75 // between 0 and S+w-1
76
77 assert(w >= 0);
78 assert(w < 128);
79 assert(S >= 0);
80 assert(S < 128);
81 if (!w)
82 return;
83
84 const long long rnum = S + w;
85 assert(rnum <= 254);
86 /* XXX: Microsoft compiler doesn't handle int32_t r[S+w] */
87 int32_t r[254];
88
89 for (;;)
90 { /* rejection-sampling loop */
91 randombytes(r, 4 * rnum);
92 for (long long j = 0; j < rnum; ++j)
93 r[j] &= ~1;
94 for (long long j = 0; j < w; ++j)
95 r[j] |= 1;
96 int32_sort(r, rnum);
97 long long collision = 0;
98 for (long long j = 1; j < w; ++j)
99 collision |= int32mask_zero((r[j] ^ r[j - 1]) & ~1);
100
101 // crypto_declassify(&collision,sizeof collision);
102 if (collision)
103 continue;
104
105 for (long long j = 0; j < rnum; ++j)
106 r[j] &= 1;
107 // now r has Hamming weight w
108
109 for (long long j = 1; j < rnum; ++j)
110 r[j] += r[j - 1];
111 // now r has >=0 copies of 0,
112 // >=1 copies of 1, >=1 copies of 2, ..., >=1 copies of w
113
114 for (long long i = 0; i < w; ++i)
115 {
116 long long numi = 0;
117 for (long long j = 0; j < rnum; ++j)
118 numi -= int32mask_equal(r[j], i);
119 e[i] = numi;
120 }
121 // now e[0]>=0, e[1]>=1, e[2]>=1, ..., e[w-1]>=1
122 // and ghost e[w]>=1, not stored
123 // e[0]+e[1]+...+e[w] = rnum
124 // so e[0]+e[1]+...+e[w-1] <= rnum-1
125
126 for (long long i = 1; i < w; ++i)
127 --e[i];
128 // now e[0]>=0, e[1]>=0, e[2]>=0, ..., e[w-1]>=0
129 // sum <= (rnum-1)-(w-1)
130 // i.e. sum <= S
131
132 // not done yet: want to allow negative e
133
134 // but simply negating will give zeros too much weight
135 // for uniformity, keep e with probability 1/2^z
136 // where z is the number of zeros in e
137
138 // speedup: actually keep e with probability 2^zmin/2^z
139 // where zmin is minimum possible value of z
140
141 // strategy: start counter at w-S
142 // and decrease by 1 for each zero bit
143 // and, if negative, flip coin for each zero bit
144 long long counter = w - S;
145
146 randombytes(r, 4 * ((w + 31) / 32));
147 long long reject = 0;
148 for (long long i = 0; i < w; ++i)
149 {
150 int32_t rbit = 1 & (r[i / 32] >> (i & 31));
151 int32_t eizeromask = int32mask_zero(e[i]);
152 counter += eizeromask;
153 reject |= int32mask_negative(counter) & eizeromask & rbit;
154 }
155
156 // crypto_declassify(&reject,sizeof reject);
157 if (reject)
158 continue;
159
160 // ok to reuse randomness in r:
161 // bits used here are for e[i] nonzero,
162 // bits used above are for e[i] zero
163 for (long long i = 0; i < w; ++i)
164 {
165 int32_t rbit = 1 & (r[i / 32] >> (i & 31));
166 e[i] ^= -rbit;
167 e[i] += rbit;
168 }
169
170#if defined(RVRSIDH)
171 // RiverSIDH ###########################
172 int negative = 0, positive = 0;
173 for (long long i = 0; i < w; ++i)
174 {
175 negative += int32mask_negative(e[i]) & e[i];
176 positive += ~int32mask_negative(e[i]) & e[i];
177 }
178
179 if ((negative < -(S >> 1)) || (positive > (S >> 1)))
180 continue;
181 // #####################################
182#endif
183
184 return;
185 }
186}
187
188// -1 if x < y, else 0
189static int64_t uint64mask_lessthan(uint64_t x, uint64_t y)
190{
191 int64_t xy = x ^ y;
192 int64_t c = x - y;
193 const int64_t flip = ((uint64_t)1) << 63;
194 c ^= xy & (c ^ x ^ flip);
195 return c >> 63;
196}
197
198int64_t random_coin(uint64_t num, uint64_t den)
199{
200 uint8_t buf[32];
201 uint64_t r = 0;
202
203 randombytes(buf, sizeof buf);
204
205 for (long long i = 0; i < 256; ++i)
206 {
207 uint64_t bit = 1 & (buf[i / 8] >> (i & 7));
208 r <<= 1;
209 r += bit;
210 r ^= (~uint64mask_lessthan(r, den)) & (r ^ (r - den));
211 }
212 // XXX: speed this up
213
214 return uint64mask_lessthan(r, num);
215}
void randombytes(void *x, size_t l)
Definition rng.c:8
#define int32_sort
Definition int32_sort.h:6
assert(var1 eq var2)
num
for i
for j
#define batch_start
Definition primes.h:55
#define batch_stop
Definition primes.h:56
void random_wombats(uint8_t *key, const long long numkeys, const long long batch_start, const long long batch_stop, const long long batch_sumykeys)
Definition random.c:15
#define random_boundedl1
Definition random.h:7
#define random_coin
Definition random.h:8