From 12d7d0bbe911aebbbe58ff77184375ce6d9ee45f Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Tue, 23 May 2000 07:08:26 +0000 Subject: [PATCH] See ChangeLog: Tue May 23 09:19:00 CEST 2000 Werner Koch --- TODO | 5 +- cipher/ChangeLog | 4 + cipher/rndw32.c | 567 ++++++++++++++++++++++++++++++++++++++++++++- g10/hkp.c | 6 +- tools/ChangeLog | 4 + tools/ring-a-party | 103 ++++++++ 6 files changed, 683 insertions(+), 6 deletions(-) create mode 100755 tools/ring-a-party diff --git a/TODO b/TODO index fa6d071f6..593e70a51 100644 --- a/TODO +++ b/TODO @@ -10,7 +10,10 @@ * INFO Kommand um z.B. default-recipients herauszufinden. * export sollte exit(1) machen bei einem Fehler - testen! Es wird ein - leerer File erzeugt. + leerer File erzeugt. Nur unter Windows? + + * No TCP support yet for W32? arggg - should go into a separate program + anyway. Scheduled for 1.1 diff --git a/cipher/ChangeLog b/cipher/ChangeLog index 7507454de..35a06e3cb 100644 --- a/cipher/ChangeLog +++ b/cipher/ChangeLog @@ -1,3 +1,7 @@ +Tue May 23 09:19:00 CEST 2000 Werner Koch + + * rndw32.c: Started with alternative code to replace entropy.dll + Thu May 18 11:38:54 CEST 2000 Werner Koch * primegen.c (register_primegen_progress): New. diff --git a/cipher/rndw32.c b/cipher/rndw32.c index 8bef6348f..d6c8e6cd8 100644 --- a/cipher/rndw32.c +++ b/cipher/rndw32.c @@ -1,5 +1,6 @@ -/* rndw32.c - interface to the Winseed DLL - * Copyright (C) 1999 Free Software Foundation, Inc. +/* rndw32.c - W32 entropy gatherer + * Copyright (C) 1999, 2000 Free Software Foundation, Inc. + * Copyright Peter Gutmann, Matt Thomlinson and Blake Coverett 1996-1999 * * This file is part of GnuPG. * @@ -16,6 +17,44 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * The code here is based on code from Cryptlib 3.0 beta by Peter Gutmann. + * Source file misc/rndwin32.c "Win32 Randomness-Gathering Code" with this + * copyright notice: + * + * This module is part of the cryptlib continuously seeded pseudorandom + * number generator. For usage conditions, see lib_rand.c + * + * [Here is the notice from lib_rand.c, which is now called dev_sys.c] + * + * This module and the misc/rnd*.c modules represent the cryptlib + * continuously seeded pseudorandom number generator (CSPRNG) as described in + * my 1998 Usenix Security Symposium paper "The generation of random numbers + * for cryptographic purposes". + * + * The CSPRNG code is copyright Peter Gutmann (and various others) 1996, + * 1997, 1998, 1999, all rights reserved. Redistribution of the CSPRNG + * modules and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice + * and this permission notice in its entirety. + * + * 2. Redistributions in binary form must reproduce the copyright notice in + * the documentation and/or other materials provided with the distribution. + * + * 3. A copy of any bugfixes or enhancements made must be provided to the + * author, to allow them to be added to the + * baseline version of the code. + * + * ALTERNATIVELY, the code may be distributed under the terms of the GNU + * General Public License, version 2 or any later version published by the + * Free Software Foundation, in which case the provisions of the GNU GPL are + * required INSTEAD OF the above restrictions. + * + * Although not required under the terms of the GPL, it would still be nice if + * you could make any changes available to the author to allow a consistent + * code base to be maintained */ #include @@ -27,10 +66,30 @@ #include +/* We need to define these types and constants: +`HEAPENTRY32' +`HEAPLIST32' +`IOCTL_DISK_PERFORMANCE' +`LPHEAPLIST32' +`LPMODULEENTRY32' +`LPPROCESSENTRY32' +`LPTHREADENTRY32' +`MODULEENTRY32' +`PPERF_DATA_BLOCK' +`PROCESSENTRY32' +`RESOURCE_DATA' +`TH32CS_SNAPALL' +`THREADENTRY32' +`VER_PLATFORM_WIN32_WINDOWS' +*/ + #include "types.h" #include "util.h" #include "dynload.h" +#define USE_ENTROPY_DLL + + #ifdef IS_MODULE #define _(a) (a) @@ -39,6 +98,8 @@ #endif +#ifdef USE_ENTROPY_DLL + #define WIN32_SLOW_SEEDER 0 #define WIN32_FAST_SEEDER 1 @@ -89,7 +150,7 @@ static size_t entropy_buffer_size; static void load_and_init_winseed( void ) { - int hInstance; + HANDLE hInstance; void *addr; unsigned int reason = 0; unsigned int n1, n2; @@ -173,7 +234,7 @@ gather_random( void (*add)(const void*, size_t, int), int requester, /* Our estimation on how much entropy we should use is very vague. * Winseed delivers some amount of entropy on each slow poll and * we add it to our random pool. Depending on the required quality - * level we adjust the requested length so that for higer quality + * level we adjust the requested length so that for higher quality * we make sure to add more entropy to our pool. However, as we don't * like to waste any entropy collected by winseed, we always add * at least everything we got from winseed. @@ -241,6 +302,504 @@ gather_random_fast( void (*add)(const void*, size_t, int), int requester ) return 0; } +#else /* !USE_ENTROPY_DLL */ +/* This is the new code which does not require the entropy.dll */ + +/* Type definitions for function pointers to call Toolhelp32 functions + * used with the windows95 gatherer */ +typedef BOOL (WINAPI * MODULEWALK) (HANDLE hSnapshot, LPMODULEENTRY32 lpme); +typedef BOOL (WINAPI * THREADWALK) (HANDLE hSnapshot, LPTHREADENTRY32 lpte); +typedef BOOL (WINAPI * PROCESSWALK) (HANDLE hSnapshot, LPPROCESSENTRY32 lppe); +typedef BOOL (WINAPI * HEAPLISTWALK) (HANDLE hSnapshot, LPHEAPLIST32 lphl); +typedef BOOL (WINAPI * HEAPFIRST) (LPHEAPENTRY32 lphe, DWORD th32ProcessID, + DWORD th32HeapID); +typedef BOOL (WINAPI * HEAPNEXT) (LPHEAPENTRY32 lphe); +typedef HANDLE (WINAPI * CREATESNAPSHOT) (DWORD dwFlags, DWORD th32ProcessID); + +static void +slow_gatherer_windows95( void (*add)(const void*, size_t, int), int requester ) +{ + static CREATESNAPSHOT pCreateToolhelp32Snapshot = NULL; + static MODULEWALK pModule32First = NULL; + static MODULEWALK pModule32Next = NULL; + static PROCESSWALK pProcess32First = NULL; + static PROCESSWALK pProcess32Next = NULL; + static THREADWALK pThread32First = NULL; + static THREADWALK pThread32Next = NULL; + static HEAPLISTWALK pHeap32ListFirst = NULL; + static HEAPLISTWALK pHeap32ListNext = NULL; + static HEAPFIRST pHeap32First = NULL; + static HEAPNEXT pHeap32Next = NULL; + HANDLE hSnapshot; + + + /* initialize the Toolhelp32 function pointers */ + if ( !pCreateToolhelp32Snapshot ) { + HANDLE hKernel; + + /* Obtain the module handle of the kernel to retrieve the addresses + * of the Toolhelp32 functions */ + if ( ( !(hKernel = GetModuleHandle ("KERNEL32.DLL"))) ) { + g10_log_fatal ( "rndw32: can't get module handle\n" ); + } + + /* Now get pointers to the functions */ + pCreateToolhelp32Snapshot = (CREATESNAPSHOT) GetProcAddress (hKernel, + "CreateToolhelp32Snapshot"); + pModule32First = (MODULEWALK) GetProcAddress (hKernel, "Module32First"); + pModule32Next = (MODULEWALK) GetProcAddress (hKernel, "Module32Next"); + pProcess32First = (PROCESSWALK) GetProcAddress (hKernel, + "Process32First"); + pProcess32Next = (PROCESSWALK) GetProcAddress (hKernel, + "Process32Next"); + pThread32First = (THREADWALK) GetProcAddress (hKernel, "Thread32First"); + pThread32Next = (THREADWALK) GetProcAddress (hKernel, "Thread32Next"); + pHeap32ListFirst = (HEAPLISTWALK) GetProcAddress (hKernel, + "Heap32ListFirst"); + pHeap32ListNext = (HEAPLISTWALK) GetProcAddress (hKernel, + "Heap32ListNext"); + pHeap32First = (HEAPFIRST) GetProcAddress (hKernel, "Heap32First"); + pHeap32Next = (HEAPNEXT) GetProcAddress (hKernel, "Heap32Next"); + + if ( !pCreateToolhelp32Snapshot + || !pModule32First || !pModule32Next + || !pProcess32First || !pProcess32Next + || !pThread32First || !pThread32Next + || !pHeap32ListFirst || !pHeap32ListNext + || !pHeap32First || !pHeap32Next ) { + g10_log_fatal ( "rndw32: failed to get a toolhep function\n" ); + } + } + + /* Take a snapshot of everything we can get to which is currently + * in the system */ + if ( !(hSnapshot = pCreateToolhelp32Snapshot (TH32CS_SNAPALL, 0)) ) { + g10_log_fatal ( "rndw32: failed to take a toolhelp snapshot\n" ); + } + + /* Walk through the local heap */ + { HEAPLIST32 hl32; + hl32.dwSize = sizeof (HEAPLIST32); + if (pHeap32ListFirst (hSnapshot, &hl32)) { + do { + HEAPENTRY32 he32; + + /* First add the information from the basic Heaplist32 struct */ + (*add) ( &hl32, sizeof (hl32), requester ); + + /* Now walk through the heap blocks getting information + * on each of them */ + he32.dwSize = sizeof (HEAPENTRY32); + if (pHeap32First (&he32, hl32.th32ProcessID, hl32.th32HeapID)){ + do { + (*add) ( &he32, sizeof (he32), requester ); + } while (pHeap32Next (&he32)); + } + } while (pHeap32ListNext (hSnapshot, &hl32)); + } + } + + + /* Walk through all processes */ + { PROCESSENTRY32 pe32; + pe32.dwSize = sizeof (PROCESSENTRY32); + if (pProcess32First (hSnapshot, &pe32)) { + do { + (*add) ( &pe32, sizeof (pe32), requester ); + } while (pProcess32Next (hSnapshot, &pe32)); + } + } + + /* Walk through all threads */ + { THREADENTRY32 te32; + te32.dwSize = sizeof (THREADENTRY32); + if (pThread32First (hSnapshot, &te32)) { + do { + (*add) ( &te32, sizeof (te32), requester ); + } while (pThread32Next (hSnapshot, &te32)); + } + } + + /* Walk through all modules associated with the process */ + { MODULEENTRY32 me32; + me32.dwSize = sizeof (MODULEENTRY32); + if (pModule32First (hSnapshot, &me32)) { + do { + (*add) ( &me32, sizeof (me32), requester ); + } while (pModule32Next (hSnapshot, &me32)); + } + } + + CloseHandle (hSnapshot); +} + + +/* Type definitions for function pointers to call NetAPI32 functions */ +typedef DWORD (WINAPI * NETSTATISTICSGET) (LPWSTR szServer, LPWSTR szService, + DWORD dwLevel, DWORD dwOptions, + LPBYTE * lpBuffer); +typedef DWORD (WINAPI * NETAPIBUFFERSIZE) (LPVOID lpBuffer, LPDWORD cbBuffer); +typedef DWORD (WINAPI * NETAPIBUFFERFREE) (LPVOID lpBuffer); + +/* When we query the performance counters, we allocate an initial buffer and + * then reallocate it as required until RegQueryValueEx() stops returning + * ERROR_MORE_DATA. The following values define the initial buffer size and + * step size by which the buffer is increased + */ +#define PERFORMANCE_BUFFER_SIZE 65536 /* Start at 64K */ +#define PERFORMANCE_BUFFER_STEP 16384 /* Step by 16K */ + +static void +slow_gatherer_windowsNT( void (*add)(const void*, size_t, int), int requester ) +{ + static int is_initialized = 0; + static NETSTATISTICSGET pNetStatisticsGet = NULL; + static NETAPIBUFFERSIZE pNetApiBufferSize = NULL; + static NETAPIBUFFERFREE pNetApiBufferFree = NULL; + static int is_workstation = 1; + + static int cbPerfData = PERFORMANCE_BUFFER_SIZE; + RESOURCE_DATA msgData; + PPERF_DATA_BLOCK pPerfData; + HANDLE hDevice; + DWORD dwSize, status; + int nDrive; + + if ( !is_initialized ) { + HKEY hKey; + + /* Find out whether this is an NT server or workstation if necessary */ + if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, + "SYSTEM\\CurrentControlSet\\Control\\ProductOptions", + 0, KEY_READ, &hKey) == ERROR_SUCCESS) { + BYTE szValue[32]; + dwSize = sizeof (szValue); + + status = RegQueryValueEx (hKey, "ProductType", 0, NULL, + szValue, &dwSize); + if (status == ERROR_SUCCESS && stricmp (szValue, "WinNT")) { + /* Note: There are (at least) three cases for ProductType: + * WinNT = NT Workstation, ServerNT = NT Server, LanmanNT = + * NT Server acting as a Domain Controller */ + is_workstation = 0; + g10_log_debug ("rndw32: this is a NT server\n"); + } + RegCloseKey (hKey); + } + + /* Initialize the NetAPI32 function pointers if necessary */ + if ( (hNetAPI32 = LoadLibrary ("NETAPI32.DLL")) ) { + pNetStatisticsGet = (NETSTATISTICSGET) GetProcAddress (hNetAPI32, + "NetStatisticsGet"); + pNetApiBufferSize = (NETAPIBUFFERSIZE) GetProcAddress (hNetAPI32, + "NetApiBufferSize"); + pNetApiBufferFree = (NETAPIBUFFERFREE) GetProcAddress (hNetAPI32, + "NetApiBufferFree"); + + if ( !pNetStatisticsGet + || !pNetApiBufferSize || !pNetApiBufferFree ) { + FreeLibrary (hNetAPI32); + hNetAPI32 = NULL; + g10_log_debug ("rndw32: No NETAPI found\n" ); + } + } + + is_initialized = 1; + } + + /* Get network statistics. Note: Both NT Workstation and NT Server by + * default will be running both the workstation and server services. The + * heuristic below is probably useful though on the assumption that the + * majority of the network traffic will be via the appropriate service. + * In any case the network statistics return almost no randomness */ + { LPBYTE lpBuffer; + if (hNetAPI32 && !pNetStatisticsGet (NULL, + is_workstation ? L"LanmanWorkstation" : + L"LanmanServer", 0, 0, &lpBuffer) ) { + pNetApiBufferSize (lpBuffer, &dwSize); + (*add) ( lpBuffer, dwSize,requester ); + pNetApiBufferFree (lpBuffer); + } + } + + /* Get disk I/O statistics for all the hard drives */ + for (nDrive = 0;; nDrive++) { + DISK_PERFORMANCE diskPerformance; + char szDevice[50]; + + /* Check whether we can access this device */ + sprintf (szDevice, "\\\\.\\PhysicalDrive%d", nDrive); + hDevice = CreateFile (szDevice, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, 0, NULL); + if (hDevice == INVALID_HANDLE_VALUE) + break; + + /* Note: This only works if you have turned on the disk performance + * counters with 'diskperf -y'. These counters are off by default */ + if (DeviceIoControl (hDevice, IOCTL_DISK_PERFORMANCE, NULL, 0, + &diskPerformance, sizeof (DISK_PERFORMANCE), + &dwSize, NULL)) + { + (*add) ( &diskPerformance, dwSize); + } + CloseHandle (hDevice); + } + + #if 0 /* we don't need this in GnuPG */ + /* Wait for any async keyset driver binding to complete. You may be + * wondering what this call is doing here... the reason it's necessary is + * because RegQueryValueEx() will hang indefinitely if the async driver + * bind is in progress. The problem occurs in the dynamic loading and + * linking of driver DLL's, which work as follows: + * + * hDriver = LoadLibrary( DRIVERNAME ); + * pFunction1 = ( TYPE_FUNC1 ) GetProcAddress( hDriver, NAME_FUNC1 ); + * pFunction2 = ( TYPE_FUNC1 ) GetProcAddress( hDriver, NAME_FUNC2 ); + * + * If RegQueryValueEx() is called while the GetProcAddress()'s are in + * progress, it will hang indefinitely. This is probably due to some + * synchronisation problem in the NT kernel where the GetProcAddress() + * calls affect something like a module reference count or function + * reference count while RegQueryValueEx() is trying to take a snapshot + * of the statistics, which include the reference counts. Because of + * this, we have to wait until any async driver bind has completed + * before we can call RegQueryValueEx() */ + waitSemaphore (SEMAPHORE_DRIVERBIND); + #endif + + /* Get information from the system performance counters. This can take + * a few seconds to do. In some environments the call to + * RegQueryValueEx() can produce an access violation at some random time + * in the future, adding a short delay after the following code block + * makes the problem go away. This problem is extremely difficult to + * reproduce, I haven't been able to get it to occur despite running it + * on a number of machines. The best explanation for the problem is that + * on the machine where it did occur, it was caused by an external driver + * or other program which adds its own values under the + * HKEY_PERFORMANCE_DATA key. The NT kernel calls the required external + * modules to map in the data, if there's a synchronisation problem the + * external module would write its data at an inappropriate moment, + * causing the access violation. A low-level memory checker indicated + * that ExpandEnvironmentStrings() in KERNEL32.DLL, called an + * interminable number of calls down inside RegQueryValueEx(), was + * overwriting memory (it wrote twice the allocated size of a buffer to a + * buffer allocated by the NT kernel). This may be what's causing the + * problem, but since it's in the kernel there isn't much which can be + * done. + * + * In addition to these problems the code in RegQueryValueEx() which + * estimates the amount of memory required to return the performance + * counter information isn't very accurate, since it always returns a + * worst-case estimate which is usually nowhere near the actual amount + * required. For example it may report that 128K of memory is required, + * but only return 64K of data */ + { pPerfData = m_alloc (cbPerfData); + for (;;) { + dwSize = cbPerfData; + status = RegQueryValueEx (HKEY_PERFORMANCE_DATA, "Global", NULL, + NULL, (LPBYTE) pPerfData, &dwSize); + if (status == ERROR_SUCCESS) { + if (!memcmp (pPerfData->Signature, L"PERF", 8)) { + (*add) ( pPerfData, dwSize, requester ); + } + else + g10_log_debug ( "rndw32: no PERF signature\n"); + break; + } + else if (status == ERROR_MORE_DATA) { + cbPerfData += PERFORMANCE_BUFFER_STEP; + pPerfData = m_realloc (pPerfData, cbPerfData); + } + else { + g10_log_debug ( "rndw32: get performance data problem\n"); + break; + } + } + m_free (cbPerfData); + } + /* Although this isn't documented in the Win32 API docs, it's necessary + to explicitly close the HKEY_PERFORMANCE_DATA key after use (it's + implicitly opened on the first call to RegQueryValueEx()). If this + isn't done then any system components which provide performance data + can't be removed or changed while the handle remains active */ + RegCloseKey (HKEY_PERFORMANCE_DATA); +} + + +static int +gather_random( void (*add)(const void*, size_t, int), int requester, + size_t length, int level ) +{ + static int is_initialized; + static int is_windows95; + + + if( !level ) + return 0; + /* We don't differentiate between level 1 and 2 here because + * there is no nternal entropy pool as ascary resource. It may + * all work slower, but because our entropy source will never + * block but deliver some not easy to measure entropy, we assume level 2 + */ + + if ( !is_initialized ) { + OSVERSIONINFO osvi = { sizeof( osvi ) }; + DWORD platform; + + GetVersionEx( &osvi ); + platform = osvi.dwPlatformId; + is_windows95 = platform == VER_PLATFORM_WIN32_WINDOWS; + + if ( platform == VER_PLATFORM_WIN32s ) { + g10_log_fatal("can't run on a W32s platform\n" ); + } + is_initialized = 1; + } + + + if (is_windows95 ) { + slow_gatherer_windows95( add, requester ); + } + else { + slow_gatherer_windowsNT( add, requester ); + } + + return 0; +} + + + +static int +gather_random_fast( void (*add)(const void*, size_t, int), int requester ) +{ + static int addedFixedItems = 0; + + /* Get various basic pieces of system information: Handle of active + * window, handle of window with mouse capture, handle of clipboard owner + * handle of start of clpboard viewer list, pseudohandle of current + * process, current process ID, pseudohandle of current thread, current + * thread ID, handle of desktop window, handle of window with keyboard + * focus, whether system queue has any events, cursor position for last + * message, 1 ms time for last message, handle of window with clipboard + * open, handle of process heap, handle of procs window station, types of + * events in input queue, and milliseconds since Windows was started */ + { byte buffer[20*sizeof(ulong)], *bufptr; + bufptr = buffer; + #define ADD(f) do { ulong along = (ulong)(f); \ + memcpy (bufptr, &along, sizeof (along) ); \ + bufptr += sizeof (along); } while (0) + ADD ( GetActiveWindow ()); + ADD ( GetCapture ()); + ADD ( GetClipboardOwner ()); + ADD ( GetClipboardViewer ()); + ADD ( GetCurrentProcess ()); + ADD ( GetCurrentProcessId ()); + ADD ( GetCurrentThread ()); + ADD ( GetCurrentThreadId ()); + ADD ( GetDesktopWindow ()); + ADD ( GetFocus ()); + ADD ( GetInputState ()); + ADD ( GetMessagePos ()); + ADD ( GetMessageTime ()); + ADD ( GetOpenClipboardWindow ()); + ADD ( GetProcessHeap ()); + ADD ( GetProcessWindowStation ()); + ADD ( GetQueueStatus (QS_ALLEVENTS)); + ADD ( GetTickCount ()); + + assert ( bufptr-buffer < sizeof (buffer) ); + (*add) ( buffer, bufptr-buffer, requester ); + #undef ADD + } + + /* Get multiword system information: Current caret position, current + * mouse cursor position */ + { POINT point; + GetCaretPos (&point); + (*add) ( &point, sizeof (point), requester ); + GetCursorPos (&point); + (*add) ( &point, sizeof (point), requester ); + } + + /* Get percent of memory in use, bytes of physical memory, bytes of free + * physical memory, bytes in paging file, free bytes in paging file, user + * bytes of address space, and free user bytes */ + { MEMORYSTATUS memoryStatus; + memoryStatus.dwLength = sizeof (MEMORYSTATUS); + GlobalMemoryStatus (&memoryStatus); + (*add) ( &memoryStatus, sizeof (memoryStatus), requester ); + } + + /* Get thread and process creation time, exit time, time in kernel mode, + and time in user mode in 100ns intervals */ + { HANDLE handle; + FILETIME creationTime, exitTime, kernelTime, userTime; + + handle = GetCurrentThread (); + GetThreadTimes (handle, &creationTime, &exitTime, + &kernelTime, &userTime); + (*add) ( &creationTime, sizeof (creationTime), requester ); + (*add) ( &exitTime, sizeof (exitTime), requester ); + (*add) ( &kernelTime, sizeof (kernelTime), requester ); + (*add) ( &userTime, sizeof (userTime), requester ); + + handle = GetCurrentProcess (); + GetProcessTimes (handle, &creationTime, &exitTime, + &kernelTime, &userTime); + (*add) ( &creationTime, sizeof (creationTime), requester ); + (*add) ( &exitTime, sizeof (exitTime), requester ); + (*add) ( &kernelTime, sizeof (kernelTime), requester ); + (*add) ( &userTime, sizeof (userTime), requester ); + } + + /* Get the minimum and maximum working set size for the current process */ + { DWORD minimumWorkingSetSize, maximumWorkingSetSize; + GetProcessWorkingSetSize (handle, &minimumWorkingSetSize, + &maximumWorkingSetSize); + (*add) ( &minimumWorkingSetSize, + sizeof (&minimumWorkingSetSize), requester ); + (*add) ( &maximumWorkingSetSize, + sizeof (&maximumWorkingSetSize), requester ); + } + + /* The following are fixed for the lifetime of the process so we only + * add them once */ + if (!addedFixedItems) { + STARTUPINFO startupInfo; + + /* Get name of desktop, console window title, new window position and + * size, window flags, and handles for stdin, stdout, and stderr */ + startupInfo.cb = sizeof (STARTUPINFO); + GetStartupInfo (&startupInfo); + (*add) ( &startupInfo, sizeof (STARTUPINFO), requester ); + addedFixedItems = 1; + } + + /* The performance of QPC varies depending on the architecture it's + * running on and on the OS. Under NT it reads the CPU's 64-bit timestamp + * counter (at least on a Pentium and newer '486's, it hasn't been tested + * on anything without a TSC), under Win95 it reads the 1.193180 MHz PIC + * timer. There are vague mumblings in the docs that it may fail if the + * appropriate hardware isn't available (possibly '386's or MIPS machines + * running NT), but who's going to run NT on a '386? */ + { LARGE_INTEGER performanceCount; + if (QueryPerformanceCounter (&performanceCount)) { + (*add) (&performanceCount, sizeof (&performanceCount), requester); + } + else { /* Millisecond accuracy at best... */ + DWORD aword = GetTickCount (); + (*add) (&aword, soeof (aword), requester ); + } + } + + return 0; +} + + + + + +#endif /* !USE_ENTROPY_DLL */ #ifndef IS_MODULE diff --git a/g10/hkp.c b/g10/hkp.c index 7950cc54b..3b1b2cea3 100644 --- a/g10/hkp.c +++ b/g10/hkp.c @@ -63,7 +63,11 @@ hkp_ask_import( u32 *keyid ) opt.keyserver_name ); request = m_alloc( strlen( opt.keyserver_name ) + 100 ); /* hkp does not accept the long keyid - we should really write a - * nicer one */ + * nicer one :-) + * FIXME: request binary mode - need to pass no_armor mode + * down to the import function. Marc told that there is such a + * binary mode ... how? + */ sprintf( request, "x-hkp://%s:11371/pks/lookup?op=get&search=0x%08lX", opt.keyserver_name, (ulong)keyid[1] ); rc = http_open_document( &hd, request, hflags ); diff --git a/tools/ChangeLog b/tools/ChangeLog index f3b32eac0..e936bfcd9 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,7 @@ +Tue May 23 09:19:00 CEST 2000 Werner Koch + + * ring-a-party: New. + Thu Jul 8 16:21:27 CEST 1999 Werner Koch diff --git a/tools/ring-a-party b/tools/ring-a-party new file mode 100755 index 000000000..561b51336 --- /dev/null +++ b/tools/ring-a-party @@ -0,0 +1,103 @@ +#!/bin/sh +# ring-a-party - print a keyring suitable for a key signing party + +if [ $# -lt 1 ]; then + echo "usage: ring-a-party keyring [headerline]" >&2 + exit 1 +fi + +keyring="$1" +hdrline="$1" +if [ $# -gt 1 ]; then + hdrline="$2" +fi + +if [ ! -f $keyring ]; then + echo "ring-a-party: '$keyring': no such file" >&2 + exit 1 +fi + +echo "ring-a-party: output will be written to 'a.pub'" >&2 + + +gpg --dry-run --with-fingerprint --with-colons $keyring \ + | gawk -v "KEYRING=$hdrline" ' +BEGIN { FS=":" + algos[1] = "RSA"; + algos[16] = "ElGamal"; + algos[17] = "DSA"; + any = 0; + lines = -1; + page = 0; + now = strftime("%b %d %H:%M %Y"); + } +$1 == "pub" { + if( any ) myflush(); + uidcount = 0; + signencrypt = 0; + uids[uidcount++] = $10; + nbits = $3; + keyid = substr($5,9); + created = $6; + expires = $7; + algostr = mapalgo($4); + if( $4 == 20 || $4 == 1 ) signencrypt = 1; + any = 1; + } +$1 == "fpr" { fpr = $10 } +$1 == "uid" { uids[uidcount++] = $10 } +$1 == "sub" { if( $4 != 17 && $4 != 3 ) signencrypt=1 } + +function myflush() +{ + # fixme: take lines to print here into account + if( lines > 50 || lines == -1 ) { + if( lines != -1 ) printf "\f"; + page++; + printf "%s %-50.50s Page %d\n\n", now, KEYRING, page ; + printf "Type Bits KeyID Created Expires Algorithm Use\n"; + lines = 1; + } + printf "pub %04d 0x%s %10s %10s %-10s %15s\n", + nbits, keyid, created, expires == ""? "----------":expires, algostr, + signencrypt == 1? "Sign & Encrypt":"Sign only"; + length(fpr) == 40 ? printfpr20( fpr ) : printfpr16( fpr ); + lnes += 2; + for( i=0; i < uidcount; i++ ) { + printf "uid %s\n", uids[i]; + lines++; + } + printf "\n\n"; + lines += 2; +} + +function mapalgo( no ) +{ + if( no in algos ) + return algos[no]; + return sprintf( "algoID=%ds", no ); +} + + +function printfpr16( s ) +{ + printf "f16 Fingerprint16 ="; + for(i=0; i < 16; i++ ) { + if( i == 8 ) printf " "; + printf " %s", substr( s, i*2, 2 ); + } + printf "\n" +} + +function printfpr20( s ) +{ + printf "f20 Fingerprint20 ="; + for(i=0; i < 10; i++ ) { + if( i == 5 ) printf " "; + printf " %s", substr( s, i*4, 4 ); + } + printf "\n" +} + +' | tee a.pub | gpg --print-mds +