gnutls-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[SCM] GNU gnutls branch, master, updated. gnutls_2_9_10-306-gf4092ad


From: Nikos Mavrogiannopoulos
Subject: [SCM] GNU gnutls branch, master, updated. gnutls_2_9_10-306-gf4092ad
Date: Sun, 11 Jul 2010 09:57:18 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU gnutls".

http://git.savannah.gnu.org/cgit/gnutls.git/commit/?id=f4092ad7c129b801b7f61ec1e721c52076fd2661

The branch, master has been updated
       via  f4092ad7c129b801b7f61ec1e721c52076fd2661 (commit)
       via  dd87d15e88d3705eddf69cf6380123a12007bb9a (commit)
      from  0de92887c94aadab46fb88e56a99e6f563f296d8 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit f4092ad7c129b801b7f61ec1e721c52076fd2661
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Sun Jul 11 11:57:06 2010 +0200

    fixed

commit dd87d15e88d3705eddf69cf6380123a12007bb9a
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Sun Jul 11 11:52:13 2010 +0200

    Added support for EGD daemon in nettle's RNG. It is used if /dev/urandom
    is not present.

-----------------------------------------------------------------------

Summary of changes:
 NEWS                   |    4 +-
 lib/nettle/Makefile.am |    2 +-
 lib/nettle/egd.c       |  256 ++++++++++++++++++++++++++++++++++++++++++++++++
 lib/nettle/egd.h       |    2 +
 lib/nettle/rnd.c       |   87 ++++++++++++++++-
 lib/system.h           |    5 +-
 6 files changed, 348 insertions(+), 8 deletions(-)
 create mode 100644 lib/nettle/egd.c
 create mode 100644 lib/nettle/egd.h

diff --git a/NEWS b/NEWS
index 2fe8a5f..d1c81a6 100644
--- a/NEWS
+++ b/NEWS
@@ -45,7 +45,9 @@ imported from tokens, and operations can be performed on 
private keys.
 
 ** libgnutls: Added abstract gnutls_privkey_t and gnutls_pubkey_t
 
-** libgnutls: Added initial support for the nettle library (unsupported)
+** libgnutls: Added initial support for the nettle library. It uses
+the system's random generator for seeding. That is /dev/urandom in Linux, 
+system calls in Win32 and EGD on other systems.
 
 ** libgnutls: Corrected issue on the %SSL3_RECORD_VERSION priority string. It 
now
     works even when resuming a session.
diff --git a/lib/nettle/Makefile.am b/lib/nettle/Makefile.am
index 5a78b92..a580fc2 100644
--- a/lib/nettle/Makefile.am
+++ b/lib/nettle/Makefile.am
@@ -35,4 +35,4 @@ endif
 
 noinst_LTLIBRARIES = libcrypto.la
 
