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