Skip to content

Commit

Permalink
Create a new randomess generating function that retries on interrupti…
Browse files Browse the repository at this point in the history
…on by external signals, etc.

Signed-off-by: DL6ER <[email protected]>
  • Loading branch information
DL6ER committed Feb 22, 2025
1 parent 8a2225f commit 633c205
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 25 deletions.
6 changes: 1 addition & 5 deletions src/api/2fa.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@
#include "webserver/json_macros.h"
#include "log.h"
#include "config/config.h"
// getrandom()
#include "daemon.h"
// generate_password()
#include "config/password.h"

Expand Down Expand Up @@ -269,10 +267,8 @@ int generateTOTP(struct ftl_conn *api)
{
// Generate random secret using the system's random number generator
uint8_t random_secret[RFC6238_SECRET_LEN];
if(getrandom(random_secret, sizeof(random_secret), 0) < (ssize_t)sizeof(random_secret))
{
if(!get_secure_randomness(random_secret, sizeof(random_secret)))
return send_json_error(api, 500, "internal_error", "Failed to generate random secret", strerror(errno));
}

// Encode base32 secret
const size_t base32_len = sizeof(random_secret)*8/5+1;
Expand Down
6 changes: 2 additions & 4 deletions src/api/auth.c
Original file line number Diff line number Diff line change
Expand Up @@ -435,11 +435,9 @@ static int send_api_auth_status(struct ftl_conn *api, const int user_id, const t
static void generateSID(char *sid)
{
uint8_t raw_sid[SID_SIZE];
if(getrandom(raw_sid, sizeof(raw_sid), 0) < 0)
{
log_err("getrandom() failed in generateSID(): %s", strerror(errno));
if(!get_secure_randomness(raw_sid, sizeof(raw_sid)))
return;
}

base64_encode_raw(NETTLE_SIGN sid, SID_BITSIZE/8, raw_sid);
sid[SID_SIZE-1] = '\0';
}
Expand Down
61 changes: 45 additions & 16 deletions src/config/password.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,47 @@ static char * __attribute__((malloc)) double_sha256_password(const char *passwor
return strdup(response);
}

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

// 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);
} while (result < 0 && errno == EINTR);

// 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");
// 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;
}
do {
result = getrandom(buffer, length, 0);
} while (result < 0 && errno == EINTR);

if (result < 0)
{
const int err = errno;
log_err("getrandom() failed in get_secure_randomness(): %s", strerror(errno));
errno = err;
return false;
}
else if((size_t)result != length)
{
log_err("getrandom() failed in get_secure_randomness(): Not enough bytes generated (%zu != %zu)", (size_t)result, length);
return false;
}
return true;
}

static char * __attribute__((malloc)) base64_encode(const uint8_t *data, const size_t length)
{
// Base64 encoding requires 4 bytes for every 3 bytes of input, plus
Expand Down Expand Up @@ -328,11 +369,8 @@ char * __attribute__((malloc)) create_password(const char *password)
// Generate a 128 bit random salt
// genrandom() returns cryptographically secure random data
uint8_t salt[SALT_LEN] = { 0 };
if(getrandom(salt, sizeof(salt), 0) < 0)
{
log_err("getrandom() failed in create_password(): %s", strerror(errno));
if(!get_secure_randomness(salt, sizeof(salt)))
return NULL;
}

// Generate balloon PHC-encoded password hash
return balloon_password(password, salt, true);
Expand Down Expand Up @@ -527,11 +565,8 @@ int run_performance_test(void)
// Generate a 128 bit random salt
// genrandom() returns cryptographically secure random data
uint8_t salt[SALT_LEN] = { 0 };
if(getrandom(salt, sizeof(salt), 0) < 0)
{
printf("Could not generate random salt!: %s\n", strerror(errno));
if(!get_secure_randomness(salt, sizeof(salt)))
return EXIT_FAILURE;
}

printf("Running time-performance test:\n");
size_t t_t_cost = 16;
Expand Down Expand Up @@ -675,11 +710,8 @@ bool generate_password(char **password, char **pwhash)
// Generate a 256 bit random password
// genrandom() returns cryptographically secure random data
uint8_t password_raw[APPPW_LEN] = { 0 };
if(getrandom(password_raw, sizeof(password_raw), 0) < 0)
{
log_err("getrandom() failed in generate_password(): %s", strerror(errno));
if(!get_secure_randomness(password_raw, sizeof(password_raw)))
return false;
}

// Encode password as base64
*password = base64_encode(password_raw, sizeof(password_raw));
Expand All @@ -698,11 +730,8 @@ bool generate_password(char **password, char **pwhash)

// Generate a 128 bit random salt
uint8_t salt[SALT_LEN] = { 0 };
if(getrandom(salt, sizeof(salt), 0) < 0)
{
log_err("getrandom() failed in generate_password(): %s", strerror(errno));
if(!get_secure_randomness(salt, sizeof(salt)))
return false;
}

// Generate balloon PHC-encoded password hash
*pwhash = balloon_password(*password, salt, true);
Expand Down
1 change: 1 addition & 0 deletions src/config/password.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

void sha256_raw_to_hex(uint8_t *data, char *buffer);
char *create_password(const char *password) __attribute__((malloc));
bool get_secure_randomness(uint8_t *buffer, const size_t length);
enum password_result verify_login(const char *password);
enum password_result verify_password(const char *password, const char *pwhash, const bool rate_limiting);
int run_performance_test(void);
Expand Down

0 comments on commit 633c205

Please sign in to comment.