Coverage Report

Created: 2022-12-08 06:09

/src/libgcrypt/random/rndjent.c
Line
Count
Source (jump to first uncovered line)
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
#include <unistd.h>
47
#include <errno.h>
48
#ifndef EOPNOTSUPP
49
# define EOPNOTSUPP ENOSYS
50
#endif
51
52
#ifdef HAVE_W32_SYSTEM
53
# if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0501
54
#  undef _WIN32_WINNT
55
#  define _WIN32_WINNT 0x0501 /* for GetNativeSystemInfo */
56
# endif
57
# include <windows.h>
58
#endif
59
60
#include "types.h"
61
#include "g10lib.h"
62
#include "../cipher/bithelp.h"
63
#include "rand-internal.h"
64
65
/*
66
 * Decide whether we can support jent at compile time.
67
 */
68
#undef USE_JENT
69
#define JENT_USES_RDTSC 1
70
#define JENT_USES_GETTIME 2
71
#define JENT_USES_READ_REAL_TIME 3
72
#ifdef ENABLE_JENT_SUPPORT
73
# if (defined (__i386__) || defined(__x86_64__)) && defined(HAVE_CPU_ARCH_X86)
74
#   define USE_JENT JENT_USES_RDTSC
75
# elif defined (HAVE_CLOCK_GETTIME)
76
#  if _AIX
77
#   define USE_JENT JENT_USES_READ_REAL_TIME
78
#  else
79
#   define USE_JENT JENT_USES_GETTIME
80
#  endif
81
# endif
82
#endif /*ENABLE_JENT_SUPPORT*/
83
84
85
#ifdef USE_JENT
86
87
#undef CONFIG_CRYPTO_CPU_JITTERENTROPY_STAT
88
/* Uncomment the next line to build with statistics.  */
89
/* #define CONFIG_CRYPTO_CPU_JITTERENTROPY_STAT 1 */
90
91
92
/* Note that we source include the actual jitter entropy code.
93
 * Platform dependent code is indirectly included from our own
94
 * jitterentropy-user-base.h file.   */
95
96
/* Tell jitterentropy* that all functions shall be static.  */
97
#define JENT_PRIVATE_COMPILE 1
98
99
#include "jitterentropy-base.c"
100
#ifdef JENT_CONF_ENABLE_INTERNAL_TIMER
101
#include <pthread.h>
102
#endif /* JENT_CONF_ENABLE_INTERNAL_TIMER */
103
#include "jitterentropy-gcd.c"
104
#include "jitterentropy-health.c"
105
#include "jitterentropy-noise.c"
106
#include "jitterentropy-sha3.c"
107
#include "jitterentropy-timer.c"
108
109
/* This is the lock we use to serialize access to this RNG.  The extra
110
 * integer variable is only used to check the locking state; that is,
111
 * it is not meant to be thread-safe but merely as a failsafe feature
112
 * to assert proper locking.  */
113
GPGRT_LOCK_DEFINE (jent_rng_lock);
114
static int jent_rng_is_locked;
115
116
/* This flag tracks whether the RNG has been initialized - either
117
 * with error or with success.  Protected by JENT_RNG_LOCK. */
118
static int jent_rng_is_initialized;
119
120
/* Our collector.  The RNG is in a working state if its value is not
121
 * NULL.  Protected by JENT_RNG_LOCK.  */
122
struct rand_data *jent_rng_collector;
123
124
/* The number of times the core entropy function has been called and
125
 * the number of random bytes retrieved.  */
126
static unsigned long jent_rng_totalcalls;
127
static unsigned long jent_rng_totalbytes;
128
129
130

