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