/**
** Simple entropy harvester based upon the havege RNG
**
** Copyright 2018-2021 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 .
*/
#ifndef HAVEGECOLLECT_H
#define HAVEGECOLLECT_H
/**
** Definitions needed to build haveged
*/
#include "havege.h"
/**
* The collection context
*/
typedef struct h_collect {
void *havege_app; /* Application block */
H_UINT havege_idx; /* Identifer */
H_UINT havege_szCollect; /* Size of collection buffer */
H_UINT havege_raw; /* RAW mode control flags */
H_UINT havege_szFill; /* Fill size */
H_UINT havege_nptr; /* Input pointer */
pRawIn havege_rawInput; /* Injection function */
pRawIn havege_testInput; /* Injection function for test */
H_UINT havege_cdidx; /* normal mode control flags */
H_UINT *havege_pwalk; /* Instance variable */
H_UINT havege_andpt; /* Instance variable */
H_UINT havege_PT; /* Instance variable */
H_UINT havege_PT2; /* Instance variable */
H_UINT havege_pt2; /* Instance variable */
H_UINT havege_PTtest; /* Instance variable */
H_UINT havege_tic; /* Instance variable */
H_UINT *havege_tics; /* loop timer noise buffer */
H_UINT havege_err; /* H_ERR enum for status */
void *havege_tests; /* opague test context */
void *havege_extra; /* other allocations */
H_UINT havege_bigarray[1]; /* collection buffer */
} volatile H_COLLECT;
/**
** Compiler intrinsics are used to make the build more portable and stable
** with fall-backs provided where the intrisics cannot be used.
*/
#ifdef __GNUC__
/* ################################################################################# */
/**
** For the GNU compiler, the use of a cpuid intrinsic is somewhat garbled by the
** fact that some distributions (Centos 5.x) carry an empty cpuid.h (in order
** to back patch glicb?). AFAIK cpuid did not appear in gcc until version 4.3
** although it was in existence before. If we do not have a valid cpuid.h,
** we provide our own copy of the file (from gcc 4.3)
**
** Also, gcc 4.4 and later provide an optimize attribute which remedies the
** effect ever increasing optimization on the collection loop
*/
#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
#define ASM __asm__ volatile
/**
** For the intel world...
*/
#ifdef HAVE_ISA_X86
#define ARCH "x86"
#if GCC_VERSION<40300
#undef HAVE_CPUID_H
#endif
#ifdef HAVE_CPUID_H
#include
#else
#include "cpuid-43.h"
#endif
/**
** Compatibility wrappers
*/
#define CPUID(level,p)\
{\
register int ecx asm ("ecx") = p[2];\
__cpuid(level,p[0],p[1],p[2],p[3]);\
(void) ecx;\
}
#define HASCPUID(p) __get_cpuid_max(0, p)
/**
** The rdtsc intrinsic is called in by x86intrin.h - also a recent gcc innovation
** There have been some discussions of the code in 4.5 and 4.6, so you may opt
** to use the inline alternative based on GCC_VERSION
*/
#ifdef HAVE_X86INTRIN_H
#include
#endif
#ifdef HAVE___RDTSC
#define HARDCLOCK(x) x=__rdtsc()
#else
#define HARDCLOCK(x) ASM("rdtsc;movl %%eax,%0":"=m"(x)::"ax","dx")
#endif
#else
/**
* Outside the x86 family
*/
#ifdef HAVE_ISA_GENERIC
#define ARCH "generic"
#define ENABLE_CLOCKGETTIME 1
#endif
#ifdef HAVE_ISA_IA64
#define ARCH "ia64"
#define HARDCLOCK(x) ASM("mov %0=ar.itc" : "=r"(x))
#endif
#ifdef HAVE_ISA_SPARC
#define ARCH "sparc"
#define HARDCLOCK(x) ASM("rd %%tick, %0":"=r"(x):"r"(x))
#endif
#ifdef HAVE_ISA_SPARCLITE
#define ARCH "sparclite"
#define HARDCLOCK(x) ASM(".byte 0x83, 0x41, 0x00, 0x00");\
ASM("mov %%g1, %0" : "=r"(x))
#endif
#ifdef HAVE_ISA_PPC
#define ARCH "ppc"
#define HARDCLOCK(x) ASM("mftb %0":"=r"(x)) /* eq. to mftb %0, 268 */
#endif
#ifdef HAVE_ISA_S390
#define ARCH "s390"
#define HARDCLOCK(x) { unsigned long long tsc; ASM("stck %0":"=Q"(tsc)::"cc"); x = (unsigned int)tsc; }
#endif
/**
* /Outside the x86 family
*/
#endif
/**
* Use the "&&" extension to calculate the LOOP_PT
*/
#define CODE_PT(a) a
#define LOOP_PT(a) &&loop##a
/* ################################################################################# */
#endif
/**
* For the MSVC world
*/
#if _MSVC_VERS
/* ################################################################################# */
#define ARCH "x86"
/**
* For the MSVC compilers V8 and above
*/
#include
/**
* Read the processor timestamp counter
*/
#define HARDCLOCK(x) x=__rdtsc()
/**
* Normalize to the gcc interface
*/
#define CPUID(level,p) return __cpuidx(p, level, p[2])
#define HASCPUID(p) \
{ \
CPUID(0,a,b,c,d) \
}
/**
* Use the __ReturnAddress intrinsic to calculate the LOOP_PT
*/
#define CODE_PT(a) __ReturnAddress()
#define LOOP_PT(a) 0
#endif
/* ################################################################################# */
/**
* Configuration defaults - allow override at compile
*/
#ifndef COLLECT_BUFSIZE
#define COLLECT_BUFSIZE 128 /* collection buffer size in KW */
#endif
#ifndef GENERIC_DCACHE
#define GENERIC_DCACHE 16 /* size of L1 data cache */
#endif
#ifndef GENERIC_ICACHE
#define GENERIC_ICACHE 16 /* size of L1 instruction cache */
#endif
#ifndef LOOP_CT
#define LOOP_CT 40 /* Max interations per collection loop */
#endif
/**
* Other useful definitions
*/
#define BITS_PER_H_UINT (8*sizeof(H_UINT)) /* Bit packing constant */
#define DEFAULT_BUFSZ 1024*sizeof(H_UINT) /* Default for ioSz */
#define MININITRAND 32 /* Number of initial fills to prime RNG */
#define NDSIZECOLLECT (COLLECT_BUFSIZE*1024) /* Collection size: 128K*H_UINT = .5M byte */
/**
** The public collection interface
*/
H_COLLECT *havege_ndcreate(H_PTR hptr, H_UINT nCollector);
void havege_nddestroy(H_COLLECT *rdr);
H_UINT havege_ndread(H_COLLECT *rdr);
void havege_ndsetup(H_PTR hptr);
#endif