1 /**
2 * High Resolution Timestamp Entropy Source
3 * 
4 * Copyright:
5 * (C) 1999-2009, 2014 Jack Lloyd
6 * (C) 2014-2015 Etienne Cimon
7 *
8 * License:
9 * Botan is released under the Simplified BSD License (see LICENSE.md)
10 */
11 module botan.entropy.hres_timer;
12 
13 import botan.constants;
14 static if (BOTAN_HAS_ENTROPY_SRC_HIGH_RESOLUTION_TIMER):
15 
16 import botan.entropy.entropy_src;
17 
18 import botan.utils.cpuid;
19 import std.datetime;
20 
21 version(Windows) import core.sys.windows.windows;
22 else version(Posix) import core.sys.linux.time;
23 
24 
25 /**
26 * Entropy source using high resolution timers
27 *
28 * @note Any results from timers are marked as not contributing entropy
29 * to the poll, as a local attacker could observe them directly.
30 */
31 final class HighResolutionTimestamp : EntropySource
32 {
33 public:
34     @property string name() const { return "High Resolution Timestamp"; }
35     /*
36 * Get the timestamp
37 */
38     void poll(ref EntropyAccumulator accum)
39     {
40         // Don't count any timestamps as contributing any entropy
41         const double ESTIMATED_ENTROPY_PER_BYTE = 1.0;
42 
43         static if (is(typeof(clock_gettime))) {
44 
45             void CLOCK_GETTIME_POLL(clockid_t src)
46             {
47                 timespec ts;
48                 clock_gettime(src, &ts);
49                 accum.add(&ts, (ts).sizeof, ESTIMATED_ENTROPY_PER_BYTE);
50             }
51             
52             static if (is(typeof(CLOCK_REALTIME))) {
53                 CLOCK_GETTIME_POLL(CLOCK_REALTIME);
54             }
55             
56             static if (is(typeof(CLOCK_MONOTONIC))) {
57                 CLOCK_GETTIME_POLL(CLOCK_MONOTONIC);
58             }
59             
60             static if (is(typeof(CLOCK_MONOTONIC_RAW))) {
61                 CLOCK_GETTIME_POLL(CLOCK_MONOTONIC_RAW);
62             }
63             
64             static if (is(typeof(CLOCK_PROCESS_CPUTIME_ID))) {
65                 CLOCK_GETTIME_POLL(CLOCK_PROCESS_CPUTIME_ID);
66             }
67             
68             static if (is(typeof(CLOCK_THREAD_CPUTIME_ID))) {
69                 CLOCK_GETTIME_POLL(CLOCK_THREAD_CPUTIME_ID);
70             }
71             
72         }
73         else 
74         {
75             auto timestamp = Clock.currStdTime();
76             accum.add(timestamp, ESTIMATED_ENTROPY_PER_BYTE);
77 
78         }
79             
80         static if (is(typeof(QueryPerformanceCounter)))
81         {
82             long tv;
83             QueryPerformanceCounter(&tv);
84             accum.add(tv, ESTIMATED_ENTROPY_PER_BYTE);
85         }
86     }
87 
88 }
89 
90 
91 
92 version (Windows)
93 {
94     extern (Windows)
95     {
96         export int queryPerformanceCounter(long *);
97     }
98 }
99 else version (D_InlineAsm_X86)
100 {
101     extern (D)
102     {
103         void queryPerformanceCounter(long* ctr)
104         {
105             asm
106             {
107                 naked                   ;
108                 mov       ECX,EAX       ;
109                 rdtsc                   ;
110                 mov   [ECX],EAX         ;
111                 mov   4[ECX],EDX        ;
112                 ret                     ;
113             }
114         }
115     }
116 }
117 else version (D_InlineAsm_X86_64)
118 {
119     extern (D)
120     {
121         void queryPerformanceCounter(long* ctr)
122         {
123             asm
124             {
125                 naked                   ;
126                 rdtsc                   ;
127                 mov   [RDI],EAX         ;
128                 mov   4[RDI],EDX        ;
129                 ret                     ;
130             }
131         }
132     }
133 }
134 else
135 {
136     static assert(0);
137 }