1 /*
2
3 Copyright 2011, 2016 Free Software Foundation, Inc.
4
5 This file is part of the GNU MP Library test suite.
6
7 The GNU MP Library test suite is free software; you can redistribute it
8 and/or modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 3 of the License,
10 or (at your option) any later version.
11
12 The GNU MP Library test suite is distributed in the hope that it will be
13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15 Public License for more details.
16
17 You should have received a copy of the GNU General Public License along with
18 the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22
23 #include <time.h>
24
25 #ifdef __unix__
26 # include <unistd.h>
27 # include <sys/time.h>
28 #endif
29
30 #include "gmp.h"
31
32 #include "hex-random.h"
33
34 static gmp_randstate_t state;
35
36 static void
mkseed(mpz_t seed)37 mkseed (mpz_t seed)
38 {
39 FILE *f = fopen ("/dev/urandom", "rb");
40 if (f)
41 {
42 unsigned char buf[6];
43 size_t res;
44
45 setbuf (f, NULL);
46 res = fread (buf, sizeof(buf), 1, f);
47 fclose (f);
48
49 if (res == 1)
50 {
51 mpz_import (seed, sizeof(buf), 1, 1, 0, 0, buf);
52 return;
53 }
54 }
55
56 #ifdef __unix__
57 {
58 struct timeval tv;
59 mpz_t usec;
60 mpz_init (usec);
61
62 gettimeofday (&tv, NULL);
63 mpz_set_ui (seed, tv.tv_sec);
64 mpz_set_ui (usec, tv.tv_usec);
65 /* usec fits in 20 bits, shift left to make it 48 bits. */
66 mpz_mul_2exp (usec, usec, 28);
67 mpz_xor (seed, seed, usec);
68
69 mpz_clear (usec);
70 }
71 #else
72 mpz_set_ui (seed, time (NULL));
73 #endif
74 }
75
76 void
hex_random_init(void)77 hex_random_init (void)
78 {
79 mpz_t seed;
80 char *env_seed;
81
82 mpz_init (seed);
83
84 env_seed = getenv ("GMP_CHECK_RANDOMIZE");
85 if (env_seed && env_seed[0])
86 {
87 mpz_set_str (seed, env_seed, 0);
88 if (mpz_cmp_ui (seed, 0) != 0)
89 gmp_printf ("Re-seeding with GMP_CHECK_RANDOMIZE=%Zd\n", seed);
90 else
91 {
92 mkseed (seed);
93 gmp_printf ("Seed GMP_CHECK_RANDOMIZE=%Zd (include this in bug reports)\n", seed);
94 }
95 fflush (stdout);
96 }
97 else
98 mpz_set_ui (seed, 4711);
99
100 gmp_randinit_default (state);
101 gmp_randseed (state, seed);
102
103 mpz_clear (seed);
104 }
105
106 char *
hex_urandomb(unsigned long bits)107 hex_urandomb (unsigned long bits)
108 {
109 char *res;
110 mpz_t x;
111
112 mpz_init (x);
113 mpz_urandomb (x, state, bits);
114 gmp_asprintf (&res, "%Zx", x);
115 mpz_clear (x);
116 return res;
117 }
118
119 char *
hex_rrandomb(unsigned long bits)120 hex_rrandomb (unsigned long bits)
121 {
122 char *res;
123 mpz_t x;
124
125 mpz_init (x);
126 mpz_rrandomb (x, state, bits);
127 gmp_asprintf (&res, "%Zx", x);
128 mpz_clear (x);
129 return res;
130 }
131
132 char *
hex_rrandomb_export(void * dst,size_t * countp,int order,size_t size,int endian,unsigned long bits)133 hex_rrandomb_export (void *dst, size_t *countp,
134 int order, size_t size, int endian, unsigned long bits)
135 {
136 char *res;
137 mpz_t x;
138 mpz_init (x);
139 mpz_rrandomb (x, state, bits);
140 gmp_asprintf (&res, "%Zx", x);
141 mpz_export (dst, countp, order, size, endian, 0, x);
142 mpz_clear (x);
143 return res;
144 }
145
hex_random_op2(enum hex_random_op op,unsigned long maxbits,char ** ap,char ** rp)146 void hex_random_op2 (enum hex_random_op op, unsigned long maxbits,
147 char **ap, char **rp)
148 {
149 mpz_t a, r;
150 unsigned long abits;
151 unsigned signs;
152
153 mpz_init (a);
154 mpz_init (r);
155
156 abits = gmp_urandomb_ui (state, 32) % maxbits;
157
158 mpz_rrandomb (a, state, abits);
159
160 signs = gmp_urandomb_ui (state, 1);
161 if (signs & 1)
162 mpz_neg (a, a);
163
164 switch (op)
165 {
166 default:
167 abort ();
168 case OP_SQR:
169 mpz_mul (r, a, a);
170 break;
171 }
172
173 gmp_asprintf (ap, "%Zx", a);
174 gmp_asprintf (rp, "%Zx", r);
175
176 mpz_clear (a);
177 mpz_clear (r);
178 }
179
180 void
hex_random_op3(enum hex_random_op op,unsigned long maxbits,char ** ap,char ** bp,char ** rp)181 hex_random_op3 (enum hex_random_op op, unsigned long maxbits,
182 char **ap, char **bp, char **rp)
183 {
184 mpz_t a, b, r;
185 unsigned long abits, bbits;
186 unsigned signs;
187
188 mpz_init (a);
189 mpz_init (b);
190 mpz_init (r);
191
192 abits = gmp_urandomb_ui (state, 32) % maxbits;
193 bbits = gmp_urandomb_ui (state, 32) % maxbits;
194
195 mpz_rrandomb (a, state, abits);
196 mpz_rrandomb (b, state, bbits);
197
198 signs = gmp_urandomb_ui (state, 3);
199 if (signs & 1)
200 mpz_neg (a, a);
201 if (signs & 2)
202 mpz_neg (b, b);
203
204 switch (op)
205 {
206 default:
207 abort ();
208 case OP_ADD:
209 mpz_add (r, a, b);
210 break;
211 case OP_SUB:
212 mpz_sub (r, a, b);
213 break;
214 case OP_MUL:
215 mpz_mul (r, a, b);
216 break;
217 case OP_GCD:
218 if (signs & 4)
219 {
220 /* Produce a large gcd */
221 unsigned long gbits = gmp_urandomb_ui (state, 32) % maxbits;
222 mpz_rrandomb (r, state, gbits);
223 mpz_mul (a, a, r);
224 mpz_mul (b, b, r);
225 }
226 mpz_gcd (r, a, b);
227 break;
228 case OP_LCM:
229 if (signs & 4)
230 {
231 /* Produce a large gcd */
232 unsigned long gbits = gmp_urandomb_ui (state, 32) % maxbits;
233 mpz_rrandomb (r, state, gbits);
234 mpz_mul (a, a, r);
235 mpz_mul (b, b, r);
236 }
237 mpz_lcm (r, a, b);
238 break;
239 case OP_AND:
240 mpz_and (r, a, b);
241 break;
242 case OP_IOR:
243 mpz_ior (r, a, b);
244 break;
245 case OP_XOR:
246 mpz_xor (r, a, b);
247 break;
248 }
249
250 gmp_asprintf (ap, "%Zx", a);
251 gmp_asprintf (bp, "%Zx", b);
252 gmp_asprintf (rp, "%Zx", r);
253
254 mpz_clear (a);
255 mpz_clear (b);
256 mpz_clear (r);
257 }
258
259 void
hex_random_op4(enum hex_random_op op,unsigned long maxbits,char ** ap,char ** bp,char ** cp,char ** dp)260 hex_random_op4 (enum hex_random_op op, unsigned long maxbits,
261 char **ap, char **bp, char **cp, char **dp)
262 {
263 mpz_t a, b, c, d;
264 unsigned long abits, bbits;
265 unsigned signs;
266
267 mpz_init (a);
268 mpz_init (b);
269 mpz_init (c);
270 mpz_init (d);
271
272 if (op == OP_POWM)
273 {
274 unsigned long cbits;
275 abits = gmp_urandomb_ui (state, 32) % maxbits;
276 bbits = 1 + gmp_urandomb_ui (state, 32) % maxbits;
277 cbits = 2 + gmp_urandomb_ui (state, 32) % maxbits;
278
279 mpz_rrandomb (a, state, abits);
280 mpz_rrandomb (b, state, bbits);
281 mpz_rrandomb (c, state, cbits);
282
283 signs = gmp_urandomb_ui (state, 3);
284 if (signs & 1)
285 mpz_neg (a, a);
286 if (signs & 2)
287 {
288 mpz_t g;
289
290 /* If we negate the exponent, must make sure that gcd(a, c) = 1 */
291 if (mpz_sgn (a) == 0)
292 mpz_set_ui (a, 1);
293 else
294 {
295 mpz_init (g);
296
297 for (;;)
298 {
299 mpz_gcd (g, a, c);
300 if (mpz_cmp_ui (g, 1) == 0)
301 break;
302 mpz_divexact (a, a, g);
303 }
304 mpz_clear (g);
305 }
306 mpz_neg (b, b);
307 }
308 if (signs & 4)
309 mpz_neg (c, c);
310
311 mpz_powm (d, a, b, c);
312 }
313 else
314 {
315 unsigned long qbits;
316 bbits = 1 + gmp_urandomb_ui (state, 32) % maxbits;
317 qbits = gmp_urandomb_ui (state, 32) % maxbits;
318 abits = bbits + qbits;
319 if (abits > 30)
320 abits -= 30;
321 else
322 abits = 0;
323
324 mpz_rrandomb (a, state, abits);
325 mpz_rrandomb (b, state, bbits);
326
327 signs = gmp_urandomb_ui (state, 2);
328 if (signs & 1)
329 mpz_neg (a, a);
330 if (signs & 2)
331 mpz_neg (b, b);
332
333 switch (op)
334 {
335 default:
336 abort ();
337 case OP_CDIV:
338 mpz_cdiv_qr (c, d, a, b);
339 break;
340 case OP_FDIV:
341 mpz_fdiv_qr (c, d, a, b);
342 break;
343 case OP_TDIV:
344 mpz_tdiv_qr (c, d, a, b);
345 break;
346 }
347 }
348 gmp_asprintf (ap, "%Zx", a);
349 gmp_asprintf (bp, "%Zx", b);
350 gmp_asprintf (cp, "%Zx", c);
351 gmp_asprintf (dp, "%Zx", d);
352
353 mpz_clear (a);
354 mpz_clear (b);
355 mpz_clear (c);
356 mpz_clear (d);
357 }
358
359 void
hex_random_bit_op(enum hex_random_op op,unsigned long maxbits,char ** ap,unsigned long * b,char ** rp)360 hex_random_bit_op (enum hex_random_op op, unsigned long maxbits,
361 char **ap, unsigned long *b, char **rp)
362 {
363 mpz_t a, r;
364 unsigned long abits, bbits;
365 unsigned signs;
366
367 mpz_init (a);
368 mpz_init (r);
369
370 abits = gmp_urandomb_ui (state, 32) % maxbits;
371 bbits = gmp_urandomb_ui (state, 32) % (maxbits + 100);
372
373 mpz_rrandomb (a, state, abits);
374
375 signs = gmp_urandomb_ui (state, 1);
376 if (signs & 1)
377 mpz_neg (a, a);
378
379 switch (op)
380 {
381 default:
382 abort ();
383
384 case OP_SETBIT:
385 mpz_set (r, a);
386 mpz_setbit (r, bbits);
387 break;
388 case OP_CLRBIT:
389 mpz_set (r, a);
390 mpz_clrbit (r, bbits);
391 break;
392 case OP_COMBIT:
393 mpz_set (r, a);
394 mpz_combit (r, bbits);
395 break;
396 case OP_CDIV_Q_2:
397 mpz_cdiv_q_2exp (r, a, bbits);
398 break;
399 case OP_CDIV_R_2:
400 mpz_cdiv_r_2exp (r, a, bbits);
401 break;
402 case OP_FDIV_Q_2:
403 mpz_fdiv_q_2exp (r, a, bbits);
404 break;
405 case OP_FDIV_R_2:
406 mpz_fdiv_r_2exp (r, a, bbits);
407 break;
408 case OP_TDIV_Q_2:
409 mpz_tdiv_q_2exp (r, a, bbits);
410 break;
411 case OP_TDIV_R_2:
412 mpz_tdiv_r_2exp (r, a, bbits);
413 break;
414 }
415
416 gmp_asprintf (ap, "%Zx", a);
417 *b = bbits;
418 gmp_asprintf (rp, "%Zx", r);
419
420 mpz_clear (a);
421 mpz_clear (r);
422 }
423
424 void
hex_random_scan_op(enum hex_random_op op,unsigned long maxbits,char ** ap,unsigned long * b,unsigned long * r)425 hex_random_scan_op (enum hex_random_op op, unsigned long maxbits,
426 char **ap, unsigned long *b, unsigned long *r)
427 {
428 mpz_t a;
429 unsigned long abits, bbits;
430 unsigned signs;
431
432 mpz_init (a);
433
434 abits = gmp_urandomb_ui (state, 32) % maxbits;
435 bbits = gmp_urandomb_ui (state, 32) % (maxbits + 100);
436
437 mpz_rrandomb (a, state, abits);
438
439 signs = gmp_urandomb_ui (state, 1);
440 if (signs & 1)
441 mpz_neg (a, a);
442
443 switch (op)
444 {
445 default:
446 abort ();
447
448 case OP_SCAN0:
449 *r = mpz_scan0 (a, bbits);
450 break;
451 case OP_SCAN1:
452 *r = mpz_scan1 (a, bbits);
453 break;
454 }
455 gmp_asprintf (ap, "%Zx", a);
456 *b = bbits;
457
458 mpz_clear (a);
459 }
460
461 void
hex_random_str_op(unsigned long maxbits,int base,char ** ap,char ** rp)462 hex_random_str_op (unsigned long maxbits,
463 int base, char **ap, char **rp)
464 {
465 mpz_t a;
466 unsigned long abits;
467 unsigned signs;
468
469 mpz_init (a);
470
471 abits = gmp_urandomb_ui (state, 32) % maxbits;
472
473 mpz_rrandomb (a, state, abits);
474
475 signs = gmp_urandomb_ui (state, 2);
476 if (signs & 1)
477 mpz_neg (a, a);
478
479 *ap = mpz_get_str (NULL, 16, a);
480 *rp = mpz_get_str (NULL, base, a);
481
482 mpz_clear (a);
483 }
484