1 /* rndw32ce.c - W32CE entropy gatherer
2 * Copyright (C) 2010 Free Software Foundation, Inc.
3 *
4 * Libgcrypt is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as
6 * published by the Free Software Foundation; either version 2.1 of
7 * the License, or (at your option) any later version.
8 *
9 * Libgcrypt is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this program; if not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include <config.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <errno.h>
22 #include <string.h>
23 #include <stdint.h>
24
25 #include <windows.h>
26 #include <wincrypt.h>
27
28 #include "types.h"
29 #include "g10lib.h"
30 #include "rand-internal.h"
31
32
33 /* The Microsoft docs say that it is suggested to see the buffer with
34 some extra random. We do this, despite that it is a questionable
35 suggestion as the OS as better means of collecting entropy than an
36 application. */
37 static size_t filler_used;
38 static size_t filler_length;
39 static unsigned char *filler_buffer;
40
41 static void
filler(const void * data,size_t datalen,enum random_origins dummy)42 filler (const void *data, size_t datalen, enum random_origins dummy)
43 {
44 (void)dummy;
45 if (filler_used + datalen > filler_length)
46 datalen = filler_length - filler_used;
47 memcpy (filler_buffer + filler_used, data, datalen);
48 filler_used += datalen;
49 }
50
51
52 static void
fillup_buffer(unsigned char * buffer,size_t length)53 fillup_buffer (unsigned char *buffer, size_t length)
54 {
55 filler_used = 0;
56 filler_length = length;
57 filler_buffer = buffer;
58
59 while (filler_used < length)
60 _gcry_rndw32ce_gather_random_fast (filler, 0);
61 }
62
63
64 int
_gcry_rndw32ce_gather_random(void (* add)(const void *,size_t,enum random_origins),enum random_origins origin,size_t length,int level)65 _gcry_rndw32ce_gather_random (void (*add)(const void*, size_t,
66 enum random_origins),
67 enum random_origins origin,
68 size_t length, int level )
69 {
70 HCRYPTPROV prov;
71 unsigned char buffer [256];
72 DWORD buflen;
73
74 if (!level)
75 return 0;
76
77 /* Note that LENGTH is not really important because the caller
78 checks the returned lengths and calls this function until it
79 feels that enough entropy has been gathered. */
80
81 buflen = sizeof buffer;
82 if (length+8 < buflen)
83 buflen = length+8; /* Return a bit more than requested. */
84
85 if (!CryptAcquireContext (&prov, NULL, NULL, PROV_RSA_FULL,
86 (CRYPT_VERIFYCONTEXT|CRYPT_SILENT)) )
87 log_debug ("CryptAcquireContext failed: rc=%d\n", (int)GetLastError ());
88 else
89 {
90 fillup_buffer (buffer, buflen);
91 if (!CryptGenRandom (prov, buflen, buffer))
92 log_debug ("CryptGenRandom(%d) failed: rc=%d\n",
93 (int)buflen, (int)GetLastError ());
94 else
95 (*add) (buffer, buflen, origin);
96 CryptReleaseContext (prov, 0);
97 wipememory (buffer, sizeof buffer);
98 }
99
100 return 0;
101 }
102
103
104
105 void
_gcry_rndw32ce_gather_random_fast(void (* add)(const void *,size_t,enum random_origins),enum random_origins origin)106 _gcry_rndw32ce_gather_random_fast (void (*add)(const void*, size_t,
107 enum random_origins),
108 enum random_origins origin)
109 {
110
111 /* Add word sized values. */
112 {
113 # define ADD(t,f) do { \
114 t along = (f); \
115 memcpy (bufptr, &along, sizeof (along)); \
116 bufptr += sizeof (along); \
117 } while (0)
118 unsigned char buffer[20*sizeof(unsigned long)], *bufptr;
119
120 bufptr = buffer;
121 ADD (HWND, GetActiveWindow ());
122 ADD (HWND, GetCapture ());
123 ADD (HWND, GetClipboardOwner ());
124 ADD (HANDLE, GetCurrentProcess ());
125 ADD (DWORD, GetCurrentProcessId ());
126 ADD (HANDLE, GetCurrentThread ());
127 ADD (DWORD, GetCurrentThreadId ());
128 ADD (HWND, GetDesktopWindow ());
129 ADD (HWND, GetFocus ());
130 ADD (DWORD, GetMessagePos ());
131 ADD (HWND, GetOpenClipboardWindow ());
132 ADD (HWND, GetProcessHeap ());
133 ADD (DWORD, GetQueueStatus (QS_ALLEVENTS));
134 ADD (DWORD, GetTickCount ());
135
136 gcry_assert ( bufptr-buffer < sizeof (buffer) );
137 (*add) ( buffer, bufptr-buffer, origin );
138 # undef ADD
139 }
140
141 /* Get multiword system information: Current caret position, current
142 mouse cursor position. */
143 {
144 POINT point;
145
146 GetCaretPos (&point);
147 (*add) ( &point, sizeof (point), origin );
148 GetCursorPos (&point);
149 (*add) ( &point, sizeof (point), origin );
150 }
151
152 /* Get percent of memory in use, bytes of physical memory, bytes of
153 free physical memory, bytes in paging file, free bytes in paging
154 file, user bytes of address space, and free user bytes. */
155 {
156 MEMORYSTATUS memoryStatus;
157
158 memoryStatus.dwLength = sizeof (MEMORYSTATUS);
159 GlobalMemoryStatus (&memoryStatus);
160 (*add) ( &memoryStatus, sizeof (memoryStatus), origin );
161 }
162
163
164 /* Get thread and process creation time, exit time, time in kernel
165 mode, and time in user mode in 100ns intervals. */
166 {
167 HANDLE handle;
168 FILETIME creationTime, exitTime, kernelTime, userTime;
169
170 handle = GetCurrentThread ();
171 GetThreadTimes (handle, &creationTime, &exitTime,
172 &kernelTime, &userTime);
173 (*add) ( &creationTime, sizeof (creationTime), origin );
174 (*add) ( &exitTime, sizeof (exitTime), origin );
175 (*add) ( &kernelTime, sizeof (kernelTime), origin );
176 (*add) ( &userTime, sizeof (userTime), origin );
177
178 handle = GetCurrentThread ();
179 GetThreadTimes (handle, &creationTime, &exitTime,
180 &kernelTime, &userTime);
181 (*add) ( &creationTime, sizeof (creationTime), origin );
182 (*add) ( &exitTime, sizeof (exitTime), origin );
183 (*add) ( &kernelTime, sizeof (kernelTime), origin );
184 (*add) ( &userTime, sizeof (userTime), origin );
185
186 }
187
188
189 /* In case the OEM provides a high precision timer get this. If
190 none is available the default implementation returns the
191 GetTickCount. */
192 {
193 LARGE_INTEGER performanceCount;
194
195 if (QueryPerformanceCounter (&performanceCount))
196 (*add) (&performanceCount, sizeof (performanceCount), origin);
197 }
198
199 }
200