131
/* JENT statistic helper code.  */
132
#ifdef CONFIG_CRYPTO_CPU_JITTERENTROPY_STAT
133
134
static void
135
jent_init_statistic (struct rand_data *rand_data)
136
{
137
  /* int i; */
138
  /* struct entropy_stat *stat = &rand_data->entropy_stat; */
139
140
  /* for (i = 0; i < 64; i++) */
141
  /*   { */
142
  /*     stat->bitslot[i] = 0; */
143
  /*     stat->bitvar[i] = 0; */
144
  /*   } */
145
146
  /* jent_get_nstime (&stat->collection_begin); */
147
}
148
149
static void
150
jent_bit_count (struct rand_data *rand_data, u64 prev_data)
151
{
152
  /* int i; */
153
154
  /* if (!rand_data->entropy_stat.enable_bit_test) */
155
  /*   return; */
156
157
  /* for (i = 0; i < 64; i++) */
158
  /*   { */
159
  /*     /\* collect the count of set bits per bit position in the */
160
  /*      * current ->data field *\/ */
161
  /*     rand_data->entropy_stat.bitslot[i] += (rand_data->data & 1<<i) ? 1:0; */
162
163
  /*     /\* collect the count of bit changes between the current */
164
  /*      * and the previous random data value per bit position *\/ */
165
  /*     if ((rand_data->data & 1<<i) != (prev_data & 1<<i)) */
166
  /*       rand_data->entropy_stat.bitvar[i] += 1; */
167
  /*   } */
168
}
169
170
171
static void
172
jent_statistic_copy_stat (struct entropy_stat *src, struct entropy_stat *dst)
173
{
174
  /* /\* not copying bitslot and bitvar as they are not needed for */
175
  /*  * statistic printout *\/ */
176
  /* dst->collection_begin = src->collection_begin; */
177
  /* dst->collection_end  = src->collection_end; */
178
  /* dst->old_delta = src->old_delta; */
179
  /* dst->setbits   = src->setbits; */
180
  /* dst->varbits   = src->varbits; */
181
  /* dst->obsbits   = src->obsbits; */
182
  /* dst->collection_loop_cnt= src->collection_loop_cnt; */
183
}
184
185
186
/*
187
 * Assessment of statistical behavior of the generated output and returning
188
 * the information to the caller by filling the target value.
189
 *
190
 * Details about the bit statistics are given in chapter 4 of the doc.
191
 * Chapter 5 documents the timer analysis and the resulting entropy.
192
 */
193
static void
194
jent_calc_statistic (struct rand_data *rand_data,
195
                     struct entropy_stat *target, unsigned int loop_cnt)
196
{
197
  /* int i; */
198
  /* struct entropy_stat *stat = &rand_data->entropy_stat; */
199
200
  /* jent_get_nstime(&stat->collection_end); */
201
202
  /* stat->collection_loop_cnt = loop_cnt; */
203
204
  /* stat->setbits = 0; */
205
  /* stat->varbits = 0; */
206
  /* stat->obsbits = 0; */
207
208
  /* for (i = 0; i < DATA_SIZE_BITS; i++) */
209
  /*   { */
210
  /*     stat->setbits += stat->bitslot[i]; */
211
  /*     stat->varbits += stat->bitvar[i]; */
212
213
  /*     /\* This is the sum of set bits in the current observation */
214
  /*      * of the random data. *\/ */
215
  /*     stat->obsbits += (rand_data->data & 1<<i) ? 1:0; */
216
  /*   } */
217
218
  /* jent_statistic_copy_stat(stat, target); */
219
220
  /* stat->old_delta = (stat->collection_end - stat->collection_begin); */
221
}
222
223
#endif /*CONFIG_CRYPTO_CPU_JITTERENTROPY_STAT*/
224
225
226
/* Acquire the jent_rng_lock.  */
227
static void
228
lock_rng (void)
229
0
{
230
0
  gpg_err_code_t rc;
231
232
0
  rc = gpgrt_lock_lock (&jent_rng_lock);
233
0
  if (rc)
234
0
    log_fatal ("failed to acquire the Jent RNG lock: %s\n",
235
0
               gpg_strerror (rc));
236
0
  jent_rng_is_locked = 1;
237
0
}
238
239
240
/* Release the jent_rng_lock.  */
241
static void
242
unlock_rng (void)
243
0
{
244
0
  gpg_err_code_t rc;
245
246
0
  jent_rng_is_locked = 0;
247
0
  rc = gpgrt_lock_unlock (&jent_rng_lock);
248
0
  if (rc)
249
0
    log_fatal ("failed to release the Jent RNG lock: %s\n",
250
0
               gpg_strerror (rc));
251
0
}
252
253
254
/* Return true if the JENT RNG code can be run.  It may not yet been
255
 * initialized, though.  */
256
static int
257
is_rng_available (void)
258
0
{
259
0
#if USE_JENT == JENT_USES_RDTSC
260
0
  return !!(_gcry_get_hw_features () & HWF_INTEL_RDTSC);
261
#elif USE_JENT == JENT_USES_GETTIME
262
  return 2;
263
#elif USE_JENT == JENT_USES_READ_REAL_TIME
264
  return 3;
265
#else  /* Ooops  */
266
  return 0;
267
#endif
268
0
}
269
270
#endif /* USE_JENT */
271
272

273
/*
274
 * The API used by the high level code.
275
 */
