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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
|
/**
** Simple entropy harvester based upon the havege RNG
**
** Copyright 2018-2022 Jirka Hladky hladky DOT jiri AT gmail DOT com
** Copyright 2009-2014 Gary Wuertz gary@issiweb.com
** Copyright 2011-2012 BenEleventh Consulting manolson@beneleventh.com
**
** This program 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 3 of the License, or
** (at your option) any later version.
**
** This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef HAVEGE_H
#define HAVEGE_H
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* header/package version as a numeric major, minor, patch triple. See havege_version()
* below for usage.
*/
#define HAVEGE_PREP_VERSION "1.9.19"
/**
* Basic types
*/
#define H_UINT uint32_t
#define H_UINT8 uint8_t
/**
* Optional metering call-back. Called with event=0 at start of collection buffer fill.
* Called with event=1 at end of collection buffer fill. The nCollect parameter indicates
* the calling process if multiple collection processes are enabled. Use a value of 0
* to disable metering.
*/
typedef void (*pMeter)(H_UINT nCollect, H_UINT event);
/**
* Optional message display call-back. This printf style method is used for all diagnostic
* output including havege_status(). Use a value of 0 to disable output.
*/
typedef void (*pMsg)(const char *format, ...);
/**
* Injection call-back for RAW diagnostics. Use a value of 0 to disable diagnostic. Ignored
* except for diaqnotic builds.
*/
typedef int (*pRawIn)(volatile H_UINT *pData, H_UINT szData);
/**
* options for H_PARAMS below. Lower byte transferred from verbose settings
* upper byte set by diagnositic run options
*/
#define H_VERBOSE 0x001 /* deprecated from ver 1.7 */
#define H_DEBUG_INFO 0x001 /* Show config info, retries */
#define H_DEBUG_OLTR 0x002 /* Show detailed test retry info */
#define H_DEBUG_TIME 0x004 /* Show collection times */
#define H_DEBUG_LOOP 0x008 /* Show loop parameters */
#define H_DEBUG_COMPILE 0x010 /* Show assembly info */
#define H_DEBUG_OLT 0x020 /* Show all test info */
#define H_RNDADDENTROPY_INFO 0x040 /* RNDADDENTROPY info */
#define H_DEBUG_RAW_OUT 0x100 /* diagnostic output */
#define H_DEBUG_RAW_IN 0x200 /* diagnostic input */
#define H_DEBUG_TEST_IN 0x400 /* input test data */
/**
* Initialization parameters. Use non-zero values to override default values.
* Notes:
*
* 1) Correspondence between provided value and value of H_PTR members are:
* ioSz <==> i_readSz, collectSize <==> i_collectSz, nCores <==> n_cores,
* options <==> havege_opts
* 2) ioSz is specified in bytes. collectSize sizes is specified as number
* of H_UINT. The default for ioSz is 1024*sizeof(H_UINT). The default
* for collecSize is 128K * sizeof(H_UINT).
* 3) The icacheSize and dcacheSize override cache sizes. Both are specified in KB.
* Either may be specified to override the tuning value. If both are provided,
* tuning code is bypassed. The fallback tuning values can be overridden
* by defining GENERIC_DCACHE and GENERIC_ICACHE (16 will be used if not
* otherwise defined)
* 4) null callback values suppress the function.
* 5) sysFs default is '/sys', procFs default is '/proc'.
* 6) testSpec same as haveged option "[t<x>][c<x>] x=[a[n][w]][b[w]]". If
* not specified (NULL) the default is "ta8b" - i.e. run the tot tests
*/
typedef struct {
H_UINT ioSz; /* size of write buffer */
H_UINT collectSize; /* size of collection buffer */
H_UINT icacheSize; /* Instruction cache size */
H_UINT dcacheSize; /* Data cache size */
H_UINT options; /* Other options */
H_UINT nCores; /* If multi-core */
pMeter metering; /* meterming method */
pMsg msg_out; /* output display method */
pRawIn injection; /* injection method */
char *procFs; /* proc mount point override */
char *sysFs; /* sys mount point override */
char *testSpec; /* test specification */
} H_PARAMS;
/**
* Status codes used in the error member of h_anchor
*/
typedef enum {
H_NOERR, /* 00 No error */
H_NOHANDLE, /* 01 No memory for handle */
H_NOBUF, /* 02 Output buffer allocation failed */
H_NOINIT, /* 03 semaphore init failed */
H_NOCOLLECT, /* 04 H_COLLECT allocation failed */
H_NOWALK, /* 05 Walk buffer allocation failed */
H_NOTESTSPEC, /* 06 invalid test specification */
H_NOTESTINIT, /* 07 test setup failed */
H_NOTESTMEM, /* 08 Unable to allocate test memory */
H_NOTESTTOT, /* 09 tot test failed */
H_NOTESTRUN, /* 10 production test failed */
H_NOCORES, /* 11 too many cores specified */
H_NOTASK, /* 12 Unable to create child task */
H_NOWAIT, /* 13 sem_wait failed */
H_NOPOST, /* 14 sem_post failed */
H_NODONE, /* 15 sem_post done failed */
H_NORQST, /* 16 sem_post request failed */
H_NOCOMP, /* 17 wait for completion failed */
H_EXIT, /* 18 Exit signal */
H_NOTIMER /* 19 timer failed */
} H_ERR;
/**
* Keep compiler honest
*/
typedef volatile void *H_VOL;
/**
* Anchor for the RNG. Should be read only at devel level and above.
*/
typedef struct h_anchor {
H_UINT *io_buf; /* output buffer */
char *arch; /* "x86","sparc","ppc","ia64",etc */
void *cpu; /* information on the cpu */
void *instCache; /* instruction cache info */
void *dataCache; /* data cache info */
pMsg print_msg; /* output display method */
pMeter metering; /* metering method */
pRawIn inject; /* Injection diagnostic only */
H_VOL collector; /* single thread collector */
H_VOL threads; /* multi thread collectors */
void *testData; /* online test data */
void *tuneData; /* tuning data */
H_UINT error; /* H_ERR enum for status */
H_UINT havege_opts; /* option flags */
H_UINT i_maxidx; /* maximum instruction loop index */
H_UINT i_maxsz; /* maximum code size */
H_UINT i_idx; /* code index used */
H_UINT i_sz; /* code size used */
H_UINT i_collectSz; /* size of collection buffer */
H_UINT i_readSz; /* size of read buffer (bytes) */
H_UINT m_sz; /* size of thread ipc area (bytes) */
H_UINT n_cores; /* number of cores */
H_UINT n_fills; /* number of buffer fills */
size_t n_entropy_bytes; /* total amount of entropy (byte) */
} *H_PTR;
/**
* Fail/Success counters for tot and production tests.
*/
typedef enum {
H_OLT_TOT_A_F, /* tot Procedure A failed */
H_OLT_TOT_A_P, /* tot Procedure A passed */
H_OLT_TOT_B_F, /* tot Procedure B failed */
H_OLT_TOT_B_P, /* tot Procedure B passed */
H_OLT_PROD_A_F, /* prod Procedure A failed */
H_OLT_PROD_A_P, /* prod Procedure A passed */
H_OLT_PROD_B_F, /* prod Procedure B failed */
H_OLT_PROD_B_P /* prod Procedure B passed */
} H_OLT_METERS;
/**
* Structure used to query RNG anchor settings for information not exposed by
* H_PTR. List formats are strings with one or more tokens separated by space.
* Sources lists show how tuning parameters are derived. D is a build default,
* P is a run time override, items V* come from linux virtual file system,
* other items trace various cpuid sources. Tuning is skipped if both cache
* sizes have 'P' sources.
*
* Notes:
*
* 1) Build: package version of source
* 2) Build options: compiler version followed by build configuration encoded
* as string of: [C][I][M][T][V] where C=clock_gettime, I=tune with cpuid,
* M=multi-core, T=online-test, V=tune with vfs
* 3) Tuning source lists: D=default, P=parameter, C=cpuid present,
* H=hyperthreading, A=AMD cpuid, A5=AMD fn5, A6=AMD fn6, A8=AMD fn8
* L2=Intel has leaf2, L4=Intel has leaf4, B=Intel leaf b,
* 4=intel leaf4, V=virtual file system available
* VS=/sys/devices/system/cpu/cpu%d/cache/index<n>/level,
* VO=/sys/devices/system/cpu/online, VI=/proc/cpuinfo
* VC=/sys/devices/system/cpu
* 4) test spec [A[1..8]][B], see H_PARAMS above.
* 5) zero unless tests are enabled
* 6) Last Coron's entropy estimate from Procedure B, test 8
*/
typedef struct h_status {
const char *version; /* Package version [1] */
const char *buildOptions; /* Options [2] */
const char *vendor; /* cpuid machines only */
const char *cpuSources; /* Tuning sources list [3] */
const char *i_cacheSources; /* Tuning sources list [3] */
const char *d_cacheSources; /* Tuning sources list [3] */
const char *tot_tests; /* tot test spec [4] */
const char *prod_tests; /* prod test spec [4] */
H_UINT i_cache; /* size of L1 instruction cache KB */
H_UINT d_cache; /* size of L1 data cache KB */
H_UINT n_tests[H_OLT_PROD_B_P+1]; /* test statistics [5] */
double last_test8; /* last test8 result [6] */
} *H_STATUS;
/**
* Standard presentation formats for havege_status_dump.
*/
typedef enum {
H_SD_TOPIC_BUILD,
/* ver: %s; arch: %s; vend: %s; build: (%s); collect: %dK */
H_SD_TOPIC_TUNE,
/* cpu: (%s); data: %dK (%s); inst: %dK (%s); idx: %d/%d; sz: %d/%d */
H_SD_TOPIC_TEST,
/* [tot tests (%s): A:%d/%d B: %d/%d;][continuous tests (%s): A:%d/%d B: %d/%d;][last entropy estimate %g] */
H_SD_TOPIC_SUM,
/* fills: %d, generated: %.4g %c bytes */
} H_SD_TOPIC;
/**
* Public prototypes. Library users note that "havege_*" is reserved for library
* public functions. Note that the multi-core option is experimental and must
* enabled in the build.
*/
/**
* Create an anchor. The caller should check for a non-null return value with
* a error value of H_NOERR. Any non-null return should be disposed of by a
* call to havege_destroy() to free all allocated resources.
*
* Possible error values: H_NOERR, H_NOTESTSPEC, H_NOBUF, H_NOTESTMEM,
* H_NOINIT
*/
H_PTR havege_create(H_PARAMS *params);
/**
* haveger_create() remembers parent pid and uses it to identify deallocating thread.
* daemonize() forks parent and effectively loses parent thread.
* havege_reparent(void) allows recovering new parent pid before havege_run() is started.
*/
void havege_reparent(H_PTR hptr);
/**
* Frees all allocated anchor resources. If the multi-core option is used, this
* method should be called from a signal handler to prevent zombie processes.
* If called by the process that called haveged_create(), hptr will be freed
* when all child processes (if any) have terminated. If called by a child
* process, H_EXIT will be set and all children awakened to exit.
*/
void havege_destroy(H_PTR hptr);
/**
* Read random words from an active anchor. The RNG must have been readied
* by a previous call to havege_run(). The read must take place within the
* allocated buffer, hptr->io_buf, and the range is specified in number of
* H_UINT to read. If the multi-core option is used, this buffer is
* memory-mapped between collectors.
*
* Returns the number of H_UINT read.
*
* Possible error values: H_NOERR, H_NOTESRUN, H_NOPOST, H_NODONE,
* H_NORQST, H_NOCOMP, H_EXIT
*/
int havege_rng(H_PTR hptr, H_UINT *buf, H_UINT sz);
/**
* Warm up the RNG and run the start-up tests. The operation suceeded if the
* error member of the handle is H_NOERR. A failed handle should be disposed
* of by a call to havege_destroy().
*
* Returns non-zero on failure.
*
* Possible error values: H_NOERR, H_NOCOLLECT, H_NOWALK, H_NOTESTMEM,
* H_NOTASK, H_NOTESTTOT, H_NOWAIT,
* any havege_rng error
*/
int havege_run(H_PTR hptr);
/**
* Fill in the h_status structure with read-only information collected from
* the package build, run-time tuning, and test components.
*/
void havege_status(H_PTR hptr, H_STATUS hsts);
/**
* Call havege_status() and generate a standard presentation of H_STATUS content.
* See the H_SD_TOPIC enum above for the formats.
*
* Returns the number of bytes placed in buf.
*/
int havege_status_dump(H_PTR hptr, H_SD_TOPIC topic, char *buf, size_t len);
/**
* Return/check library prep version. Calling havege_version() with a NULL version
* returns the definition of HAVEGE_PREP_VERSION used to build the library. Calling
* with HAVEGE_PREP_VERSION as the version checks if this headers definition is
* compatible with that of the library, returning NULL if the input is incompatible
* with the library.
*/
const char *havege_version(const char *version);
#ifdef __cplusplus
}
#endif
#endif
|