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