unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* New function: secure-random-bytes
@ 2011-06-24  7:50 Leo
  2011-06-24  9:57 ` Ted Zlatanov
  2011-06-24 13:33 ` James Cloos
  0 siblings, 2 replies; 12+ messages in thread
From: Leo @ 2011-06-24  7:50 UTC (permalink / raw)
  To: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 277 bytes --]

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


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: srb.diff --]
[-- Type: text/x-diff, Size: 5221 bytes --]

=== 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));
 }
+\f
+#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 */
 \f
 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);


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: New function: secure-random-bytes
  2011-06-24  7:50 New function: secure-random-bytes Leo
@ 2011-06-24  9:57 ` Ted Zlatanov
  2011-06-24 17:33   ` Paul Eggert
  2011-06-24 13:33 ` James Cloos
  1 sibling, 1 reply; 12+ messages in thread
From: Ted Zlatanov @ 2011-06-24  9:57 UTC (permalink / raw)
  To: emacs-devel

On Fri, 24 Jun 2011 15:50:06 +0800 Leo <sdl.web@gmail.com> wrote: 

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

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

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

Do you think you could you provide three functions,
`secure-random-bytes-{urandom,gnutls,openssl}' instead of three versions
with the same name?  Then there can be a `secure-random-bytes' in
simple.el or wherever:

(secure-random-bytes) ; auto, checking with fboundp
(secure-random-bytes 'gnutls) ; try the GnuTLS version first

The nice part is that you can put `secure-random-bytes-gnutls' in
gnutls.c; make openssl.c for `secure-random-bytes-openssl' and use a
HAVE_OPENSSL ifdef; and put `secure-random-bytes-urandom' in fileio.c
inside a HAVE_URANDOM ifdef.  That will avoid making up numeric
constants for SECURE_RANDOM_TYPE in favor of more meaningful constants
and puts all the new functions in the right place.

I can imagine other uses for the OpenSSL functions, so at least the
HAVE_OPENSSL macro makes a lot of sense.

I'm not sure what the auto priority should be.  Are the GnuTLS/OpenSSL
functions better than /dev/urandom?  They are certainly slower.

Thanks
Ted




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: New function: secure-random-bytes
  2011-06-24  7:50 New function: secure-random-bytes Leo
  2011-06-24  9:57 ` Ted Zlatanov
@ 2011-06-24 13:33 ` James Cloos
  2011-06-25  7:27   ` Leo
  1 sibling, 1 reply; 12+ messages in thread
From: James Cloos @ 2011-06-24 13:33 UTC (permalink / raw)
  To: Leo; +Cc: emacs-devel

>>>>> "L" == Leo  <sdl.web@gmail.com> writes:

L> +case $with_secure_random in
L> +    urandom | yes) AC_CHECK_FILE("/dev/urandom", HAVE_RANDOMDEV=yes, HAVE_RANDOMDEV=no)
L> +            if test "${HAVE_RANDOMDEV}" = "no"; then
L> +                AC_DEFINE(SECURE_RANDOM_TYPE, 1, [Set 1 if /dev/urandom exists.])
L> +                AC_DEFINE(RANDOMDEV, "/dev/urandom", [Define if /dev/urandom exists])
L> +            fi
L> +            ;;

Shouldn't that be?:

  if test "${HAVE_RANDOMDEV}" = "yes"; then

PS  +1 on Ted's suggestion.

-JimC
-- 
James Cloos <cloos@jhcloos.com>         OpenPGP: 1024D/ED7DAEA6



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: New function: secure-random-bytes
  2011-06-24  9:57 ` Ted Zlatanov
@ 2011-06-24 17:33   ` Paul Eggert
  2011-06-25  7:26     ` Leo
                       ` (2 more replies)
  0 siblings, 3 replies; 12+ messages in thread
From: Paul Eggert @ 2011-06-24 17:33 UTC (permalink / raw)
  To: emacs-devel

On 06/24/11 02:57, Ted Zlatanov wrote:

> Do you think you could you provide three functions,
> `secure-random-bytes-{urandom,gnutls,openssl}' instead of three versions
> with the same name?

I dunno, I kind of like the simpler interface.
It's better to have the notion of a random-source,
independent of the notion of generating random bytes from it.
Whether that source should be represenated by an atom or
by something else is a different matter.

> I'm not sure what the auto priority should be.  Are the GnuTLS/OpenSSL
> functions better than /dev/urandom?  They are certainly slower.

If they're slower than /dev/urandom, they must be pretty slow.

I suggest using ISAAC-64, which is what coreutils' random-bytes
generators use by default.  (Coreutils originally defaulted to
/dev/urandom, but users complained because that was too slow.)
On my list of things to do is to gnulib-ize the coreutils
ISAAC-64 and random-bytes generators, and I can do that if
there's interest.

Here's one benchmark of the performance difference, run on
Fedora 14 x86-64.  The benchmark creates 1 GB of random data
and outputs it to /dev/null.  With ISAAC-64, it takes 0.48
seconds real-time.  With /dev/urandom, it takes 146 seconds
real-time.  So ISAAC-64 is about 300x faster.

