Home | History | Annotate | Line # | Download | only in tls
      1 /*	$NetBSD: tls_prng_egd.c,v 1.2 2017/02/14 01:16:48 christos Exp $	*/
      2 
      3 /*++
      4 /* NAME
      5 /*	tls_prng_egd 3
      6 /* SUMMARY
      7 /*	seed OpenSSL PRNG from EGD server
      8 /* SYNOPSIS
      9 /*	#include <tls_prng_src.h>
     10 /*
     11 /*	TLS_PRNG_SRC *tls_prng_egd_open(name, timeout)
     12 /*	const char *name;
     13 /*	int	timeout;
     14 /*
     15 /*	ssize_t tls_prng_egd_read(egd, length)
     16 /*	TLS_PRNG_SRC *egd;
     17 /*	size_t length;
     18 /*
     19 /*	int	tls_prng_egd_close(egd)
     20 /*	TLS_PRNG_SRC *egd;
     21 /* DESCRIPTION
     22 /*	tls_prng_egd_open() connect to the specified UNIX-domain service
     23 /*	and returns a handle that should be used with all subsequent
     24 /*	access.
     25 /*
     26 /*	tls_prng_egd_read() reads the requested number of bytes from
     27 /*	the EGD server and updates the OpenSSL PRNG.
     28 /*
     29 /*	tls_prng_egd_close() disconnects from the specified EGD server
     30 /*	and releases memory that was allocated for the handle.
     31 /*
     32 /*	Arguments:
     33 /* .IP name
     34 /*	The UNIX-domain pathname of the EGD service.
     35 /* .IP length
     36 /*	The number of bytes to read from the EGD server.
     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_egd_open() returns a null pointer on error.
     42 /*
     43 /*	tls_prng_egd_read() returns -1 on error, the number
     44 /*	of bytes received on success.
     45 /*
     46 /*	tls_prng_egd_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 <unistd.h>
     64 #include <limits.h>
     65 
     66 #ifndef UCHAR_MAX
     67 #define UCHAR_MAX 0xff
     68 #endif
     69 
     70 /* OpenSSL library. */
     71 
     72 #ifdef USE_TLS
     73 #include <openssl/rand.h>		/* For the PRNG */
     74 
     75 /* Utility library. */
     76 
     77 #include <msg.h>
     78 #include <mymalloc.h>
     79 #include <connect.h>
     80 #include <iostuff.h>
     81 
     82 /* TLS library. */
     83 
     84 #include <tls_prng.h>
     85 
     86 /* tls_prng_egd_open - connect to EGD server */
     87 
     88 TLS_PRNG_SRC *tls_prng_egd_open(const char *name, int timeout)
     89 {
     90     const char *myname = "tls_prng_egd_open";
     91     TLS_PRNG_SRC *egd;
     92     int     fd;
     93 
     94     if (msg_verbose)
     95 	msg_info("%s: connect to EGD server %s", myname, name);
     96 
     97     if ((fd = unix_connect(name, BLOCKING, timeout)) < 0) {
     98 	if (msg_verbose)
     99 	    msg_info("%s: cannot connect to EGD server %s: %m", myname, name);
    100 	return (0);
    101     } else {
    102 	egd = (TLS_PRNG_SRC *) mymalloc(sizeof(*egd));
    103 	egd->fd = fd;
    104 	egd->name = mystrdup(name);
    105 	egd->timeout = timeout;
    106 	if (msg_verbose)
    107 	    msg_info("%s: connected to EGD server %s", myname, name);
    108 	return (egd);
    109     }
    110 }
    111 
    112 /* tls_prng_egd_read - update internal PRNG from EGD server */
    113 
    114 ssize_t tls_prng_egd_read(TLS_PRNG_SRC *egd, size_t len)
    115 {
    116     const char *myname = "tls_prng_egd_read";
    117     unsigned char buffer[UCHAR_MAX];
    118     ssize_t count;
    119 
    120     if (len <= 0)
    121 	msg_panic("%s: bad length %ld", myname, (long) len);
    122 
    123     buffer[0] = 1;
    124     buffer[1] = (len > UCHAR_MAX ? UCHAR_MAX : len);
    125 
    126     if (timed_write(egd->fd, buffer, 2, egd->timeout, (void *) 0) != 2) {
    127 	msg_info("cannot write to EGD server %s: %m", egd->name);
    128 	return (-1);
    129     }
    130     if (timed_read(egd->fd, buffer, 1, egd->timeout, (void *) 0) != 1) {
    131 	msg_info("cannot read from EGD server %s: %m", egd->name);
    132 	return (-1);
    133     }
    134     count = buffer[0];
    135     if (count > sizeof(buffer))
    136 	count = sizeof(buffer);
    137     if (count == 0) {
    138 	msg_info("EGD server %s reports zero bytes available", egd->name);
    139 	return (-1);
    140     }
    141     if (timed_read(egd->fd, buffer, count, egd->timeout, (void *) 0) != count) {
    142 	msg_info("cannot read %ld bytes from EGD server %s: %m",
    143 		 (long) count, egd->name);
    144 	return (-1);
    145     }
    146     if (msg_verbose)
    147 	msg_info("%s: got %ld bytes from EGD server %s", myname,
    148 		 (long) count, egd->name);
    149     RAND_seed(buffer, count);
    150     return (count);
    151 }
    152 
    153 /* tls_prng_egd_close - disconnect from EGD server */
    154 
    155 int     tls_prng_egd_close(TLS_PRNG_SRC *egd)
    156 {
    157     const char *myname = "tls_prng_egd_close";
    158     int     err;
    159 
    160     if (msg_verbose)
    161 	msg_info("%s: close EGD server %s", myname, egd->name);
    162     err = close(egd->fd);
    163     myfree(egd->name);
    164     myfree((void *) egd);
    165     return (err);
    166 }
    167 
    168 #endif
    169