random: Update jitterentropy to 2.1.0.
[libgcrypt.git] / random / rndjent.c
1 /* rndjent.c  - Driver for the jitterentropy module.
2  * Copyright (C) 2017 g10 Code GmbH
3  * Copyright (C) 2017 Bundesamt für Sicherheit in der Informationstechnik
4  * Copyright (C) 2013 Stephan Mueller <smueller@chronox.de>
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, and the entire permission notice in its entirety,
11  *    including the disclaimer of warranties.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. The name of the author may not be used to endorse or promote
16  *    products derived from this software without specific prior
17  *    written permission.
18  *
19  * ALTERNATIVELY, this product may be distributed under the terms of
20  * the GNU General Public License, in which case the provisions of the GPL are
21  * required INSTEAD OF the above restrictions.  (This clause is
22  * necessary due to a potential bad interaction between the GPL and
23  * the restrictions contained in a BSD-style copyright.)
24  *
25  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
26  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
28  * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
29  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
31  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
32  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
35  * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
36  * DAMAGE.
37  */
38
39 #include <config.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <time.h>
43 #ifdef HAVE_STDINT_H
44 # include <stdint.h>
45 #endif
46
47 #include "types.h"
48 #include "g10lib.h"
49 #include "../cipher/bithelp.h"
50 #include "rand-internal.h"
51
52 /*
53  * Decide whether we can support jent at compile time.
54  */
55 #undef USE_JENT
56 #define JENT_USES_RDTSC 1
57 #define JENT_USES_GETTIME 2
58 #define JENT_USES_READ_REAL_TIME 3
59 #ifdef ENABLE_JENT_SUPPORT
60 # if defined (__i386__) || defined(__x86_64__)
61 #   define USE_JENT JENT_USES_RDTSC
62 # elif defined (HAVE_CLOCK_GETTIME)
63 #  if _AIX
64 #   define USE_JENT JENT_USES_READ_REAL_TIME
65 #  else
66 #   define USE_JENT JENT_USES_GETTIME
67 #  endif
68 # endif
69 #endif /*ENABLE_JENT_SUPPORT*/
70
71
72 #ifdef USE_JENT
73
74 #undef CONFIG_CRYPTO_CPU_JITTERENTROPY_STAT
75 /* Uncomment the next line to build with statistics.  */
76 /* #define CONFIG_CRYPTO_CPU_JITTERENTROPY_STAT 1 */
77
78
79 /* Note that we source include the actual jitter entropy code.
80  * Platform dependent code is indirectly included from our own
81  * jitterentropy-user-base.h file.   */
82
83 /* Tell jitterentropy* that all functions shall be static.  */
84 #define JENT_PRIVATE_COMPILE 1
85
86 #include "jitterentropy-base.c"
87
88
89 /* This is the lock we use to serialize access to this RNG.  The extra
90  * integer variable is only used to check the locking state; that is,
91  * it is not meant to be thread-safe but merely as a failsafe feature
92  * to assert proper locking.  */
93 GPGRT_LOCK_DEFINE (jent_rng_lock);
94 static int jent_rng_is_locked;
95
96 /* This flag tracks whether the RNG has been initialized - either
97  * with error or with success.  Protected by JENT_RNG_LOCK. */
98 static int jent_rng_is_initialized;
99
100 /* Our collector.  The RNG is in a working state if its value is not
101  * NULL.  Protected by JENT_RNG_LOCK.  */
102 struct rand_data *jent_rng_collector;
103
104 /* The number of times the core entropy function has been called and
105  * the number of random bytes retrieved.  */
106 static unsigned long jent_rng_totalcalls;
107 static unsigned long jent_rng_totalbytes;
108
109
110 \f
111 /* JENT statistic helper code.  */
112 #ifdef CONFIG_CRYPTO_CPU_JITTERENTROPY_STAT
113
114 static void
115 jent_init_statistic (struct rand_data *rand_data)
116 {
117   /* int i; */
118   /* struct entropy_stat *stat = &rand_data->entropy_stat; */
119
120   /* for (i = 0; i < 64; i++) */
121   /*   { */
122   /*     stat->bitslot[i] = 0; */
123   /*     stat->bitvar[i] = 0; */
124   /*   } */
125
126   /* jent_get_nstime (&stat->collection_begin); */
127 }
128
129 static void
130 jent_bit_count (struct rand_data *rand_data, u64 prev_data)
131 {
132   /* int i; */
133
134   /* if (!rand_data->entropy_stat.enable_bit_test) */
135   /*   return; */
136
137   /* for (i = 0; i < 64; i++) */
138   /*   { */
139   /*     /\* collect the count of set bits per bit position in the */
140   /*      * current ->data field *\/ */
141   /*     rand_data->entropy_stat.bitslot[i] += (rand_data->data & 1<<i) ? 1:0; */
142
143   /*     /\* collect the count of bit changes between the current */
144   /*      * and the previous random data value per bit position *\/ */
145   /*     if ((rand_data->data & 1<<i) != (prev_data & 1<<i)) */
146   /*       rand_data->entropy_stat.bitvar[i] += 1; */
147   /*   } */
148 }
149
150
151 static void
152 jent_statistic_copy_stat (struct entropy_stat *src, struct entropy_stat *dst)
153 {
154   /* /\* not copying bitslot and bitvar as they are not needed for */
155   /*  * statistic printout *\/ */
156   /* dst->collection_begin = src->collection_begin; */
157   /* dst->collection_end        = src->collection_end; */
158   /* dst->old_delta     = src->old_delta; */
159   /* dst->setbits               = src->setbits; */
160   /* dst->varbits               = src->varbits; */
161   /* dst->obsbits               = src->obsbits; */
162   /* dst->collection_loop_cnt= src->collection_loop_cnt; */
163 }
164
165
166 /*
167  * Assessment of statistical behavior of the generated output and returning
168  * the information to the caller by filling the target value.
169  *
170  * Details about the bit statistics are given in chapter 4 of the doc.
171  * Chapter 5 documents the timer analysis and the resulting entropy.
172  */
173 static void
174 jent_calc_statistic (struct rand_data *rand_data,
175                      struct entropy_stat *target, unsigned int loop_cnt)
176 {
177   /* int i; */
178   /* struct entropy_stat *stat = &rand_data->entropy_stat; */
179
180   /* jent_get_nstime(&stat->collection_end); */
181
182   /* stat->collection_loop_cnt = loop_cnt; */
183
184   /* stat->setbits = 0; */
185   /* stat->varbits = 0; */
186   /* stat->obsbits = 0; */
187
188   /* for (i = 0; i < DATA_SIZE_BITS; i++) */
189   /*   { */
190   /*     stat->setbits += stat->bitslot[i]; */
191   /*     stat->varbits += stat->bitvar[i]; */
192
193   /*     /\* This is the sum of set bits in the current observation */
194   /*      * of the random data. *\/ */
195   /*     stat->obsbits += (rand_data->data & 1<<i) ? 1:0; */
196   /*   } */
197
198   /* jent_statistic_copy_stat(stat, target); */
199
200   /* stat->old_delta = (stat->collection_end - stat->collection_begin); */
201 }
202
203 #endif /*CONFIG_CRYPTO_CPU_JITTERENTROPY_STAT*/
204
205
206 /* Acquire the jent_rng_lock.  */
207 static void
208 lock_rng (void)
209 {
210   gpg_err_code_t rc;
211
212   rc = gpgrt_lock_lock (&jent_rng_lock);
213   if (rc)
214     log_fatal ("failed to acquire the Jent RNG lock: %s\n",
215                gpg_strerror (rc));
216   jent_rng_is_locked = 1;
217 }
218
219
220 /* Release the jent_rng_lock.  */
221 static void
222 unlock_rng (void)
223 {
224   gpg_err_code_t rc;
225
226   jent_rng_is_locked = 0;
227   rc = gpgrt_lock_unlock (&jent_rng_lock);
228   if (rc)
229     log_fatal ("failed to release the Jent RNG lock: %s\n",
230                gpg_strerror (rc));
231 }
232
233
234 /* Return true if the JENT RNG code can be run.  It may not yet been
235  * initialized, though.  */
236 static int
237 is_rng_available (void)
238 {
239 #if USE_JENT == JENT_USES_RDTSC
240   return !!(_gcry_get_hw_features () & HWF_INTEL_RDTSC);
241 #elif USE_JENT == JENT_USES_GETTIME
242   return 2;
243 #elif USE_JENT == JENT_USES_READ_REAL_TIME
244   return 3;
245 #else  /* Ooops  */
246   return 0;
247 #endif
248 }
249
250 #endif /* USE_JENT */
251
252 \f
253 /*
254  * The API used by the high level code.
255  */
256
257 /* Read up to LENGTH bytes from a jitter RNG and return the number of
258  * bytes actually read.  */
259 size_t
260 _gcry_rndjent_poll (void (*add)(const void*, size_t, enum random_origins),
261                     enum random_origins origin, size_t length)
262 {
263   size_t nbytes = 0;
264
265 #ifdef USE_JENT
266   if ( is_rng_available () )
267     {
268       lock_rng ();
269
270       if (!jent_rng_is_initialized)
271         {
272           /* Auto-initialize.  */
273           jent_rng_is_initialized = 1;
274           jent_entropy_collector_free (jent_rng_collector);
275           jent_rng_collector = NULL;
276           if ( !(_gcry_random_read_conf () & RANDOM_CONF_DISABLE_JENT))
277             {
278               if (!jent_entropy_init ())
279                 jent_rng_collector = jent_entropy_collector_alloc (1, 0);
280             }
281         }
282
283       if (jent_rng_collector && add)
284         {
285           /* We have a working JENT and it has not been disabled.  */
286           char buffer[32];
287
288           while (length)
289             {
290               int rc;
291               size_t n = length < sizeof(buffer)? length : sizeof (buffer);
292
293               jent_rng_totalcalls++;
294               rc = jent_read_entropy (jent_rng_collector, buffer, n);
295               if (rc < 0)
296                 break;
297               /* We need to hash the output to conform to the BSI
298                * NTG.1 specs.  */
299               _gcry_md_hash_buffer (GCRY_MD_SHA256, buffer, buffer, rc);
300               n = rc < 32? rc : 32;
301               (*add) (buffer, n, origin);
302               length -= n;
303               nbytes += n;
304               jent_rng_totalbytes += n;
305             }
306           wipememory (buffer, sizeof buffer);
307         }
308
309       unlock_rng ();
310     }
311
312 #else
313
314   (void)add;
315   (void)origin;
316
317 #endif
318
319   return nbytes;
320 }
321
322
323 /* Return the version number of the JENT RNG.  If the RNG is not
324  * initialized or usable 0 is returned.  If R_ACTIVE is not NULL the
325  * jitter RNG will be initialized and true is stored at R_ACTIVE if
326  * the initialization succeeded.  */
327 unsigned int
328 _gcry_rndjent_get_version (int *r_active)
329 {
330 #ifdef USE_JENT
331   if ( is_rng_available () )
332     {
333       if (r_active)
334         {
335           /* Make sure the RNG is initialized.  */
336           _gcry_rndjent_poll (NULL, 0, 0);
337           /* To ease debugging we store 2 for a clock_gettime based
338            * implementation and 1 for a rdtsc based code.  */
339           *r_active = jent_rng_collector? is_rng_available () : 0;
340         }
341       return jent_version ();
342     }
343   else
344     return 0;
345 #else
346   return 0;
347 #endif
348 }
349
350
351 /* Log statistical informantion about the use of this module.  */
352 void
353 _gcry_rndjent_dump_stats (void)
354 {
355   /* In theory we would need to lock the stats here.  However this
356    * function is usually called during cleanup and then we _might_ run
357    * into problems.  */
358
359 #ifdef USE_JENT
360   if ( is_rng_available () )
361     {
362       log_info ("rndjent stat: collector=%p calls=%lu bytes=%lu\n",
363                 jent_rng_collector, jent_rng_totalcalls, jent_rng_totalbytes);
364
365     }
366 #endif /*USE_JENT*/
367 }