emacs-devel
[Top][All Lists]
Advanced

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

New function: secure-random-bytes


From: Leo
Subject: New function: secure-random-bytes
Date: Fri, 24 Jun 2011 15:50:06 +0800
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/23.3.50 (Mac OS X 10.6.7)

Hello,

It seems useful to provide a way to get some cryptographically strong
random bytes (e.g. for uuid generation or passwords).

See discussion: http://thread.gmane.org/gmane.emacs.devel/138494

The attached preliminary patch does this. Comments are welcome. Thanks.

Leo

=== modified file 'configure.in'
--- configure.in        2011-06-21 17:10:10 +0000
+++ configure.in        2011-06-24 07:30:10 +0000
@@ -174,6 +174,7 @@
 OPTION_DEFAULT_ON([gconf],[don't compile with GConf support])
 OPTION_DEFAULT_ON([selinux],[don't compile with SELinux support])
 OPTION_DEFAULT_ON([gnutls],[don't use -lgnutls for SSL/TLS support])
+OPTION_DEFAULT_ON([secure-random],[don't compile secure-random support])
 
 ## For the times when you want to build Emacs but don't have
 ## a suitable makeinfo, and can live without the manuals.
@@ -1999,6 +2000,32 @@
 AC_SUBST(LIBGNUTLS_LIBS)
 AC_SUBST(LIBGNUTLS_CFLAGS)
 
+case $with_secure_random in
+    urandom | yes) AC_CHECK_FILE("/dev/urandom", HAVE_RANDOMDEV=yes, 
HAVE_RANDOMDEV=no)
+            if test "${HAVE_RANDOMDEV}" = "no"; then
+                AC_DEFINE(SECURE_RANDOM_TYPE, 1, [Set 1 if /dev/urandom 
exists.])
+                AC_DEFINE(RANDOMDEV, "/dev/urandom", [Define if /dev/urandom 
exists])
+            fi
+            ;;
+    gnutls) if test -z "$HAVE_GNUTLS"; then
+                PKG_CHECK_MODULES([LIBGNUTLS], [gnutls >= 2.6.0], 
HAVE_GNUTLS=yes, HAVE_GNUTLS=no)
+            fi
+            if test "$HAVE_GNUTLS" = yes; then
+                AC_DEFINE(SECURE_RANDOM_TYPE, 2, [Set to 2 if using GnuTLS.])
+            fi
+            ;;
+    openssl) PKG_CHECK_MODULES([LIBOPENSSL], [openssl >= 0.9.8], 
HAVE_OPENSSL=yes, HAVE_OPENSSL=no)
+            if test "$HAVE_OPENSSL" = "yes"; then
+                AC_DEFINE(SECURE_RANDOM_TYPE, 3, [Set to 3 if using OpenSSL.])
+            fi
+            CFLAGS="$CFLAGS $LIBOPENSSL_CFLAGS"
+            LIBS="$LIBOPENSSL_LIBS $LIBS"
+            ;;
+esac
+
+AC_SUBST(LIBOPENSSL_LIBS)
+AC_SUBST(LIBOPENSSL_CFLAGS)
+
 dnl Do not put whitespace before the #include statements below.
 dnl Older compilers (eg sunos4 cc) choke on it.
 HAVE_XAW3D=no

=== modified file 'src/Makefile.in'
--- src/Makefile.in     2011-05-21 02:04:48 +0000
+++ src/Makefile.in     2011-06-24 06:28:33 +0000
@@ -269,6 +269,9 @@
 LIBGNUTLS_LIBS = @LIBGNUTLS_LIBS@
 LIBGNUTLS_CFLAGS = @LIBGNUTLS_CFLAGS@
 
+LIBOPENSSL_LIBS = @LIBOPENSSL_LIBS@
+LIBOPENSSL_CFLAGS = @LIBOPENSSL_CFLAGS@
+
 INTERVALS_H = dispextern.h intervals.h composite.h
 
 GETLOADAVG_LIBS = @GETLOADAVG_LIBS@
@@ -307,7 +310,7 @@
   $(LIBXML2_CFLAGS) $(DBUS_CFLAGS) \
   $(GCONF_CFLAGS) $(FREETYPE_CFLAGS) $(FONTCONFIG_CFLAGS) \
   $(LIBOTF_CFLAGS) $(M17N_FLT_CFLAGS) $(DEPFLAGS) $(PROFILING_CFLAGS) \
-  $(LIBGNUTLS_CFLAGS) \
+  $(LIBGNUTLS_CFLAGS) $(LIBOPENSSL_CFLAGS) \
   $(C_WARNINGS_SWITCH) $(CFLAGS)
 ALL_OBJC_CFLAGS=$(ALL_CFLAGS) $(GNU_OBJC_CFLAGS)
 
@@ -383,7 +386,7 @@
    $(LIBXML2_LIBS) $(LIBGPM) $(LIBRESOLV) $(LIBS_SYSTEM) \
    $(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(GCONF_LIBS) $(LIBSELINUX_LIBS) \
    $(FREETYPE_LIBS) $(FONTCONFIG_LIBS) $(LIBOTF_LIBS) $(M17N_FLT_LIBS) \
-   $(LIBGNUTLS_LIBS) \
+   $(LIBGNUTLS_LIBS) $(LIBOPENSSL_LIBS) \
    $(LIB_GCC) $(LIB_MATH) $(LIB_STANDARD) $(LIB_GCC)
 
 all: emacs$(EXEEXT) $(OTHER_FILES)

=== modified file 'src/fileio.c'
--- src/fileio.c        2011-06-19 19:06:16 +0000
+++ src/fileio.c        2011-06-24 07:23:58 +0000
@@ -5420,7 +5420,76 @@
   args[6] = predicate;
   RETURN_UNGCPRO (Ffuncall (7, args));
 }
+
+#if SECURE_RANDOM_TYPE==1
+
+DEFUN ("secure-random-bytes", Fsecure_random_bytes, Ssecure_random_bytes, 1, 
1, 0,
+       doc: /* Return N cryptographically strong pseudo-random bytes.  */)
+  (Lisp_Object n)
+{
+  register int nbytes;
+  int         fd;
+  Lisp_Object  val;
+  struct stat  st;
+
+  CHECK_NATNUM (n);
+
+  /* Return empty string for 0 bytes */
+  if (XFASTINT(n) == 0)
+    return build_string ("");
+
+  if ((stat (RANDOMDEV, &st) < 0)
+#ifdef S_ISCHR
+      || (!S_ISCHR (st.st_mode))
+#endif
+      )
+    error ("Secure random device does not exist");
+
+  val = make_uninit_string (XFASTINT (n));
+
+  fd = emacs_open (RANDOMDEV, O_RDONLY | O_NONBLOCK, 0);
+  nbytes = emacs_read (fd, SDATA (val), XFASTINT (n));
+  emacs_close (fd);
 
+  if (nbytes < XFASTINT (n))
+    error ("IO error reading secure random device");
+
+  return val;
+}
+
+#elif SECURE_RANDOM_TYPE==2 || SECURE_RANDOM_TYPE==3
+
+#ifdef SECURE_RANDOM_TYPE==2
+#include <gnutls/gnutls.h>
+#include <gnutls/crypto.h>
+#else
+#include <openssl/rand.h>
+#endif
+
+DEFUN ("secure-random-bytes", Fsecure_random_bytes, Ssecure_random_bytes, 1, 
1, 0,
+       doc: /* Return N cryptographically strong pseudo-random bytes.  */)
+  (Lisp_Object n)
+{
+  Lisp_Object val;
+
+  CHECK_NATNUM (n);
+
+  /* Return empty string for 0 bytes */
+  if (XFASTINT(n) == 0)
+    return build_string ("");
+
+  val = make_uninit_string (XFASTINT (n));
+
+#if SECURE_RANDOM_TYPE==2
+  if (gnutls_rnd (GNUTLS_RND_NONCE, SDATA (val), XFASTINT (n)) < 0)
+#else
+  if (RAND_bytes (SDATA (val), XFASTINT (n)) == 0)
+#endif
+    error ("Failed to generate random data");
+
+  return val;
+}
+#endif /* SECURE_RANDOM_TYPE */
 
 void
 syms_of_fileio (void)
@@ -5701,6 +5770,9 @@
   defsubr (&Smake_directory_internal);
   defsubr (&Sdelete_directory_internal);
   defsubr (&Sdelete_file);
+#ifdef SECURE_RANDOM_TYPE
+  defsubr (&Ssecure_random_bytes);
+#endif
   defsubr (&Srename_file);
   defsubr (&Sadd_name_to_file);
   defsubr (&Smake_symbolic_link);


reply via email to

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