$ time shred -v -n1 -s 1GB /dev/null
shred: /dev/null: pass 1/1 (random)...

real	0m0.476s
user	0m0.397s
sys	0m0.072s
$ time shred -v -n1 -s 1GB --random-source=/dev/urandom /dev/null
shred: /dev/null: pass 1/1 (random)...
shred: /dev/null: pass 1/1 (random)...32MiB/954MiB 3%
shred: /dev/null: pass 1/1 (random)...63MiB/954MiB 6%
...
shred: /dev/null: pass 1/1 (random)...954MiB/954MiB 100%

real	2m25.969s
user	0m0.013s
sys	2m24.189s



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: New function: secure-random-bytes
  2011-06-24 17:33   ` Paul Eggert
@ 2011-06-25  7:26     ` Leo
  2011-06-27 16:10     ` Ted Zlatanov
  2013-03-18 10:26     ` Leo Liu
  2 siblings, 0 replies; 12+ messages in thread
From: Leo @ 2011-06-25  7:26 UTC (permalink / raw)
  To: Paul Eggert; +Cc: emacs-devel

On 2011-06-25 01:33 +0800, Paul Eggert wrote:
> I suggest using ISAAC-64, which is what coreutils' random-bytes
> generators use by default.  (Coreutils originally defaulted to
> /dev/urandom, but users complained because that was too slow.)
> On my list of things to do is to gnulib-ize the coreutils
> ISAAC-64 and random-bytes generators, and I can do that if
> there's interest.

This looks like a better solution. I like it.

Leo



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: New function: secure-random-bytes
  2011-06-24 13:33 ` James Cloos
@ 2011-06-25  7:27   ` Leo
  0 siblings, 0 replies; 12+ messages in thread
From: Leo @ 2011-06-25  7:27 UTC (permalink / raw)
  To: emacs-devel

On 2011-06-24 21:33 +0800, James Cloos wrote:
> Shouldn't that be?:
>
>   if test "${HAVE_RANDOMDEV}" = "yes"; then

Sorry for the typo.

Leo




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: New function: secure-random-bytes
  2011-06-24 17:33   ` Paul Eggert
  2011-06-25  7:26     ` Leo
@ 2011-06-27 16:10     ` Ted Zlatanov
  2013-03-18 10:26     ` Leo Liu
  2 siblings, 0 replies; 12+ messages in thread
From: Ted Zlatanov @ 2011-06-27 16:10 UTC (permalink / raw)
  To: emacs-devel

On Fri, 24 Jun 2011 10:33:47 -0700 Paul Eggert <eggert@cs.ucla.edu> wrote: 

PE> On 06/24/11 02:57, Ted Zlatanov wrote:
>> Do you think you could you provide three functions,
>> `secure-random-bytes-{urandom,gnutls,openssl}' instead of three versions
>> with the same name?

PE> I dunno, I kind of like the simpler interface.
PE> It's better to have the notion of a random-source,
PE> independent of the notion of generating random bytes from it.
PE> Whether that source should be represenated by an atom or
PE> by something else is a different matter.

At least for GnuTLS it would make sense to put the function that
actually calls GnuTLS at the C level in gnutls.c.  Ditto for OpenSSL.

Beyond that, it can be abstracted any way you like :)  My way was just a
suggestion.

PE> I suggest using ISAAC-64, which is what coreutils' random-bytes
PE> generators use by default.  (Coreutils originally defaulted to
PE> /dev/urandom, but users complained because that was too slow.)
PE> On my list of things to do is to gnulib-ize the coreutils
PE> ISAAC-64 and random-bytes generators, and I can do that if
PE> there's interest.

Works for me.  I think you're right about the /dev/urandom performance.

Ted




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: New function: secure-random-bytes
  2011-06-24 17:33   ` Paul Eggert
  2011-06-25  7:26     ` Leo
  2011-06-27 16:10     ` Ted Zlatanov
@ 2013-03-18 10:26     ` Leo Liu
  2013-03-18 16:48       ` Paul Eggert
  2 siblings, 1 reply; 12+ messages in thread
From: Leo Liu @ 2013-03-18 10:26 UTC (permalink / raw)
  To: Paul Eggert; +Cc: emacs-devel

Hi Paul,

On 2011-06-25 01:33 +0800, Paul Eggert wrote:
> I suggest using ISAAC-64, which is what coreutils' random-bytes
> generators use by default.  (Coreutils originally defaulted to
> /dev/urandom, but users complained because that was too slow.)
> On my list of things to do is to gnulib-ize the coreutils
> ISAAC-64 and random-bytes generators, and I can do that if
> there's interest.

From that discussion (almost two years ago) there was clearly interest
in having a strongly random source. The solution you proposed looks
excellent. Are there any progress on this matter? Thanks.

Leo



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: New function: secure-random-bytes
  2013-03-18 10:26     ` Leo Liu
@ 2013-03-18 16:48       ` Paul Eggert
  2013-03-18 21:07         ` Romain Francoise
  2019-05-15 12:09         ` Julian Scheid
  0 siblings, 2 replies; 12+ messages in thread
From: Paul Eggert @ 2013-03-18 16:48 UTC (permalink / raw)
  To: Leo Liu; +Cc: emacs-devel

On 03/18/13 03:26, Leo Liu wrote:

> From that discussion (almost two years ago) there was clearly interest
> in having a strongly random source. The solution you proposed looks
> excellent. Are there any progress on this matter?

There's been no progress, alas.
Yours is the first sign of interest that I've seen since then.
I may be able to find a student or two
who might volunteer to work on this; we'll see.

There's one extra wrinkle I'd like to add while we're at it:
if available we should use the random-number instructions
in recent implementations of x86 and x86-64 architectures
as this should yield even better performance.

http://en.wikipedia.org/wiki/RdRand



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: New function: secure-random-bytes
  2013-03-18 16:48       ` Paul Eggert
@ 2013-03-18 21:07         ` Romain Francoise
  2019-05-15 12:09         ` Julian Scheid
  1 sibling, 0 replies; 12+ messages in thread
From: Romain Francoise @ 2013-03-18 21:07 UTC (permalink / raw)
  To: Paul Eggert; +Cc: emacs-devel

Paul Eggert <eggert@cs.ucla.edu> writes:

> There's one extra wrinkle I'd like to add while we're at it:
> if available we should use the random-number instructions
> in recent implementations of x86 and x86-64 architectures
> as this should yield even better performance.

Yes, although some people think they shouldn't be used directly but mixed
with other sources, for trust reasons:

 http://git.kernel.org/linus/c2557a303ab6712bb6e09447df828c557c710ac9



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: New function: secure-random-bytes
  2013-03-18 16:48       ` Paul Eggert
  2013-03-18 21:07         ` Romain Francoise
@ 2019-05-15 12:09         ` Julian Scheid
  2019-05-16 17:34           ` Paul Eggert
  1 sibling, 1 reply; 12+ messages in thread
From: Julian Scheid @ 2019-05-15 12:09 UTC (permalink / raw)
  To: Paul Eggert; +Cc: Leo Liu, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1653 bytes --]

On Tue, Mar 19, 2013 at 5:49 AM Paul Eggert <eggert@cs.ucla.edu> wrote:

> On 03/18/13 03:26, Leo Liu wrote:
>
> > From that discussion (almost two years ago) there was clearly interest
> > in having a strongly random source. The solution you proposed looks
> > excellent. Are there any progress on this matter?
>
> There's been no progress, alas.
> Yours is the first sign of interest that I've seen since then.
> I may be able to find a student or two
> who might volunteer to work on this; we'll see.
>
> There's one extra wrinkle I'd like to add while we're at it:
> if available we should use the random-number instructions
> in recent implementations of x86 and x86-64 architectures
> as this should yield even better performance.
>
> http://en.wikipedia.org/wiki/RdRand


I'm working on an implementation of SASL authentication and for that I
need to generate a reasonably secure nonce.

Performance is not an issue in my application because it only needs to
perform authentication every now and then, and each time only a single
nonce is needed.

I'm now using `(random t)' but that's brittle: I don't see a way to
guarantee that the random data it produces is of sufficient quality.

(There's a chance both /dev/urandom is unavailable (perhaps because
Emacs is running in a chroot or a container) and GnuTLS initialization
throws an error, in which case `random' would silently fall back to a
non-secure source.  I suppose it's good enough for my use case but it
does highlight the absence of `secure-random-bytes'.)

I wonder, is there anything speaking against adding a simple
implementation now and worrying about maximal performance later?

[-- Attachment #2: Type: text/html, Size: 2357 bytes --]

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: New function: secure-random-bytes
  2019-05-15 12:09         ` Julian Scheid
@ 2019-05-16 17:34           ` Paul Eggert
  0 siblings, 0 replies; 12+ messages in thread
From: Paul Eggert @ 2019-05-16 17:34 UTC (permalink / raw)
  To: Julian Scheid; +Cc: Leo Liu, emacs-devel

On 5/15/19 5:09 AM, Julian Scheid wrote:
> I wonder, is there anything speaking against adding a simple
> implementation now and worrying about maximal performance later?

No, we could do something. What sort of API would work well for you?
Something like this?

(insert-entropy N)

Insert N bytes of high-quality random data after point, where N is an
integer and 0 <= N <= 256. Signal an error on failure.

This would be a wrapper around the glibc getentropy function. I'd write
a Gnulib substitute for platforms lacking getentropy.




^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2019-05-16 17:34 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-06-24  7:50 New function: secure-random-bytes Leo
2011-06-24  9:57 ` Ted Zlatanov
2011-06-24 17:33   ` Paul Eggert
2011-06-25  7:26     ` Leo
2011-06-27 16:10     ` Ted Zlatanov
2013-03-18 10:26     ` Leo Liu
2013-03-18 16:48       ` Paul Eggert
2013-03-18 21:07         ` Romain Francoise
2019-05-15 12:09         ` Julian Scheid
2019-05-16 17:34           ` Paul Eggert
2011-06-24 13:33 ` James Cloos
2011-06-25  7:27   ` Leo

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).