/* @brief A program to seed fake entropy bits to /dev/random and /dev/urandom
 * @author Haris O. at NI.
 */

#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/random.h>

int main(int argc, const char** argv)
{
    int result = 1;
    struct rand_pool_info poolInfo;
    int rand = -1;
    int urand = -1;

    if (argc != 2) {
        errno = EINVAL;
        perror("Need to specify exactly one arg; number of bytes to seed");
        goto end;
    }

    memset(&poolInfo, 0, sizeof(struct rand_pool_info));
    errno = ERANGE;
    poolInfo.entropy_count = atoi(argv[1]);
    if (poolInfo.entropy_count == INT_MIN || poolInfo.entropy_count == INT_MAX) {
        perror("atoi failed");
        goto end;
    }

    rand = open("/dev/random", O_RDWR);
    if (rand == -1) {
        perror("failed to open /dev/random");
        goto end;
    }

    urand = open("/dev/urandom", O_RDWR);
    if (urand == -1) {
        perror("failed to open /dev/urandom");
        goto end;
    }

    if (ioctl(rand, RNDADDENTROPY, &poolInfo) != 0) {
        perror("failed to ioctl(RNDADDENTROPY) on /dev/random");
        goto end;
    }
    printf("%s: Seeded %d bytes of fake entropy to /dev/random\n", argv[0], poolInfo.entropy_count);

    if (ioctl(urand, RNDADDENTROPY, &poolInfo) != 0) {
        perror("failed to ioctl(RNDADDENTROPY) on /dev/urandom");
        goto end;
    }
    printf("%s: Seeded %d bytes of fake entropy to /dev/urandom\n", argv[0], poolInfo.entropy_count);

    /* success */
    result = 0;

    end:
        close(urand);
        close(rand);
        return result;
}
