mod_entropy_add_entropy.c 2.39 KB
/**
 * \file
 *
 * This adds the generated random bytes (sha1 hash of request) to the
 * /dev/random
 *
 * \author  Georg Hopp <georg@steffers.org
 *
 * \copyright
 * Copyright © 2012  Georg Hopp
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <linux/random.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>

int get_entropy_bits(const unsigned char *, size_t);

/**
 * fill /dev/random with sha1 from current request
 *
 * \todo add error handling...
 */
void
add_entropy(const unsigned char * data, size_t ndata)
{
	int                     i;
	int                     fd;
	int                     entropy = get_entropy_bits(data, ndata);
	struct rand_pool_info * output;

	output = (struct rand_pool_info *)malloc(
			sizeof(struct rand_pool_info) + ndata); 

	output->entropy_count = entropy;
	output->buf_size      = ndata;
	memcpy(output->buf, data, ndata);

	fd = open("/dev/random", O_WRONLY|O_NONBLOCK);

	if (ioctl(fd, RNDADDENTROPY, output) == -1) {
		switch(errno) {
			case EBADF:
				fprintf(stderr,
						"ioctl failed: no valid file descriptor %d\n",
						fd);
				break;

			case EFAULT:
				fprintf(stderr,
						"ioctl failed: invalid argument: %p\n",
						output);
				break;

			case EINVAL:
				fprintf(stderr,
						"ioctl failed: invalid request\n",
						errno);
				break;

			case ENOTTY:
				fprintf(stderr,
						"ioctl failed: discriptor not associated to "
						"character device\n",
						errno);
				break;

			case EPERM:
				fprintf(stderr,
						"ioctl failed: invalid permissions\n",
						errno);
				break;

			default:
				fprintf(stderr,
						"ioctl(RNDADDENTROPY) failed: %d\n",
						errno);
				break;
		}
	}

	fflush(stderr);
	free(output);
	close(fd);
}

// vim: set ts=4 sw=4: