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 83 TLS_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 102 void 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 132 void 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