Home | History | Annotate | Line # | Download | only in tls
      1 /*	$NetBSD: tls_prng_dev.c,v 1.2 2017/02/14 01:16:48 christos Exp $	*/
      2 
      3 /*++
      4 /* NAME
      5 /*	tls_prng_dev 3
      6 /* SUMMARY
      7 /*	seed OpenSSL PRNG from entropy device
      8 /* SYNOPSIS
      9 /*	#include <tls_prng_src.h>
     10 /*
     11 /*	TLS_PRNG_SRC *tls_prng_dev_open(name, timeout)
     12 /*	const char *name;
     13 /*	int	timeout;
     14 /*
     15 /*	ssize_t tls_prng_dev_read(dev, length)
     16 /*	TLS_PRNG_SRC *dev;
     17 /*	size_t length;
     18 /*
     19 /*	int	tls_prng_dev_close(dev)
     20 /*	TLS_PRNG_SRC *dev;
     21 /* DESCRIPTION
     22 /*	tls_prng_dev_open() opens the specified entropy device
     23 /*	and returns a handle that should be used with all subsequent
     24 /*	access.
     25 /*
     26 /*	tls_prng_dev_read() reads the requested number of bytes from
     27 /*	the entropy device and updates the OpenSSL PRNG.
     28 /*
     29 /*	tls_prng_dev_close() closes the specified entropy device
     30 /*	and releases memory that was allocated for the handle.
     31 /*
     32 /*	Arguments:
     33 /* .IP name
     34 /*	The pathname of the entropy device.
     35 /* .IP length
     36 /*	The number of bytes to read from the entropy device.
     37 /*	Request lengths will be truncated at 255 bytes.
     38 /* .IP timeout
     39 /*	Time limit on individual I/O operations.
     40 /* DIAGNOSTICS
     41 /*	tls_prng_dev_open() returns a null pointer on error.
     42 /*
     43 /*	tls_prng_dev_read() returns -1 on error, the number
     44 /*	of bytes received on success.
     45 /*
     46 /*	tls_prng_dev_close() returns -1 on error, 0 on success.
     47 /*
     48 /*	In all cases the errno variable indicates the type of error.
     49 /* LICENSE
     50 /* .ad
     51 /* .fi
     52 /*	The Secure Mailer license must be distributed with this software.
     53 /* AUTHOR(S)
     54 /*	Wietse Venema
     55 /*	IBM T.J. Watson Research
     56 /*	P.O. Box 704
     57 /*	Yorktown Heights, NY 10598, USA
     58 /*--*/
     59 
     60 /* System library. */
     61 
     62 #include <sys_defs.h>
     63 #include <fcntl.h>
     64 #include <unistd.h>
     65 #include <limits.h>
     66 #include <errno.h>
     67 
     68 #ifndef UCHAR_MAX
     69 #define UCHAR_MAX 0xff
     70 #endif
     71 
     72 /* OpenSSL library. */
     73 
     74 #ifdef USE_TLS
     75 #include <openssl/rand.h>		/* For the PRNG */
     76 
     77 /* Utility library. */
     78 
     79 #include <msg.h>
     80 #include <mymalloc.h>
     81 #include <connect.h>
     82 #include <iostuff.h>
     83 
     84 /* TLS library. */
     85 
     86 #include <tls_prng.h>
     87 
     88 /* tls_prng_dev_open - open entropy device */
     89 
     90 TLS_PRNG_SRC *tls_prng_dev_open(const char *name, int timeout)
     91 {
     92     const char *myname = "tls_prng_dev_open";
     93     TLS_PRNG_SRC *dev;
     94     int     fd;
     95 
     96     if ((fd = open(name, O_RDONLY, 0)) < 0) {
     97 	if (msg_verbose)
     98 	    msg_info("%s: cannot open entropy device %s: %m", myname, name);
     99 	return (0);
    100     } else {
    101 	dev = (TLS_PRNG_SRC *) mymalloc(sizeof(*dev));
    102 	dev->fd = fd;
    103 	dev->name = mystrdup(name);
    104 	dev->timeout = timeout;
    105 	if (msg_verbose)
    106 	    msg_info("%s: opened entropy device %s", myname, name);
    107 	return (dev);
    108     }
    109 }
    110 
    111 /* tls_prng_dev_read - update internal PRNG from device */
    112 
    113 ssize_t tls_prng_dev_read(TLS_PRNG_SRC *dev, size_t len)
    114 {
    115     const char *myname = "tls_prng_dev_read";
    116     unsigned char buffer[UCHAR_MAX];
    117     ssize_t count;
    118     size_t  rand_bytes;
    119 
    120     if (len <= 0)
    121 	msg_panic("%s: bad read length: %ld", myname, (long) len);
    122 
    123     if (len > sizeof(buffer))
    124 	rand_bytes = sizeof(buffer);
    125     else
    126 	rand_bytes = len;
    127     errno = 0;
    128     count = timed_read(dev->fd, buffer, rand_bytes, dev->timeout, (void *) 0);
    129     if (count > 0) {
    130 	if (msg_verbose)
    131 	    msg_info("%s: read %ld bytes from entropy device %s",
    132 		     myname, (long) count, dev->name);
    133 	RAND_seed(buffer, count);
    134     } else {
    135 	if (msg_verbose)
    136 	    msg_info("%s: cannot read %ld bytes from entropy device %s: %m",
    137 		     myname, (long) rand_bytes, dev->name);
    138     }
    139     return (count);
    140 }
    141 
    142 /* tls_prng_dev_close - disconnect from EGD server */
    143 
    144 int     tls_prng_dev_close(TLS_PRNG_SRC *dev)
    145 {
    146     const char *myname = "tls_prng_dev_close";
    147     int     err;
    148 
    149     if (msg_verbose)
    150 	msg_info("%s: close entropy device %s", myname, dev->name);
    151     err = close(dev->fd);
    152     myfree(dev->name);
    153     myfree((void *) dev);
    154     return (err);
    155 }
    156 
    157 #endif
    158