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