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