276
277
/* Read up to LENGTH bytes from a jitter RNG and return the number of
278
 * bytes actually read.  */
279
size_t
280
_gcry_rndjent_poll (void (*add)(const void*, size_t, enum random_origins),
281
                    enum random_origins origin, size_t length)
282
0
{
283
0
  size_t nbytes = 0;
284
285
0
#ifdef USE_JENT
286
0
  if ( is_rng_available () )
287
0
    {
288
0
      lock_rng ();
289
290
0
      if (!jent_rng_is_initialized)
291
0
        {
292
          /* Auto-initialize.  */
293
0
          jent_rng_is_initialized = 1;
294
0
          jent_entropy_collector_free (jent_rng_collector);
295
0
          jent_rng_collector = NULL;
296
0
          if ( !(_gcry_random_read_conf () & RANDOM_CONF_DISABLE_JENT))
297
0
            {
298
0
              if (!jent_entropy_init ())
299
0
                jent_rng_collector = jent_entropy_collector_alloc (1, 0);
300
0
            }
301
0
        }
302
303
0
      if (jent_rng_collector && add)
304
0
        {
305
          /* We have a working JENT and it has not been disabled.  */
306
0
          char buffer[32];
307
308
0
          while (length)
309
0
            {
310
0
              int rc;
311
0
              size_t n = length < sizeof(buffer)? length : sizeof (buffer);
312
313
0
              jent_rng_totalcalls++;
314
0
              rc = jent_read_entropy_safe (&jent_rng_collector, buffer, n);
315
0
              if (rc < 0)
316
0
                break;
317
              /* We need to hash the output to conform to the BSI
318
               * NTG.1 specs.  */
319
0
              _gcry_md_hash_buffer (GCRY_MD_SHA256, buffer, buffer, rc);
320
0
              n = rc < 32? rc : 32;
321
0
              (*add) (buffer, n, origin);
322
0
              length -= n;
323
0
              nbytes += n;
324
0
              jent_rng_totalbytes += n;
325
0
            }
326
0
          wipememory (buffer, sizeof buffer);
327
0
        }
328
329
0
      unlock_rng ();
330
0
    }
331
332
#else
333
334
  (void)add;
335
  (void)origin;
336
337
#endif
338
339
0
  return nbytes;
340
0
}
341
342
343
/* Return the version number of the JENT RNG.  If the RNG is not
344
 * initialized or usable 0 is returned.  If R_ACTIVE is not NULL the
345
 * jitter RNG will be initialized and true is stored at R_ACTIVE if
346
 * the initialization succeeded.  */
347
unsigned int
348
_gcry_rndjent_get_version (int *r_active)
349
0
{
350
0
  if (r_active)
351
0
    *r_active = 0;
352
0
#ifdef USE_JENT
353
0
  if ( is_rng_available () )
354
0
    {
355
0
      if (r_active)
356
0
        {
357
          /* Make sure the RNG is initialized.  */
358
0
          _gcry_rndjent_poll (NULL, 0, 0);
359
360
0
          lock_rng ();
361
          /* To ease debugging we store 2 for a clock_gettime based
362
           * implementation and 1 for a rdtsc based code.  */
363
0
          *r_active = jent_rng_collector? is_rng_available () : 0;
364
0
          unlock_rng ();
365
0
        }
366
0
      return jent_version ();
367
0
    }
368
0
  else
369
0
    return 0;
370
#else
371
  return 0;
372
#endif
373
0
}
374
375
376
/* Log statistical informantion about the use of this module.  */
377
void
378
_gcry_rndjent_dump_stats (void)
379
0
{
380
  /* In theory we would need to lock the stats here.  However this
381
   * function is usually called during cleanup and then we _might_ run
382
   * into problems.  */
383
384
0
#ifdef USE_JENT
385
0
  if ( is_rng_available () )
386
0
    {
387
0
      log_info ("rndjent stat: collector=%p calls=%lu bytes=%lu\n",
388
0
                jent_rng_collector, jent_rng_totalcalls, jent_rng_totalbytes);
389
390
0
    }
391
0
#endif /*USE_JENT*/
392
0
}
393
394
395
void
396
_gcry_rndjent_fini (void)
397
0
{
398
0
#ifdef USE_JENT
399
0
  lock_rng ();
400
401
0
  if (jent_rng_is_initialized)
402
0
    {
403
0
      jent_entropy_collector_free (jent_rng_collector);
404
0
      jent_rng_collector = NULL;
405
0
    }
406
407
0
  unlock_rng ();
408
0
#endif
409
0
}