1/*++
2/* NAME
3/*	tls_prng_file 3
4/* SUMMARY
5/*	seed OpenSSL PRNG from entropy file
6/* SYNOPSIS
7/*	#include <tls_prng_src.h>
8/*
9/*	TLS_PRNG_SRC *tls_prng_file_open(name, timeout)
10/*	const char *name;
11/*	int	timeout;
12/*
13/*	ssize_t tls_prng_file_read(fh, length)
14/*	TLS_PRNG_SRC *fh;
15/*	size_t length;
16/*
17/*	int	tls_prng_file_close(fh)
18/*	TLS_PRNG_SRC *fh;
19/* DESCRIPTION
20/*	tls_prng_file_open() open the specified file and returns
21/*	a handle that should be used with all subsequent access.
22/*
23/*	tls_prng_file_read() reads the requested number of bytes from
24/*	the entropy file and updates the OpenSSL PRNG. The file is not
25/*	locked for shared or exclusive access.
26/*
27/*	tls_prng_file_close() closes the specified entropy file
28/*	and releases memory that was allocated for the handle.
29/*
30/*	Arguments:
31/* .IP name
32/*	The pathname of the entropy file.
33/* .IP length
34/*	The number of bytes to read from the entropy file.
35/* .IP timeout
36/*	Time limit on individual I/O operations.
37/* DIAGNOSTICS
38/*	tls_prng_file_open() returns a null pointer on error.
39/*
40/*	tls_prng_file_read() returns -1 on error, the number
41/*	of bytes received on success.
42/*
43/*	tls_prng_file_close() returns -1 on error, 0 on success.
44/*
45/*	In all cases the errno variable indicates the type of error.
46/* LICENSE
47/* .ad
48/* .fi
49/*	The Secure Mailer license must be distributed with this software.
50/* AUTHOR(S)
51/*	Wietse Venema
52/*	IBM T.J. Watson Research
53/*	P.O. Box 704
54/*	Yorktown Heights, NY 10598, USA
55/*--*/
56
57/* System library. */
58
59#include <sys_defs.h>
60#include <fcntl.h>
61#include <unistd.h>
62#include <limits.h>
63#include <errno.h>
64
65/* OpenSSL library. */
66
67#ifdef USE_TLS
68#include <openssl/rand.h>		/* For the PRNG */
69
70/* Utility library. */
71
72#include <msg.h>
73#include <mymalloc.h>
74#include <connect.h>
75#include <iostuff.h>
76
77/* TLS library. */
78
79#include <tls_prng.h>
80
81/* tls_prng_file_open - open entropy file */
82
83TLS_PRNG_SRC *tls_prng_file_open(const char *name, int timeout)
84{
85    const char *myname = "tls_prng_file_open";
86    TLS_PRNG_SRC *fh;
87    int     fd;
88
89    if ((fd = open(name, O_RDONLY, 0)) < 0) {
90	if (msg_verbose)
91	    msg_info("%s: cannot open entropy file %s: %m", myname, name);
92	return (0);
93    } else {
94	fh = (TLS_PRNG_SRC *) mymalloc(sizeof(*fh));
95	fh->fd = fd;
96	fh->name = mystrdup(name);
97	fh->timeout = timeout;
98	if (msg_verbose)
99	    msg_info("%s: opened entropy file %s", myname, name);
100	return (fh);
101    }
102}
103
104/* tls_prng_file_read - update internal PRNG from entropy file */
105
106ssize_t tls_prng_file_read(TLS_PRNG_SRC *fh, size_t len)
107{
108    const char *myname = "tls_prng_file_read";
109    char    buffer[8192];
110    ssize_t to_read;
111    ssize_t count;
112
113    if (msg_verbose)
114	msg_info("%s: seed internal pool from file %s", myname, fh->name);
115
116    if (lseek(fh->fd, 0, SEEK_SET) < 0) {
117	if (msg_verbose)
118	    msg_info("cannot seek entropy file %s: %m", fh->name);
119	return (-1);
120    }
121    errno = 0;
122    for (to_read = len; to_read > 0; to_read -= count) {
123	if ((count = timed_read(fh->fd, buffer, to_read > sizeof(buffer) ?
124				sizeof(buffer) : to_read,
125				fh->timeout, (void *) 0)) < 0) {
126	    if (msg_verbose)
127		msg_info("cannot read entropy file %s: %m", fh->name);
128	    return (-1);
129	}
130	if (count == 0)
131	    break;
132	RAND_seed(buffer, count);
133    }
134    if (msg_verbose)
135	msg_info("read %ld bytes from entropy file %s: %m",
136		 (long) (len - to_read), fh->name);
137    return (len - to_read);
138}
139
140/* tls_prng_file_close - close entropy file */
141
142int     tls_prng_file_close(TLS_PRNG_SRC *fh)
143{
144    const char *myname = "tls_prng_file_close";
145    int     err;
146
147    if (msg_verbose)
148	msg_info("%s: close entropy file %s", myname, fh->name);
149    err = close(fh->fd);
150    myfree(fh->name);
151    myfree((char *) fh);
152    return (err);
153}
154
155#endif
156