]> git.ipfire.org Git - thirdparty/rng-tools.git/blame - rngd_entsource.c
Release version 5.
[thirdparty/rng-tools.git] / rngd_entsource.c
CommitLineData
61af3de3
JG
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.
d1b4c504 10 *
61af3de3
JG
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
d32709d1 18 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
61af3de3
JG
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>
2a014536 38#include <stddef.h>
61af3de3
JG
39
40#include "rngd.h"
41#include "fips.h"
42#include "exits.h"
43#include "rngd_entsource.h"
44
45
d1b4c504
JG
46/* The overhead incured when tpm returns the random nos as per TCG spec
47 * it is 14 bytes.*/
48#define TPM_GET_RNG_OVERHEAD 14
61af3de3
JG
49
50/* Read data from the entropy source */
d1b4c504 51int xread(void *buf, size_t size, struct rng *ent_src)
61af3de3
JG
52{
53 size_t off = 0;
54 ssize_t r;
55
56 while (size > 0) {
57 do {
d1b4c504 58 r = read(ent_src->rng_fd, buf + off, size);
61af3de3
JG
59 } while ((r == -1) && (errno == EINTR));
60 if (r <= 0)
61 break;
62 off += r;
63 size -= r;
64 }
65
66 if (size) {
67 message(LOG_DAEMON|LOG_ERR, "read error\n");
d1b4c504
JG
68 return -1;
69 }
70 return 0;
71}
72
73/* tpm rng read call to kernel has 13 bytes of overhead
74 * the logic to process this involves reading to a temporary_buf
75 * and copying the no generated to buf */
76int xread_tpm(void *buf, size_t size, struct rng *ent_src)
77{
78 size_t bytes_read = 0;
79 ssize_t r;
80 int retval;
81 unsigned char *temp_buf = NULL;
82 unsigned char rng_cmd[] = {
83 0, 193, /* TPM_TAG_RQU_COMMAND */
84 0, 0, 0, 14, /* length */
85 0, 0, 0, 70, /* TPM_ORD_GetRandom */
86 0, 0, 0, 0, /* number of bytes to return */
87 };
88 char *offset;
89
90 ent_src->rng_fd = open(ent_src->rng_name, O_RDWR);
91 if (ent_src->rng_fd == -1) {
2a014536 92 message(LOG_ERR|LOG_INFO,"Unable to open file: %s",ent_src->rng_name);
d1b4c504
JG
93 return -1;
94 }
95
96 temp_buf = (unsigned char *) malloc(size + TPM_GET_RNG_OVERHEAD);
97 memset(temp_buf, 0, (size+TPM_GET_RNG_OVERHEAD));
98 if (temp_buf == NULL) {
99 message(LOG_ERR|LOG_INFO,"No memory");
2a014536 100 close(ent_src->rng_fd);
d1b4c504 101 return -1;
61af3de3 102 }
d1b4c504
JG
103 /* 32 bits has been reserved for random byte size */
104 rng_cmd[13] = (unsigned char)(size & 0xFF);
105 rng_cmd[12] = (unsigned char)((size >> 8) & 0xFF);
106 rng_cmd[11] = (unsigned char)((size >> 16) & 0xFF);
107 rng_cmd[10] = (unsigned char)((size >> 24) & 0xFF);
108 offset = buf;
109 while (bytes_read < size) {
110 r=0;
111 while (r < sizeof(rng_cmd)) {
112 retval = write(ent_src->rng_fd,
113 rng_cmd + r,
114 sizeof(rng_cmd) - r);
115 if (retval < 0) {
116 message(LOG_ERR|LOG_INFO,
117 "Error writing %s\n",
118 ent_src->rng_name);
119 retval = -1;
120 goto error_out;
121 }
122 r += retval;
123 }
124 if (r < sizeof(rng_cmd)) {
125 message(LOG_ERR|LOG_INFO,
126 "Error writing %s\n", ent_src->rng_name);
127 retval = -1;
128 goto error_out;
129 }
130 r = read(ent_src->rng_fd, temp_buf,size);
2a014536
BH
131 r = (r - TPM_GET_RNG_OVERHEAD);
132 if(r <= 0) {
e42da63c
BH
133 message(LOG_ERR|LOG_INFO,
134 "Error reading from TPM, no entropy gathered");
135 retval = -1;
136 goto error_out;
137 }
d1b4c504
JG
138 bytes_read = bytes_read + r;
139 if (bytes_read > size) {
140 memcpy(offset,temp_buf + TPM_GET_RNG_OVERHEAD,
141 r - (bytes_read - size));
142 break;
143 }
144 memcpy(offset, temp_buf + TPM_GET_RNG_OVERHEAD, r);
145 offset = offset + r;
146 }
147 retval = 0;
148error_out:
149 close(ent_src->rng_fd);
150 free(temp_buf);
151 return retval;
61af3de3
JG
152}
153
154/* Initialize entropy source */
d1b4c504 155static int discard_initial_data(struct rng *ent_src)
61af3de3
JG
156{
157 /* Trash 32 bits of what is probably stale (non-random)
158 * initial state from the RNG. For Intel's, 8 bits would
159 * be enough, but since AMD's generates 32 bits at a time...
d1b4c504 160 *
61af3de3
JG
161 * The kernel drivers should be doing this at device powerup,
162 * but at least up to 2.4.24, it doesn't. */
163 unsigned char tempbuf[4];
2a014536 164 xread(tempbuf, sizeof(tempbuf), ent_src);
61af3de3
JG
165
166 /* Return 32 bits of bootstrap data */
2a014536 167 xread(tempbuf, sizeof(tempbuf), ent_src);
61af3de3 168
d1b4c504 169 return tempbuf[0] | (tempbuf[1] << 8) |
61af3de3
JG
170 (tempbuf[2] << 16) | (tempbuf[3] << 24);
171}
172
173/*
174 * Open entropy source, and initialize it
175 */
d1b4c504 176int init_entropy_source(struct rng *ent_src)
61af3de3 177{
d1b4c504
JG
178 ent_src->rng_fd = open(ent_src->rng_name, O_RDONLY);
179 if (ent_src->rng_fd == -1) {
180 return 1;
61af3de3 181 }
a26d20cf 182 src_list_add(ent_src);
61af3de3 183 /* Bootstrap FIPS tests */
d1b4c504
JG
184 ent_src->fipsctx = malloc(sizeof(fips_ctx_t));
185 fips_init(ent_src->fipsctx, discard_initial_data(ent_src));
186 return 0;
61af3de3
JG
187}
188
d1b4c504
JG
189/*
190 * Open tpm entropy source, and initialize it
191 */
192int init_tpm_entropy_source(struct rng *ent_src)
193{
194 ent_src->rng_fd = open(ent_src->rng_name, O_RDWR);
195 if (ent_src->rng_fd == -1) {
2a014536 196 message(LOG_ERR|LOG_INFO,"Unable to open file: %s",ent_src->rng_name);
d1b4c504
JG
197 return 1;
198 }
a26d20cf 199 src_list_add(ent_src);
d1b4c504
JG
200 /* Bootstrap FIPS tests */
201 ent_src->fipsctx = malloc(sizeof(fips_ctx_t));
202 fips_init(ent_src->fipsctx, 0);
203 close(ent_src->rng_fd);
204 return 0;
205}