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