Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prevent crash on failure to source secure randomness #2300

Merged
merged 6 commits into from
Mar 1, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 32 additions & 13 deletions src/config/password.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,8 @@ static char * __attribute__((malloc)) double_sha256_password(const char *passwor

bool get_secure_randomness(uint8_t *buffer, const size_t length)
{
ssize_t result;

ssize_t result = -1;
const char *generator = "getrandom";
// First try to get randomness in non-blocking mode and print a warning when not enough entropy is available right now
do {
result = getrandom(buffer, length, GRND_NONBLOCK);
Expand All @@ -103,32 +103,51 @@ bool get_secure_randomness(uint8_t *buffer, const size_t length)
// If not enough entropy is available right now, try again in blocking mode
if (result < 0 && errno == EAGAIN)
{
log_warn("getrandom() failed in get_secure_randomness(): Not enough entropy available right now, retrying in blocking mode");
log_warn("Not enough entropy available right now for generating secure randomness, retrying in blocking mode");
// Sleep for 1 second to give the kernel some time to gather entropy
sleepms(1000);
}
else
{
// If the first try was successful, return the result
if (result >= 0)
return true;
goto random_success;
}
do {
result = getrandom(buffer, length, 0);
} while (result < 0 && errno == EINTR);

if (result < 0)
if(result < 0)
{
const int err = errno;
log_err("getrandom() failed in get_secure_randomness(): %s", strerror(errno));
errno = err;
return false;
log_debug(DEBUG_API, "Getting secure randomness failed (%s), trying /dev/urandom", strerror(errno));
generator = "/dev/urandom";
result = getrandom_fallback(buffer, length, 0);
if(result < 0 || result < (ssize_t)length)
{
log_debug(DEBUG_API, "Fallback failed, trying internal DRBG generator");
generator = "internal DRBG";
result = drbg_random(buffer, length);
if(result < 0)
{
// Warning will be printed by drbg_random()
return false;
}

log_debug(DEBUG_API, "Internal DRBG generator successfully used");
}
else
log_debug(DEBUG_API, "Fallback to /dev/urandom successful");
}
else if((size_t)result != length)

// Check if enough bytes were generated
if(result != (ssize_t)length)
{
log_err("getrandom() failed in get_secure_randomness(): Not enough bytes generated (%zu != %zu)", (size_t)result, length);
log_err("Randomness generator (%s) failed: not enough bytes generated (%zd != %zu)", generator, result, length);
return false;
}

random_success:
log_debug(DEBUG_ANY, "Generated %zd bytes of secure randomness", result);
return true;
}

Expand Down Expand Up @@ -185,7 +204,7 @@ static char * __attribute__((malloc)) balloon_password(const char *password,
{
// Parameter check
if(password == NULL || salt == NULL)
return NULL;
return strdup("");

struct timespec start, end;
// Record starting time
Expand Down Expand Up @@ -370,7 +389,7 @@ char * __attribute__((malloc)) create_password(const char *password)
// genrandom() returns cryptographically secure random data
uint8_t salt[SALT_LEN] = { 0 };
if(!get_secure_randomness(salt, sizeof(salt)))
return NULL;
return strdup("");

// Generate balloon PHC-encoded password hash
return balloon_password(password, salt, true);
Expand Down
5 changes: 5 additions & 0 deletions src/daemon.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
#include <locale.h>
// freeEnvVars()
#include "config/env.h"
// destroy_entropy()
#include "webserver/x509.h"

pthread_t threads[THREADS_MAX] = { 0 };
bool resolver_ready = false;
Expand Down Expand Up @@ -425,6 +427,9 @@ void cleanup(const int ret)
// This should be the last action when c
destroy_shmem();

// De-initialize the random number generator and entropy collector
destroy_entropy();

// Free environment variables
freeEnvVars();

Expand Down
5 changes: 5 additions & 0 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
#include "database/query-table.h"
// verify_FTL()
#include "files.h"
// init_entropy()
#include "webserver/x509.h"

char *username;
bool startup = true;
Expand Down Expand Up @@ -62,6 +64,9 @@ int main (int argc, char *argv[])
log_info("########## FTL started on %s! ##########", hostname());
log_FTL_version(false);

// Initialize entropy and random number generator
init_entropy();

// Catch signals not handled by dnsmasq
// We configure real-time signals later (after dnsmasq has forked)
handle_signals();
Expand Down
Loading
Loading