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. */ 37static size_t filler_used; 38static size_t filler_length; 39static unsigned char *filler_buffer; 40 41static void 42filler (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 52static void 53fillup_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 64int 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 105void 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(ulong)], *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