1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
/*
This file is part of GNUnet.
(C) 2001, 2002, 2003, 2004, 2005, 2006 Christian Grothoff (and other contributing authors)
GNUnet is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
by the Free Software Foundation; either version 2, or (at your
option) any later version.
GNUnet is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNUnet; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
/**
* @file util/crypto_random.c
* @brief functions to gather random numbers
* @author Christian Grothoff
*/
#include "platform.h"
#include "gnunet_common.h"
#include "gnunet_crypto_lib.h"
#include <gcrypt.h>
/**
* @return a random value in the interval [0,i[.
*/
unsigned int
GNUNET_CRYPTO_random_u32 (enum GNUNET_CRYPTO_Quality mode, unsigned int i)
{
#ifdef gcry_fast_random_poll
static unsigned int invokeCount;
#endif
unsigned int ret;
GNUNET_assert (i > 0);
if (mode == GNUNET_CRYPTO_QUALITY_STRONG)
{
/* see http://lists.gnupg.org/pipermail/gcrypt-devel/2004-May/000613.html */
#ifdef gcry_fast_random_poll
if ((invokeCount++ % 256) == 0)
gcry_fast_random_poll ();
#endif
ret = rand (); /* in case gcry_randomize fails,
we at least get a pseudo-
random number this way */
gcry_randomize ((unsigned char *) &ret,
sizeof (unsigned int), GCRY_STRONG_RANDOM);
return ret % i;
}
else
{
ret = i * ((double) RANDOM () / RAND_MAX);
if (ret >= i)
ret = i - 1;
return ret;
}
}
/**
* Get an array with a random permutation of the
* numbers 0...n-1.
* @param mode GNUNET_RANDOM_QUALITY_STRONG if the strong (but expensive)
* PRNG should be used, GNUNET_RANDOM_QUALITY_WEAK otherwise
* @param n the size of the array
* @return the permutation array (allocated from heap)
*/
unsigned int *
GNUNET_CRYPTO_random_permute (enum GNUNET_CRYPTO_Quality mode, unsigned int n)
{
unsigned int *ret;
unsigned int i;
unsigned int tmp;
unsigned int x;
GNUNET_assert (n > 0);
ret = GNUNET_malloc (n * sizeof (int));
for (i = 0; i < n; i++)
ret[i] = i;
for (i = 0; i < n; i++)
{
x = GNUNET_CRYPTO_random_u32 (mode, n);
tmp = ret[x];
ret[x] = ret[i];
ret[i] = tmp;
}
return ret;
}
/**
* Random on unsigned 64-bit values.
*/
unsigned long long
GNUNET_CRYPTO_random_u64 (enum GNUNET_CRYPTO_Quality mode,
unsigned long long u)
{
unsigned long long ret;
GNUNET_assert (u > 0);
if (mode == GNUNET_CRYPTO_QUALITY_STRONG)
{
gcry_randomize ((unsigned char *) &ret,
sizeof (unsigned long long), GCRY_STRONG_RANDOM);
return ret % u;
}
else
{
ret = u * ((double) RANDOM () / RAND_MAX);
if (ret >= u)
ret = u - 1;
return ret;
}
}
/**
* This function should only be called in testcases
* where strong entropy gathering is not desired
* (for example, for hostkey generation).
*/
void
GNUNET_CRYPTO_random_disable_entropy_gathering ()
{
gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
}
/* end of crypto_random.c */
|