[PATCH] Add OS/2 entropy gatherer
KO Myung-Hun
komh78 at gmail.com
Fri Mar 9 14:08:05 CET 2012
---
configure.ac | 20 ++++
doc/Makefile.am | 6 +-
random/rand-internal.h | 6 +
random/random-csprng.c | 5 +
random/rndos2.c | 252 ++++++++++++++++++++++++++++++++++++++++++++++++
src/hmac256.c | 9 +-
tests/fipsdrv.c | 4 +
7 files changed, 296 insertions(+), 6 deletions(-)
create mode 100644 random/rndos2.c
diff --git a/configure.ac b/configure.ac
index cf4a082..1f0c27a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -197,6 +197,7 @@ LIBGCRYPT_THREAD_MODULES=""
print_egd_notice=no
have_w32_system=no
have_w32ce_system=no
+have_os2_system=no
have_pthread=no
@@ -227,8 +228,10 @@ case "${host}" in
i?86-emx-os2 | i?86-*-os2*emx)
# OS/2 with the EMX environment
ac_cv_have_dev_random=no
+ have_os2_system=yes
AC_DEFINE(HAVE_DRIVE_LETTERS)
AC_DEFINE(HAVE_DOSISH_SYSTEM)
+ LDFLAGS="$LDFLAGS -no-undefined -Zbin-files"
;;
i?86-*-msdosdjgpp*)
@@ -271,6 +274,11 @@ fi
AM_CONDITIONAL(HAVE_W32_SYSTEM, test "$have_w32_system" = yes)
AM_CONDITIONAL(HAVE_W32CE_SYSTEM, test "$have_w32ce_system" = yes)
+if test "$have_os2_system" = yes; then
+ AC_DEFINE(HAVE_OS2_SYSTEM,1, [Defined if we run on an OS/2 API based system])
+fi
+AM_CONDITIONAL(HAVE_OS2_SYSTEM, test "$have_os2_system" = yes)
+
# A printable OS Name is sometimes useful.
@@ -882,6 +890,11 @@ if test "$random" = "default"; then
# Windows random device.
random_modules="w32"
;;
+
+ *-emx-os2 | *-*-os2*emx)
+ # OS/2 random device.
+ random_modules="os2"
+ ;;
*)
# Build everything, allow to select at runtime.
random_modules="$auto_random_modules"
@@ -1190,6 +1203,13 @@ if test "$found" = "1" ; then
[Defined if the WindowsCE specific RNG should be used.])
fi
+LIST_MEMBER(os2, $random_modules)
+if test "$found" = "1" ; then
+ GCRYPT_RANDOM="$GCRYPT_RANDOM rndos2.lo"
+ AC_DEFINE(USE_RNDOS2, 1,
+ [Defined if the OS/2 specific RNG should be used.])
+fi
+
AC_SUBST([GCRYPT_CIPHERS])
AC_SUBST([GCRYPT_PUBKEY_CIPHERS])
AC_SUBST([GCRYPT_DIGESTS])
diff --git a/doc/Makefile.am b/doc/Makefile.am
index a6bd2ae..451d42f 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -24,7 +24,7 @@ EXTRA_DIST = README.apichanges HACKING \
yat2m.c
DISTCLEANFILES = gcrypt.cps yat2m-stamp.tmp yat2m-stamp $(myman_pages)
-CLEANFILES = yat2m
+CLEANFILES = yat2m$(EXEEXT)
BUILT_SOURCES = libgcrypt-modules.eps fips-fsm.eps \
libgcrypt-modules.png fips-fsm.png \
@@ -41,7 +41,7 @@ myman_pages = hmac256.1
man_MANS = $(myman_pages)
-yat2m: yat2m.c
+yat2m$(EXEEXT): yat2m.c
$(CC_FOR_BUILD) -o $@ $(srcdir)/yat2m.c
.fig.png:
@@ -64,7 +64,7 @@ yat2m-stamp: $(myman_sources)
`test -f '$$file' || echo '$(srcdir)/'`$$file ; done
@mv -f yat2m-stamp.tmp $@
-yat2m-stamp: yat2m
+yat2m-stamp: yat2m$(EXEEXT)
$(myman_pages) : yat2m-stamp
@if test -f $@; then :; else \
diff --git a/random/rand-internal.h b/random/rand-internal.h
index a04a2d4..5b2b3be 100644
--- a/random/rand-internal.h
+++ b/random/rand-internal.h
@@ -132,6 +132,12 @@ void _gcry_rndw32ce_gather_random_fast (void (*add)(const void*, size_t,
enum random_origins),
enum random_origins origin );
+/*-- rndos2.c --*/
+int _gcry_rndos2_gather_random (void (*add) (const void *, size_t,
+ enum random_origins),
+ enum random_origins origin,
+ size_t length, int level);
+
/*-- rndhw.c --*/
int _gcry_rndhw_failed_p (void);
void _gcry_rndhw_poll_fast (void (*add)(const void*, size_t,
diff --git a/random/random-csprng.c b/random/random-csprng.c
index 50357d1..e22d873 100644
--- a/random/random-csprng.c
+++ b/random/random-csprng.c
@@ -1151,6 +1151,11 @@ getfnc_gather_random (void))(void (*)(const void*, size_t,
return fnc;
#endif
+#if USE_RNDOS2
+ fnc = _gcry_rndos2_gather_random;
+ return fnc;
+#endif
+
log_fatal (_("no entropy gathering module detected\n"));
return NULL; /*NOTREACHED*/
diff --git a/random/rndos2.c b/random/rndos2.c
new file mode 100644
index 0000000..4e1589f
--- /dev/null
+++ b/random/rndos2.c
@@ -0,0 +1,252 @@
+/* rndos2.c - OS/2 entropy gatherer
+ * Copyright (C) 2012 KO Myung-Hun <komh at chollian.net>
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#define INCL_DOS
+#define INCL_DOSERRORS
+#include <os2.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sys/ioctl.h>
+#include <net/if.h>
+
+#include "types.h"
+#include "g10lib.h"
+#include "rand-internal.h"
+
+#define ADD( buf, bufsize, origin, remain ) \
+ do { \
+ int n = ( bufsize ) < ( remain ) ? ( bufsize ) : ( remain ); \
+ add( buf, n, origin ); \
+ ( remain ) -= n; \
+ } while( 0 )
+
+#define BUF_SIZE_REQUESTER ( sizeof( unsigned long ) * 30 )
+#define BUF_SIZE_SERVER ( sizeof( unsigned long ) * 17 )
+#define BUF_SIZE_IFMIB ( sizeof( struct ifmib ))
+#define BUF_SIZE_CPUUTIL ( sizeof( ULONG ) * 8 )
+#define BUF_SIZE_SYS_STATE ( 64 * 1024 )
+#define BUF_SIZE_SYS_STATE_DELTA 4096
+#define BUF_SIZE_SYS_STATE_MARGIN 1024
+
+static HMODULE hmodNetApi32;
+static HMODULE hmodTcpIp32;
+static HMODULE hmodDosCalls;
+
+static unsigned APIENTRY ( *pfnNet32StatisticsGet2 )(
+ const unsigned char *, const unsigned char *,
+ unsigned long, unsigned long, unsigned long,
+ unsigned char *, unsigned long,
+ unsigned long * );
+
+static int _System ( *pfnsocket )( int, int, int );
+static int _System ( *pfnos2_ioctl )( int, unsigned long, char *, int );
+static int _System ( *pfnsoclose )( int );
+
+static APIRET APIENTRY ( *pfnDosPerfSysCall )( ULONG, ULONG, ULONG, ULONG );
+static APIRET APIENTRY ( *pfnDosQuerySysState )( ULONG, ULONG, PID, TID, PVOID,
+ ULONG );
+
+int
+_gcry_rndos2_gather_random( void ( *add )( const void *, size_t,
+ enum random_origins ),
+ enum random_origins origin, size_t length,
+ int level )
+{
+ static BOOL fInit = FALSE;
+ static ULONG ulCpuCount = 1;
+
+ unsigned char *buf;
+ ULONG rc;
+
+ if( !level )
+ return 0;
+
+ /* We never block, assume level 2. */
+
+ if( !fInit )
+ {
+ CHAR szFail[ 260 ];
+
+ hmodNetApi32 = NULLHANDLE;
+ if( !DosLoadModule( szFail, sizeof( szFail ), "netapi32",
+ &hmodNetApi32 ))
+ {
+ if( DosQueryProcAddr( hmodNetApi32, 125, NULL,
+ ( PFN * )&pfnNet32StatisticsGet2 ))
+ {
+ DosFreeModule( hmodNetApi32 );
+
+ hmodNetApi32 = NULLHANDLE;
+ }
+ }
+
+ hmodTcpIp32 = NULLHANDLE;
+ if( !DosLoadModule( szFail, sizeof( szFail ), "tcpip32",
+ &hmodTcpIp32 ))
+ {
+ rc = DosQueryProcAddr( hmodTcpIp32, 16, NULL,
+ ( PFN * )&pfnsocket );
+
+ if( !rc )
+ rc = DosQueryProcAddr( hmodTcpIp32, 17, NULL,
+ ( PFN * )&pfnsoclose );
+
+ if( !rc )
+ rc = DosQueryProcAddr( hmodTcpIp32, 200, NULL,
+ ( PFN * )&pfnos2_ioctl );
+
+ if( rc )
+ {
+ DosFreeModule( hmodTcpIp32 );
+
+ hmodTcpIp32 = NULLHANDLE;
+ }
+ }
+
+ hmodDosCalls = NULLHANDLE;
+ if( !DosLoadModule( szFail, sizeof( szFail ), "doscalls",
+ &hmodDosCalls ))
+ {
+ if( DosQueryProcAddr( hmodDosCalls, 976, NULL,
+ ( PFN * )&pfnDosPerfSysCall ))
+ pfnDosPerfSysCall = NULL;
+ else
+ /* Query CPU count */
+ pfnDosPerfSysCall( 0x41, 0, ( ULONG )&ulCpuCount, 0 );
+
+ if( DosQueryProcAddr( hmodDosCalls, 368, NULL,
+ ( PFN * )&pfnDosQuerySysState ))
+ pfnDosQuerySysState = NULL;
+
+ if( !pfnDosPerfSysCall && !pfnDosQuerySysState )
+ {
+ DosFreeModule( hmodDosCalls );
+
+ hmodDosCalls = NULLHANDLE;
+ }
+ }
+
+ fInit = TRUE;
+ }
+
+ while( length )
+ {
+ if( hmodNetApi32 )
+ {
+ ULONG ulAvail;
+
+ buf = gcry_xmalloc( BUF_SIZE_REQUESTER );
+
+ if( !pfnNet32StatisticsGet2( NULL, "REQUESTER", 0, 0, 1, buf,
+ BUF_SIZE_REQUESTER, &ulAvail ))
+ ADD( buf, BUF_SIZE_REQUESTER, origin, length );
+
+ gcry_free( buf );
+
+ buf = gcry_xmalloc( BUF_SIZE_SERVER );
+
+ if( !pfnNet32StatisticsGet2( NULL, "SERVER", 0, 0, 1, buf,
+ BUF_SIZE_SERVER, &ulAvail ))
+ ADD( buf, BUF_SIZE_SERVER, origin, length );
+
+ gcry_free( buf );
+ }
+
+ if( hmodTcpIp32 )
+ {
+ int s;
+
+ s = pfnsocket( PF_INET, SOCK_RAW, 0 );
+
+ if( s != -1 )
+ {
+ buf = gcry_xmalloc( BUF_SIZE_IFMIB );
+
+ if( !pfnos2_ioctl( s, SIOSTATIF, ( caddr_t )buf,
+ BUF_SIZE_IFMIB ))
+ ADD( buf, BUF_SIZE_IFMIB, origin, length );
+
+ gcry_free( buf );
+
+ pfnsoclose( s );
+ }
+ }
+
+ if( hmodDosCalls )
+ {
+ if( pfnDosPerfSysCall )
+ {
+ buf = gcry_xcalloc( ulCpuCount, BUF_SIZE_CPUUTIL );
+
+ /* Query CPU utilization snapshot */
+ if( !pfnDosPerfSysCall( 0x63, ( ULONG )buf, 0, 0 ))
+ ADD( buf, BUF_SIZE_CPUUTIL * ulCpuCount, origin, length );
+
+ gcry_free( buf );
+ }
+
+ if( pfnDosQuerySysState )
+ {
+ size_t bufSize = BUF_SIZE_SYS_STATE;
+
+ /* Allocate additional memory because DosQuerySysState()
+ sometimes seems to overwrite to a memory boundary. */
+ buf = gcry_xmalloc( bufSize + BUF_SIZE_SYS_STATE_MARGIN );
+
+ do
+ {
+ /* Query all the system information supported by OS */
+ rc = DosQuerySysState( QS_SUPPORTED, 0, 0, 0, ( PCHAR )buf,
+ bufSize );
+ if( rc == ERROR_BUFFER_OVERFLOW )
+ {
+ bufSize += BUF_SIZE_SYS_STATE_DELTA;
+ gcry_free( buf );
+ buf = gcry_xmalloc( bufSize +
+ BUF_SIZE_SYS_STATE_MARGIN );
+ }
+ } while( rc == ERROR_BUFFER_OVERFLOW );
+
+ if( !rc )
+ ADD( buf, bufSize, origin, length );
+
+ gcry_free( buf );
+ }
+ }
+
+#define ADD_QSV( ord ) \
+ do { \
+ ULONG ulSV; \
+ DosQuerySysInfo( ord, ord, &ulSV, sizeof( ulSV )); \
+ ADD( &ulSV, sizeof( ulSV ), origin, length ); \
+ } while( 0 )
+
+ /* Fail safe */
+ ADD_QSV( QSV_MS_COUNT );
+ ADD_QSV( QSV_TIME_LOW );
+ ADD_QSV( QSV_TIME_HIGH );
+ ADD_QSV( QSV_TOTAVAILMEM );
+ ADD_QSV( QSV_FOREGROUND_FS_SESSION );
+ ADD_QSV( QSV_FOREGROUND_PROCESS );
+ }
+
+ return 0;
+}
diff --git a/src/hmac256.c b/src/hmac256.c
index 34def76..a887e99 100644
--- a/src/hmac256.c
+++ b/src/hmac256.c
@@ -52,7 +52,10 @@
#include <string.h>
#include <assert.h>
#include <errno.h>
-#if defined(__WIN32) && defined(STANDALONE)
+#if (defined(__WIN32) || defined(__OS2__)) && defined(STANDALONE)
+# ifdef __OS2__
+# include <io.h>
+# endif
# include <fcntl.h> /* We need setmode(). */
#endif
@@ -658,7 +661,7 @@ main (int argc, char **argv)
int use_binary = 0;
assert (sizeof (u32) == 4);
-#ifdef __WIN32
+#if defined(__WIN32) || defined(__OS2__)
setmode (fileno (stdin), O_BINARY);
#endif
@@ -707,7 +710,7 @@ main (int argc, char **argv)
exit (1);
}
-#ifdef __WIN32
+#if defined(__WIN32) || defined(__OS2__)
if (use_binary)
setmode (fileno (stdout), O_BINARY);
#endif
diff --git a/tests/fipsdrv.c b/tests/fipsdrv.c
index 2d4c362..d1be32d 100644
--- a/tests/fipsdrv.c
+++ b/tests/fipsdrv.c
@@ -29,6 +29,10 @@
#ifdef HAVE_W32_SYSTEM
# include <fcntl.h> /* We need setmode(). */
#else
+# ifdef HAVE_DOSISH_SYSTEM
+# include <io.h> /* We need setmode(). */
+# include <fcntl.h> /* We need O_BINARY */
+# endif
# include <signal.h>
#endif
#include <assert.h>
--
1.7.3.2
More information about the Gcrypt-devel
mailing list