]> git.ipfire.org Git - thirdparty/rng-tools.git/blob - rngd_entsource.c
s/list_add/src_list_add/
[thirdparty/rng-tools.git] / rngd_entsource.c
1 /*
2 * rngd_entsource.c -- Entropy source and conditioning
3 *
4 * Copyright (C) 2001 Philipp Rumpf
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #define _GNU_SOURCE
22
23 #ifndef HAVE_CONFIG_H
24 #error Invalid or missing autoconf build environment
25 #endif
26
27 #include "rng-tools-config.h"
28
29 #include <unistd.h>
30 #include <stdint.h>
31 #include <stdlib.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <fcntl.h>
35 #include <errno.h>
36 #include <syslog.h>
37 #include <string.h>
38
39 #include "rngd.h"
40 #include "fips.h"
41 #include "exits.h"
42 #include "rngd_entsource.h"
43
44
45 /* The overhead incured when tpm returns the random nos as per TCG spec
46 * it is 14 bytes.*/
47 #define TPM_GET_RNG_OVERHEAD 14
48
49 /* Read data from the entropy source */
50 int xread(void *buf, size_t size, struct rng *ent_src)
51 {
52 size_t off = 0;
53 ssize_t r;
54
55 while (size > 0) {
56 do {
57 r = read(ent_src->rng_fd, buf + off, size);
58 } while ((r == -1) && (errno == EINTR));
59 if (r <= 0)
60 break;
61 off += r;
62 size -= r;
63 }
64
65 if (size) {
66 message(LOG_DAEMON|LOG_ERR, "read error\n");
67 return -1;
68 }
69 return 0;
70 }
71
72 /* tpm rng read call to kernel has 13 bytes of overhead
73 * the logic to process this involves reading to a temporary_buf
74 * and copying the no generated to buf */
75 int xread_tpm(void *buf, size_t size, struct rng *ent_src)
76 {
77 size_t bytes_read = 0;
78 ssize_t r;
79 int retval;
80 unsigned char *temp_buf = NULL;
81 unsigned char rng_cmd[] = {
82 0, 193, /* TPM_TAG_RQU_COMMAND */
83 0, 0, 0, 14, /* length */
84 0, 0, 0, 70, /* TPM_ORD_GetRandom */
85 0, 0, 0, 0, /* number of bytes to return */
86 };
87 char *offset;
88
89 ent_src->rng_fd = open(ent_src->rng_name, O_RDWR);
90 if (ent_src->rng_fd == -1) {
91 return -1;
92 }
93
94 temp_buf = (unsigned char *) malloc(size + TPM_GET_RNG_OVERHEAD);
95 memset(temp_buf, 0, (size+TPM_GET_RNG_OVERHEAD));
96 if (temp_buf == NULL) {
97 message(LOG_ERR|LOG_INFO,"No memory");
98 return -1;
99 }
100 /* 32 bits has been reserved for random byte size */
101 rng_cmd[13] = (unsigned char)(size & 0xFF);
102 rng_cmd[12] = (unsigned char)((size >> 8) & 0xFF);
103 rng_cmd[11] = (unsigned char)((size >> 16) & 0xFF);
104 rng_cmd[10] = (unsigned char)((size >> 24) & 0xFF);
105 offset = buf;
106 while (bytes_read < size) {
107 r=0;
108 while (r < sizeof(rng_cmd)) {
109 retval = write(ent_src->rng_fd,
110 rng_cmd + r,
111 sizeof(rng_cmd) - r);
112 if (retval < 0) {
113 message(LOG_ERR|LOG_INFO,
114 "Error writing %s\n",
115 ent_src->rng_name);
116 retval = -1;
117 goto error_out;
118 }
119 r += retval;
120 }
121 if (r < sizeof(rng_cmd)) {
122 message(LOG_ERR|LOG_INFO,
123 "Error writing %s\n", ent_src->rng_name);
124 retval = -1;
125 goto error_out;
126 }
127 r = read(ent_src->rng_fd, temp_buf,size);
128 r = (r - TPM_GET_RNG_OVERHEAD);
129 bytes_read = bytes_read + r;
130 if (bytes_read > size) {
131 memcpy(offset,temp_buf + TPM_GET_RNG_OVERHEAD,
132 r - (bytes_read - size));
133 break;
134 }
135 memcpy(offset, temp_buf + TPM_GET_RNG_OVERHEAD, r);
136 offset = offset + r;
137 }
138 retval = 0;
139 error_out:
140 close(ent_src->rng_fd);
141 free(temp_buf);
142 return retval;
143 }
144
145 /* Initialize entropy source */
146 static int discard_initial_data(struct rng *ent_src)
147 {
148 /* Trash 32 bits of what is probably stale (non-random)
149 * initial state from the RNG. For Intel's, 8 bits would
150 * be enough, but since AMD's generates 32 bits at a time...
151 *
152 * The kernel drivers should be doing this at device powerup,
153 * but at least up to 2.4.24, it doesn't. */
154 unsigned char tempbuf[4];
155 xread(tempbuf, sizeof tempbuf, ent_src);
156
157 /* Return 32 bits of bootstrap data */
158 xread(tempbuf, sizeof tempbuf, ent_src);
159
160 return tempbuf[0] | (tempbuf[1] << 8) |
161 (tempbuf[2] << 16) | (tempbuf[3] << 24);
162 }
163
164 /*
165 * Open entropy source, and initialize it
166 */
167 int init_entropy_source(struct rng *ent_src)
168 {
169 ent_src->rng_fd = open(ent_src->rng_name, O_RDONLY);
170 if (ent_src->rng_fd == -1) {
171 return 1;
172 }
173 src_list_add(ent_src);
174 /* Bootstrap FIPS tests */
175 ent_src->fipsctx = malloc(sizeof(fips_ctx_t));
176 fips_init(ent_src->fipsctx, discard_initial_data(ent_src));
177 return 0;
178 }
179
180 /*
181 * Open tpm entropy source, and initialize it
182 */
183 int init_tpm_entropy_source(struct rng *ent_src)
184 {
185 ent_src->rng_fd = open(ent_src->rng_name, O_RDWR);
186 if (ent_src->rng_fd == -1) {
187 return 1;
188 }
189 src_list_add(ent_src);
190 /* Bootstrap FIPS tests */
191 ent_src->fipsctx = malloc(sizeof(fips_ctx_t));
192 fips_init(ent_src->fipsctx, 0);
193 close(ent_src->rng_fd);
194 return 0;
195 }