1/*++ 2/* NAME 3/* tls_prng_dev 3 4/* SUMMARY 5/* seed OpenSSL PRNG from entropy device 6/* SYNOPSIS 7/* #include <tls_prng_src.h> 8/* 9/* TLS_PRNG_SRC *tls_prng_dev_open(name, timeout) 10/* const char *name; 11/* int timeout; 12/* 13/* ssize_t tls_prng_dev_read(dev, length) 14/* TLS_PRNG_SRC *dev; 15/* size_t length; 16/* 17/* int tls_prng_dev_close(dev) 18/* TLS_PRNG_SRC *dev; 19/* DESCRIPTION 20/* tls_prng_dev_open() opens the specified entropy device 21/* and returns a handle that should be used with all subsequent 22/* access. 23/* 24/* tls_prng_dev_read() reads the requested number of bytes from 25/* the entropy device and updates the OpenSSL PRNG. 26/* 27/* tls_prng_dev_close() closes the specified entropy device 28/* and releases memory that was allocated for the handle. 29/* 30/* Arguments: 31/* .IP name 32/* The pathname of the entropy device. 33/* .IP length 34/* The number of bytes to read from the entropy device. 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_dev_open() returns a null pointer on error. 40/* 41/* tls_prng_dev_read() returns -1 on error, the number 42/* of bytes received on success. 43/* 44/* tls_prng_dev_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 <fcntl.h> 62#include <unistd.h> 63#include <limits.h> 64#include <errno.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_dev_open - open entropy device */ 87 88TLS_PRNG_SRC *tls_prng_dev_open(const char *name, int timeout) 89{ 90 const char *myname = "tls_prng_dev_open"; 91 TLS_PRNG_SRC *dev; 92 int fd; 93 94 if ((fd = open(name, O_RDONLY, 0)) < 0) { 95 if (msg_verbose) 96 msg_info("%s: cannot open entropy device %s: %m", myname, name); 97 return (0); 98 } else { 99 dev = (TLS_PRNG_SRC *) mymalloc(sizeof(*dev)); 100 dev->fd = fd; 101 dev->name = mystrdup(name); 102 dev->timeout = timeout; 103 if (msg_verbose) 104 msg_info("%s: opened entropy device %s", myname, name); 105 return (dev); 106 } 107} 108 109/* tls_prng_dev_read - update internal PRNG from device */ 110 111ssize_t tls_prng_dev_read(TLS_PRNG_SRC *dev, size_t len) 112{ 113 const char *myname = "tls_prng_dev_read"; 114 unsigned char buffer[UCHAR_MAX]; 115 ssize_t count; 116 size_t rand_bytes; 117 118 if (len <= 0) 119 msg_panic("%s: bad read length: %ld", myname, (long) len); 120 121 if (len > sizeof(buffer)) 122 rand_bytes = sizeof(buffer); 123 else 124 rand_bytes = len; 125 errno = 0; 126 count = timed_read(dev->fd, buffer, rand_bytes, dev->timeout, (void *) 0); 127 if (count > 0) { 128 if (msg_verbose) 129 msg_info("%s: read %ld bytes from entropy device %s", 130 myname, (long) count, dev->name); 131 RAND_seed(buffer, count); 132 } else { 133 if (msg_verbose) 134 msg_info("%s: cannot read %ld bytes from entropy device %s: %m", 135 myname, (long) rand_bytes, dev->name); 136 } 137 return (count); 138} 139 140/* tls_prng_dev_close - disconnect from EGD server */ 141 142int tls_prng_dev_close(TLS_PRNG_SRC *dev) 143{ 144 const char *myname = "tls_prng_dev_close"; 145 int err; 146 147 if (msg_verbose) 148 msg_info("%s: close entropy device %s", myname, dev->name); 149 err = close(dev->fd); 150 myfree(dev->name); 151 myfree((char *) dev); 152 return (err); 153} 154 155#endif 156