1 /* $NetBSD: tls_prng_egd.c,v 1.2 2017/02/14 01:16:48 christos 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
tls_prng_egd_open(const char * name,int timeout)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
tls_prng_egd_read(TLS_PRNG_SRC * egd,size_t len)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
tls_prng_egd_close(TLS_PRNG_SRC * egd)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((void *) egd);
165 return (err);
166 }
167
168 #endif
169