-libcrypto_la_SOURCES = pk.c mpi.c mac.c cipher.c rnd.c init.c
+libcrypto_la_SOURCES = pk.c mpi.c mac.c cipher.c rnd.c init.c egd.c egd.h
diff --git a/lib/nettle/egd.c b/lib/nettle/egd.c
new file mode 100644
index 0000000..60467c6
--- /dev/null
+++ b/lib/nettle/egd.c
@@ -0,0 +1,256 @@
+/* rndegd.c  - interface to the EGD
+ *     Copyright (C) 1999, 2000, 2002, 2003 Free Software Foundation, Inc.
+ *
+ * This file is part of Libgcrypt.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include "egd.h"
+
+#include <gnutls_errors.h>
+
+#ifndef offsetof
+#define offsetof(type, member) ((size_t) &((type *)0)->member)
+#endif
+
+static int egd_socket = -1;
+
+static int
+do_write( int fd, void *buf, size_t nbytes )
+{
+  size_t nleft = nbytes;
+  int nwritten;
+  
+  while( nleft > 0 ) 
+    {
+      nwritten = write( fd, buf, nleft);
+      if( nwritten < 0 )
+        {
+          if( errno == EINTR )
+            continue;
+          return -1;
+       }
+      nleft -= nwritten;
+      buf = (char*)buf + nwritten;
+    }
+  return 0;
+}
+
+static int
+do_read( int fd, void *buf, size_t nbytes )
+{
+  int n, nread = 0;
+
+  do
+    {
+      do
+        {
+          n = read(fd, (char*)buf + nread, nbytes );
+        } 
+      while( n == -1 && errno == EINTR );
+      if( n == -1)
+        return nread? nread:-1;
+      if( n == 0)
+        return -1;
+      nread += n;
+      nbytes -= n;
+    } 
+  while( nread < nbytes );
+  return nread;
+}
+
+static const char* egd_names[] = { 
+  "/var/run/egd-pool", 
+  "/dev/egd-pool", 
+  "/etc/egd-pool", 
+  "/etc/entropy", 
+  "/var/run/entropy", 
+  "/dev/entropy",
+  NULL 
+};
+
+static const char* find_egd_name(void)
+{
+int i = 0;
+struct stat st;
+
+  do {
+    if (stat(egd_names[i], &st) != 0) continue;
+    
+    if (st.st_mode & S_IFSOCK) { /* found */
+      return egd_names[i];
+    }
+  
+  } while(egd_names[++i] != NULL);
+  
+  return NULL;
+}
+
+/* Connect to the EGD and return the file descriptor.  Return -1 on
+   error.  With NOFAIL set to true, silently fail and return the
+   error, otherwise print an error message and die. */
+int _rndegd_connect_socket (void)
+{
+  int fd;
+  const char *name;
+  struct sockaddr_un addr;
+  int addr_len;
+
+  if (egd_socket != -1)
+    {
+      close (egd_socket);
+      egd_socket = -1;
+    }
+
+  name = find_egd_name();
+
+  if (strlen(name)+1 >= sizeof addr.sun_path) 
+    {
+      _gnutls_debug_log ("EGD socketname is too long\n");
+      return -1;
+    }
+  
+  memset( &addr, 0, sizeof addr );
+  addr.sun_family = AF_LOCAL;
+  strcpy( addr.sun_path, name );         
+  addr_len = (offsetof( struct sockaddr_un, sun_path )
+              + strlen( addr.sun_path ));
+  
+  fd = socket(AF_LOCAL, SOCK_STREAM, 0);
+  if (fd == -1)
+    {
+      _gnutls_debug_log("can't create unix domain socket: %s\n", 
strerror(errno) );
+      return -1;
+    }
+  else if (connect (fd, (struct sockaddr*)&addr, addr_len) == -1)
+    {
+      _gnutls_debug_log("can't connect to EGD socket `%s': %s\n",
+                 name, strerror(errno) );
+      close (fd);
+      fd = -1;
+    }
+
+  if (fd != -1)
+    egd_socket = fd;
+  return fd;
+}
+
+/****************
+ * Note: We always use the highest level.
+ * To boost the performance we may want to add some
+ * additional code for level 1
+ *
+ * Using a level of 0 should never block and better add nothing
+ * to the pool.  So this is just a dummy for EGD.
+ */
+int _rndegd_read (int * fd, void* _output, size_t _length)
+{
+  int n;
+  uint8_t buffer[256+2];
+  int nbytes;
+  int do_restart = 0;
+  unsigned char* output = _output;
+  size_t length = _length;
+
+  if( !length )
+    return 0;
+
+
+ restart:
+  if (*fd == -1 || do_restart)
+    *fd = _rndegd_connect_socket ();
+
+  do_restart = 0;
+
+  nbytes = length < 255 ? length : 255;
+  /* First time we do it with a non blocking request */
+  buffer[0] = 1; /* non blocking */
+  buffer[1] = nbytes;
+
+  if( do_write( *fd, buffer, 2 ) == -1 )
+    _gnutls_debug_log("can't write to the EGD: %s\n", strerror(errno) );
+
+  n = do_read( *fd, buffer, 1 );
+  if( n == -1 )
+    {
+      _gnutls_debug_log("read error on EGD: %s\n", strerror(errno));
+      do_restart = 1;
+      goto restart;
+    }
+
+  n = buffer[0];
+  if( n )
+    {
+      n = do_read( *fd, buffer, n );
+      if( n == -1 )
+        {
+          _gnutls_debug_log("read error on EGD: %s\n", strerror(errno));
+          do_restart = 1;
+          goto restart;
+       }
+
+      if (n > length)
+        {
+          _gnutls_debug_log("read error on EGD: returned more bytes!\n");
+          n = length;
+        }
+
+      memcpy(output, buffer, n);
+      output += n;
+      length -= n;
+    }
+
+  while( length )
+    {
+      nbytes = length < 255? length : 255;
+
+      buffer[0] = 2; /* blocking */
+      buffer[1] = nbytes;
+      if( do_write( *fd, buffer, 2 ) == -1 )
+        _gnutls_debug_log("can't write to the EGD: %s\n", strerror(errno) );
+      n = do_read( *fd, buffer, nbytes );
+      if( n == -1 )
+        {
+          _gnutls_debug_log("read error on EGD: %s\n", strerror(errno));
+          do_restart = 1;
+          goto restart;
+       }
+
+      if (n > length)
+        {
+          _gnutls_debug_log("read error on EGD: returned more bytes!\n");
+          n = length;
+        }
+      
+      memcpy(output, buffer, n);
+      output += n;
+      length -= n;
+    }
+
+  return _length; /* success */
+}
+
diff --git a/lib/nettle/egd.h b/lib/nettle/egd.h
new file mode 100644
index 0000000..74f3ed9
--- /dev/null
+++ b/lib/nettle/egd.h
@@ -0,0 +1,2 @@
+int _rndegd_read (int * fd, void* output, size_t length);
+int _rndegd_connect_socket (void);
diff --git a/lib/nettle/rnd.c b/lib/nettle/rnd.c
index c4a0057..d130eda 100644
--- a/lib/nettle/rnd.c
+++ b/lib/nettle/rnd.c
@@ -47,14 +47,15 @@ static time_t trivia_time_count = 0;
 
 static void* rnd_mutex;
 
