xref: /netbsd-src/external/ibm-public/postfix/dist/src/tls/tls_prng_dev.c (revision e89934bbf778a6d6d6894877c4da59d0c7835b0f)
1 /*	$NetBSD: tls_prng_dev.c,v 1.2 2017/02/14 01:16:48 christos Exp $	*/
2 
3 /*++
4 /* NAME
5 /*	tls_prng_dev 3
6 /* SUMMARY
7 /*	seed OpenSSL PRNG from entropy device
8 /* SYNOPSIS
9 /*	#include <tls_prng_src.h>
10 /*
11 /*	TLS_PRNG_SRC *tls_prng_dev_open(name, timeout)
12 /*	const char *name;
13 /*	int	timeout;
14 /*
15 /*	ssize_t tls_prng_dev_read(dev, length)
16 /*	TLS_PRNG_SRC *dev;
17 /*	size_t length;
18 /*
19 /*	int	tls_prng_dev_close(dev)
20 /*	TLS_PRNG_SRC *dev;
21 /* DESCRIPTION
22 /*	tls_prng_dev_open() opens the specified entropy device
23 /*	and returns a handle that should be used with all subsequent
24 /*	access.
25 /*
26 /*	tls_prng_dev_read() reads the requested number of bytes from
27 /*	the entropy device and updates the OpenSSL PRNG.
28 /*
29 /*	tls_prng_dev_close() closes the specified entropy device
30 /*	and releases memory that was allocated for the handle.
31 /*
32 /*	Arguments:
33 /* .IP name
34 /*	The pathname of the entropy device.
35 /* .IP length
36 /*	The number of bytes to read from the entropy device.
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_dev_open() returns a null pointer on error.
42 /*
43 /*	tls_prng_dev_read() returns -1 on error, the number
44 /*	of bytes received on success.
45 /*
46 /*	tls_prng_dev_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 <fcntl.h>
64 #include <unistd.h>
65 #include <limits.h>
66 #include <errno.h>
67 
68 #ifndef UCHAR_MAX
69 #define UCHAR_MAX 0xff
70 #endif
71 
72 /* OpenSSL library. */
73 
74 #ifdef USE_TLS
75 #include <openssl/rand.h>		/* For the PRNG */
76 
77 /* Utility library. */
78 
79 #include <msg.h>
80 #include <mymalloc.h>
81 #include <connect.h>
82 #include <iostuff.h>
83 
84 /* TLS library. */
85 
86 #include <tls_prng.h>
87 
88 /* tls_prng_dev_open - open entropy device */
89 
tls_prng_dev_open(const char * name,int timeout)90 TLS_PRNG_SRC *tls_prng_dev_open(const char *name, int timeout)
91 {
92     const char *myname = "tls_prng_dev_open";
93     TLS_PRNG_SRC *dev;
94     int     fd;
95 
96     if ((fd = open(name, O_RDONLY, 0)) < 0) {
97 	if (msg_verbose)
98 	    msg_info("%s: cannot open entropy device %s: %m", myname, name);
99 	return (0);
100     } else {
101 	dev = (TLS_PRNG_SRC *) mymalloc(sizeof(*dev));
102 	dev->fd = fd;
103 	dev->name = mystrdup(name);
104 	dev->timeout = timeout;
105 	if (msg_verbose)
106 	    msg_info("%s: opened entropy device %s", myname, name);
107 	return (dev);
108     }
109 }
110 
111 /* tls_prng_dev_read - update internal PRNG from device */
112 
tls_prng_dev_read(TLS_PRNG_SRC * dev,size_t len)113 ssize_t tls_prng_dev_read(TLS_PRNG_SRC *dev, size_t len)
114 {
115     const char *myname = "tls_prng_dev_read";
116     unsigned char buffer[UCHAR_MAX];
117     ssize_t count;
118     size_t  rand_bytes;
119 
120     if (len <= 0)
121 	msg_panic("%s: bad read length: %ld", myname, (long) len);
122 
123     if (len > sizeof(buffer))
124 	rand_bytes = sizeof(buffer);
125     else
126 	rand_bytes = len;
127     errno = 0;
128     count = timed_read(dev->fd, buffer, rand_bytes, dev->timeout, (void *) 0);
129     if (count > 0) {
130 	if (msg_verbose)
131 	    msg_info("%s: read %ld bytes from entropy device %s",
132 		     myname, (long) count, dev->name);
133 	RAND_seed(buffer, count);
134     } else {
135 	if (msg_verbose)
136 	    msg_info("%s: cannot read %ld bytes from entropy device %s: %m",
137 		     myname, (long) rand_bytes, dev->name);
138     }
139     return (count);
140 }
141 
142 /* tls_prng_dev_close - disconnect from EGD server */
143 
tls_prng_dev_close(TLS_PRNG_SRC * dev)144 int     tls_prng_dev_close(TLS_PRNG_SRC *dev)
145 {
146     const char *myname = "tls_prng_dev_close";
147     int     err;
148 
149     if (msg_verbose)
150 	msg_info("%s: close entropy device %s", myname, dev->name);
151     err = close(dev->fd);
152     myfree(dev->name);
153     myfree((void *) dev);
154     return (err);
155 }
156 
157 #endif
158