1
0
mirror of https://gitlab.xiph.org/xiph/icecast-server.git synced 2024-06-23 06:25:24 +00:00
icecast-server/src/prng.c
2023-06-01 12:32:17 +00:00

156 lines
4.1 KiB
C

/* Icecast
*
* This program is distributed under the GNU General Public License, version 2.
* A copy of this license is included with this source.
*
* Copyright 2020, Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>
*
* The SHA3 implementation is based on rhash:
* 2013 by Aleksey Kravchenko <rhash.admin@gmail.com>
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#ifdef HAVE_UNAME
#include <sys/utsname.h>
#endif
#ifdef HAVE_OPENSSL
#include <openssl/rand.h>
#include <openssl/err.h>
#endif
#include <igloo/prng.h>
#include "prng.h"
#include "global.h"
#include "cfgfile.h"
#include "logging.h"
#define CATMODULE "prng"
#define BLOCK_LENGTH (512/8)
#define SEEDING_FACTOR 128
#define SEEDING_MAX_BEFORE_RESEED 32768
static int initialized = 0;
static void prng_initial_seed(void)
{
#ifdef HAVE_OPENSSL
char buffer[1024];
const char *filename;
#endif
#ifdef HAVE_OPENSSL
filename = RAND_file_name(buffer, sizeof(buffer));
if (filename)
RAND_load_file(filename, -1);
ERR_get_error(); // clear error if any
#endif
}
static void prng_cross_seed(void)
{
char buffer[1024];
ssize_t len;
#ifdef HAVE_OPENSSL
if (RAND_bytes((unsigned char*)buffer, sizeof(buffer)) == 1) {
igloo_prng_write(igloo_instance, buffer, sizeof(buffer), -1, igloo_PRNG_FLAG_NONE);
} else {
ERR_get_error(); // clear error
}
len = igloo_prng_read(igloo_instance, buffer, sizeof(buffer), igloo_PRNG_FLAG_NONE);
if (len > 0)
RAND_add(buffer, len, len/10.);
#endif
}
static void prng_read_seeds(prng_seed_config_t *seed, int configure_time)
{
while (seed) {
switch (seed->type) {
case PRNG_SEED_TYPE_READ_ONCE:
case PRNG_SEED_TYPE_READ_WRITE:
if (configure_time)
igloo_prng_read_file(igloo_instance, seed->filename, seed->size, -1, igloo_PRNG_FLAG_NONE);
break;
case PRNG_SEED_TYPE_DEVICE:
igloo_prng_read_file(igloo_instance, seed->filename, seed->size, -1, igloo_PRNG_FLAG_NONE);
break;
case PRNG_SEED_TYPE_STATIC:
igloo_prng_write(igloo_instance, seed->filename, strlen(seed->filename), -1, igloo_PRNG_FLAG_NONE);
break;
case PRNG_SEED_TYPE_PROFILE:
if (strcmp(seed->filename, "linux") == 0) {
igloo_prng_read_file(igloo_instance, "/proc/sys/kernel/random/uuid", -1, -1, igloo_PRNG_FLAG_NONE);
}
if (strcmp(seed->filename, "linux") == 0 || strcmp(seed->filename, "bsd") == 0) {
igloo_prng_read_file(igloo_instance, "/dev/urandom", 64, -1, igloo_PRNG_FLAG_NONE);
}
break;
}
seed = seed->next;
}
}
void prng_initialize(void)
{
if (initialized)
return;
initialized = 1;
prng_initial_seed();
prng_cross_seed();
}
void prng_shutdown(void)
{
if (!initialized)
return;
initialized = 0;
}
void prng_configure(ice_config_t *config)
{
if (!initialized)
return;
igloo_prng_write(igloo_instance, config->location, strlen(config->location), -1, igloo_PRNG_FLAG_NONE);
igloo_prng_write(igloo_instance, config->admin, strlen(config->admin), -1, igloo_PRNG_FLAG_NONE);
igloo_prng_write(igloo_instance, config->hostname, strlen(config->hostname), -1, igloo_PRNG_FLAG_NONE);
igloo_prng_write(igloo_instance, config, sizeof(*config), -1, igloo_PRNG_FLAG_NONE);
prng_read_seeds(config->prng_seed, 1);
prng_cross_seed();
}
void prng_deconfigure(void)
{
ice_config_t *config;
prng_seed_config_t *seed;
if (!initialized)
return;
config = config_get_config();
seed = config->prng_seed;
while (seed) {
if (seed->type == PRNG_SEED_TYPE_READ_WRITE) {
igloo_prng_write_file(igloo_instance, seed->filename, seed->size, igloo_PRNG_FLAG_NONE);
}
seed = seed->next;
}
config_release_config();
}