Coverage Report

Created: 2022-12-08 06:09

/src/libgcrypt/random/jitterentropy-base-user.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Non-physical true random number generator based on timing jitter.
3
 *
4
 * Copyright Stephan Mueller <smueller@chronox.de>, 2013
5
 *
6
 * License
7
 * =======
8
 *
9
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions
11
 * are met:
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, and the entire permission notice in its entirety,
14
 *    including the disclaimer of warranties.
15
 * 2. Redistributions in binary form must reproduce the above copyright
16
 *    notice, this list of conditions and the following disclaimer in the
17
 *    documentation and/or other materials provided with the distribution.
18
 * 3. The name of the author may not be used to endorse or promote
19
 *    products derived from this software without specific prior
20
 *    written permission.
21
 *
22
 * ALTERNATIVELY, this product may be distributed under the terms of
23
 * the GNU General Public License, in which case the provisions of the GPL are
24
 * required INSTEAD OF the above restrictions.  (This clause is
25
 * necessary due to a potential bad interaction between the GPL and
26
 * the restrictions contained in a BSD-style copyright.)
27
 *
28
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
29
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
30
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
31
 * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
32
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
34
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
35
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
36
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
38
 * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
39
 * DAMAGE.
40
 */
41
42
#include <fcntl.h>
43
#include <limits.h>
44
45
#ifndef GCRYPT_JITTERENTROPY_BASE_USER_H
46
#define GCRYPT_JITTERENTROPY_BASE_USER_H
47
48
/*
49
 * This is Libgcrypt specific platform dependent code.  We use a
50
 * separate file because jitterentropy.h expects such a file.
51
 */
52
53
#ifndef USE_JENT
54
# error This file expects to be included from rndjent.c (via jitterentropy.h)
55
#endif
56
#ifndef HAVE_STDINT_H
57
# error This module needs stdint.h - try ./configure --disable-jent-support
58
#endif
59
60
61
/* When using the libgcrypt secure memory mechanism, all precautions
62
 * are taken to protect our state.  If the user disables secmem during
63
 * runtime, it is his decision and we thus try not to overrule his
64
 * decision for less memory protection.  */
65
#define JENT_CPU_JITTERENTROPY_SECURE_MEMORY 1
66
0
#define jent_zalloc(n) _gcry_calloc_secure (1, (n))
67
68
69
static void
70
jent_get_nstime(u64 *out)
71
0
{
72
0
#if USE_JENT == JENT_USES_RDTSC
73
74
0
  u32 t_eax, t_edx;
75
76
0
  asm volatile (".byte 0x0f,0x31\n\t"
77
0
                : "=a" (t_eax), "=d" (t_edx)
78
0
                );
79
0
  *out = (((u64)t_edx << 32) | t_eax);
80
81
#elif USE_JENT == JENT_USES_GETTIME
82
83
  struct timespec tv;
84
  u64 tmp;
85
86
  /* On Linux we could use CLOCK_MONOTONIC(_RAW), but with
87
   * CLOCK_REALTIME we get some nice extra entropy once in a while
88
   * from the NTP actions that we want to use as well... though, we do
89
   * not rely on that extra little entropy.  */
90
  if (!clock_gettime (CLOCK_REALTIME, &tv))
91
    {
92
      tmp = tv.tv_sec;
93
      tmp = tmp << 32;
94
      tmp = tmp | tv.tv_nsec;
95
    }
96
  else
97
    tmp = 0;
98
  *out = tmp;
99
100
#elif USE_JENT == JENT_USES_READ_REAL_TIME
101
102
  /* clock_gettime() on AIX returns a timer value that increments in
103
   * steps of 1000.  */
104
  u64 tmp = 0;
105
106
  timebasestruct_t aixtime;
107
  read_real_time (&aixtime, TIMEBASE_SZ);
108
  tmp = aixtime.tb_high;
109
  tmp = tmp << 32;
110
  tmp = tmp | aixtime.tb_low;
111
  *out = tmp;
112
113
#else
114
# error No clock available in jent_get_nstime
115
#endif
116
0
}
117
118
119
static GPGRT_INLINE void
120
jent_zfree (void *ptr, unsigned int len)
121
0
{
122
0
  if (ptr)
123
0
    {
124
0
      wipememory (ptr, len);
125
0
      _gcry_free (ptr);
126
0
    }
127
0
}
128
129
130
static GPGRT_INLINE int
131
jent_fips_enabled(void)
132
0
{
133
0
  return fips_mode();
134
0
}
135
136
137
static inline void jent_memset_secure(void *s, size_t n)
138
0
{
139
0
  wipememory (s, n);
140
0
}
141
142
static inline long jent_ncpu(void)
143
0
{
144
0
#if defined(_POSIX_SOURCE)
145
0
  long ncpu = sysconf(_SC_NPROCESSORS_ONLN);
146
0
147
0
  if (ncpu == -1)
148
0
    return -errno;
149
0
150
0
  if (ncpu == 0)
151
0
    return -EFAULT;
152
0
153
0
  return ncpu;
154
0
#elif defined(HAVE_W32_SYSTEM)
155
0
  SYSTEM_INFO sysinfo;
156
0
  long ncpu;
157
0
158
0
  GetNativeSystemInfo (&sysinfo);
159
0
  ncpu = sysinfo.dwNumberOfProcessors;
160
0
  if (ncpu <= 0) {
161
0
    GetSystemInfo (&sysinfo);
162
0
    ncpu = sysinfo.dwNumberOfProcessors;
163
0
  }
164
0
  if (ncpu <= 0)
165
0
    ncpu = 1;
166
0
  return ncpu;
167
0
#else
168
0
  return 1;
169
0
#endif
170
0
}
171
172
#ifdef __linux__
173
174
# if defined(_SC_LEVEL1_DCACHE_SIZE) &&         \
175
     defined(_SC_LEVEL2_CACHE_SIZE) &&          \