-#define DEVICE_READ_SIZE 16
-#define DEVICE_READ_SIZE_MAX 32
 #define DEVICE_READ_INTERVAL 1200
 
 #ifdef _WIN32
 
 # include <windows.h>
 
+# define DEVICE_READ_SIZE 16
+# define DEVICE_READ_SIZE_MAX 32
+
 static HCRYPTPROV device_fd = NULL;
 
 static int do_trivia_source(int init)
@@ -133,6 +134,10 @@ static void wrap_nettle_rnd_deinit(void* ctx)
 # include <sys/time.h>
 # include <fcntl.h>
 # include <locks.h>
+# include "egd.h"
+
+# define DEVICE_READ_SIZE 16
+# define DEVICE_READ_SIZE_MAX 32
 
 static int device_fd;
 static time_t trivia_previous_time = 0;
@@ -185,10 +190,10 @@ static int do_trivia_source(int init)
                            sizeof(event), (const uint8_t *) &event);
 }
 
-static int do_device_source(int init)
+static int do_device_source_urandom(int init)
 {
     time_t now = time(NULL);
-       int read_size = DEVICE_READ_SIZE;
+    int read_size = DEVICE_READ_SIZE;
 
     if (init) {
                int old;
@@ -242,6 +247,80 @@ static int do_device_source(int init)
     return 0;
 }
 
+static int do_device_source_egd(int init)
+{
+    time_t now = time(NULL);
+    int read_size = DEVICE_READ_SIZE;
+
+    if (init) {
+               device_fd = _rndegd_connect_socket();
+               if (device_fd < 0) {
+                       _gnutls_debug_log("Cannot open egd socket!\n");
+                       return GNUTLS_E_FILE_ERROR;
+               }
+
+               device_last_read = now;
+               
+               read_size = DEVICE_READ_SIZE_MAX; /* initially read more data */
+    }
+
+    if ((device_fd > 0)
+               && (init || ((now - device_last_read) > DEVICE_READ_INTERVAL))) 
{
+
+               /* More than a minute since we last read the device */
+               uint8_t buf[DEVICE_READ_SIZE_MAX];
+               uint32_t done;
+
+               for (done = 0; done < read_size;) {
+                       int res;
+                       res = _rndegd_read(&device_fd, buf + done, sizeof(buf) 
- done);
+                       if (res <= 0) {
+                               if (res < 0) {
+                                       _gnutls_debug_log("Failed to read 
egd.\n");
+                               } else {
+                                       _gnutls_debug_log("Failed to read egd: 
end of file\n");
+                               }
+
+                               return GNUTLS_E_INTERNAL_ERROR;
+                       }
+                       done += res;
+               }
+
+               device_last_read = now;
+               return yarrow256_update(&yctx, RANDOM_SOURCE_DEVICE, 
read_size*8/2, 
+                                       read_size, buf);
+    }
+    return 0;
+}
+
+static int do_device_source(int init)
+{
+int ret;
+static int (*do_source)(int init) = NULL;
+/* using static var here is ok since we are
+ * always called with mutexes down 
+ */
+
+    if (init == 1) {
+        do_source = do_device_source_urandom;
+        ret = do_source(init);
+        if (ret < 0) {
+            do_source = do_device_source_egd;
+            ret = do_source(init);
+        }
+        
+        if (ret < 0) {
+            gnutls_assert();
+            return ret;
+        }
+        
+        return ret;
+    } else {
+        return do_source(init);
+    }
+}
+
+
 static void wrap_nettle_rnd_deinit(void* ctx)
 {
        RND_LOCK;
diff --git a/lib/system.h b/lib/system.h
index c18e74b..e42e485 100644
--- a/lib/system.h
+++ b/lib/system.h
@@ -18,8 +18,6 @@ ssize_t system_writev(gnutls_transport_ptr ptr, const 
giovec_t * iovec, int iove
 ssize_t system_read(gnutls_transport_ptr ptr, void* data, size_t data_size);
 ssize_t system_read_peek(gnutls_transport_ptr ptr, void* data, size_t 
data_size);
 
-#endif
-
 #ifdef _WIN32
 # define HAVE_WIN32_LOCKS
 #else
@@ -31,3 +29,6 @@ ssize_t system_read_peek(gnutls_transport_ptr ptr, void* 
data, size_t data_size)
 #endif
 
 int _gnutls_atfork(void (*prepare)(void), void (*parent)(void), void 
(*child)(void));
+
+#endif /* SYSTEM_H */
+


hooks/post-receive
-- 
GNU gnutls



reply via email to

[Prev in Thread] Current Thread [Next in Thread]