xref: /netbsd-src/external/ibm-public/postfix/dist/src/tls/tls_prng_exch.c (revision e89934bbf778a6d6d6894877c4da59d0c7835b0f)
1 /*	$NetBSD: tls_prng_exch.c,v 1.2 2017/02/14 01:16:48 christos Exp $	*/
2 
3 /*++
4 /* NAME
5 /*	tls_prng_exch 3
6 /* SUMMARY
7 /*	maintain PRNG exchange file
8 /* SYNOPSIS
9 /*	#include <tls_prng_src.h>
10 /*
11 /*	TLS_PRNG_SRC *tls_prng_exch_open(name, timeout)
12 /*	const char *name;
13 /*	int	timeout;
14 /*
15 /*	void	tls_prng_exch_update(fh, length)
16 /*	TLS_PRNG_SRC *fh;
17 /*	size_t length;
18 /*
19 /*	void	tls_prng_exch_close(fh)
20 /*	TLS_PRNG_SRC *fh;
21 /* DESCRIPTION
22 /*	tls_prng_exch_open() opens the specified PRNG exchange file
23 /*	and returns a handle that should be used with all subsequent
24 /*	access.
25 /*
26 /*	tls_prng_exch_update() reads the requested number of bytes
27 /*	from the PRNG exchange file, updates the OpenSSL PRNG, and
28 /*	writes the requested number of bytes to the exchange file.
29 /*	The file is locked for exclusive access.
30 /*
31 /*	tls_prng_exch_close() closes the specified PRNG exchange
32 /*	file and releases memory that was allocated for the handle.
33 /*
34 /*	Arguments:
35 /* .IP name
36 /*	The name of the PRNG exchange file.
37 /* .IP length
38 /*	The number of bytes to read from/write to the entropy file.
39 /* .IP timeout
40 /*	Time limit on individual I/O operations.
41 /* DIAGNOSTICS
42 /*	All errors are fatal.
43 /* LICENSE
44 /* .ad
45 /* .fi
46 /*	The Secure Mailer license must be distributed with this software.
47 /* AUTHOR(S)
48 /*	Wietse Venema
49 /*	IBM T.J. Watson Research
50 /*	P.O. Box 704
51 /*	Yorktown Heights, NY 10598, USA
52 /*--*/
53 
54 /* System library. */
55 
56 #include <sys_defs.h>
57 #include <fcntl.h>
58 #include <unistd.h>
59 #include <limits.h>
60 
61 /* OpenSSL library. */
62 
63 #ifdef USE_TLS
64 #include <openssl/rand.h>		/* For the PRNG */
65 
66 /* Utility library. */
67 
68 #include <msg.h>
69 #include <mymalloc.h>
70 #include <iostuff.h>
71 #include <myflock.h>
72 
73 /* TLS library. */
74 
75 #include <tls_prng.h>
76 
77 /* Application specific. */
78 
79 #define TLS_PRNG_EXCH_SIZE	1024	/* XXX Why not configurable? */
80 
81 /* tls_prng_exch_open - open PRNG exchange file */
82 
tls_prng_exch_open(const char * name)83 TLS_PRNG_SRC *tls_prng_exch_open(const char *name)
84 {
85     const char *myname = "tls_prng_exch_open";
86     TLS_PRNG_SRC *eh;
87     int     fd;
88 
89     if ((fd = open(name, O_RDWR | O_CREAT, 0600)) < 0)
90 	msg_fatal("%s: cannot open PRNG exchange file %s: %m", myname, name);
91     eh = (TLS_PRNG_SRC *) mymalloc(sizeof(*eh));
92     eh->fd = fd;
93     eh->name = mystrdup(name);
94     eh->timeout = 0;
95     if (msg_verbose)
96 	msg_info("%s: opened PRNG exchange file %s", myname, name);
97     return (eh);
98 }
99 
100 /* tls_prng_exch_update - update PRNG exchange file */
101 
tls_prng_exch_update(TLS_PRNG_SRC * eh)102 void    tls_prng_exch_update(TLS_PRNG_SRC *eh)
103 {
104     unsigned char buffer[TLS_PRNG_EXCH_SIZE];
105     ssize_t count;
106 
107     /*
108      * Update the PRNG exchange file. Since other processes may have added
109      * entropy, we use a read-stir-write cycle.
110      */
111     if (myflock(eh->fd, INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) != 0)
112 	msg_fatal("cannot lock PRNG exchange file %s: %m", eh->name);
113     if (lseek(eh->fd, 0, SEEK_SET) < 0)
114 	msg_fatal("cannot seek PRNG exchange file %s: %m", eh->name);
115     if ((count = read(eh->fd, buffer, sizeof(buffer))) < 0)
116 	msg_fatal("cannot read PRNG exchange file %s: %m", eh->name);
117 
118     if (count > 0)
119 	RAND_seed(buffer, count);
120     RAND_bytes(buffer, sizeof(buffer));
121 
122     if (lseek(eh->fd, 0, SEEK_SET) < 0)
123 	msg_fatal("cannot seek PRNG exchange file %s: %m", eh->name);
124     if (write(eh->fd, buffer, sizeof(buffer)) != sizeof(buffer))
125 	msg_fatal("cannot write PRNG exchange file %s: %m", eh->name);
126     if (myflock(eh->fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) != 0)
127 	msg_fatal("cannot unlock PRNG exchange file %s: %m", eh->name);
128 }
129 
130 /* tls_prng_exch_close - close PRNG exchange file */
131 
tls_prng_exch_close(TLS_PRNG_SRC * eh)132 void    tls_prng_exch_close(TLS_PRNG_SRC *eh)
133 {
134     const char *myname = "tls_prng_exch_close";
135 
136     if (close(eh->fd) < 0)
137 	msg_fatal("close PRNG exchange file %s: %m", eh->name);
138     if (msg_verbose)
139 	msg_info("%s: closed PRNG exchange file %s", myname, eh->name);
140     myfree(eh->name);
141     myfree((void *) eh);
142 }
143 
144 #endif
145