7 /* seed OpenSSL PRNG from EGD server
9 /* #include <tls_prng_src.h>
11 /* TLS_PRNG_SRC *tls_prng_egd_open(name, timeout)
15 /* ssize_t tls_prng_egd_read(egd, length)
19 /* int tls_prng_egd_close(egd)
22 /* tls_prng_egd_open() connect to the specified UNIX-domain service
23 /* and returns a handle that should be used with all subsequent
26 /* tls_prng_egd_read() reads the requested number of bytes from
27 /* the EGD server and updates the OpenSSL PRNG.
29 /* tls_prng_egd_close() disconnects from the specified EGD server
30 /* and releases memory that was allocated for the handle.
34 /* The UNIX-domain pathname of the EGD service.
36 /* The number of bytes to read from the EGD server.
37 /* Request lengths will be truncated at 255 bytes.
39 /* Time limit on individual I/O operations.
41 /* tls_prng_egd_open() returns a null pointer on error.
43 /* tls_prng_egd_read() returns -1 on error, the number
44 /* of bytes received on success.
46 /* tls_prng_egd_close() returns -1 on error, 0 on success.
48 /* In all cases the errno variable indicates the type of error.
52 /* The Secure Mailer license must be distributed with this software.
55 /* IBM T.J. Watson Research
57 /* Yorktown Heights, NY 10598, USA
67 #define UCHAR_MAX 0xff
70 /* OpenSSL library. */
73 #include <openssl/rand.h> /* For the PRNG */
75 /* Utility library. */
86 /* tls_prng_egd_open - connect to EGD server */
88 TLS_PRNG_SRC
*tls_prng_egd_open(const char *name
, int timeout
)
90 const char *myname
= "tls_prng_egd_open";
95 msg_info("%s: connect to EGD server %s", myname
, name
);
97 if ((fd
= unix_connect(name
, BLOCKING
, timeout
)) < 0) {
99 msg_info("%s: cannot connect to EGD server %s: %m", myname
, name
);
102 egd
= (TLS_PRNG_SRC
*) mymalloc(sizeof(*egd
));
104 egd
->name
= mystrdup(name
);
105 egd
->timeout
= timeout
;
107 msg_info("%s: connected to EGD server %s", myname
, name
);
112 /* tls_prng_egd_read - update internal PRNG from EGD server */
114 ssize_t
tls_prng_egd_read(TLS_PRNG_SRC
*egd
, size_t len
)
116 const char *myname
= "tls_prng_egd_read";
117 unsigned char buffer
[UCHAR_MAX
];
121 msg_panic("%s: bad length %ld", myname
, (long) len
);
124 buffer
[1] = (len
> UCHAR_MAX
? UCHAR_MAX
: len
);
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
);
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
);
135 if (count
> sizeof(buffer
))
136 count
= sizeof(buffer
);
138 msg_info("EGD server %s reports zero bytes available", egd
->name
);
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
);
147 msg_info("%s: got %ld bytes from EGD server %s", myname
,
148 (long) count
, egd
->name
);
149 RAND_seed(buffer
, count
);
153 /* tls_prng_egd_close - disconnect from EGD server */
155 int tls_prng_egd_close(TLS_PRNG_SRC
*egd
)
157 const char *myname
= "tls_prng_egd_close";
161 msg_info("%s: close EGD server %s", myname
, egd
->name
);
162 err
= close(egd
->fd
);
164 myfree((char *) egd
);