[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