176
     defined(_SC_LEVEL3_CACHE_SIZE)
177
178
static inline void jent_get_cachesize(long *l1, long *l2, long *l3)
179
0
{
180
0
  *l1 = sysconf(_SC_LEVEL1_DCACHE_SIZE);
181
0
  *l2 = sysconf(_SC_LEVEL2_CACHE_SIZE);
182
0
  *l3 = sysconf(_SC_LEVEL3_CACHE_SIZE);
183
0
}
184
185
# else
186
187
static inline void jent_get_cachesize(long *l1, long *l2, long *l3)
188
{
189
#define JENT_SYSFS_CACHE_DIR "/sys/devices/system/cpu/cpu0/cache"
190
  long val;
191
  unsigned int i;
192
  char buf[10], file[50];
193
  int fd = 0;
194
195
  /* Iterate over all caches */
196
  for (i = 0; i < 4; i++) {
197
    unsigned int shift = 0;
198
    char *ext;
199
200
    /*
201
     * Check the cache type - we are only interested in Unified
202
     * and Data caches.
203
     */
204
    memset(buf, 0, sizeof(buf));
205
    snprintf(file, sizeof(file), "%s/index%u/type",
206
       JENT_SYSFS_CACHE_DIR, i);
207
    fd = open(file, O_RDONLY);
208
    if (fd < 0)
209
      continue;
210
    while (read(fd, buf, sizeof(buf)) < 0 && errno == EINTR);
211
    close(fd);
212
    buf[sizeof(buf) - 1] = '\0';
213
214
    if (strncmp(buf, "Data", 4) && strncmp(buf, "Unified", 7))
215
      continue;
216
217
    /* Get size of cache */
218
    memset(buf, 0, sizeof(buf));
219
    snprintf(file, sizeof(file), "%s/index%u/size",
220
       JENT_SYSFS_CACHE_DIR, i);
221
222
    fd = open(file, O_RDONLY);
223
    if (fd < 0)
224
      continue;
225
    while (read(fd, buf, sizeof(buf)) < 0 && errno == EINTR);
226
    close(fd);
227
    buf[sizeof(buf) - 1] = '\0';
228
229
    ext = strstr(buf, "K");
230
    if (ext) {
231
      shift = 10;
232
      ext = '\0';
233
    } else {
234
      ext = strstr(buf, "M");
235
      if (ext) {
236
        shift = 20;
237
        ext = '\0';
238
      }
239
    }
240
241
    val = strtol(buf, NULL, 10);
242
    if (val == LONG_MAX)
243
      continue;
244
    val <<= shift;
245
246
    if (!*l1)
247
      *l1 = val;
248
    else if (!*l2)
249
      *l2 = val;
250
    else {
251
      *l3 = val;
252
      break;
253
    }
254
  }
255
#undef JENT_SYSFS_CACHE_DIR
256
}
257
258
# endif
259
260
static inline uint32_t jent_cache_size_roundup(void)
261
0
{
262
0
  static int checked = 0;
263
0
  static uint32_t cache_size = 0;
264
265
0
  if (!checked) {
266
0
    long l1 = 0, l2 = 0, l3 = 0;
267
268
0
    jent_get_cachesize(&l1, &l2, &l3);
269
0
    checked = 1;
270
271
    /* Cache size reported by system */
272
0
    if (l1 > 0)
273
0
      cache_size += (uint32_t)l1;
274
0
    if (l2 > 0)
275
0
      cache_size += (uint32_t)l2;
276
0
    if (l3 > 0)
277
0
      cache_size += (uint32_t)l3;
278
279
    /*
280
     * Force the output_size to be of the form
281
     * (bounding_power_of_2 - 1).
282
     */
283
0
    cache_size |= (cache_size >> 1);
284
0
    cache_size |= (cache_size >> 2);
285
0
    cache_size |= (cache_size >> 4);
286
0
    cache_size |= (cache_size >> 8);
287
0
    cache_size |= (cache_size >> 16);
288
289
0
    if (cache_size == 0)
290
0
      return 0;
291
292
    /*
293
     * Make the output_size the smallest power of 2 strictly
294
     * greater than cache_size.
295
     */
296
0
    cache_size++;
297
0
  }
298
299
0
  return cache_size;
300
0
}
301
302
#else /* __linux__ */
303
304
static inline uint32_t jent_cache_size_roundup(void)
305
{
306
  return 0;
307
}
308
309
#endif /* __linux__ */
310
311
#ifdef JENT_CONF_ENABLE_INTERNAL_TIMER
312
#include <sched.h>
313
314
static inline void jent_yield(void)
315
{
316
  sched_yield();
317
}
318
#endif
319
320
#endif /* GCRYPT_JITTERENTROPY_BASE_USER_H */