1/*++ 2/* NAME 3/* tls_prng_exch 3 4/* SUMMARY 5/* maintain PRNG exchange file 6/* SYNOPSIS 7/* #include <tls_prng_src.h> 8/* 9/* TLS_PRNG_SRC *tls_prng_exch_open(name, timeout) 10/* const char *name; 11/* int timeout; 12/* 13/* void tls_prng_exch_update(fh, length) 14/* TLS_PRNG_SRC *fh; 15/* size_t length; 16/* 17/* void tls_prng_exch_close(fh) 18/* TLS_PRNG_SRC *fh; 19/* DESCRIPTION 20/* tls_prng_exch_open() opens the specified PRNG exchange file 21/* and returns a handle that should be used with all subsequent 22/* access. 23/* 24/* tls_prng_exch_update() reads the requested number of bytes 25/* from the PRNG exchange file, updates the OpenSSL PRNG, and 26/* writes the requested number of bytes to the exchange file. 27/* The file is locked for exclusive access. 28/* 29/* tls_prng_exch_close() closes the specified PRNG exchange 30/* file and releases memory that was allocated for the handle. 31/* 32/* Arguments: 33/* .IP name 34/* The name of the PRNG exchange file. 35/* .IP length 36/* The number of bytes to read from/write to the entropy file. 37/* .IP timeout 38/* Time limit on individual I/O operations. 39/* DIAGNOSTICS 40/* All errors are fatal. 41/* LICENSE 42/* .ad 43/* .fi 44/* The Secure Mailer license must be distributed with this software. 45/* AUTHOR(S) 46/* Wietse Venema 47/* IBM T.J. Watson Research 48/* P.O. Box 704 49/* Yorktown Heights, NY 10598, USA 50/*--*/ 51 52/* System library. */ 53 54#include <sys_defs.h> 55#include <fcntl.h> 56#include <unistd.h> 57#include <limits.h> 58 59/* OpenSSL library. */ 60 61#ifdef USE_TLS 62#include <openssl/rand.h> /* For the PRNG */ 63 64/* Utility library. */ 65 66#include <msg.h> 67#include <mymalloc.h> 68#include <iostuff.h> 69#include <myflock.h> 70 71/* TLS library. */ 72 73#include <tls_prng.h> 74 75/* Application specific. */ 76 77#define TLS_PRNG_EXCH_SIZE 1024 /* XXX Why not configurable? */ 78 79/* tls_prng_exch_open - open PRNG exchange file */ 80 81TLS_PRNG_SRC *tls_prng_exch_open(const char *name) 82{ 83 const char *myname = "tls_prng_exch_open"; 84 TLS_PRNG_SRC *eh; 85 int fd; 86 87 if ((fd = open(name, O_RDWR | O_CREAT, 0600)) < 0) 88 msg_fatal("%s: cannot open PRNG exchange file %s: %m", myname, name); 89 eh = (TLS_PRNG_SRC *) mymalloc(sizeof(*eh)); 90 eh->fd = fd; 91 eh->name = mystrdup(name); 92 eh->timeout = 0; 93 if (msg_verbose) 94 msg_info("%s: opened PRNG exchange file %s", myname, name); 95 return (eh); 96} 97 98/* tls_prng_exch_update - update PRNG exchange file */ 99 100void tls_prng_exch_update(TLS_PRNG_SRC *eh) 101{ 102 unsigned char buffer[TLS_PRNG_EXCH_SIZE]; 103 ssize_t count; 104 105 /* 106 * Update the PRNG exchange file. Since other processes may have added 107 * entropy, we use a read-stir-write cycle. 108 */ 109 if (myflock(eh->fd, INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) != 0) 110 msg_fatal("cannot lock PRNG exchange file %s: %m", eh->name); 111 if (lseek(eh->fd, 0, SEEK_SET) < 0) 112 msg_fatal("cannot seek PRNG exchange file %s: %m", eh->name); 113 if ((count = read(eh->fd, buffer, sizeof(buffer))) < 0) 114 msg_fatal("cannot read PRNG exchange file %s: %m", eh->name); 115 116 if (count > 0) 117 RAND_seed(buffer, count); 118 RAND_bytes(buffer, sizeof(buffer)); 119 120 if (lseek(eh->fd, 0, SEEK_SET) < 0) 121 msg_fatal("cannot seek PRNG exchange file %s: %m", eh->name); 122 if (write(eh->fd, buffer, sizeof(buffer)) != sizeof(buffer)) 123 msg_fatal("cannot write PRNG exchange file %s: %m", eh->name); 124 if (myflock(eh->fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) != 0) 125 msg_fatal("cannot unlock PRNG exchange file %s: %m", eh->name); 126} 127 128/* tls_prng_exch_close - close PRNG exchange file */ 129 130void tls_prng_exch_close(TLS_PRNG_SRC *eh) 131{ 132 const char *myname = "tls_prng_exch_close"; 133 134 if (close(eh->fd) < 0) 135 msg_fatal("close PRNG exchange file %s: %m", eh->name); 136 if (msg_verbose) 137 msg_info("%s: closed PRNG exchange file %s", myname, eh->name); 138 myfree(eh->name); 139 myfree((char *) eh); 140} 141 142#endif 143